Treesort, literally ...

Treesort, literally ...

Once upon a time I found myself working a contract with a requirement to sort random packets of data presented as parallel streams, in real time, quantized on a per-second basis. (in assembler) So, not THAT difficult, but trying to keep a folder/file tree in order in a User Interface can prove to be a little tricky.

Specifically I'm working with zTree which is a very useful and flexible JS widget, but unfortunately it has no concept of either sorting, or ordering such that folders are grouped together and presented ahead of files. I did consider re-writing zTree for all of about 0.68 seconds (everyone get the reference?) but then figured there ought to be an easier approach.

So if zTree won't be sorted (easily), why not just sort the presentation layer, i.e. the DOM? Found a lovely little snippet of black magic on StackOverflow to utilize jQuery's built in sort engine on a DOM node;

jQuery.fn.sortDomElements = (function() {
    return function(comparator) {
        return Array.prototype.sort.call(this, comparator).each(
            function(i) {
                this.parentNode.appendChild(this);
            }
        );
    };
})();

So all we need to do with that is supply it with the right comparator, so after adding a node;

$("ul","#"+node.parentTId).children().sortDomElements(
    function(a,b){     
        akey = $('.node_name',a).text();
        bkey = $('.node_name',b).text();
        if (akey == bkey) return 0;
        if (akey < bkey) return -1;
        if (akey > bkey) return 1;
});

Now if you call that after any node update, i.e. any sort of rename or insert operation, you will end up with all nodes in sorted order. Relatively efficient in that it only reorders nodes in the branch into which you are inserting. Problem here is that you end up with folders interspersed with files, whereas traditionally we expect the files to appear at the top of any given branch listing. So, revision #2;

        akey = $('.node_name',a).text();
        bkey = $('.node_name',b).text();   
        //
        apfx = $('.noline_close',a);
        bpfx = $('.noline_close',b);
        if(apfx.length) akey = "."+akey;
        if(bpfx.length) bkey = "."+bkey;
        //                             
        if (akey == bkey) return 0;
        if (akey < bkey) return -1;
        if (akey > bkey) return 1;

zTree folders contain the class ".noline_close", so for folders we just prefix the sort key with a dot, and they still get sorted, but all folders will now have a key value which is less than a non-folder node .. so we see folders first (sorted), then files (sorted).

Part of me is sort of waiting to see exactly where zTree is going get upset about the fact it's DOM presentation doesn't match it's internal tree representation, but thus far it doesn't seem to care .. :)