optimize dom-heavy JS sorting
So I've built this mail-program-like HTML v开发者_如何学Ciewer (no real emails, just some messages from user to user). It basically behaves just like windows explorer, where you have the labels at the top and the files you can sort by date or alphabetically. Each message looks like this:
<div class="mail_msg" d_id="363">
<div class="done"><img src="../"></div>
<div class="absender">demo</div>
<div class="subject">subject</div>
<div class="name">name</div>
<div class="date">16.09.2010</div>
</div>
Atop of all these messages there is a bar to sort them alphabetically or by date. (using prototypejs)
$$('.absender_label','.subject_label', '.bname_label').each(function(el){
el.observe('click', function(){
/* ... */
var tar = el.className.split('_')[0];
var els = $('widget_mail_'+target).select('.mail_msg'),
sortedEls = els.sort(function(x, y) {
var a = x.down('.'+tar).innerHTML.toLowerCase(),
b = y.down('.'+tar).innerHTML.toLowerCase();
return a < b ? -1 : a > b ? 1 : 0;
});
$('widget_mail_'+target).select('.mail_msg').invoke('remove');
sortedEls.each(function(x){
if(dir=='bottom') {
$('widget_mail_'+target).insert({bottom:x});
} else if(dir=='top') {
$('widget_mail_'+target).down('.mail_msg_label').insert({after:x});
}
});
});
});
I know that there is way too much DOM-manipulation going on. I select all related divs, sort them, throw away all the old unsorted messages and insert the sorted ones at the top or at the bottom (first click from A-Z, second click from Z-A).
It still works with hundreds of messages, but it takes 2 or 3 seconds. I receive the messages as JSON and parse HTML from that, so using a table sorting script like this is not an option at this point.
How can I optimize this sorting?
Each time the user sort, you sort the dataset.
Then you render them as HTML using innerHTML, each time.
You can use a Javascript template engine to do that(I contribute to PURE but there are plenty of engines available today)
If a template engine is an overkill for you, you can:
- stringify your HTML above
- for each record in your data, build a line filling some placeholders
- concatenate the lines in a string
- and finally inject the string using innerHTML
- sort your data and restart
While it seems heavier, this will be faster than all the DOM manipulations.
You can use .detach()
to remove elements from the DOM, sort it and then display it. Maybe this will speed up you script.
You could give elements absolute positions via CSS and just change their positions, instead of manipulating the DOM.
Add to your JSON dataset just one more field like: related DOMElement position or DOMElement reference.
mail_msg["dom_el_ref"] = createRelatedDomEL(mail_msg);
Do all sorting and comparing stuff with JSON dataset. And after that make according order in DOM-list.
精彩评论