Client side javascript, creation of several elements and show each asap - javascript

Client side javascript code creates some elements (about 50-100) in a cycle:
for (var i = 0; i < list.length; i++) {
var obj = document.createElement("DIV");
obj.innerHTML = "<span class=\"itemId\">" + list[i].Id
+ "</span><!-- some more simple code --> ";
mainObj.appendChild(obj);
}
There are some problems with browser rendering. For example, IE just freezes until it finishes the cycle, and then shows all elements at once. Is there a way to show each created element separately and immediately after appendChild()?

This is due to the single threaded nature of browsers. Rendering will not begin until the thread becomes idle. In this case, it's when your loop has completed and the function exits. The only way around this is to (sort of) simulate multiple threads using timers, like so:
var timer,
i = 0,
max = list.length;
timer = window.setInterval(function ()
{
if (i < max)
{
var obj = document.createElement("DIV");
obj.innerHTML = "<span class=\"itemId\">" + list[i].Id
+ "</span><!-- some more simple code --> ";
mainObj.appendChild(obj);
i++;
}
else
window.clearInterval(timer);
}, 1);
The obvious drawback is that this will take your loop longer to complete because it's fitting the rendering inbetween each iteration.

insert a delay between adding successive entries, with setTimeout().
function insertEntry(list, ix) {
if (ix == null) {
ix = 0;
}
else if (ix < list.length) {
var elt= document.createElement("DIV");
var attr = document.createAttribute('id');
attr.value = 'item'+ix;
elt.setAttributeNode(attr);
elt.innerHTML = "<span class='itemCls'>" + list[ix].Id + ': ' + list[ix].Name +
"</span><!-- some more simple code -->\n";
mainObj.appendChild(elt);
ix++;
}
if (ix < list.length) {
setTimeout(function(){insertEntry(list, ix);}, 20);
}
}
Kick it off with:
insertEntry(myList);
where myList is like this:
var myList = [
{ Id : '1938377', Name : 'Sven'},
{ Id : '1398737', Name : 'Walt'},
{ Id : '9137387', Name : 'Edie'}
...
};
demo: http://jsbin.com/ehogo/4

I wold do it like this using jQuery instead:
<!DOCTYPE html>
<html>
<head>
<script src="http://code.jquery.com/jquery-latest.js"></script>
<script>
$(document).ready(function() {
timer = window.setInterval(function ()
{
for (var i = 0; i < 100; i++) {
$('#container').append('<div>testing</div><br />');
}
},10);
});
</script>
</head>
<body>
<div id="container"></div>
</body>
</html>
jQuery does it so quickly, you won't even need to bother about showing as they are created, but you can make it smoother by adding a timer as the example shows.

Is there a specific reason you want the DOM to be updated after every cycle?
It would be alot faster if you create all the elements in one javascript element, and add this one element to the DOM when the cycle is finished.
var holder = document.createElement("DIV");
for (var i = 0; i < list.Length; i++) {
var obj = document.createElement("DIV");
obj.innerHTML = "<span class=\"itemId\">" + list[i].Id
+ "</span><!-- some more simple code --> ";
holder.appendChild(obj);
}
mainObj.appendChild(holder);

Related

Right way to dynamically update table

I am getting data over websocket every 10 seconds and i am updating the cells using this function:
agentStatSocket.onmessage = function (e) {
data = JSON.parse(e.data);
//console.log(typeof(data));
for (var i = 0; i < data.length; i++) {
var inboundTd = '#' + data[i]['id'] + '-inbound';
var outboundTd = '#' + data[i]['id'] + '-outbound';
if (data[i]['inboundCalls'] != 0) {
$(inboundTd).html(data[i]['inboundCalls']);
}
if (data[i]['outboundCalls'] != 0) {
$(outboundTd).html(data[i]['outboundCalls']);
}
}
};
This is working pretty fine. However, I see some lag with the table being updated. Currently, there are only 150 rows in the table. I do not know what will be the latency if rows will become 1000 or more.
I have the following questions:
What is the correct approach to design these kinds of tables in which data is changing very frequently? I am not using any library like react or angular. This is plain jQuery.I am using dataTables
jQuery to enhance table view.
One thing to consider is that, in many cases, accessing an element based on an ID is usually a lot quicker in vanilla javascript compared to jquery.
A simple example of that is:
function jsTest() {
for (let i = 0; i < 1000; i++) {
document.getElementById("js").innerHTML = i;
}
}
function jqueryTest() {
for (let i = 0; i < 1000; i++) {
$("#jquery").html(i);
}
}
function startup() {
console.time("javascript");
jsTest();
console.timeEnd("javascript");
console.time("jquery");
jqueryTest();
console.timeEnd("jquery");
}
// For testing purposes only
window.onload = startup;
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Javascript: <div id="js"></div>
Jquery: <div id="jquery"></div>
So, you could try changing your code to:
agentStatSocket.onmessage = function (e) {
data = JSON.parse(e.data);
//console.log(typeof(data));
for (var i = 0; i < data.length; i++) {
//var inboundTd = '#' + data[i]['id'] + '-inbound';
//var outboundTd = '#' + data[i]['id'] + '-outbound';
var inboundTd = data[i]['id'] + '-inbound';
var outboundTd = data[i]['id'] + '-outbound';
if (data[i]['inboundCalls'] != 0) {
//$(inboundTd).html(data[i]['inboundCalls']);
document.getElementById(inboundTd).innerHTML = data[i]['inboundCalls'];
}
if (data[i]['outboundCalls'] != 0) {
//$(outboundTd).html(data[i]['outboundCalls']);
document.getElementById(outboundTd).innerHTML = data[i]['outboundCalls'];
}
}
};
You can still use jquery for the rest of your code, if you wish, but simple updates to elements that can be targeted by ID are usually quicker with vanilla javascript.

Returning html code in javascript

I want to print html code in Javascript code.
I want to open and close the bottom line of five li tags. How can I do this with a for loop
jQuery(document).ready(function () {
InsertLi();
});
function InsertLi(){
var count = 5;
for (var i = 0; i < count; i++) {
var codeBlock = ' <li>' + i + '</li>';
$(".bildirimMetin").html(codeBlock);
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="bildirimMetin">
</ul>
You need to use append function instead. html function every time overrides your html content with the new content and you get only the last one. Also create your string with 5 li-s and then call the append at the end to work with DOM one time and have more performance.
function InsertLi() {
var count = 5;
var codeBlock = '';
for (var i = 0; i < count; i++) {
codeBlock += ' <li>' + i + '</li>';
}
$(".bildirimMetin").append(codeBlock);
}
jQuery(document).ready(function () {
InsertLi();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="bildirimMetin"></ul>
If you have only one item with bildirimMetin class, it will be better to use id instead of class.
Well, another solution, close to your code, with html, store all strings in your variable via += then you must define your variable before for loop also move your html after it. Your current code not working because it just store last string not all.
InsertLi();
function InsertLi() {
var count = 5;
var codeBlock = '';
for (var i = 0; i < count; i++) {
codeBlock += '<li>' + i + '</li>';
}
$(".bildirimMetin").html(codeBlock);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="bildirimMetin">
</ul>
you had a couple issues. One was overwriting the inner HTML instead of appending. The other was a syntax issue.
function InsertLi(){
var count = 5;
for (var i = 0; i < count; i++) {
var codeBlock = ' <li>' + i + '</li>';
$(".bildirimMetin").append(codeBlock);
}
}
jQuery(document).ready(function () {
InsertLi();
}
);

JavaScript Arrays - Iteration Trouble

I'm building a (very) mini JS framework to use for customizing my eBay listings. I do know how to circumvent their "no remote scripts" policy, and I could use jQuery, but this is really an exercise in getting myself better at JS.
I have a function of the global window object which returns a bunch of methods, like this:
window.iq = (function(){
return {
tag: function(tag) {
return document.getElementsByTagName(tag);
},
map: function(el, attr) {
var arr = [];
el = iq.tag(el);
for (i = 0; i < el.length; i++) {
var x = el[i].getAttribute(attr);
arr.push(x);
}
return arr;
},
// A bunch of others like this
};
})();
I'm having trouble (by which I mean I'm utterly stuck) iterating through an array of data-name attributes and hiding or showing images based on whether there is a match. Here's the function:
iq.click('#mblThumbs img', function(){
var dn = iq.map('img', 'data-name');
for (i = 0; i < dn.length; i++) {
if (this.getAttribute('data-name') === dn[i]) {
iq.fadeOut(200, iq.sel('#mblSlide img:not([data-name="' + dn[i] + '"])'));
iq.fadeIn(200, iq.sel('#mblSlide img[data-name="' + dn[i] + '"]'));
}
}
});
I can cycle through the first two images as many times as my heart desires, but as soon as I click on anything past the second image, the function only continues to work for it, and the subsequent indexes in the array. I'm guessing that this is either a problem with my map method, or maybe something to do with array length? I don't know. I'm flummoxed. Any thoughts or suggested are much appreciated.
FIDDLE: http://jsfiddle.net/h8z7c/
The issue is indeed with your click callback. Your fadeout selector is finding the first image that is not data-name=dn[i], which is always either "one" (if you clicked 2), or "two" (if you clicked 1). You either need to use selAll to grab all of the elements that are not the clicked one, or keep track of which one is currently selected. Here are the two ways of fixing it.
// Make sure they are all hidden
iq.click('#mblThumbs img', function(){
var dn = iq.map('img', 'data-name');
for (i = 0; i < dn.length; i++) {
if (this.getAttribute('data-name') === dn[i]) {
var outs = iq.selAll('#mblSlide img:not([data-name="' + dn[i] + '"])');
for (var j = 0; j < outs.length; j++) {
iq.fadeOut(200, outs[j]);
}
iq.fadeIn(200, iq.sel('#mblSlide img[data-name="' + dn[i] + '"]'));
}
}
});
// Or keep track of the currently selected
var selected = "one";
iq.click('#mblThumbs img', function(){
var dn = iq.map('img', 'data-name');
for (i = 0; i < dn.length; i++) {
if (this.getAttribute('data-name') === dn[i] && dn[i] !== selected) {
iq.fadeOut(200, iq.sel('#mblSlide img[data-name="' + selected + '"]'));
iq.fadeIn(200, iq.sel('#mblSlide img[data-name="' + dn[i] + '"]'));
selected = dn[i];
}
}
});

How do I step though an array one cell at a time using onclick?

I am new to JavaScript and am trying to create a function that changes the background color of my HTML document each time I click on a DIV. The code I have just loops though my array all the way to the end instead of one loop per click on my DIV. I know I am missing something that increments each time I click on the DIV, but can't figure out what. In my HTML document I have a DIV
<div id="autoText" onclick="moveMe()"></div>.
Here is my JavaScript so far:
var multipleColors = [];
multipleColors[0] = "red";
multipleColors[1] = "blue";
multipleColors[2] = "yellow";
function moveMe() {
for (i=0; i < multipleColors.length; i++) {
console.log("This is step " + i);
this.document.body.style.backgroundColor=multipleColors[i];
}
}
I would really appreciate anyone's advice?
Thanks.
If you want to continue from the beginning of the after you reached its end, use %(modulo) operator:
var multipleColors = [];
multipleColors[0] = "red";
multipleColors[1] = "blue";
multipleColors[2] = "yellow";
var current = 0;
function moveMe() {
current++;
var newIdx = current % multipleColors.length;
this.document.body.style.backgroundColor = multipleColors[newIdx];
}
Instead of using a loop, use a counter variable that you increase whenever the element is clicked:
var index = 0;
function moveMe() {
console.log("This is step " + index);
this.document.body.style.backgroundColor=multipleColors[index];
index += 1;
}
If you want to continue from the beginning of the array after you reached its end, reset the variable:
var index = 0;
function moveMe() {
console.log("This is step " + index);
this.document.body.style.backgroundColor=multipleColors[index];
index += 1;
if (index === multipleColors.length) {
index = 0;
}
}
try something like this
var multipleColors = [];
multipleColors[0] = "red";
multipleColors[1] = "blue";
multipleColors[2] = "yellow";
function moveMe() {
this.document.body.style.backgroundColor=(multipleColors[multipleColors.indexOf(this.document.body.style.backgroundColor)+1])?multipleColors[multipleColors.indexOf(this.document.body.style.backgroundColor)+1]:multipleColors[0];
}
You can keep adding the more colors in array.
DEMO

add div tags after specific amount of time repeatedly in javascript/jquery

I need to add append 10 div tags to another one but I need to wait random time before appending each one, something like this:
function start()
{
for (var i= 0; i< 10; i++)
{
var time = generateRandomWaitingTime();
sleep(time);
$('#div1').append('<div> div num' + i + '</div>');
}
}
I tried implementing my own sleep(time); function like here but it didn't work with me as it hangs any page event till the wait(time) finishes
setTimout() Seems to be exactly what you're looking for.
You should make use of setTimeout and a closure:
//closure
var addElement = function(i){
return function(){
$('#div1').append('<div> div num' + i + '</div>');
};
};
function start() {
for (var i = 0; i < 10; i++) {
var time = generateRandomWaitingTime();
setTimeout(addElement(i), time);
}
}
Living demo: http://jsfiddle.net/JaR34/
Update:
Living demo: http://jsfiddle.net/JaR34/1/
try this:
var elements = [1000,2000,3000,4000,5000,6000,7000];
function generateRandomWaitingTime(){
//will give you random index
var index = Math.floor((Math.random()*elements.length));
return (elements[index]);
}
function appendDiv(i){
var time = generateRandomWaitingTime();
setTimeout(function () {
$('#div1').append('<div> div num' + i + '</div>');
}, time);
}
for (var i = 0; i < 10; i++) {
appendDiv(i)
}
working fiddle here: http://jsfiddle.net/6neFA/1/

Categories

Resources