Thursday, February 4, 2010

MooTools Users: Implement a Hash.sort method

I notice that Firefox seems to maintain the order of key:value pairs in objects when iterating over them, while Safari and Chrome seem to sort the object internally (within their respective JS engines).  I  noticed this especially when making select elements.  I store the options as an object, then when drawing the page, I iterate over that  object making option elements. 
For example, I am making a select box that lists users  alphabetically.  Users are identified in the database by an id: 

 
var foo = new Element('select').inject($$('body')[0]); 
var options = {5082:'User A', 5085:'User B', 5074:'User C'} 
$H(options).each(function(name,id){ 
  new Element('option', {text:name, value:id}).inject(foo); 

}); 
In Firefox the select box would present users in order: A,B,C, but in the others, users would appear in order by id: C,A,B.  A neat function  for tackling this sort of problem would be Hash.sort. 
 
/* 
        Function: Hash.sort 
                Takes {c:0, a:1, b:2} and returns [{a:1},{b:2},{c:0}] 
*/ 
Hash.Implement({ 
sort:function(fn){ 
        var out = [], 
                keysToSort = this.getKeys(), 
                m = this.getLength(); 
        (typeof fn == 'function') ? keysToSort.sort(fn) : keysToSort.sort(); 
        for (var i=0; i<m; i++){ 
                var o = {}; 
                o[keysToSort[i]] = this[keysToSort[i]]; 
                out.push(o); 
        } 
        return out; 

} 
}); 
____________ 
 
Usage: 

 
$H({'a':1,'z':2,'c':3,'b':4}).sort() 

 
Results In: 

 
[Object { a=1}, Object { b=4}, Object { c=3}, Object { z=2}] 
______________________ 

 
Then our select box routine becomes: 

 
var foo = new Element('select').inject($$('body')[0]); 
var options = {5082:'User A', 5085:'User B', 5074:'User C'} 
$H(options).sort().each(function(el){ 
  $each(el,function(name, id){ 
    new Element('option', {text:name, value:id}).inject(foo); 
  }); 

}); 
_______ 
 
Ruby programmers may recognize this method (http://ruby-doc.org/core/ 
classes/Hash.html#M002865).