views:

35

answers:

2

Is there an easy way to sort a list of HTML Select elements in Javascript? I would want it sorted by their names. Each Select element has other fields like title and value. Would I have to use arrays?

+1  A: 

I would use arrays:

var x = [];
var select = document.getElementById('mySelect');
var length = select.options.length;
for(var i=length-1; i>=0; --i) {
   x.push(select.options[i]);
   select.removeChild(select.options[i]);
}
x.sort(function(o1,o2){
   if(o1.value > o2.value) {
      return 1;
   } else if(o1.value < o2.value) {
      return -1;
   }
   return 0;
});
for(var i=0; i<length; ++i) {
   select.appendChild(x[i]);
}
Javaguru
I just added: "o1 = o1.toLowerCase();o2 = o2.toLowerCase();" After the sort function so it sorts case insensitive. Worked perfectly, thanks :-)
+1  A: 

The reasons why you should use arrays:

  • NodeLists are read-only (you can't apply array sorting to them)
  • Array operations are super fast compared to DOM operations

So you basically need to convert the options into an array, then apply the sort function to it with the custom compare function. Finally you append back the elements in the correct order.

Usage

sortSelect("selection_id");

Code [See it in action]

(function(window){

// array functions are not working
// on nodeLists on IE, we need to
// to convert them to array
function toArray( obj ) {
  var i, arr = [];
  for ( i = obj.length; i--; ){
    arr[i] = obj[i];
  }
  return arr;
}

// custom compare function for sorting
// by the option's value
function sortByName( a, b ) {
  if ( a.value < b.value ) return -1;
  else if( a.value > b.value ) return 1;
  else return 0;
}

window.sortSelect = function(id) {

  // select the elements to be ordered
  var sel   = document.getElementById(id),
      items = sel.getElementsByTagName("option"),
      len   = items.length;

  // convert to array, to make sorting possible
  items = toArray( items );

  // do the item sorting by their value
  items = items.sort( sortByName );

  // append them back to the parent in order
  for ( var i = 0; i < len; i++ ) {
    sel.appendChild( items[i] );
  }
};

})(this);​

Tested on: IE5.5+, FF2+, Chrome, Opera 9.6+

galambalazs