I'm loading SELECT element with 6000 items using createElement and add methods. The code is shown below, and can also be accessed here. In IE8 it takes around 16 seconds to load the list and about the same time to clear it. In IE9 and Firefox the loading time is < 2 seconds and clearing time is < 1 second. Any ideas on how I can improve the speed in IE8?
Thank you.
<script type="text/javascript">
window.onload = loadList;
function loadList() {
clearList();
var start = new Date().getTime();
var o = document.getElementById("listLookupAvailableItems")
for (var i = 0; i < 6000; i++) {
var option = document.createElement("option");
option.text = 'ABCDF ' + i;
option.value = option.text;
o.add(option, o.options[null]);
}
log('Load time: ' + (new Date().getTime() - start));
}
function clearList() {
var start = new Date().getTime();
document.getElementById("listLookupAvailableItems").options.length = 0;
log('Clear time: ' + (new Date().getTime() - start));
return false;
}
function log(txt) {
document.getElementById('infoPanel').innerHTML += '</br>' + txt;
}
</script>
I'm loading SELECT element with 6000 items using createElement and add methods. The code is shown below, and can also be accessed here. In IE8 it takes around 16 seconds to load the list and about the same time to clear it. In IE9 and Firefox the loading time is < 2 seconds and clearing time is < 1 second. Any ideas on how I can improve the speed in IE8?
Thank you.
<script type="text/javascript">
window.onload = loadList;
function loadList() {
clearList();
var start = new Date().getTime();
var o = document.getElementById("listLookupAvailableItems")
for (var i = 0; i < 6000; i++) {
var option = document.createElement("option");
option.text = 'ABCDF ' + i;
option.value = option.text;
o.add(option, o.options[null]);
}
log('Load time: ' + (new Date().getTime() - start));
}
function clearList() {
var start = new Date().getTime();
document.getElementById("listLookupAvailableItems").options.length = 0;
log('Clear time: ' + (new Date().getTime() - start));
return false;
}
function log(txt) {
document.getElementById('infoPanel').innerHTML += '</br>' + txt;
}
</script>
Share
Improve this question
asked Mar 9, 2012 at 19:15
RossRoss
2,1411 gold badge19 silver badges19 bronze badges
2
- 1 You can improve the speed by loading less than 6000 items. Seriously, 6000 is too many. Your users don't want to sift through 6000 items in a dropdown. – Dagg Nabbit Commented Mar 9, 2012 at 19:33
-
You can declare
i
andoption
outside of the loop. Propably you are assigning real values through some variable instead of literalABCDF
. Compressing the whole loop in one line will speed up a little. IE9 is faster than IE8 , but that much...? – Teemu Commented Mar 9, 2012 at 19:37
3 Answers
Reset to default 10My guess is that that particular DOM operation is just really slow in IE8. In general, manipulating the DOM is the slowest type of operation in any browser. To get around that I typically try to find ways to bine my changes into one DOM update (e.g. add an HTML "batch" of 6000 rows to a table instead of individually adding 6000 rows to a table).
In this example the only way to do that would probably be to create all of the <option>
elements as HTML and then use innerHTML
to insert them into the <select>
. See this jsfiddle example: http://jsfiddle/pseudosavant/bVAFF/
I don't have IE8 to test with, but it is much faster even in Firefox (22ms vs 500ms) for me.
Update
Looks like it didn't work with innerHTML
in IE for loading the list, but it did work for clearing it. Loading it works using jQuery $(o).html(html);
though. I updated the jsfiddle example and it works in IE9, and hopefully IE8 now.
Javascript:
$(document).ready(function(){
loadListBatch();
});
function loadListBatch() {
clearListBatch();
var start = new Date().getTime();
var o = document.getElementById("listLookupAvailableItems")
var html = "";
for (var i = 0; i < 6000; i++) {
html += "<option value='"+'XYZ' + i+"'>"+'XYZ ' + i+"</option>";
}
// o.innerHTML = html; // Only one DOM operation, but still doesn't work in IE
$(o).html(html); // Using jQuery to insert the HTML makes it work with IE
console.log('Load time: ' + (new Date().getTime() - start));
}
function clearListBatch() {
var start = new Date().getTime();
document.getElementById("listLookupAvailableItems").innerHTML = ""; // It was already only one DOM call, but this is faster it seems.
console.log('Clear time: ' + (new Date().getTime() - start));
return false;
}
If you are supporting IE7/IE8 you should minimize JavaScript manipulation of the DOM. So if you are appending, inserting or deleting nodes you need to minimize DOM manipulation in general. The best solution is to bulk update items.
So, if you have a select list and you are doing JQuery.append() you will get better performance if you concatenate your entire options string before appending.
var str = $('<option value="x">Item 1</option>' + '<option value="y">Item 2</option>');
$('#selectMenu').append(str);
//or in a loop
var array = ['orange','apple','grapes','mangoes'];
var str = '';
for (var x= 0; x < array.length; x++) {
str = str + '<option value="' + x + '">' + x + '</option>';
}
$('#selectMenu').append(str);
Additionally, if you want to see how slowly JavaScript is executed by IE8 run the SunSpider JS test. Firefox 22 and Chrome 27 are around 300 ms while IE8 is around 4,000 ms. That tells a lot about why your JS speeds are slow. Interestingly IE10 es in at less than 200 ms now. http://www.webkit/perf/sunspider/sunspider.html
I had a very similar situation.
I have a set of inputs with 1700+ so I provided a "filter" option that would copy the select and apply a filter based on a besides the copied list. (It "opens" a dialog that expands the dropdownlistbox to a list almost as big as 80% of the screen)
Copying the worked unnoticeably in other browsers but took 8-15 secs in IE.
The solution, based on previous answers, and also based on this post (Learn the slow (and fast) way to append elements to the DOM) was to add all the items to a HTL string, then assigning this to the innerHTML of a new object, one that is not yet part of the DOM. And finally, replacing the object from the DOM with the new one.
This apparently reduces the number of "reflow" operations performed by the browser, which is most likely the culprit of such slow performance.
Some of the test before implementing this style, was to run the full for loop without adding the options to the list, and in such test, the code executed very fast, it was clear that selectElement.add(optionElement) was the slow part.
Here is an example of what my function ended like:
function fillselector(IdSelect){
var selector = document.getElementById(IdSelect);
if( !selector ){
alert('Original select element not found.');
return;
}
var lista = document.getElementById('selectFilter_lista');
if( !lista ){
alert('Copied list element not found.');
return;
}
var filterText = noSpecialChars(document.getElementById('selectFilter_text').value);
var options =''
for (var i = 0; i < selector.length; i++){
if (filterText == '' || noSpecialChars(selector[i].text).indexOf(filterText) != -1 ){
//Commented code works but is painfuly slow on IE
//var option = document.createElement("option");
//option.value = selector[i].value;
//option.text = selector[i].text;
//lista.add(option);
options += '<option value="'+selector[i].value+'">'+selector[i].text+'</option>';
}
}
var newList = document.createElement('select');
newList.id='selectFilter_list';
newList.className='selectFilter_list';
newList.size = 20;
newList.ondblclick= function(){closeselector(IdSelect, true);}
newList.innerHTML = options;
newList.value = selector.value;
var listParent = lista.parentElement; //<div> that only contains the <select>
listParent.removeChild(lista);
listParent.appendChild(newList);
}