views:

125

answers:

4

I have a form with over 100 list items that I must reorder on submit. The following code works to reorder my list without any apparent problems in Firefox; however, IE prompts with the message "A script on this page is causing Internet Explorer to run slowly. If it continues to run, your computer may become unresponsive. Do you want to abort the script?" If the user clicks 'No', the script will work as expected.

var listitems = $(form).find('li').get();
listitems.sort(function(a, b) {
    var compA = $(a).attr('id');
    var compB = $(b).attr('id');
    return (compA - compB);
});

Any ideas on how to make this more efficient?

+4  A: 

I didn't try it with 100 items but it totally worked with 2.

listitems.sort(function(a, b) {
    return (a.id - b.id);
});
Andy Gaskell
Creating two jQuery objects *per comparison* is really slow for larger sorts, and removing both constructions would probably give a significant speed boost.
strager
On Safari, this gives an 84x improvement for a list with 100 elements.
Anurag
Thanks Andy! This worked great.
Jason
A: 

You can also break it into smaller chunks and give the browser 'control' periodically:

http://stackoverflow.com/questions/210821/#210994

Dan Heberden
+1  A: 

Your code suggests that your IDs are numeric, which is not valid in HTML. You should change your design. Also, you can do this very simply and with better performance without jQuery.

The following assumes your IDs are of the form "li_x" where x is an integer. It isn't fully optimized since it calls the function to extract the numeric ID in every comparison. You could instead cache the numeric IDs in advance if you need to improve performance, but I don't think it'll be bad enough to warrant it.

function getNumericId(li) {
    return li.id.split("_")[1];
}

var liList = form.getElementsByTagName("li");
var liArray = Array.prototype.slice.call(liList, 0);
liArray.sort(function(a, b) {
    return getNumericId(a) - getNumericId(b);
});
Tim Down
Yea, you're right. The IDs are numeric. Thanks for pointing that out! I guess I forgot IDs can't be numeric.
Jason
+2  A: 

Used a couple of different approaches and got interesting results for different browsers. Unfortunately, the one browser that's troubling as usual is the one I don't have access to. I would appreciate if anyone can remark on how these tests run on IE.

There was not much to be gained by removing the use of jQuery altogether on Chrome, but skipping jQuery had much better results on other browsers. Also, as the number of <li> elements increases, it helps to construct an array with just the id's and sort that. Once the sorting is done, the sorted ID's array can be used to get the nodes data in proper order using this array.

Sort an array of list items.

function sortListItems() {
    var listItems = $("li").get();

    listItems.sort(function(a, b) {
        return a.id - b.id;
    });
}

Sort an array of id's.

function sortIDs() {
    var listItems = $("li");
    var ids = [];
    for(var i = 0; i < listItems.length; i++) {
        ids.push(listItems[i].id);
    }

    ids.sort(function(a, b) {
        return a - b;
    });
}

See the results at http://jsfiddle.net/hwxmJ/4/. Safari crapped out for some reason at 1000 items, while others - Chrome, Opera, Firefox worked fine with 2000 elements.

Anurag
Thanks for testing this out! Awesome work!
Jason