ScrollTop doesn't work on dynamically generated elements - javascript

I am trying to create a chat system (like Facebook)'s where a user clicks the name of the online user and a chat box will appear. _chatbox is generated dynamically using javascript. It will scroll down to the last message. The chat box and messages load/display successfully but the scroll down function is not working... why?
//displays the popups. Displays based on the maximum number of popups that can be displayed on the current viewport width
function display_popups() {
//code for popup here
}
//creates markup for a new popup. Adds the id to popups array.
function register_popup(id, name) {
var element = '<div class="popup-box chat-popup" id="' + id + '">';
element = element + '<div class="popup-head">';
element = element + '<div class="popup-head-left">' + name + '</div>';
element = element + '<div class="popup-head-right">✕</div>';
element = element + '<div style="clear: both"></div></div><div class="popup-messages"></div></div>';
document.getElementsByTagName("body")[0].innerHTML = document.getElementsByTagName("body")[0].innerHTML + element;
calculate_popups();
scrollDown(id);
}
//scroll down to the last message
function scrollDown(id) {
var messages = document.getElementById(id);
messages.scrollTop = messages.scrollHeight;
}
//calculate the total number of popups suitable and then populate the toatal_popups variable.
function calculate_popups() {
//calculate popups here
}
<div class="sidebar-name">
<a href="javascript:register_popup('ind', 'Indiana Pacers');">
<img width="30" height="30" src="img/ind.png" />
<span>Indiana Pacers</span>
</a>
</div>

It works, but you seemed to select the wrong element. I adapted your code so that i can demonstrate what is going on. Your scrollable element here is the message container (class ".popup-messages"), not the popup itself.
You need to adapt this code though, as i selected directly the .popup-messages element, but you might want to select the one that is specifically inside your popup.
//displays the popups. Displays based on the maximum number of popups that can be displayed on the current viewport width
function display_popups()
{
//code for popup here
}
//creates markup for a new popup. Adds the id to popups array.
function register_popup(id, name)
{
var element = '<div class="popup-box chat-popup" id="'+ id +'">';
element = element + '<div class="popup-head">';
element = element + '<div class="popup-head-left">'+ name +'</div>';
element = element + '<div class="popup-head-right">✕</div>';
element = element + '<div style="clear: both"></div></div><div class="popup-messages"><p>message</p><p>message</p><p>message</p><p>message</p><p>message</p><p>message</p><p>message</p><p>message</p><p>message</p><p>message</p><p>message</p><p>last message</p></div></div>';
document.getElementsByTagName("body")[0].innerHTML = document.getElementsByTagName("body")[0].innerHTML + element;
calculate_popups();
scrollDown(id);
}
//scroll down to the last message
function scrollDown(id)
{
var messages = document.getElementsByClassName('popup-messages')[0];
messages.scrollTop = messages.scrollHeight;
}
//calculate the total number of popups suitable and then populate the toatal_popups variable.
function calculate_popups()
{
//calculate popups here
}
window.onload = function(){
register_popup('test', 'testName');
};
.popup-messages {
height: 100px;
overflow-y: scroll;
}
<div class="sidebar-name">
<a href="javascript:register_popup('ind', 'Indiana Pacers');">
<img width="30" height="30" src="img/ind.png" />
<span>Indiana Pacers</span>
</a>
</div>

Why do you use innerHTML instead of creating an element?
Can you try creating the element with Javascript and adding it to DOM manually like:
var popupBox = document.createElement("div");
// Set properties
var popupHead = document.createElement("div");
// Set properties
popupBox.appendChild(popupHead);
// etc. etc
// Then add it to DOM
document.getElementsByTagName("body")[0].appendChild(element)
// This should work now
calculate_popups();
scrollDown(id);
I think setting innerHtml and converting it to DOM is processed later than your function call.
Read up on creating elements with Javascript here:
https://developer.mozilla.org/en-US/docs/Web/API/Document/createElement

Related

Javascript - Get Id from innerHTML element

I have a function which creates new elements in a for loop. For example, I want a div for every item in an array. But I need the ID of the created html div-tag to trigger another function.
This is what I currently got:
function change() {
for (let i = 0; i <= 2; i++) {
let modal = document.createElement('div');
let a = '<div id="id'+i+'"> innerHTML </div>';
modal.innerHTML = a;
// document.getElementById(a.this.id).innerHTML = "get by id";
document.getElementById('test').appendChild(
modal
);
}
}
<div class="test" id="test">test</div>
<button onclick="change()">Change</button>
I need to get the id of every div which is created onclick.
I tried to to like document.getElementById('id' + i).innerHTML = "do something"; but this doesnt work. Someone have a solution for my problem? jQuery is also an option!
You can only use document.getElementById after the element has been added to the DOM.
//...
document.getElementById('test').appendChild(modal);
document.getElementById('id' + i).innerHTML = "get by id";
//...

How can I get innerhtml except one of its child Jquery

I want to print my elements so I need to get innerHtml of the whole div but I need to hide one element from printed but still found in the main page
My attempt looks like this
var printcontent = document.getElementById(el).innerHTML
+" <div class='row'><span class='glyphicon glyphicon-tasks'></span><b></b></div>"
+ document.getElementById(tble).innerHTML
+ document.getElementById(img).innerHTML;
this works fine but I need to hide the elment ID ="attach"
var panel = document.getElementById(el).innerHTML;
var filteredpanel = panel.remove(document.getElementById("attach").innerHTML)
Using jQuery:
$('#divID').not('#attach');
or
$('#divID:not(#attach)');
Try this
$('#attach').hide(); /* hide */
var printcontent = $(el).html() /* assign var */
+" <div class='row'><span class='glyphicon glyphicon-tasks'></span><b></b></div>"
+ $(tble).html()
+ $(img).html();
$('#attach').show(); /* show again */

Extract Link Query String Data And Create A New Link Inside A Different List

The goal is to have info from a link in #list and have it create a new link in #list3.
Here is the link http://jsfiddle.net/4y5V6/24/
Is there a way to make it where once you click a link it will push it to #list3 and make the link look like this twitch.tv/chat/embed?channel=(channelname)&popout_chat=true ?
Thank you for your time!!
HTML:
<div id="navi">
<ul>
<li>Stream Selection:</li>
<li>SC2<ul id="list"><li><ul></ul></li></ul></li>
<li>League<ul id="list2"><li><ul></ul></li></ul></li>
<li>Chat<ul id="list3"><li><ul></ul></li></ul></li>
</ul>
</div>
<iframe id="iframe1" name="iframe1" type="text/html" src="" frameBorder="0" height="200px" width="300px">
</iframe>
Current function that populates the list.
// first set of streams SC2
$.getJSON("https://api.twitch.tv/kraken/search/streams?q=starcraft&limit=18&&type=top&callback=?", function (data) {
var temp = "";
$.each(data.streams, function (index, item) {
temp = temp + "<li><a target='iframe1' href='http://www.twitch.tv/widgets/live_embed_player.swf?channel=" + item.channel.name + "'>" + item.channel.display_name + "</a></li>";
});
$("#list ul ").html(temp);
});
// next set of streams LoL
$.getJSON("https://api.twitch.tv/kraken/search/streams?q=League%20of%20Legends&limit=18&&type=top&callback=?", function (data) {
var temp = "";
$.each(data.streams, function (index, item) {
temp = temp + "<li><a target='iframe1' href='http://www.twitch.tv/widgets/live_embed_player.swf?channel=" + item.channel.name + "'>" + item.channel.display_name + "</a></li>";
});
$("#list2 ul ").html(temp);
});
$('#navi').on('click', '#list a', function(e) {
var x = $(this).prop('href'),
y = x.slice(x.indexOf('channel')+8),
z = 'twitch.tv/chat/embed?channel=('+y+')&popout_chat=true',
clone = $(this).clone().attr('href', z);
$('#list3 ul').append($('<li />', { html: clone }));
});
Fork
Alternate version: No duplicates.
Adding ability to open new chat link in new smaller window
jsFiddle only copies list 1 to list 3
jsFiddle Copies from both list 1 and 2 to list 3
// The following call is jQuery's way of assigning events to both "Static"
// && "Dynamic" Elements. This way, even if the element is loaded after
// page load, it still gets the event callback.
// Keep in mind, you do need either a static parent (such as below, I use
// `$('#navi')`, since I assume this element is always present on your page
// load) |OR| you can use `$(document)`. The later is often recommended
// against, as you could run into "slowed down response" issues or naming
// issues. Personally, I use `$(document)` all the time and haven't had a
// complaint yet.
// Then you simply assign your event(s) to your "Selectors"
// For just list 1 that would be
// .on('click', '#list a'
// For list 1, and 2 that would be
// .on('click', '#list a, #list2 a'
// See Also: http://api.jquery.com/on/
$('#navi').on('click', '#list a, #list2 a', function(e) {
var x = $(this).prop('href'), // get href of <a> clicked
y = x.slice(x.indexOf('channel')+8), // extract name
z = 'twitch.tv/chat/embed?channel=('+y+')&popout_chat=true', // create new href link
clone = $(this).clone().attr('href', z), // clone this <a> and replace href with new one created
item = $('<li />', { class: y, html: clone }); // create new <li> making our cloned <a> it's innerHTML
if (!$('#list3 ul .' + y).length) $('#list3 ul').append(item); // check <li> item doesn't already exist and add to list
}) // Thanks to jQuery "chaining", I don't have to "recall" our static parent
.on('click', '#list3 a', function(e) {
e.preventDefault();
var lnk = $(this).attr('href');
// The following is basic JavaScript and simply opens a new window
// simply adjust width and height based on PIXELS
// see more window.open options #: http://www.w3schools.com/jsref/met_win_open.asp
// See Also: http://stackoverflow.com/questions/tagged/javascript+window+open
window.open(lnk, "myWindowName", "width=800, height=600");
})

Problems updating the content of a Kendo UI TabStrip without AJAX?

I have a small console that displayed the output of certain actions in my website, the need to have another console that would display a different kind of output made me want to combine both consoles in a Kendo UI TabStrip, the thing is that the information displayed on the console isn't received with AJAX so when I started to insert the HTML elements like before, the tab didn't got updated.
This is how I initialize the tab:
$('#tabConsole').kendoTabStrip({
animation: {
open: {
effects:'fadeIn'
}
}
});
This is how my HTML looks:
<div id="tabConsole">
<ul>
<li class="k-state-active">Salida</li>
<li id="notificacionTab">Notificaciones</li>
</ul>
<div id="userConsole"></div>
<div id="notificationConsole"></div>
</div>
This is how I try to update it:
function appendToConsole(content, type, optional) {
//code to append to console
var actualDate = new Date();
var prevContent = $('#userConsole').html();
if (typeof prevContent === 'undefined') {
prevContent = '';
}
var strType = '';
var iconType = '';
var moreOutput = '';
if (type == 1) {
strType = 'infoConsole';
iconType = 'infoIcon.png';
} else if (type == 2) {
strType = 'warningConsole';
iconType = 'warningIcon.png';
moreOutput = '<img id="viewDetails" value="' + optional + '" class="moreConsole" src="../Content/images/icons/arrow.png">';
} else if (type == 3) {
strType = 'errorConsole';
iconType = 'errorIcon.png';
}
var iconOutput = '<img class="iconConsole" src="../Content/images/icons/' + iconType + '">';
var dateOutput = '<div class="dateConsole">' + iconOutput + ' ' + actualDate.toLocaleDateString() + ', ' + actualDate.toLocaleTimeString() + ' : </div>';
var consoleOutput = prevContent + '<div class="outputConsole">' + dateOutput + content + moreOutput + '</div>';
$('#userConsole').html(consoleOutput.toString());
var height = $('#userConsole')[0].scrollHeight;
$('#userConsole').scrollTop(height);
//my try to update the tab
var tabStrip = $('#tabConsole'),
selectedIndex = tabStrip.data('kendoTabStrip').select().index(),
clone = original.clone(true);
clone.children('ul')
.children('li')
.eq(selectedIndex)
.addClass('k-state-active')
.end();
tabStrip.replaceWith(clone);
$('#tabConsole').kendoTabStrip({
animation: {
open: {
effects: 'fadeIn'
}
}
});
}
How can I update the contents of the DIV that are inside the TabStrip?
EDIT
It seems Kendo UI renames the DIVs' ids that represent the tabs to tabConsole-1 and tabConsole-2, explaining why the update wasn't working, still there's a lot of strange behavior, I had to specify the height for each DIV so the overflow propety would work, also the images with id viewDetails and class moreConsole when set to position absolute, get rendered outside the DIV that represents the tab, but if I change the position property to relative, the images stay inside the DIV but are displayed not at the end of the DIV like I want to, but relative to the size of the DIV that comes before them.
I'm really confused as to how to set the styles so the contents are displayed properly.
Adding content to a tabStrip can be achieved using:
$(tabConsole.contentElement(idx)).append(newContent)
where:
idx is the tab index,
newContent is what you want to add to the existing content and
tabConsole is the variable set to $("#...").kendoTabStrip(...).data("kendoTabStrip");.
You don't need to create a new tabStrip (in addition you should not re-create KendoUI elements since this is a pretty expensive operation).
About using multiple tags with the same id... you should not use it, use class instead. ids should be unique.
I'm still trying to understand your problem with the styling.

How to get contents of a child div javascript

I want to get the get the contents of a div that's inside another div and put them in a list, to send it to the database after that.
I loop around the div and get all it's contents but all what it just returns the content of the first item of the loop.
The Div looks like this:
$('#Classes').append('<div> <h1 class = "flip" wpID="' + subjects[i].Wkp_ID+ '</h1><div id ="NewBody" class="panel" contenteditable>' + subjects[i].Wkp_Body + '</div> </div>');
I use these lines to get the content:
$('#Classes div').each(function (index) {
var header = $(this).children('h1');
var wpID = header.attr('wpID');
var WeekBody = document.getElementById("NewBody");
var Weekbodycontent = WeekBody.innerHTML;
WeekPlan[index] = {"Wkp_Body": WeekBody};
});
So , do you know how can I add all the items to the list one by one ?
Thanks
You have several issues. First off, you can't have the same ID present in more than one object in your document. You need to change that.
Then, I would suggest this type of solution using a class on the desired .panel div:
$('#Classes').append('<div class="container"><div class="panel" contenteditable>' +
subjects[i].Wkp_Body + '</div> </div>');
$('#Classes .container').each(function (index) {
var header = $(this).children('h1');
var body = $(this).find(".panel");
var Weekbodycontent = body.html();
WeekPlan[index] = {"Wkp_Body": body.get(0)};
});

Categories