// Original JavaScript code by Chirp Internet: www.chirp.com.au
// Please acknowledge use of this code by including this header.

function shellSort(parent, childName, colName)
{
  var parent = parent;			// 'parent' node
  var childName = childName;	// nodeName for 'children'
  var colName = colName;		// nodeName for 'columns'

  // build array of 'child' nodes
  var items = parent.getElementsByTagName(childName);
  var N = items.length;

  // define private methods
  var get = function(i, col, wrapper)
  {
    var retval = null;
    var node = null;
    var sort;

    if(colName) {
      // sort by col'th element of i'th child
      node = items[i].getElementsByTagName(colName)[col];
    } else {
      // sort by i'th child
      node = items[i];
    }

    if(null != (sort = node.getAttribute("sort"))) {
      // use 'sort' attribute if available
      retval = sort;
    } else if(node.childNodes.length > 0) {
      if(wrapper) {
        // sort by contents of first 'wrapper' element in 'child'
        retval = node.getElementsByTagName(wrapper)[0].firstChild.nodeValue;
      } else {
        // sort by 'child' contents
        retval = node.firstChild.nodeValue;
      }
    } else {
      return "";
    }

    if(parseFloat(retval) == retval) return parseFloat(retval);
    return retval;
  }

  var compare = function(val1, val2, desc)
  {
    return (desc) ? val1 > val2 : val1 < val2;
  }

  var exchange = function(i, j)
  {
    if(i == j+1) {
      parent.insertBefore(items[i], items[j]);
    } else if(j == i+1) {
      parent.insertBefore(items[j], items[i]);
    } else {
      var tmpNode = parent.replaceChild(items[i], items[j]);
      if(typeof(items[i]) == "undefined") {
        parent.appendChild(tmpNode);
      } else {
        parent.insertBefore(tmpNode, items[i]);
      }
    }
  }

  var isort = function(m, k, col, desc, wrapper)
  {
    for(var j=m+k; j < N; j+= k) {
      for(var i=j; i >= k && compare(get(i, col, wrapper), get(i-k, col, wrapper), desc); i -= k) {
        exchange(i, i-k);
      }
    }
  }

  // define public method
  this.sort = function(col, desc, wrapper)
  {
    if(N > 200) {
      if(!confirm("Warning: you are sorting more than 200 items!\nThis may overload your browser.\nDo you want to continue?")) return;
    }

    if((k = Math.floor(N/5)) > 7) {
      for(var m=0; m < k; m++) isort(m, k, col, desc, wrapper);
    }

    if((k = Math.floor(N/7)) > 7) {
      for(var m=0; m < k; m++) isort(m, k, col, desc, wrapper);
    }

    for(k=7; k > 0; k -= 2) {
      for(var m=0; m < k; m++) isort(m, k, col, desc, wrapper);
    }
  }
}
