Taking long time to load selectBox - javascript

Below code snippet, "for" loop is taking long time to load the data to select box, could any one help me ? even I am using Jquery 1.3.2 which is new to me.
here names.response.length is 120000 records.
function personNameChangedCallback(names){
if(names.response.length > 0){
var options = [];
for (var i = 0; i< names.response.length; i++) {
options.push('<option>'+ names.response[i] +'</option>');
}
jQuery('[id=personNameSelected]').append(options.join(''));
}

What could help is to avoid using an array to store the options and instead concatenate the strings directly.
Here is a jsperf comparison for this, using array is around 80% slower than directly concatenating a string:
https://jsperf.com/javascript-test-string-concat-vs-array/1
So you can change your function like this:
function personNameChangedCallback(names){
if(names.response.length > 0){
var htmlOptions = '';
for (var i = 0; i< names.response.length; i++) {
htmlOptions += '<option>'+ names.response[i] +'</option>';
}
jQuery('[id=personNameSelected]').html(htmlOptions);
}
The reason why it is slow in Internet Explorer, is because it's Javascript engine is not as advanced as the ones of other browsers.
Internet Explorer will also have issues letting you scroll through all these options.
Using a suggestion box as already mentioned by someone else is a better option, especially when your applciation has to be compatible with Internet Explorer.

Related

Trying to make sense of "this" in my javascript code (one thing works, the other doesn't)

I've been trying to learn javascript by refactoring some Jquery examples in a book into javascript. In the following code I add a click listener to a tab and make it change to active when the user clicks on the tab.
var tabs = document.querySelectorAll(".tabs a span");
var content = document.querySelectorAll("main .content li");
for (var tabNumber = 0; tabNumber <= 2; tabNumber++) {
tabs[tabNumber].addEventListener("click", function (event) {
for (var i = 0; i < tabs.length; i++) {
tabs[i].classList.remove("active");
}
tabs[tabNumber].classList.add("active");
for (var i = 0; i < content.length; i++) {
content[i].innerHTML = "";
}
event.preventDefault();
});
}
This returns an undefined error when I run it. However, I tried replacing tabs[tabNumber].classList.add("active") with this.classList.add("active") and it worked.
Why doesn't the previous code work? As far as I can see they are referring to the same thing, and tabs[tabNumber] should work since at that point in the code it is tabs[0].
If use this, I think it's better and a more polished solution. If you still want to use tabNumber, it's probably evaluating to 3 in every click callback, because it's the number after the last iteration, and you don't have a tabs[3] position.
So, you just have to make a closure of the tabNumber variable.
I guess other answers told you why tabs[tabNumber] does not work (because it comes from the score of the for loop and so, is always equal to the greater value of tabNumber).
That's why I would recommend using a .forEach loop. Careful though because it doesn't work on arrays of DOM nodes produced by document.querySelectorAll(), but you can use:
// ES6
Array.from(document.querySelectorAll('...'))
// ES5
[].slice.call(document.querySelectorAll('...'))
Anyway, I made a simplified working demo of your code.
Note that I save the currently active tab in a variable, to prevent another for loop. You could also do:
document.querySelector('.active').classList.remove('active')
But I like to reduce the amount of DOM reading.
Good luck for your apprentissage, re-writing some jQuery code into Vanilla JS seems like a good method, and you might acquire a far better comprehension of JavaScript.

It appears that getElementsByTagName('table') doesn't work properly in IE11. Is there a work around?

var tables= dragContainer.getElementsByTagName('table');
The array returned by this call doesn't have the rows array filled out every time. This works properly in Chrome and IE9, but not in IE11.
Is there a work around I can use? I tried doing the following but it doesn't appear to be working. I'm not quite a javascript expert to tell exactly why but I am going to keep digging for a bit.
I could just pull the rowNodeList and store it, but I want to override the tables[j].rows because there is a large amount of code expecting this sort of structure.
var tables= dragContainer.getElementsByTagName('table');
for (i = 0; i < tables.length; i++) {
var rowNodeList = tables[j].getElementsByTagName('tr');
tables[j].rows.length = 0; //clear array
for (k=0; k < rowNodeList.length; k++) {
tables[j].rows[k] = rowNodeList[k];
}
}
EDIT: I just realized since this code is FOSS, I can just link to it.
https://github.com/dbunic/REDIPS_drag/blob/master/redips-drag-source.js#L334

Measure what part of a loop that is slow?

I'm looping through a dataset with a couple of thousand items in it like this.
users.forEach(function(user){
//List ALLTHETHINGS!
listAllEverything(user)
//Add gropings
user.groupings = groupings.filter(function(grouping){
return grouping.conditional(user)
})
//Add conversions to user, one per user.
user.conversions = {}
//for each conversionList
conversionLists.forEach(function(conversionList){
user.conversions[conversionList.name] = [];
//for each conversion
for (var i = conversionList.conversions.length - 1; i >= 0; i--) {
var conversion = conversionList.conversions[i]
//test against each users apilog
var converted = user.apilog.some(function(event){
return conversion.conditional(event);
})
if (converted){
//Lägg till konverteringen och alla konverteringar som kommer innan.
for (var i = i; i >= 0; i--){
user.conversions[conversionList.name].push(conversionList.conversions[i])
}
break;
}
};
})
})
I know this is not the most optimized code and I have some ideas how it can be improved. But i'm pretty new to these kinds of problems, so I'm not sure how I should prioritize. I know about console.time, which is useful but I want to use something that allows me to compound the time spent on each part of the forEach-loop, either a tool (I usually use chrome) or some debugging-method. Perferably something that doesn't effect the performance too much.
Since you are using Chrome you shoud check out the Timeline tab in your browsers DevTools - just hit the record button before running the loop and stop it once it's done. You will se a nice breakdown of everything that just happened and you will be mostly interested in yellow bars - they show JavaScript operations.
Please check out this video presentation by Paul Irish about Performance Tooling
As you know, in Chrome or Firefox you can just wrap a piece of code with console.time (and console.timeEnd) and it will measure the speed of particular operation and print it in the console.
For example: to measure the time it takes for an entire loop to execute use:
console.time('For loop benchmark');
for(i=0; i<1000; i++) {
// do some operations here
}
console.timeEnd('For loop benchmark');
But, if you want to measure each iteration you can parameterize the name of the log inside the loop so that you can name each specific operation the way you want:
for(i=0; i<1000; i++)
var consoleTimeName = 'Measuring iteration no '+i+' which is doing this and that...';
console.time(consoleTimeName);
// do some operations here
console.timeEnd(consoleTimeName);
}
Using it you can see for yourself how much faster simple for loop can be in comparsion to jQuery's $.each loop.
You can find more about this on developer.mozilla.org and developer.chrome.com. Please not that this is note a standarized, cross-browser compatibile feature and you should not be using it on a production website, since some browser like IE may throw you an error when they see it.

parentNode not deleting properly

my javascript knowledge is pretty poor. I'm trying to run a script with greasemonkey on http://www.twitch.tv/directory/all to remove certain kinds of streams from the list based on an image provided next to a shot of the stream(like picture of hearthstone, minecraft etc.). Here's the code:
//what you want to remove
var killIt=["http://static-cdn.jtvnw.net/ttv-boxart/Hearthstone%3A%20Heroes%20of%20Warcraft-138x190.jpg", "http://static-cdn.jtvnw.net/ttv-boxart/League%20of%20Legends-138x190.jpg", "http://static-cdn.jtvnw.net/ttv-boxart/Minecraft-138x190.jpg"];
var el = document.getElementsByClassName("boxart");
//runthrough elements killing certain ones
for (i = 0; i < el.length; i++) {
for (j = 0; j < killIt.length; i++) {
if (el[i].src == killIt[j]) {
var ely = el[i].parentNode;
ely.parentNode.removeChild(ely);
}
}
}
So i tried it on w3schools site and the code works fine, but when i try to actually run it in twitch.tv it does nothing(seemingly).
Am i missing something about parent nodes? Or greasemonkey?
The second for should be j++. Also you can use .indexOf to test if the URL is listed in the array to avoid a other for loop.

Improvements in JavaScript animation

I am trying to create a train station text effect.
You can see here what i have achieved so far: http://www.jaspreetkaur.com/chatter/
here's the code, for your reference: http://jsfiddle.net/alokjain_lucky/ARhvu/
Issues:
The effect is running very slow, not giving it a very smooth and realistic effect.
Not working in IE7
I think the script i have created can be improved.
Please provide your expert advise to resolve the issues.
Thanks :)
Update:
The script is for the animation of text "Get to the chatter that matters"
Following is the Javascript code i have used:
$(document).ready(function() {
var newSrt = '';
for (var i=0; i<str.length; i++) {
if (str[i] != ' ') {
newSrt += '<span>'+str[i]+'</span>';
//newSrt += '<span> </span>';
} else {
newSrt += '<span class="nobg">'+str[i]+'</span>';
//newSrt += '<span class="nobg"> </span>';
}
}
$('.animate').html(newSrt);
scroll();
});
var str = ('The quick brown fox jumps over the lazy dog').toUpperCase();
var symtype=new Array(" ","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z");
var symarray=new Array();
for (var i=0; i<str.length; i++){ symarray[i]=" "; }
function scroll(){
for (var i=0; i<str.length; i++){
if (symarray[i]!=str.substring(i,i+1)) {
for (var x=0; x<symtype.length; x++) {
if (symarray[i]==symtype[x]) {
symarray[i]=symtype[x+1];
break;
}
}
}
}
for (var i=0; i<str.length; i++) {
$('.animate').find('span').eq(i).html(symarray[i]);
}
setTimeout('scroll()',10);
}
I hope this describes the code batter.
Update 2
Script is working in IE7 now, it's too fast on all browsers, i can make it slow by changing the setTimeout, but it's too slow in Firefox (only), I am using Firefox 9.0.1
Update 3
Surprisingly firebug is making the script slow in Firefox, turning firebug off, resolves the speed issue in Firefox.
in IE7 issue is related to CSS, which i think i will be able to resolve.
The only think left is to improve the script to make it reusable for other places in the website.
I fixed up your jsFiddle here: http://jsfiddle.net/jfriend00/VWXFp/ to make it run and it appears to work now, even in IE.
I moved the $(document).ready() block to the end so the globals are defined first which was only required because of the way you had the jsFiddle configured.
I changed to setTimeout(scroll,100); to use the direct function reference rather than a text string.
I changed the timeout vale on the timer to 100ms
I changed the jsFiddle setting in the upper left to "no wrap (body)"
I changed your letter setting loop to be massively more efficient. You were re-finding ever single letter span for every single letter rather than finding them all once and just looping through them. This could have been a performance issue in some browsers.
For #5, I changed from this:
for (var i=0; i<str.length; i++) {
$('.animate').find('span').eq(i).html(symarray[i]);
}
to this:
$('.animate').find('span').each(function(index, element) {
$(this).html(symarray[index]);
});
Which evaluates $('.animate').find('span') only once instead of str.length times.

Categories

Resources