1

I have to manage big drop down list (thousands of items) and I encounter performance problem with IE8 with the jQuery .html method. Indeed it takes 3-4seconds to clear the content.

Do you have any workarounds ?

Code :

var selectHtml = "";
$(data.items).each(function () {

    var option = "<option value='";
    option += this.Value + "'";

    if (this.Selected) {
        option += " selected";
    }

    option += ">" + this.Text + "</option>";
    selectHtml += option;
});
$(target).html(selectHtml);

.html of jQuery call .empty and in the IE profiler I can see that it is .empty that takes most of the time.

Pak
  • 2,639
  • 2
  • 21
  • 27

2 Answers2

1

Assuming you mean something like

<ul id='mylist'>
  <li>Item 1</li>
  .... 
  <li>Item n</li>
</ul>

or the equivalent select/option statement, you need:

$('#mylist').empty()

Alternatively, if you're only actually changing a few items in your dropdown list, perhaps you should maintain a map between the data.value and the element in the select list, so you only need to add items which have not already been placed in the list, and have a simple reference to items to remove.

I suspect you are wrong about the time split and most of the time is building the list. Try pushing all your new option items onto an array and then performing a single join of the array at the end.

var list = [];

$(data.items).each(function () {
    var selected = this.Selected ? ' selected' : '';
    var option = "<option value='" + this.Value + "'" + selected + ">" 
                 + this.Text + "</option>";
    list.push( option);
});

$(target).html(list.join( "\n"));
vogomatix
  • 4,856
  • 2
  • 23
  • 46
  • The array increased slightly the performance. Maintain a map would be another solution perfectly viable, thanks ! – Pak Jul 15 '15 at 15:04
  • If data.items is an array and not an object, you can use: `list = data.items.map( function () ....);` instead of your each loop – vogomatix Jul 15 '15 at 15:07
0

I found the solution here : https://stackoverflow.com/a/23552898/1431524

I ended up with this code :

function clearOptions(select) {
    var selectParentNode = select.parentNode;
    if (selectParentNode) {
        var newSelect = select.cloneNode(false); // Make a shallow copy
        selectParentNode.replaceChild(newSelect, select);
        return newSelect;
    }
    return undefined;
}

function appendSelectHtml(data, target) {
    var selectHtml = [];
    $(data.items).each(function () {
        var selected = this.Selected ? ' selected' : '';
        var option = "<option value='" + this.Value + "'" + selected + ">" + this.Text + "</option>";
        selectHtml.push(option);
    });
    target = $(clearOptions(target[0])); //The item that was contained in the selector isn't in the DOM anymore
    target.append(selectHtml.join(""));       
}
Community
  • 1
  • 1
Pak
  • 2,639
  • 2
  • 21
  • 27