Skip to main content
Post Locked by 200_success
Notice added Content dispute by 200_success
Rollback to Revision 12
Source Link
Ethan Bierlein
  • 15.9k
  • 4
  • 60
  • 146

UPDATE Long overdue, mainly cause I forgot about it, here's an updated code that needs some more modifying.

if (Object['defineProperty'] && !Array.prototype['smartSort']) { var smartSortAsc = function(a, b) { if (a == null || a == undefined) return 1; if (b == null || b == undefined) return -1; var c = typeof a, d = typeof b, e = c + d; if (/^numbernumber$/ig.test(e)) return a - b; if (/^stringstring$/ig.test(e)) return a > b; if (/(string|number){2}/ig.test(e)) return /string/i.test(c) ? 1 : -1; if (/number/ig.test(e) && /object/ig.test(e)) return /object/i.test(c) ? 1 : -1; if (/string/ig.test(e) && /object/ig.test(e)) return /object/i.test(c) ? 1 : -1; if (/^objectobject$/ig.test(e)) { if (a instanceof Array) a.smartSort('a'); if (b instanceof Array) b.smartSort('a'); if (a instanceof Date && b instanceof Date) return a - b; if (a instanceof Array && b instanceof Array) { var f = Object.keys(a), g = Object.keys(b), h = f.concat(g).smartSort('a'); for (var x in h) { var i = h[x]; if (a[i] != b[i]) { var j = [ a[i], b[i] ].smartSort('a'); return a[i] == j[0] ? -1 : 1; } } var k = [ a[Object.keys(a)[0]], b[Object.keys(b)[0]] ].smartSort('a'); return a[Object.keys(a)[0]] == k[0] ? -1 : 1; } if (a instanceof Element && b instanceof Element) { if (a.tagName == b.tagName) { var f = [ a.id, b.id ].smartSort('a'); return a.id == f[0] ? 1 : -1; } var f = [ a.tagName, b.tagName ].smartSort('a'); return a.tagName == f[0] ? 1 : -1; } if (a instanceof Date || b instanceof Date) return a instanceof Date ? 1 : -1; if (a instanceof Array || b instanceof Array) return a instanceof Array ? -1 : 1; var f = Object.keys(a), g = Object.keys(b), h = f.concat(g).smartSort('a'); for (var i = 0; i < 20; i++) { var j = f[i], k = g[i]; if (a.hasOwnProperty(j) && b.hasOwnProperty(k)) { if (a[j] instanceof Element && b[k] instanceof Element) { if (a[j].tagName == b[k].tagName) { var l = [ a[j].id, b[k].id ].smartSort('a'); return a[j].id == l[0] ? -1 : 1; } var l = [ a[j].tagName, b[k].tagName ].smartSort('a'); return a[j].tagName == l[0] ? -1 : 1; } if (a[j] instanceof Element || b[k] instanceof Element) return a[j] instanceof Element ? 1 : -1; if (a[j] != b[k]) { var m = [ a[j], b[k] ].smartSort('a'); return a[j] == m[0] ? -1 : 1; } } if (a.hasOwnProperty(j) && a[j] instanceof Element) return 1; if (b.hasOwnProperty(k) && b[k] instanceof Element) return -1; if (!a.hasOwnProperty(j)) return -1; if (!b.hasOwnProperty(j)) return 1; } var m = [ a[Object.keys(a)[0]], b[Object.keys(b)[0]] ].smartSort('a'); return a[Object.keys(a)[0]] == m[0] ? 1 : -1; } var g = [a, b].sort(); return g[0] > g[1]; } var smartSortDesc = function(a, b) { if (a == null || a == undefined) return 1; if (b == null || b == undefined) return -1; var c = typeof a, d = typeof b, e = c + d; if (/^numbernumber$/ig.test(e)) return b - a; if (/^stringstring$/ig.test(e)) return b > a; if (/(string|number){2}/ig.test(e)) return /string/i.test(c) ? 1 : -1; if (/number/ig.test(e) && /object/ig.test(e)) return /object/i.test(c) ? 1 : -1; if (/string/ig.test(e) && /object/ig.test(e)) return /object/i.test(c) ? 1 : -1; if (/^objectobject$/ig.test(e)) { // both are OBJECT if (a instanceof Array) a.smartSort('d'); if (b instanceof Array) b.smartSort('d'); if (a instanceof Date && b instanceof Date) return b - a; if (a instanceof Array && b instanceof Array) { // both are ARRAY var f = Object.keys(a), g = Object.keys(b), h = f.concat(g).smartSort('a'); for (var x in h) { var i = h[x]; if (a[i] != b[i]) { var j = [ a[i], b[i] ].smartSort('d'); return a[i] == j[0] ? -1 : 1; } } var k = [ a[Object.keys(a)[0]], b[Object.keys(b)[0]] ].smartSort('d'); return a[Object.keys(a)[0]] == k[0] ? -1 : 1; } if (a instanceof Element && b instanceof Element) { // both are ELEMENT if (a.tagName == b.tagName) { var f = [ a.id, b.id ].smartSort('d'); return a.id == f[0] ? -1 : 1; } var f = [ a.tagName, b.tagName ].smartSort('d'); return a.tagName == f[0] ? -1 : 1; } if (a instanceof Date || b instanceof Date) return a instanceof Date ? 1 : -1; if (a instanceof Array || b instanceof Array) return a instanceof Array ? -1 : 1; var f = Object.keys(a), g = Object.keys(b), h = f.concat(g).smartSort('a'); for (var i = 0; i < 20; i++) { var j = f[i], k = g[i]; if (a.hasOwnProperty(j) && b.hasOwnProperty(k)) { if (a[j] instanceof Element && b[k] instanceof Element) { if (a[j].tagName == b[k].tagName) { var l = [ a[j].id, b[k].id ].smartSort('d'); return a[j].id == l[0] ? -1 : 1; } var l = [ a[j].tagName, b[k].tagName ].smartSort('d'); return a[j].tagName == l[0] ? -1 : 1; } if (a[j] instanceof Element || b[k] instanceof Element) return a[j] instanceof Element ? 1 : -1; if (a[j] != b[k]) { var m = [ a[j], b[k] ].smartSort('d'); return a[j] == m[0] ? -1 : 1; } } if (a.hasOwnProperty(j) && a[j] instanceof Element) return 1; if (b.hasOwnProperty(k) && b[k] instanceof Element) return -1; if (!a.hasOwnProperty(j)) return 1; if (!b.hasOwnProperty(j)) return -1; } var m = [ a[Object.keys(a)[0]], b[Object.keys(b)[0]] ].smartSort('d'); return a[Object.keys(a)[0]] == m[0] ? -1 : 1; } var g = [a, b].sort(); return g[0] < g[1]; } Object.defineProperty(Array.prototype, 'smartSort', { value: function() { if (arguments && (!arguments.length || arguments.length == 1 && /^a([sc]{2})?$|^d([esc]{3})?$/i.test(arguments[0]))) return this.sort(!arguments.length || /^a([sc]{2})?$/i.test(arguments[0]) ? smartSortAsc : smartSortDesc); return this.sort(); } }); } 

jsFiddle

smartSort(Array, 'asc|desc')

;;(function() { var dir = void 0; // numbers, strings, booleans, dates, elements, arrays, objects, null|undefined function smartSort(a, b/* , dir */) { // immidiate return for emtpy values if (null == a || void 0 == a || a !== a) return 1; if (null == b || void 0 == b || b !== b) return -1; // make string numbers into real numbers var regNum = new RegExp(/^-?\d+\.?\d*$|^\d*\.?\d+$/); if (regNum.test(a)) a = parseFloat(a); if (regNum.test(b)) b = parseFloat(b); var aType = typeof a, bType = typeof b, cType = aType + bType; var aInstance = Object.prototype.toString.call(a).slice(8, -1), bInstance = Object.prototype.toString.call(b).slice(8, -1), cInstance = aInstance + bInstance; if (/Array/ig.test(aInstance)) a.smartSort(dir); if (/Array/ig.test(bInstance)) b.smartSort(dir); if (aType == bType) { switch (aType || bType) { case 'boolean': return a === b ? 0 : (dir ? (a ? 1 : -1) : (b ? 1 : -1)); case 'number': return a === b ? 0 : (dir ? (a < b ? -1 : 1) : (a > b ? -1 : 1)); case 'string': a = a.valueOf().toLowerCase(); b = b.valueOf().toLowerCase(); return a === b ? 0 : (dir ? (a < b ? -1 : 1) : (a > b ? -1 : 1)); case 'object': if (aInstance == bInstance) { if (/(date){2}/ig.test(cInstance)) { var aValue = a.valueOf(), bValue = b.valueOf(); return aValue === bValue ? 0 : (dir ? (aValue < bValue ? -1 : 1) : (aValue > bValue ? -1 : 1)); } else if (/^(HTML)\w+(Element)$/.test(cInstance)) { if (a.id && b.id) return a.id === b.id ? 0 : (dir ? (a.id < b.id ? -1 : 1) : (a.id > b.id ? -1 : 1)); else if (a.id || b.id) return a.id && !b.id ? 1 : -1; if (a.name && b.name) return a.name === b.name ? 0 : (dir ? (a.name < b.name ? -1 : 1) : (a.name > b.name ? -1 : 1)); else if (a.name || b.name) return a.name && !b.name ? 1 : -1; return a.tagName === b.tagName ? 0 : (dir ? (a.tagName < b.tagName ? -1 : 1) : (a.tagName > b.tagName ? -1 : 1)); } /*TODO: else if (window['jQuery'] && a instanceof jQuery) { } */ else if (/(array){2}/ig.test(cInstance)) { var aFirst = Object.keys(a)[0], bFirst = Object.keys(b)[0]; if (aFirst === bFirst) { aFirst = a[aFirst]; bFirst = b[bFirst]; if (aFirst === bFirst) return 0; var firstSorted = [aFirst, bFirst].smartSort(dir); return aFirst == firstSorted[0] ? 1 : -1; } else return dir ? (aFirst < bFirst ? -1 : 1) : (aFirst > bFirst ? -1 : 1); } else if (/(object){2}/ig.test(cInstance)) { var aFirst = Object.keys(a)[0], bFirst = Object.keys(b)[0]; if (void 0 != aFirst && aFirst === bFirst) { aFirst = a[aFirst]; bFirst = b[bFirst]; if (aFirst === bFirst) return 0; var firstSorted = [aFirst, bFirst].smartSort(dir); return aFirst == firstSorted[0] ? 1 : -1; } else return dir ? (aFirst < bFirst ? -1 : 1) : (aFirst > bFirst ? -1 : 1); if (!window['smartSort']) { window.smartSort = function() { if (arguments) { var a, b; for (var x in arguments) arguments[x] instanceof Array && (a = arguments[x], void 0 == b && (b = "a")), "string" == typeof arguments[x] && (b = /^a([sc]{2})?$/i.test(arguments[x]) ? "a" : "d"); if (a instanceof Array) return a.sort(b == 'a' ? smartSort.asc : smartSort.desc); } return this.sort(); } smartSort.asc = function(a, b) { if (a == null || a == undefined) return 1; if (b == null || b == undefined) return -1; var c = typeof a, d = typeof b, e = c + d; if (/^numbernumber$/ig.test(e)) return a - b; if (/^stringstring$/ig.test(e)) return a > b; if (/(string|number){2}/ig.test(e)) return /string/i.test(c) ? 1 : -1; if (/number/ig.test(e) && /object/ig.test(e)) return /object/i.test(c) ? 1 : -1; if (/string/ig.test(e) && /object/ig.test(e)) return /object/i.test(c) ? 1 : -1; if (/^objectobject$/ig.test(e)) { if (a instanceof Array) a.sort(smartSort.asc); if (b instanceof Array) b.sort(smartSort.asc); if (a instanceof Date && b instanceof Date) return a - b; if (a instanceof Array && b instanceof Array) { var f = Object.keys(a), g = Object.keys(b), h = smartSort(f.concat(g), 'a'); for (var x in h) { var i = h[x]; if (a[i] != b[i]) { var j = smartSort([ a[i], b[i] ], 'a'); return a[i] == j[0] ? -1 : 1; } } var k = smartSort([ a[Object.keys(a)[0]], b[Object.keys(b)[0]] ], 'a'); return a[Object.keys(a)[0]] == k[0] ? -1 : 1; } if (a instanceof Element && b instanceof Element) { if (a.tagName == b.tagName) { var f = smartSort([ a.id, b.id ], 'a'); return a.id == f[0] ? 1 : -1; } var f = smartSort([ a.tagName, b.tagName ], 'a'); return a.tagName == f[0] ? 1 : -1; } if (a instanceof Date || b instanceof Date) return a instanceof Date ? 1 : -1; if (a instanceof Array || b instanceof Array) return a instanceof Array ? -1 : 1; var f = Object.keys(a), g = Object.keys(b), h = smartSort(f.concat(g), 'a'); for (var i = 0; i < 20; i++) { var j = f[i], k = g[i]; if (a.hasOwnProperty(j) && b.hasOwnProperty(k)) { if (a[j] instanceof Element && b[k] instanceof Element) { if (a[j].tagName == b[k].tagName) { var l = smartSort([ a[j].id, b[k].id ], 'a'); return a[j].id == l[0] ? -1 : 1;  } var l = smartSort([ a[j].tagName, b[k].tagName ], 'a'); return a[j].tagName == l[0] ? -1 : 1; } else { // Organize as [DATE, ELEMENT, ARRAY, OBJECT, NAN|NULL|UNDEFINED] if (/Date/ig.test(cInstance)) return /Date/ig.test(aInstance) ? -1 : 1; a[j] instanceof Element || b[k] ifinstanceof (/Element/ig.test(cInstance)) return /a[j] instanceof Element/ig.test(aInstance) ? -1 : -1;   //  quick jQuery check to organize jQuery elements right behind standard elements if (window['jQuery'] && (a instanceof jQuery || ba[j] instanceof!= jQuery)b[k]) return a instanceof jQuery ? -1 : 1;{ ifvar (/Array/ig.test(cInstance))m return= /Array/ig.testsmartSort(aInstance)[ ?a[j], -1b[k] :], 1;'a'); return /object/ig.test(aInstance)a[j] == m[0] ? -1 : 1; }  break; } } else { // Organize as [NUMBER, STRING, BOOLEAN, DATE, ELEMENT, ARRAY, OBJECT, NAN|NULL|UNDEFINED] if (/number/ig.test(cType)) return /number/ig.test(aType) ? -1 : 1; if (/string/ig.test(cType)) return /string/ig.test(aType) ? -1 : 1; if (/boolean/ig.test(cType)) return /boolean/ig.test(aType) ? -1 : 1; if (/object/ig.test(cType)) { // TODO: think up every possible test to ensure this is never reached, as it shouldnt be if (window['console'] && console['log']) { console.log(new Array(50).join('-') + 'H I T' + new Array(50).join('-')); console.log(new Array(50).join('-') + 'H I T' + new Array(50).join('-')); console.log(new Array(50).join('-') + 'H I T' + new Array(50).join('-'));  } if (a instanceof Date.hasOwnProperty(j) ||&& ba[j] instanceof DateElement) return a instanceof Date ? -1 : 1; if (a instanceof Element || b instanceof Element.hasOwnProperty(k) return&& ab[k] instanceof Element) ?return -1 : 1; if (!a instanceof Array || b instanceof Array.hasOwnProperty(j)) return a instanceof Array ? -1 : 1; returnif /object/ig(!b.testhasOwnProperty(aTypej) ? -1) :return 1; } ifvar m = smartSort(/function/ig[ a[Object.testkeys(cType)a) return[0]], /function/igb[Object.testkeys(aTypeb)[0]] ?], -1'a');  : 1;  return a[Object.keys(a)[0]] else== returnm[0] ? 1 : -1; }  var g = [a, b].sort(); return g[0] > g[1];  } smartSort.desc = function(a, b) {   if (Object['defineProperty']a &&== !Array.prototype['smartSort']null || a == undefined) {return 1; Object.definePropertyif (Array.prototypeb == null || b == undefined) return -1; var c = typeof a, 'smartSort'd = typeof b, {e value:= functionc + d; if (/^numbernumber$/ig.test(e)) { return b - a;  if (/^stringstring$/ig.test(e)) return firstb determine> a;  if a(/(string|number){2}/ig.test(e)) specificreturn /string/i.test(c) for? a|asc|d|dsc|desc1 was: passed-1;  in if (/number/ig.test(e) && /object/ig.test(e)) return /object/i.test(c) ? 1 : -1; if (/string/ig.test(e) && /object/ig.test(e)) forreturn /object/i.test(varc) x? in1 arguments: -1; if (/^objectobject$/ig.test(e)) { // both are OBJECT if (a instanceof Array) a.sort(smartSort.desc); if (typeofb arguments[x]instanceof ==Array) 'string'b.sort(smartSort.desc);  && /^a if ([sc]{2}a instanceof Date && b instanceof Date)?$|^d return b - a; if ([e]?[sc]a instanceof Array && b instanceof Array) {2 // both are ARRAY var f = Object.keys(a),3} g = Object.keys(b)?$/i, h = smartSort(f.testconcat(arguments[x]g), 'a');  for (var x in h) { dirvar i = /^ah[x]; if ([sc]{2}a[i] != b[i])?$/i.test { var j = smartSort(arguments[x])[ ?a[i], trueb[i] :], false;'d'); delete arguments[x]; return a[i] == j[0] ? -1 : 1; break;} }  var k = smartSort([ a[Object.keys(a)[0]], b[Object.keys(b)[0]] ], 'd'); return a[Object.keys(a)[0]] == k[0] ? -1 : 1;  }  if (a instanceof Element && b instanceof Element) { //  add extraboth argumentsare toELEMENT  current array for sorting  /*if var(a.tagName arr== =b.tagName) this;{ for (var x in arguments) {  var f = smartSort([ a.id, b.id ], 'd');  // check if direction is set yet, if current item is boolean  return a.id == f[0] ? -1 : 1;  // if not yet set, set it to first found}  given boolean  var f if= smartSort(typeof arguments[x][ ==a.tagName, 'boolean'b.tagName &&], void'd');  0 == dir) dir = arguments[x];  return a.tagName == f[0] ? -1 else: arr.push(arguments[x]);1; } returnif arr.sort(function(a, instanceof Date || b instanceof Date) {return a instanceof Date ? 1 : -1; if (a instanceof Array || b instanceof Array) return smartSorta instanceof Array ? -1 : 1; var f = Object.keys(a),  g = Object.keys(b),   dir h = smartSort(f.concat(g);, }'a'); */   for (var i = 0; i < 20; i++) { // if direction stillvar notj set= f[i], thenk set= tog[i];  true/asc if (a.hasOwnProperty(j) && b.hasOwnProperty(k)) {   if (voida[j] 0instanceof Element && b[k] instanceof Element) {  if (a[j].tagName == dirb[k].tagName) dir{  var l = true;smartSort([ a[j].id, b[k].id ], 'd');    Object return a[j].definePropertyid == l[0] ? -1 : 1; } var l = smartSort(this[ a[j].tagName, "direction"b[k].tagName ], {'d'); enumerable return a[j].tagName == l[0] ? -1 : false,1; value } if (a[j] instanceof Element || b[k] instanceof Element) return a[j] instanceof Element ? 1 : dir-1; if (a[j] != b[k]) { var m = smartSort([ a[j], b[k] ], 'd'); writable return a[j] == m[0] ? -1 : true1;  }  } if (a.hasOwnProperty(j); && a[j] instanceof Element) return 1;   if (b.hasOwnProperty(k) && b[k] instanceof Element) return this-1; if (!a.sorthasOwnProperty(j)) return 1; if (!b.hasOwnProperty(j)) return -1; } var m = smartSort([ a[Object.keys(a)[0]], b[Object.keys(b)[0]] ], 'd'); } return a[Object.keys(a)[0]] == m[0] ? -1 : 1;  } var g = [a, b].sort(); return g[0] < g[1]; } })(); 

jsFiddlejsFiddle

UPDATE Long overdue, mainly cause I forgot about it, here's an updated code that needs some more modifying.

;;(function() { var dir = void 0; // numbers, strings, booleans, dates, elements, arrays, objects, null|undefined function smartSort(a, b/* , dir */) { // immidiate return for emtpy values if (null == a || void 0 == a || a !== a) return 1; if (null == b || void 0 == b || b !== b) return -1; // make string numbers into real numbers var regNum = new RegExp(/^-?\d+\.?\d*$|^\d*\.?\d+$/); if (regNum.test(a)) a = parseFloat(a); if (regNum.test(b)) b = parseFloat(b); var aType = typeof a, bType = typeof b, cType = aType + bType; var aInstance = Object.prototype.toString.call(a).slice(8, -1), bInstance = Object.prototype.toString.call(b).slice(8, -1), cInstance = aInstance + bInstance; if (/Array/ig.test(aInstance)) a.smartSort(dir); if (/Array/ig.test(bInstance)) b.smartSort(dir); if (aType == bType) { switch (aType || bType) { case 'boolean': return a === b ? 0 : (dir ? (a ? 1 : -1) : (b ? 1 : -1)); case 'number': return a === b ? 0 : (dir ? (a < b ? -1 : 1) : (a > b ? -1 : 1)); case 'string': a = a.valueOf().toLowerCase(); b = b.valueOf().toLowerCase(); return a === b ? 0 : (dir ? (a < b ? -1 : 1) : (a > b ? -1 : 1)); case 'object': if (aInstance == bInstance) { if (/(date){2}/ig.test(cInstance)) { var aValue = a.valueOf(), bValue = b.valueOf(); return aValue === bValue ? 0 : (dir ? (aValue < bValue ? -1 : 1) : (aValue > bValue ? -1 : 1)); } else if (/^(HTML)\w+(Element)$/.test(cInstance)) { if (a.id && b.id) return a.id === b.id ? 0 : (dir ? (a.id < b.id ? -1 : 1) : (a.id > b.id ? -1 : 1)); else if (a.id || b.id) return a.id && !b.id ? 1 : -1; if (a.name && b.name) return a.name === b.name ? 0 : (dir ? (a.name < b.name ? -1 : 1) : (a.name > b.name ? -1 : 1)); else if (a.name || b.name) return a.name && !b.name ? 1 : -1; return a.tagName === b.tagName ? 0 : (dir ? (a.tagName < b.tagName ? -1 : 1) : (a.tagName > b.tagName ? -1 : 1)); } /*TODO: else if (window['jQuery'] && a instanceof jQuery) { } */ else if (/(array){2}/ig.test(cInstance)) { var aFirst = Object.keys(a)[0], bFirst = Object.keys(b)[0]; if (aFirst === bFirst) { aFirst = a[aFirst]; bFirst = b[bFirst]; if (aFirst === bFirst) return 0; var firstSorted = [aFirst, bFirst].smartSort(dir); return aFirst == firstSorted[0] ? 1 : -1; } else return dir ? (aFirst < bFirst ? -1 : 1) : (aFirst > bFirst ? -1 : 1); } else if (/(object){2}/ig.test(cInstance)) { var aFirst = Object.keys(a)[0], bFirst = Object.keys(b)[0]; if (void 0 != aFirst && aFirst === bFirst) { aFirst = a[aFirst]; bFirst = b[bFirst]; if (aFirst === bFirst) return 0; var firstSorted = [aFirst, bFirst].smartSort(dir); return aFirst == firstSorted[0] ? 1 : -1; } else return dir ? (aFirst < bFirst ? -1 : 1) : (aFirst > bFirst ? -1 : 1);  } } else { // Organize as [DATE, ELEMENT, ARRAY, OBJECT, NAN|NULL|UNDEFINED] if (/Date/ig.test(cInstance)) return /Date/ig.test(aInstance) ? -1 : 1;  if (/Element/ig.test(cInstance)) return /Element/ig.test(aInstance) ? -1 : 1;   //  quick jQuery check to organize jQuery elements right behind standard elements if (window['jQuery'] && (a instanceof jQuery || b instanceof jQuery)) return a instanceof jQuery ? -1 : 1; if (/Array/ig.test(cInstance)) return /Array/ig.test(aInstance) ? -1 : 1; return /object/ig.test(aInstance) ? -1 : 1; }  break; } } else { // Organize as [NUMBER, STRING, BOOLEAN, DATE, ELEMENT, ARRAY, OBJECT, NAN|NULL|UNDEFINED] if (/number/ig.test(cType)) return /number/ig.test(aType) ? -1 : 1; if (/string/ig.test(cType)) return /string/ig.test(aType) ? -1 : 1; if (/boolean/ig.test(cType)) return /boolean/ig.test(aType) ? -1 : 1; if (/object/ig.test(cType)) { // TODO: think up every possible test to ensure this is never reached, as it shouldnt be if (window['console'] && console['log']) { console.log(new Array(50).join('-') + 'H I T' + new Array(50).join('-')); console.log(new Array(50).join('-') + 'H I T' + new Array(50).join('-')); console.log(new Array(50).join('-') + 'H I T' + new Array(50).join('-'));  } if (a instanceof Date || b instanceof Date) return a instanceof Date ? -1 : 1; if (a instanceof Element || b instanceof Element) return a instanceof Element ? -1 : 1; if (a instanceof Array || b instanceof Array) return a instanceof Array ? -1 : 1; return /object/ig.test(aType) ? -1 : 1; } if (/function/ig.test(cType)) return /function/ig.test(aType) ? -1 : 1;  else return -1; } } if (Object['defineProperty'] && !Array.prototype['smartSort']) { Object.defineProperty(Array.prototype, 'smartSort', { value: function() {  // first determine if a specific string for a|asc|d|dsc|desc was passed in for (var x in arguments) { if (typeof arguments[x] == 'string' && /^a([sc]{2})?$|^d([e]?[sc]{2,3})?$/i.test(arguments[x])) { dir = /^a([sc]{2})?$/i.test(arguments[x]) ? true : false; delete arguments[x]; break; } }   //  add extra arguments to current array for sorting  /* var arr = this; for (var x in arguments) {  // check if direction is set yet, if current item is boolean  // if not yet set, set it to first found given boolean  if (typeof arguments[x] == 'boolean' && void 0 == dir) dir = arguments[x];  else arr.push(arguments[x]); } return arr.sort(function(a, b) { return smartSort(a, b, dir); }); */ // if direction still not set, then set to true/asc if (void 0 == dir) dir = true;    Object.defineProperty(this, "direction", { enumerable: false, value: dir, writable: true }); return this.sort(smartSort); } }); } })(); 

jsFiddle

if (Object['defineProperty'] && !Array.prototype['smartSort']) { var smartSortAsc = function(a, b) { if (a == null || a == undefined) return 1; if (b == null || b == undefined) return -1; var c = typeof a, d = typeof b, e = c + d; if (/^numbernumber$/ig.test(e)) return a - b; if (/^stringstring$/ig.test(e)) return a > b; if (/(string|number){2}/ig.test(e)) return /string/i.test(c) ? 1 : -1; if (/number/ig.test(e) && /object/ig.test(e)) return /object/i.test(c) ? 1 : -1; if (/string/ig.test(e) && /object/ig.test(e)) return /object/i.test(c) ? 1 : -1; if (/^objectobject$/ig.test(e)) { if (a instanceof Array) a.smartSort('a'); if (b instanceof Array) b.smartSort('a'); if (a instanceof Date && b instanceof Date) return a - b; if (a instanceof Array && b instanceof Array) { var f = Object.keys(a), g = Object.keys(b), h = f.concat(g).smartSort('a'); for (var x in h) { var i = h[x]; if (a[i] != b[i]) { var j = [ a[i], b[i] ].smartSort('a'); return a[i] == j[0] ? -1 : 1; } } var k = [ a[Object.keys(a)[0]], b[Object.keys(b)[0]] ].smartSort('a'); return a[Object.keys(a)[0]] == k[0] ? -1 : 1; } if (a instanceof Element && b instanceof Element) { if (a.tagName == b.tagName) { var f = [ a.id, b.id ].smartSort('a'); return a.id == f[0] ? 1 : -1; } var f = [ a.tagName, b.tagName ].smartSort('a'); return a.tagName == f[0] ? 1 : -1; } if (a instanceof Date || b instanceof Date) return a instanceof Date ? 1 : -1; if (a instanceof Array || b instanceof Array) return a instanceof Array ? -1 : 1; var f = Object.keys(a), g = Object.keys(b), h = f.concat(g).smartSort('a'); for (var i = 0; i < 20; i++) { var j = f[i], k = g[i]; if (a.hasOwnProperty(j) && b.hasOwnProperty(k)) { if (a[j] instanceof Element && b[k] instanceof Element) { if (a[j].tagName == b[k].tagName) { var l = [ a[j].id, b[k].id ].smartSort('a'); return a[j].id == l[0] ? -1 : 1; } var l = [ a[j].tagName, b[k].tagName ].smartSort('a'); return a[j].tagName == l[0] ? -1 : 1; } if (a[j] instanceof Element || b[k] instanceof Element) return a[j] instanceof Element ? 1 : -1; if (a[j] != b[k]) { var m = [ a[j], b[k] ].smartSort('a'); return a[j] == m[0] ? -1 : 1; } } if (a.hasOwnProperty(j) && a[j] instanceof Element) return 1; if (b.hasOwnProperty(k) && b[k] instanceof Element) return -1; if (!a.hasOwnProperty(j)) return -1; if (!b.hasOwnProperty(j)) return 1; } var m = [ a[Object.keys(a)[0]], b[Object.keys(b)[0]] ].smartSort('a'); return a[Object.keys(a)[0]] == m[0] ? 1 : -1; } var g = [a, b].sort(); return g[0] > g[1]; } var smartSortDesc = function(a, b) { if (a == null || a == undefined) return 1; if (b == null || b == undefined) return -1; var c = typeof a, d = typeof b, e = c + d; if (/^numbernumber$/ig.test(e)) return b - a; if (/^stringstring$/ig.test(e)) return b > a; if (/(string|number){2}/ig.test(e)) return /string/i.test(c) ? 1 : -1; if (/number/ig.test(e) && /object/ig.test(e)) return /object/i.test(c) ? 1 : -1; if (/string/ig.test(e) && /object/ig.test(e)) return /object/i.test(c) ? 1 : -1; if (/^objectobject$/ig.test(e)) { // both are OBJECT if (a instanceof Array) a.smartSort('d'); if (b instanceof Array) b.smartSort('d'); if (a instanceof Date && b instanceof Date) return b - a; if (a instanceof Array && b instanceof Array) { // both are ARRAY var f = Object.keys(a), g = Object.keys(b), h = f.concat(g).smartSort('a'); for (var x in h) { var i = h[x]; if (a[i] != b[i]) { var j = [ a[i], b[i] ].smartSort('d'); return a[i] == j[0] ? -1 : 1; } } var k = [ a[Object.keys(a)[0]], b[Object.keys(b)[0]] ].smartSort('d'); return a[Object.keys(a)[0]] == k[0] ? -1 : 1; } if (a instanceof Element && b instanceof Element) { // both are ELEMENT if (a.tagName == b.tagName) { var f = [ a.id, b.id ].smartSort('d'); return a.id == f[0] ? -1 : 1; } var f = [ a.tagName, b.tagName ].smartSort('d'); return a.tagName == f[0] ? -1 : 1; } if (a instanceof Date || b instanceof Date) return a instanceof Date ? 1 : -1; if (a instanceof Array || b instanceof Array) return a instanceof Array ? -1 : 1; var f = Object.keys(a), g = Object.keys(b), h = f.concat(g).smartSort('a'); for (var i = 0; i < 20; i++) { var j = f[i], k = g[i]; if (a.hasOwnProperty(j) && b.hasOwnProperty(k)) { if (a[j] instanceof Element && b[k] instanceof Element) { if (a[j].tagName == b[k].tagName) { var l = [ a[j].id, b[k].id ].smartSort('d'); return a[j].id == l[0] ? -1 : 1; } var l = [ a[j].tagName, b[k].tagName ].smartSort('d'); return a[j].tagName == l[0] ? -1 : 1; } if (a[j] instanceof Element || b[k] instanceof Element) return a[j] instanceof Element ? 1 : -1; if (a[j] != b[k]) { var m = [ a[j], b[k] ].smartSort('d'); return a[j] == m[0] ? -1 : 1; } } if (a.hasOwnProperty(j) && a[j] instanceof Element) return 1; if (b.hasOwnProperty(k) && b[k] instanceof Element) return -1; if (!a.hasOwnProperty(j)) return 1; if (!b.hasOwnProperty(j)) return -1; } var m = [ a[Object.keys(a)[0]], b[Object.keys(b)[0]] ].smartSort('d'); return a[Object.keys(a)[0]] == m[0] ? -1 : 1; } var g = [a, b].sort(); return g[0] < g[1]; } Object.defineProperty(Array.prototype, 'smartSort', { value: function() { if (arguments && (!arguments.length || arguments.length == 1 && /^a([sc]{2})?$|^d([esc]{3})?$/i.test(arguments[0]))) return this.sort(!arguments.length || /^a([sc]{2})?$/i.test(arguments[0]) ? smartSortAsc : smartSortDesc); return this.sort(); } }); } 

jsFiddle

smartSort(Array, 'asc|desc')

if (!window['smartSort']) { window.smartSort = function() { if (arguments) { var a, b; for (var x in arguments) arguments[x] instanceof Array && (a = arguments[x], void 0 == b && (b = "a")), "string" == typeof arguments[x] && (b = /^a([sc]{2})?$/i.test(arguments[x]) ? "a" : "d"); if (a instanceof Array) return a.sort(b == 'a' ? smartSort.asc : smartSort.desc); } return this.sort(); } smartSort.asc = function(a, b) { if (a == null || a == undefined) return 1; if (b == null || b == undefined) return -1; var c = typeof a, d = typeof b, e = c + d; if (/^numbernumber$/ig.test(e)) return a - b; if (/^stringstring$/ig.test(e)) return a > b; if (/(string|number){2}/ig.test(e)) return /string/i.test(c) ? 1 : -1; if (/number/ig.test(e) && /object/ig.test(e)) return /object/i.test(c) ? 1 : -1; if (/string/ig.test(e) && /object/ig.test(e)) return /object/i.test(c) ? 1 : -1; if (/^objectobject$/ig.test(e)) { if (a instanceof Array) a.sort(smartSort.asc); if (b instanceof Array) b.sort(smartSort.asc); if (a instanceof Date && b instanceof Date) return a - b; if (a instanceof Array && b instanceof Array) { var f = Object.keys(a), g = Object.keys(b), h = smartSort(f.concat(g), 'a'); for (var x in h) { var i = h[x]; if (a[i] != b[i]) { var j = smartSort([ a[i], b[i] ], 'a'); return a[i] == j[0] ? -1 : 1; } } var k = smartSort([ a[Object.keys(a)[0]], b[Object.keys(b)[0]] ], 'a'); return a[Object.keys(a)[0]] == k[0] ? -1 : 1; } if (a instanceof Element && b instanceof Element) { if (a.tagName == b.tagName) { var f = smartSort([ a.id, b.id ], 'a'); return a.id == f[0] ? 1 : -1; } var f = smartSort([ a.tagName, b.tagName ], 'a'); return a.tagName == f[0] ? 1 : -1; } if (a instanceof Date || b instanceof Date) return a instanceof Date ? 1 : -1; if (a instanceof Array || b instanceof Array) return a instanceof Array ? -1 : 1; var f = Object.keys(a), g = Object.keys(b), h = smartSort(f.concat(g), 'a'); for (var i = 0; i < 20; i++) { var j = f[i], k = g[i]; if (a.hasOwnProperty(j) && b.hasOwnProperty(k)) { if (a[j] instanceof Element && b[k] instanceof Element) { if (a[j].tagName == b[k].tagName) { var l = smartSort([ a[j].id, b[k].id ], 'a'); return a[j].id == l[0] ? -1 : 1;  } var l = smartSort([ a[j].tagName, b[k].tagName ], 'a'); return a[j].tagName == l[0] ? -1 : 1; } if (a[j] instanceof Element || b[k] instanceof Element) return a[j] instanceof Element ? 1 : -1; if (a[j] != b[k]) { var m = smartSort([ a[j], b[k] ], 'a'); return a[j] == m[0] ? -1 : 1; } } if (a.hasOwnProperty(j) && a[j] instanceof Element) return 1; if (b.hasOwnProperty(k) && b[k] instanceof Element) return -1; if (!a.hasOwnProperty(j)) return -1; if (!b.hasOwnProperty(j)) return 1; } var m = smartSort([ a[Object.keys(a)[0]], b[Object.keys(b)[0]] ], 'a');  return a[Object.keys(a)[0]] == m[0] ? 1 : -1; }  var g = [a, b].sort(); return g[0] > g[1];  } smartSort.desc = function(a, b) {   if (a == null || a == undefined) return 1; if (b == null || b == undefined) return -1; var c = typeof a, d = typeof b, e = c + d; if (/^numbernumber$/ig.test(e)) return b - a;  if (/^stringstring$/ig.test(e)) return b > a;  if (/(string|number){2}/ig.test(e)) return /string/i.test(c) ? 1 : -1;   if (/number/ig.test(e) && /object/ig.test(e)) return /object/i.test(c) ? 1 : -1; if (/string/ig.test(e) && /object/ig.test(e)) return /object/i.test(c) ? 1 : -1; if (/^objectobject$/ig.test(e)) { // both are OBJECT if (a instanceof Array) a.sort(smartSort.desc); if (b instanceof Array) b.sort(smartSort.desc);   if (a instanceof Date && b instanceof Date) return b - a; if (a instanceof Array && b instanceof Array) { // both are ARRAY var f = Object.keys(a), g = Object.keys(b), h = smartSort(f.concat(g), 'a');  for (var x in h) { var i = h[x]; if (a[i] != b[i]) { var j = smartSort([ a[i], b[i] ], 'd');  return a[i] == j[0] ? -1 : 1; } }  var k = smartSort([ a[Object.keys(a)[0]], b[Object.keys(b)[0]] ], 'd'); return a[Object.keys(a)[0]] == k[0] ? -1 : 1;  } if (a instanceof Element && b instanceof Element) { // both are ELEMENT  if (a.tagName == b.tagName) { var f = smartSort([ a.id, b.id ], 'd');  return a.id == f[0] ? -1 : 1;  }  var f = smartSort([ a.tagName, b.tagName ], 'd');  return a.tagName == f[0] ? -1 : 1; } if (a instanceof Date || b instanceof Date) return a instanceof Date ? 1 : -1; if (a instanceof Array || b instanceof Array) return a instanceof Array ? -1 : 1; var f = Object.keys(a),  g = Object.keys(b),    h = smartSort(f.concat(g), 'a');   for (var i = 0; i < 20; i++) { var j = f[i], k = g[i];   if (a.hasOwnProperty(j) && b.hasOwnProperty(k)) {   if (a[j] instanceof Element && b[k] instanceof Element) {  if (a[j].tagName == b[k].tagName) {  var l = smartSort([ a[j].id, b[k].id ], 'd');  return a[j].id == l[0] ? -1 : 1; } var l = smartSort([ a[j].tagName, b[k].tagName ], 'd');  return a[j].tagName == l[0] ? -1 : 1;  } if (a[j] instanceof Element || b[k] instanceof Element) return a[j] instanceof Element ? 1 : -1; if (a[j] != b[k]) { var m = smartSort([ a[j], b[k] ], 'd');  return a[j] == m[0] ? -1 : 1;  }  } if (a.hasOwnProperty(j) && a[j] instanceof Element) return 1;   if (b.hasOwnProperty(k) && b[k] instanceof Element) return -1; if (!a.hasOwnProperty(j)) return 1; if (!b.hasOwnProperty(j)) return -1; } var m = smartSort([ a[Object.keys(a)[0]], b[Object.keys(b)[0]] ], 'd');  return a[Object.keys(a)[0]] == m[0] ? -1 : 1;  } var g = [a, b].sort(); return g[0] < g[1]; } } 

jsFiddle

Rollback to Revision 11
Source Link
user10934
user10934
if (Object['defineProperty'] && !Array.prototype['smartSort']) { var smartSortAsc = function(a, b) { if (a == null || a == undefined) return 1; if (b == null || b == undefined) return -1; var c = typeof a, d = typeof b, e = c + d; if (/^numbernumber$/ig.test(e)) return a - b; if (/^stringstring$/ig.test(e)) return a > b; if (/(string|number){2}/ig.test(e)) return /string/i.test(c) ? 1 : -1; if (/number/ig.test(e) && /object/ig.test(e)) return /object/i.test(c) ? 1 : -1; if (/string/ig.test(e) && /object/ig.test(e)) return /object/i.test(c) ? 1 : -1; if (/^objectobject$/ig.test(e)) { if (a instanceof Array) a.smartSort('a'); if (b instanceof Array) b.smartSort('a'); if (a instanceof Date && b instanceof Date) return a - b; if (a instanceof Array && b instanceof Array) { var f = Object.keys(a), g = Object.keys(b), h = f.concat(g).smartSort('a'); for (var x in h) { var i = h[x]; if (a[i] != b[i]) { var j = [ a[i], b[i] ].smartSort('a'); return a[i] == j[0] ? -1 : 1; } } var k = [ a[Object.keys(a)[0]], b[Object.keys(b)[0]] ].smartSort('a'); return a[Object.keys(a)[0]] == k[0] ? -1 : 1; } if (a instanceof Element && b instanceof Element) { if (a.tagName == b.tagName) { var f = [ a.id, b.id ].smartSort('a'); return a.id == f[0] ? 1 : -1; } var f = [ a.tagName, b.tagName ].smartSort('a'); return a.tagName == f[0] ? 1 : -1; } if (a instanceof Date || b instanceof Date) return a instanceof Date ? 1 : -1; if (a instanceof Array || b instanceof Array) return a instanceof Array ? -1 : 1; var f = Object.keys(a), g = Object.keys(b), h = f.concat(g).smartSort('a'); for (var i = 0; i < 20; i++) { var j = f[i], k = g[i]; if (a.hasOwnProperty(j) && b.hasOwnProperty(k)) { if (a[j] instanceof Element && b[k] instanceof Element) { if (a[j].tagName == b[k].tagName) { var l = [ a[j].id, b[k].id ].smartSort('a'); return a[j].id == l[0] ? -1 : 1; } var l = [ a[j].tagName, b[k].tagName ].smartSort('a'); return a[j].tagName == l[0] ? -1 : 1; } if (a[j] instanceof Element || b[k] instanceof Element) return a[j] instanceof Element ? 1 : -1; if (a[j] != b[k]) { var m = [ a[j], b[k] ].smartSort('a'); return a[j] == m[0] ? -1 : 1; } } if (a.hasOwnProperty(j) && a[j] instanceof Element) return 1; if (b.hasOwnProperty(k) && b[k] instanceof Element) return -1; if (!a.hasOwnProperty(j)) return -1; if (!b.hasOwnProperty(j)) return 1; } var m = [ a[Object.keys(a)[0]], b[Object.keys(b)[0]] ].smartSort('a'); return a[Object.keys(a)[0]] == m[0] ? 1 : -1; } var g = [a, b].sort(); return g[0] > g[1]; } var smartSortDesc = function(a, b) { if (a == null || a == undefined) return 1; if (b == null || b == undefined) return -1; var c = typeof a, d = typeof b, e = c + d; if (/^numbernumber$/ig.test(e)) return b - a; if (/^stringstring$/ig.test(e)) return b > a; if (/(string|number){2}/ig.test(e)) return /string/i.test(c) ? 1 : -1; if (/number/ig.test(e) && /object/ig.test(e)) return /object/i.test(c) ? 1 : -1; if (/string/ig.test(e) && /object/ig.test(e)) return /object/i.test(c) ? 1 : -1; if (/^objectobject$/ig.test(e)) { // both are OBJECT if (a instanceof Array) a.smartSort('d'); if (b instanceof Array) b.smartSort('d'); if (a instanceof Date && b instanceof Date) return b - a; if (a instanceof Array && b instanceof Array) { // both are ARRAY var f = Object.keys(a), g = Object.keys(b), h = f.concat(g).smartSort('a'); for (var x in h) { var i = h[x]; if (a[i] != b[i]) { var j = [ a[i], b[i] ].smartSort('d'); return a[i] == j[0] ? -1 : 1; } } var k = [ a[Object.keys(a)[0]], b[Object.keys(b)[0]] ].smartSort('d'); return a[Object.keys(a)[0]] == k[0] ? -1 : 1; } if (a instanceof Element && b instanceof Element) { // both are ELEMENT if (a.tagName == b.tagName) { var f = [ a.id, b.id ].smartSort('d'); return a.id == f[0] ? -1 : 1; } var f = [ a.tagName, b.tagName ].smartSort('d'); return a.tagName == f[0] ? -1 : 1; } if (a instanceof Date || b instanceof Date) return a instanceof Date ? 1 : -1; if (a instanceof Array || b instanceof Array) return a instanceof Array ? -1 : 1; var f = Object.keys(a), g = Object.keys(b), h = f.concat(g).smartSort('a'); for (var i = 0; i < 20; i++) { var j = f[i], k = g[i]; if (a.hasOwnProperty(j) && b.hasOwnProperty(k)) { if (a[j] instanceof Element && b[k] instanceof Element) { if (a[j].tagName == b[k].tagName) { var l = [ a[j].id, b[k].id ].smartSort('d'); return a[j].id == l[0] ? -1 : 1; } var l = [ a[j].tagName, b[k].tagName ].smartSort('d'); return a[j].tagName == l[0] ? -1 : 1; } if (a[j] instanceof Element || b[k] instanceof Element) return a[j] instanceof Element ? 1 : -1; if (a[j] != b[k]) { var m = [ a[j], b[k] ].smartSort('d'); return a[j] == m[0] ? -1 : 1; } } if (a.hasOwnProperty(j) && a[j] instanceof Element) return 1; if (b.hasOwnProperty(k) && b[k] instanceof Element) return -1; if (!a.hasOwnProperty(j)) return 1; if (!b.hasOwnProperty(j)) return -1; } var m = [ a[Object.keys(a)[0]], b[Object.keys(b)[0]] ].smartSort('d'); return a[Object.keys(a)[0]] == m[0] ? -1 : 1; } var g = [a, b].sort(); return g[0] < g[1]; } Object.defineProperty(Array.prototype, 'smartSort', { value: function() { if (arguments && (!arguments.length || arguments.length == 1 && /^a([sc]{2})?$|^d([esc]{3})?$/i.test(arguments[0]))) return this.sort(!arguments.length || /^a([sc]{2})?$/i.test(arguments[0]) ? smartSortAsc : smartSortDesc); return this.sort(); } }); } 

jsFiddle

smartSort(Array, 'asc|desc')

UPDATE Long overdue, mainly cause I forgot about it, here's an updated code that needs some more modifying.

if ;;(!window['smartSort']) { window.smartSort = function() {   var dir if= (arguments)void {0;  // numbers, strings, booleans, dates, elements, vararrays, aobjects, b;null|undefined   for (var x in arguments) arguments[x] instanceof Array &&function smartSort(a = arguments[x], void 0 == b && (b =/* "a")), "string" == typeof arguments[x] && (b =dir /^a([sc]{2})?$*/i.test(arguments[x]) ? "a" : "d");{   if (a// instanceof Array)immidiate return a.sort(b == 'a' ? smartSort.asc : smartSort.desc); for emtpy }values returnif this.sort(); } smartSort.ascnull === function(a, b) {  || ifvoid (a0 == nulla || a !== undefineda) return 1; if (null == b || void 0 == nullb || b !== undefinedb) return -1; var c = typeof a, d = typeof b, e = c + d;   if (/^numbernumber$/ig.test(e)) return a - b;  make string numbers ifinto (/^stringstring$/ig.test(e))real returnnumbers  a > b;  var regNum = ifnew RegExp(/(string|number){2}/ig^-?\d+\.test(e)) return /string/i?\d*$|^\d*\.test(c) ? 1 : -1;\d+$/); if (/number/ig.test(e) && /object/igregNum.test(ea)) returna /object/i.test= parseFloat(ca) ? 1 : -1;; if (/string/ig.test(e) && /object/igregNum.test(eb)) returnb /object/i.test= parseFloat(cb) ? 1 : -1;;   if (/^objectobject$/ig.test(e)) {   ifvar (aaType instanceof= Array)typeof a.sort(smartSort.asc);, if (bbType instanceof= Array)typeof b.sort(smartSort.asc);,   if (a instanceof Date && b instanceof Date)cType return= aaType -+ b;bType;   if (a instanceof Array && b instanceof Array) {   var faInstance = Object.keysprototype.toString.call(a).slice(8,  -1),  gbInstance = Object.keysprototype.toString.call(b), h = smartSort(f.concatslice(g)8, 'a'-1);,   for (varcInstance x= inaInstance h)+ {bInstance;   var i = h[x];   if (a[i] != b[i]/Array/ig.test(aInstance)) {a.smartSort(dir);   var jif =(/Array/ig.test(bInstance)) b.smartSort([ a[i], b[i] ], 'a'dir);      returnif a[i](aType == j[0] ? -1 :bType) 1;{   switch (aType || bType) }{   }  case 'boolean': return a === b var? k0 =: smartSort([dir a[Object.keys(a)[0]],? b[Object.keys(b)[0]] ], 'a'); a ? 1 return: a[Object.keys(a-1)[0]] ==: k[0](b ? -1 : 1;-1));   }  case 'number': ifreturn (a instanceof Element &&=== b instanceof Element) {  ? 0 : (dir if? (a.tagName ==< b.tagName) {  ? -1 var: f1) =: smartSort([ a.id, > b.id ],? 'a'-1 : 1));   return a.id == f[0] ? 1case 'string': -1;   }  var fa = smartSort([ a.tagName, bvalueOf().tagName ], 'a'toLowerCase();   return a.tagName == f[0] ? 1 : -1;  b = }b.valueOf().toLowerCase(); if (a instanceof Date || b instanceof Date) return a instanceof=== Dateb ? 10 : -1;  (dir if? (a instanceof< Arrayb ||? b-1 instanceof: Array1) return: (a instanceof> Arrayb ? -1 : 1; var f = Object.keys(a1),); g =case Object.keys(b),'object':   h = smartSort(f.concat(g), 'a');  forif (var i = 0; i <aInstance 20;== i++bInstance) {   var j = f[i], k = g[i];  if (a.hasOwnProperty/(jdate) && b{2}/ig.hasOwnPropertytest(kcInstance)) {   if (a[j] instanceof Element && b[k] instanceof Element) {  var aValue = a.valueOf(),  if (a[j].tagName == b[k].tagName) {  bValue = b.valueOf();  var l = smartSort([ a[j].id, b[k].id ], 'a');  return aValue === bValue ? 0 : (dir ? (aValue < bValue ? -1 : 1) return: a[j].id(aValue ==> l[0]bValue ? -1 : 1;1)); } else if (/^(HTML)\w+(Element)$/.test(cInstance)) { if (a.id && b.id) return a.id === b.id ? 0 : (dir ? (a.id < b.id ? -1 : 1) : (a.id > b.id ? -1 : 1)); else if (a.id || b.id) return a.id && !b.id ? 1 : -1; if (a.name && b.name) return a.name === b.name ? 0 : (dir ? (a.name < b.name ? -1 : 1) : (a.name > b.name ? -1 : 1)); else if (a.name || b.name) return a.name && !b.name ? 1 : -1; return a.tagName === b.tagName ? 0 : (dir ? (a.tagName < b.tagName ? -1 : 1) : (a.tagName > b.tagName ? -1 : 1)); } /*TODO: else if (window['jQuery'] && a instanceof jQuery) { } */ else if (/(array){2}/ig.test(cInstance)) { var laFirst = Object.keys(a)[0], bFirst = Object.keys(b)[0]; if (aFirst === bFirst) { aFirst = a[aFirst];  bFirst = b[bFirst]; if (aFirst === bFirst) return 0; var firstSorted = [aFirst, bFirst].smartSort([dir);  a[j] return aFirst == firstSorted[0] ? 1 : -1; } else return dir ? (aFirst < bFirst ? -1 : 1) : (aFirst > bFirst ? -1 : 1); } else if (/(object){2}/ig.tagNametest(cInstance)) { var aFirst = Object.keys(a)[0],   b[k] bFirst = Object.tagNamekeys(b)[0];  ] if (void 0 != aFirst && aFirst === bFirst) { aFirst = a[aFirst]; bFirst = b[bFirst]; if (aFirst === bFirst) return 0; var firstSorted = [aFirst, 'a'bFirst].smartSort(dir);   return a[j].tagNameaFirst == l[0]firstSorted[0] ? -1 : -1; } else return dir ? (aFirst < bFirst ? -1 : 1) : (aFirst > bFirst ? -1 : 1); }  } else { // Organize as [DATE, ELEMENT, ARRAY, OBJECT, NAN|NULL|UNDEFINED] if (a[j]/Date/ig.test(cInstance)) instanceofreturn Element/Date/ig.test(aInstance) ||? b[k]-1 instanceof: 1;  if (/Element/ig.test(cInstance)) return a[j] instanceof /Element/ig.test(aInstance) ? -1 : -1; if (a[j] != b[k]) {// quick jQuery check to organize jQuery elements right behind standard elements varif m(window['jQuery'] =&& smartSort([a a[j],instanceof b[k]jQuery ],|| 'a'b instanceof jQuery);) return a instanceof jQuery ? -1 : 1; if (/Array/ig.test(cInstance)) return a[j]/Array/ig.test(aInstance) ==? m[0]-1 : 1; return /object/ig.test(aInstance) ? -1 : 1; } }  if (a.hasOwnProperty(j) && a[j] instanceof Element) return 1;   if (b.hasOwnProperty(k) && b[k] instanceof Element) return -1;  if (!a.hasOwnProperty(j)) return -1; if (!b.hasOwnProperty(j)) return 1;break; }  var m = smartSort([ a[Object.keys(a)[0]], b[Object.keys(b)[0]] ], 'a'); return a[Object.keys(a)[0]] == m[0] ? 1 : -1;  } var g = [a, b].sort(); return g[0] > g[1]; } smartSort.desc = function(a, b)else { if (a == null || a == undefined) return 1;  if (b == null || b == undefined) return -1; // var c =Organize typeofas a[NUMBER, d = typeofSTRING, bBOOLEAN, eDATE, =ELEMENT, cARRAY, +OBJECT, d;NAN|NULL|UNDEFINED]  if (/^numbernumber$/ig.test(e)) return b - a;  if (/^stringstring$number/ig.test(ecType)) return b > a;  if (/(string|number){2}number/ig.test(e)) return /string/i.test(caType) ? -1 : -1; if (/number/ig.test(e) &&  if (/objectstring/ig.test(ecType)) return /objectstring/iig.test(caType) ? -1 : -1; if (/string/ig.test(e) &&  if (/objectboolean/ig.test(ecType)) return /objectboolean/iig.test(caType) ? -1 : -1;    if (/^objectobject$object/ig.test(ecType)) { // both are OBJECT if (a instanceof Array) a.sort(smartSort.desc);  if (b instanceof Array) b.sort(smartSort.desc); // TODO: think up every possible test to ensure ifthis (ais instanceofnever Datereached, &&as bit instanceofshouldnt Date)be  return b - a;  if (a instanceof Arraywindow['console'] && b instanceof Arrayconsole['log']) { // both are ARRAY var f = Object console.keyslog(a), g =new ObjectArray(50).keysjoin(b'-'),  + 'H I T' h+ =new smartSortArray(f50).concatjoin(g'-'), 'a');   for (var x in h) {  var i = h[x]; if console.log(a[i] !=new b[i]Array(50) { .join('-') + 'H I varT' j+ =new smartSortArray([ a[i], b[i] ], 'd'50).join('-'));   return a[i] == j[0] ?console.log(new Array(50).join('-1 : 1; ') + 'H I T' + new }Array(50).join('-')); } varif k(a =instanceof smartSort([Date a[Object.keys|| b instanceof Date) return a instanceof Date ? -1 : 1; if (a instanceof Element || b instanceof Element)[0]], b[Object.keysreturn a instanceof Element ? -1 : 1; if (a instanceof Array || b)[0]] ],instanceof 'd'Array); return a instanceof Array ? -1 : 1; return a[Object/object/ig.keystest(aaType)[0]] == k[0] ? -1 : 1; } if (a/function/ig.test(cType)) instanceofreturn Element/function/ig.test(aType) ? -1 : 1; else return -1; } }   if (Object['defineProperty'] && b!Array.prototype['smartSort']) instanceof{  Element Object.defineProperty(Array.prototype, 'smartSort', { value: function() {  // bothfirst aredetermine ELEMENTif a specific string for a|asc|d|dsc|desc was passed in for (var x in arguments) { if (a.tagNametypeof arguments[x] == b'string' && /^a([sc]{2})?$|^d([e]?[sc]{2,3})?$/i.tagNametest(arguments[x])) { var fdir = smartSort/^a([ a[sc]{2})?$/i.id,test(arguments[x]) b.id? ],true 'd');: false; returndelete a.idarguments[x];  == f[0] ? -1 : 1; break; }  var f = smartSort([ a.tagName, b.tagName ], 'd'); return a.tagName == f[0] ? -1 : 1;  } if (a instanceof Date || b instanceof Date) return a instanceof Date ? 1 : -1; if (a instanceof Array || b instanceof Array) return a instanceof Array ? -1 : 1;   var f = Object.keys(a),  // add extra arguments to current garray =for Object.keys(b),sorting   /* var harr = smartSort(f.concat(g), 'a');this; for (var i = 0; i <x 20;in i++arguments) {  var j = f[i], k = g[i];  // check if (a.hasOwnProperty(j) && b.hasOwnProperty(k)) { direction is set yet, if (a[j] instanceof Element && b[k]current instanceofitem Element)is {boolean   // if (a[j].tagName == b[k].tagName) { var l = smartSort([ a[j].id, b[k].id ], 'd'); return a[j].id == l[0] ? -1 : 1; }  var l = smartSort([ a[j].tagName,not b[k].tagNameyet ]set, 'd'); return a[j].tagName == l[0] ? -1 : 1; }  if (a[j] instanceof Element || b[k] instanceof Element) return a[j]set instanceofit Elementto ?first 1found :given -1;boolean   if (a[j] != b[k]) {  var m = smartSort([ a[j], b[k] ], 'd'); returntypeof a[j]arguments[x] == m[0] ? -1 : 1;  } } if (a.hasOwnProperty(j)'boolean' && a[j] instanceof Element) return 1;  if (b.hasOwnProperty(k) &&void b[k]0 instanceof== Elementdir) return -1; if (!a.hasOwnProperty(j))dir return= 1;arguments[x]; ifelse (!barr.hasOwnPropertypush(j)arguments[x]) return -1;; } varreturn marr.sort(function(a, =b) smartSort([{ a[Object.keysreturn smartSort(a)[0]], b[Object.keys(b, dir)[0]]; ]}); */ // if direction still not set, 'd'then set to true/asc if (void 0 == dir); dir = true; return   a[Object Object.keysdefineProperty(a)[0]]this, =="direction", m[0]{  ? -1  enumerable: 1;false,   value: dir, writable: true }); var g = [a, b]return this.sort(smartSort);   return g[0] <} g[1];}); } })(); 

jsFiddlejsFiddle

if (Object['defineProperty'] && !Array.prototype['smartSort']) { var smartSortAsc = function(a, b) { if (a == null || a == undefined) return 1; if (b == null || b == undefined) return -1; var c = typeof a, d = typeof b, e = c + d; if (/^numbernumber$/ig.test(e)) return a - b; if (/^stringstring$/ig.test(e)) return a > b; if (/(string|number){2}/ig.test(e)) return /string/i.test(c) ? 1 : -1; if (/number/ig.test(e) && /object/ig.test(e)) return /object/i.test(c) ? 1 : -1; if (/string/ig.test(e) && /object/ig.test(e)) return /object/i.test(c) ? 1 : -1; if (/^objectobject$/ig.test(e)) { if (a instanceof Array) a.smartSort('a'); if (b instanceof Array) b.smartSort('a'); if (a instanceof Date && b instanceof Date) return a - b; if (a instanceof Array && b instanceof Array) { var f = Object.keys(a), g = Object.keys(b), h = f.concat(g).smartSort('a'); for (var x in h) { var i = h[x]; if (a[i] != b[i]) { var j = [ a[i], b[i] ].smartSort('a'); return a[i] == j[0] ? -1 : 1; } } var k = [ a[Object.keys(a)[0]], b[Object.keys(b)[0]] ].smartSort('a'); return a[Object.keys(a)[0]] == k[0] ? -1 : 1; } if (a instanceof Element && b instanceof Element) { if (a.tagName == b.tagName) { var f = [ a.id, b.id ].smartSort('a'); return a.id == f[0] ? 1 : -1; } var f = [ a.tagName, b.tagName ].smartSort('a'); return a.tagName == f[0] ? 1 : -1; } if (a instanceof Date || b instanceof Date) return a instanceof Date ? 1 : -1; if (a instanceof Array || b instanceof Array) return a instanceof Array ? -1 : 1; var f = Object.keys(a), g = Object.keys(b), h = f.concat(g).smartSort('a'); for (var i = 0; i < 20; i++) { var j = f[i], k = g[i]; if (a.hasOwnProperty(j) && b.hasOwnProperty(k)) { if (a[j] instanceof Element && b[k] instanceof Element) { if (a[j].tagName == b[k].tagName) { var l = [ a[j].id, b[k].id ].smartSort('a'); return a[j].id == l[0] ? -1 : 1; } var l = [ a[j].tagName, b[k].tagName ].smartSort('a'); return a[j].tagName == l[0] ? -1 : 1; } if (a[j] instanceof Element || b[k] instanceof Element) return a[j] instanceof Element ? 1 : -1; if (a[j] != b[k]) { var m = [ a[j], b[k] ].smartSort('a'); return a[j] == m[0] ? -1 : 1; } } if (a.hasOwnProperty(j) && a[j] instanceof Element) return 1; if (b.hasOwnProperty(k) && b[k] instanceof Element) return -1; if (!a.hasOwnProperty(j)) return -1; if (!b.hasOwnProperty(j)) return 1; } var m = [ a[Object.keys(a)[0]], b[Object.keys(b)[0]] ].smartSort('a'); return a[Object.keys(a)[0]] == m[0] ? 1 : -1; } var g = [a, b].sort(); return g[0] > g[1]; } var smartSortDesc = function(a, b) { if (a == null || a == undefined) return 1; if (b == null || b == undefined) return -1; var c = typeof a, d = typeof b, e = c + d; if (/^numbernumber$/ig.test(e)) return b - a; if (/^stringstring$/ig.test(e)) return b > a; if (/(string|number){2}/ig.test(e)) return /string/i.test(c) ? 1 : -1; if (/number/ig.test(e) && /object/ig.test(e)) return /object/i.test(c) ? 1 : -1; if (/string/ig.test(e) && /object/ig.test(e)) return /object/i.test(c) ? 1 : -1; if (/^objectobject$/ig.test(e)) { // both are OBJECT if (a instanceof Array) a.smartSort('d'); if (b instanceof Array) b.smartSort('d'); if (a instanceof Date && b instanceof Date) return b - a; if (a instanceof Array && b instanceof Array) { // both are ARRAY var f = Object.keys(a), g = Object.keys(b), h = f.concat(g).smartSort('a'); for (var x in h) { var i = h[x]; if (a[i] != b[i]) { var j = [ a[i], b[i] ].smartSort('d'); return a[i] == j[0] ? -1 : 1; } } var k = [ a[Object.keys(a)[0]], b[Object.keys(b)[0]] ].smartSort('d'); return a[Object.keys(a)[0]] == k[0] ? -1 : 1; } if (a instanceof Element && b instanceof Element) { // both are ELEMENT if (a.tagName == b.tagName) { var f = [ a.id, b.id ].smartSort('d'); return a.id == f[0] ? -1 : 1; } var f = [ a.tagName, b.tagName ].smartSort('d'); return a.tagName == f[0] ? -1 : 1; } if (a instanceof Date || b instanceof Date) return a instanceof Date ? 1 : -1; if (a instanceof Array || b instanceof Array) return a instanceof Array ? -1 : 1; var f = Object.keys(a), g = Object.keys(b), h = f.concat(g).smartSort('a'); for (var i = 0; i < 20; i++) { var j = f[i], k = g[i]; if (a.hasOwnProperty(j) && b.hasOwnProperty(k)) { if (a[j] instanceof Element && b[k] instanceof Element) { if (a[j].tagName == b[k].tagName) { var l = [ a[j].id, b[k].id ].smartSort('d'); return a[j].id == l[0] ? -1 : 1; } var l = [ a[j].tagName, b[k].tagName ].smartSort('d'); return a[j].tagName == l[0] ? -1 : 1; } if (a[j] instanceof Element || b[k] instanceof Element) return a[j] instanceof Element ? 1 : -1; if (a[j] != b[k]) { var m = [ a[j], b[k] ].smartSort('d'); return a[j] == m[0] ? -1 : 1; } } if (a.hasOwnProperty(j) && a[j] instanceof Element) return 1; if (b.hasOwnProperty(k) && b[k] instanceof Element) return -1; if (!a.hasOwnProperty(j)) return 1; if (!b.hasOwnProperty(j)) return -1; } var m = [ a[Object.keys(a)[0]], b[Object.keys(b)[0]] ].smartSort('d'); return a[Object.keys(a)[0]] == m[0] ? -1 : 1; } var g = [a, b].sort(); return g[0] < g[1]; } Object.defineProperty(Array.prototype, 'smartSort', { value: function() { if (arguments && (!arguments.length || arguments.length == 1 && /^a([sc]{2})?$|^d([esc]{3})?$/i.test(arguments[0]))) return this.sort(!arguments.length || /^a([sc]{2})?$/i.test(arguments[0]) ? smartSortAsc : smartSortDesc); return this.sort(); } }); } 

jsFiddle

smartSort(Array, 'asc|desc')

if (!window['smartSort']) { window.smartSort = function() {   if (arguments) {   var a, b;   for (var x in arguments) arguments[x] instanceof Array && (a = arguments[x], void 0 == b && (b = "a")), "string" == typeof arguments[x] && (b = /^a([sc]{2})?$/i.test(arguments[x]) ? "a" : "d");   if (a instanceof Array) return a.sort(b == 'a' ? smartSort.asc : smartSort.desc);  } return this.sort(); } smartSort.asc = function(a, b) {  if (a == null || a == undefined) return 1; if (b == null || b == undefined) return -1; var c = typeof a, d = typeof b, e = c + d;   if (/^numbernumber$/ig.test(e)) return a - b;  if (/^stringstring$/ig.test(e)) return a > b;  if (/(string|number){2}/ig.test(e)) return /string/i.test(c) ? 1 : -1; if (/number/ig.test(e) && /object/ig.test(e)) return /object/i.test(c) ? 1 : -1; if (/string/ig.test(e) && /object/ig.test(e)) return /object/i.test(c) ? 1 : -1;   if (/^objectobject$/ig.test(e)) {   if (a instanceof Array) a.sort(smartSort.asc); if (b instanceof Array) b.sort(smartSort.asc);   if (a instanceof Date && b instanceof Date) return a - b;   if (a instanceof Array && b instanceof Array) {   var f = Object.keys(a),  g = Object.keys(b), h = smartSort(f.concat(g), 'a');   for (var x in h) {   var i = h[x];   if (a[i] != b[i]) {   var j = smartSort([ a[i], b[i] ], 'a');   return a[i] == j[0] ? -1 : 1;   }   }  var k = smartSort([ a[Object.keys(a)[0]], b[Object.keys(b)[0]] ], 'a');  return a[Object.keys(a)[0]] == k[0] ? -1 : 1;   }  if (a instanceof Element && b instanceof Element) {  if (a.tagName == b.tagName) {  var f = smartSort([ a.id, b.id ], 'a');   return a.id == f[0] ? 1 : -1;   }  var f = smartSort([ a.tagName, b.tagName ], 'a');   return a.tagName == f[0] ? 1 : -1;  } if (a instanceof Date || b instanceof Date) return a instanceof Date ? 1 : -1;  if (a instanceof Array || b instanceof Array) return a instanceof Array ? -1 : 1; var f = Object.keys(a), g = Object.keys(b),   h = smartSort(f.concat(g), 'a');  for (var i = 0; i < 20; i++) {   var j = f[i], k = g[i];  if (a.hasOwnProperty(j) && b.hasOwnProperty(k)) {   if (a[j] instanceof Element && b[k] instanceof Element) {  if (a[j].tagName == b[k].tagName) {  var l = smartSort([ a[j].id, b[k].id ], 'a');  return a[j].id == l[0] ? -1 : 1; } var l = smartSort([ a[j].tagName, b[k].tagName ], 'a'); return a[j].tagName == l[0] ? -1 : 1; } if (a[j] instanceof Element || b[k] instanceof Element) return a[j] instanceof Element ? 1 : -1; if (a[j] != b[k]) { var m = smartSort([ a[j], b[k] ], 'a'); return a[j] == m[0] ? -1 : 1; } }  if (a.hasOwnProperty(j) && a[j] instanceof Element) return 1;   if (b.hasOwnProperty(k) && b[k] instanceof Element) return -1;  if (!a.hasOwnProperty(j)) return -1; if (!b.hasOwnProperty(j)) return 1; }  var m = smartSort([ a[Object.keys(a)[0]], b[Object.keys(b)[0]] ], 'a'); return a[Object.keys(a)[0]] == m[0] ? 1 : -1;  } var g = [a, b].sort(); return g[0] > g[1]; } smartSort.desc = function(a, b) { if (a == null || a == undefined) return 1;  if (b == null || b == undefined) return -1;  var c = typeof a, d = typeof b, e = c + d;  if (/^numbernumber$/ig.test(e)) return b - a;  if (/^stringstring$/ig.test(e)) return b > a;  if (/(string|number){2}/ig.test(e)) return /string/i.test(c) ? 1 : -1; if (/number/ig.test(e) && /object/ig.test(e)) return /object/i.test(c) ? 1 : -1; if (/string/ig.test(e) && /object/ig.test(e)) return /object/i.test(c) ? 1 : -1;  if (/^objectobject$/ig.test(e)) { // both are OBJECT if (a instanceof Array) a.sort(smartSort.desc);  if (b instanceof Array) b.sort(smartSort.desc);  if (a instanceof Date && b instanceof Date) return b - a;  if (a instanceof Array && b instanceof Array) { // both are ARRAY var f = Object.keys(a), g = Object.keys(b),  h = smartSort(f.concat(g), 'a');   for (var x in h) {  var i = h[x]; if (a[i] != b[i]) {  var j = smartSort([ a[i], b[i] ], 'd');   return a[i] == j[0] ? -1 : 1;  } } var k = smartSort([ a[Object.keys(a)[0]], b[Object.keys(b)[0]] ], 'd'); return a[Object.keys(a)[0]] == k[0] ? -1 : 1; } if (a instanceof Element && b instanceof Element) { // both are ELEMENT if (a.tagName == b.tagName) { var f = smartSort([ a.id, b.id ], 'd'); return a.id == f[0] ? -1 : 1; }  var f = smartSort([ a.tagName, b.tagName ], 'd'); return a.tagName == f[0] ? -1 : 1;  } if (a instanceof Date || b instanceof Date) return a instanceof Date ? 1 : -1; if (a instanceof Array || b instanceof Array) return a instanceof Array ? -1 : 1;   var f = Object.keys(a),  g = Object.keys(b),   h = smartSort(f.concat(g), 'a'); for (var i = 0; i < 20; i++) {  var j = f[i], k = g[i];  if (a.hasOwnProperty(j) && b.hasOwnProperty(k)) {  if (a[j] instanceof Element && b[k] instanceof Element) {   if (a[j].tagName == b[k].tagName) { var l = smartSort([ a[j].id, b[k].id ], 'd'); return a[j].id == l[0] ? -1 : 1; }  var l = smartSort([ a[j].tagName, b[k].tagName ], 'd'); return a[j].tagName == l[0] ? -1 : 1; }  if (a[j] instanceof Element || b[k] instanceof Element) return a[j] instanceof Element ? 1 : -1;   if (a[j] != b[k]) {  var m = smartSort([ a[j], b[k] ], 'd'); return a[j] == m[0] ? -1 : 1;  } } if (a.hasOwnProperty(j) && a[j] instanceof Element) return 1;  if (b.hasOwnProperty(k) && b[k] instanceof Element) return -1; if (!a.hasOwnProperty(j)) return 1; if (!b.hasOwnProperty(j)) return -1; } var m = smartSort([ a[Object.keys(a)[0]], b[Object.keys(b)[0]] ], 'd'); return a[Object.keys(a)[0]] == m[0] ? -1 : 1; } var g = [a, b].sort();   return g[0] < g[1]; } } 

jsFiddle

UPDATE Long overdue, mainly cause I forgot about it, here's an updated code that needs some more modifying.

;;(function() { var dir = void 0; // numbers, strings, booleans, dates, elements, arrays, objects, null|undefined function smartSort(a, b/* , dir */) { // immidiate return for emtpy values if (null == a || void 0 == a || a !== a) return 1; if (null == b || void 0 == b || b !== b) return -1; // make string numbers into real numbers  var regNum = new RegExp(/^-?\d+\.?\d*$|^\d*\.?\d+$/); if (regNum.test(a)) a = parseFloat(a); if (regNum.test(b)) b = parseFloat(b); var aType = typeof a, bType = typeof b, cType = aType + bType; var aInstance = Object.prototype.toString.call(a).slice(8, -1),  bInstance = Object.prototype.toString.call(b).slice(8, -1), cInstance = aInstance + bInstance; if (/Array/ig.test(aInstance)) a.smartSort(dir); if (/Array/ig.test(bInstance)) b.smartSort(dir);    if (aType == bType) { switch (aType || bType) { case 'boolean': return a === b ? 0 : (dir ? (a ? 1 : -1) : (b ? 1 : -1)); case 'number': return a === b ? 0 : (dir ? (a < b ? -1 : 1) : (a > b ? -1 : 1)); case 'string': a = a.valueOf().toLowerCase(); b = b.valueOf().toLowerCase(); return a === b ? 0 : (dir ? (a < b ? -1 : 1) : (a > b ? -1 : 1)); case 'object': if (aInstance == bInstance) { if (/(date){2}/ig.test(cInstance)) { var aValue = a.valueOf(),  bValue = b.valueOf();  return aValue === bValue ? 0 : (dir ? (aValue < bValue ? -1 : 1) : (aValue > bValue ? -1 : 1)); } else if (/^(HTML)\w+(Element)$/.test(cInstance)) { if (a.id && b.id) return a.id === b.id ? 0 : (dir ? (a.id < b.id ? -1 : 1) : (a.id > b.id ? -1 : 1)); else if (a.id || b.id) return a.id && !b.id ? 1 : -1; if (a.name && b.name) return a.name === b.name ? 0 : (dir ? (a.name < b.name ? -1 : 1) : (a.name > b.name ? -1 : 1)); else if (a.name || b.name) return a.name && !b.name ? 1 : -1; return a.tagName === b.tagName ? 0 : (dir ? (a.tagName < b.tagName ? -1 : 1) : (a.tagName > b.tagName ? -1 : 1)); } /*TODO: else if (window['jQuery'] && a instanceof jQuery) { } */ else if (/(array){2}/ig.test(cInstance)) { var aFirst = Object.keys(a)[0], bFirst = Object.keys(b)[0]; if (aFirst === bFirst) { aFirst = a[aFirst];  bFirst = b[bFirst]; if (aFirst === bFirst) return 0; var firstSorted = [aFirst, bFirst].smartSort(dir);   return aFirst == firstSorted[0] ? 1 : -1; } else return dir ? (aFirst < bFirst ? -1 : 1) : (aFirst > bFirst ? -1 : 1); } else if (/(object){2}/ig.test(cInstance)) { var aFirst = Object.keys(a)[0],    bFirst = Object.keys(b)[0];   if (void 0 != aFirst && aFirst === bFirst) { aFirst = a[aFirst]; bFirst = b[bFirst]; if (aFirst === bFirst) return 0; var firstSorted = [aFirst, bFirst].smartSort(dir);   return aFirst == firstSorted[0] ? 1 : -1; } else return dir ? (aFirst < bFirst ? -1 : 1) : (aFirst > bFirst ? -1 : 1); }  } else { // Organize as [DATE, ELEMENT, ARRAY, OBJECT, NAN|NULL|UNDEFINED] if (/Date/ig.test(cInstance)) return /Date/ig.test(aInstance) ? -1 : 1;  if (/Element/ig.test(cInstance)) return /Element/ig.test(aInstance) ? -1 : 1; // quick jQuery check to organize jQuery elements right behind standard elements if (window['jQuery'] && (a instanceof jQuery || b instanceof jQuery)) return a instanceof jQuery ? -1 : 1; if (/Array/ig.test(cInstance)) return /Array/ig.test(aInstance) ? -1 : 1; return /object/ig.test(aInstance) ? -1 : 1; } break; } } else { // Organize as [NUMBER, STRING, BOOLEAN, DATE, ELEMENT, ARRAY, OBJECT, NAN|NULL|UNDEFINED] if (/number/ig.test(cType)) return /number/ig.test(aType) ? -1 : 1;   if (/string/ig.test(cType)) return /string/ig.test(aType) ? -1 : 1;   if (/boolean/ig.test(cType)) return /boolean/ig.test(aType) ? -1 : 1;   if (/object/ig.test(cType)) { // TODO: think up every possible test to ensure this is never reached, as it shouldnt be  if (window['console'] && console['log']) {  console.log(new Array(50).join('-') + 'H I T' + new Array(50).join('-')); console.log(new Array(50).join('-') + 'H I T' + new Array(50).join('-')); console.log(new Array(50).join('-') + 'H I T' + new Array(50).join('-')); } if (a instanceof Date || b instanceof Date) return a instanceof Date ? -1 : 1; if (a instanceof Element || b instanceof Element) return a instanceof Element ? -1 : 1; if (a instanceof Array || b instanceof Array) return a instanceof Array ? -1 : 1; return /object/ig.test(aType) ? -1 : 1; } if (/function/ig.test(cType)) return /function/ig.test(aType) ? -1 : 1; else return -1; } }   if (Object['defineProperty'] && !Array.prototype['smartSort']) {   Object.defineProperty(Array.prototype, 'smartSort', { value: function() {  // first determine if a specific string for a|asc|d|dsc|desc was passed in for (var x in arguments) { if (typeof arguments[x] == 'string' && /^a([sc]{2})?$|^d([e]?[sc]{2,3})?$/i.test(arguments[x])) { dir = /^a([sc]{2})?$/i.test(arguments[x]) ? true : false; delete arguments[x];   break; } } // add extra arguments to current array for sorting /* var arr = this; for (var x in arguments) { // check if direction is set yet, if current item is boolean // if not yet set, set it to first found given boolean if (typeof arguments[x] == 'boolean' && void 0 == dir) dir = arguments[x]; else arr.push(arguments[x]); } return arr.sort(function(a, b) { return smartSort(a, b, dir); }); */ // if direction still not set, then set to true/asc if (void 0 == dir) dir = true;     Object.defineProperty(this, "direction", {    enumerable: false,   value: dir, writable: true }); return this.sort(smartSort); } }); } })(); 

jsFiddle

Rollback to Revision 10
Source Link
Ethan Bierlein
  • 15.9k
  • 4
  • 60
  • 146

UPDATE Long overdue, mainly cause I forgot about it, here's an updated code that needs some more modifying.

if (Object['defineProperty'] && !Array.prototype['smartSort']) { var smartSortAsc = function(a, b) { if (a == null || a == undefined) return 1; if (b == null || b == undefined) return -1; var c = typeof a, d = typeof b, e = c + d; if (/^numbernumber$/ig.test(e)) return a - b; if (/^stringstring$/ig.test(e)) return a > b; if (/(string|number){2}/ig.test(e)) return /string/i.test(c) ? 1 : -1; if (/number/ig.test(e) && /object/ig.test(e)) return /object/i.test(c) ? 1 : -1; if (/string/ig.test(e) && /object/ig.test(e)) return /object/i.test(c) ? 1 : -1; if (/^objectobject$/ig.test(e)) { if (a instanceof Array) a.smartSort('a'); if (b instanceof Array) b.smartSort('a'); if (a instanceof Date && b instanceof Date) return a - b; if (a instanceof Array && b instanceof Array) { var f = Object.keys(a), g = Object.keys(b), h = f.concat(g).smartSort('a'); for (var x in h) { var i = h[x]; if (a[i] != b[i]) { var j = [ a[i], b[i] ].smartSort('a'); return a[i] == j[0] ? -1 : 1; } } var k = [ a[Object.keys(a)[0]], b[Object.keys(b)[0]] ].smartSort('a'); return a[Object.keys(a)[0]] == k[0] ? -1 : 1; } if (a instanceof Element && b instanceof Element) { if (a.tagName == b.tagName) { var f = [ a.id, b.id ].smartSort('a'); return a.id == f[0] ? 1 : -1; } var f = [ a.tagName, b.tagName ].smartSort('a'); return a.tagName == f[0] ? 1 : -1; } if (a instanceof Date || b instanceof Date) return a instanceof Date ? 1 : -1; if (a instanceof Array || b instanceof Array) return a instanceof Array ? -1 : 1; var f = Object.keys(a), g = Object.keys(b), h = f.concat(g).smartSort('a'); for (var i = 0; i < 20; i++) { var j = f[i], k = g[i]; if (a.hasOwnProperty(j) && b.hasOwnProperty(k)) { if (a[j] instanceof Element && b[k] instanceof Element) { if (a[j].tagName == b[k].tagName) { var l = [ a[j].id, b[k].id ].smartSort('a'); return a[j].id == l[0] ? -1 : 1; } var l = [ a[j].tagName, b[k].tagName ].smartSort('a'); return a[j].tagName == l[0] ? -1 : 1; } if (a[j] instanceof Element || b[k] instanceof Element) return a[j] instanceof Element ? 1 : -1; if (a[j] != b[k]) { var m = [ a[j], b[k] ].smartSort('a'); return a[j] == m[0] ? -1 : 1; } } if (a.hasOwnProperty(j) && a[j] instanceof Element) return 1; if (b.hasOwnProperty(k) && b[k] instanceof Element) return -1; if (!a.hasOwnProperty(j)) return -1; if (!b.hasOwnProperty(j)) return 1; } var m = [ a[Object.keys(a)[0]], b[Object.keys(b)[0]] ].smartSort('a'); return a[Object.keys(a)[0]] == m[0] ? 1 : -1; } var g = [a, b].sort(); return g[0] > g[1]; } var smartSortDesc = function(a, b) { if (a == null || a == undefined) return 1; if (b == null || b == undefined) return -1; var c = typeof a, d = typeof b, e = c + d; if (/^numbernumber$/ig.test(e)) return b - a; if (/^stringstring$/ig.test(e)) return b > a; if (/(string|number){2}/ig.test(e)) return /string/i.test(c) ? 1 : -1; if (/number/ig.test(e) && /object/ig.test(e)) return /object/i.test(c) ? 1 : -1; if (/string/ig.test(e) && /object/ig.test(e)) return /object/i.test(c) ? 1 : -1; if (/^objectobject$/ig.test(e)) { // both are OBJECT if (a instanceof Array) a.smartSort('d'); if (b instanceof Array) b.smartSort('d'); if (a instanceof Date && b instanceof Date) return b - a; if (a instanceof Array && b instanceof Array) { // both are ARRAY var f = Object.keys(a), g = Object.keys(b), h = f.concat(g).smartSort('a'); for (var x in h) { var i = h[x]; if (a[i] != b[i]) { var j = [ a[i], b[i] ].smartSort('d'); return a[i] == j[0] ? -1 : 1; } } var k = [ a[Object.keys(a)[0]], b[Object.keys(b)[0]] ].smartSort('d'); return a[Object.keys(a)[0]] == k[0] ? -1 : 1; } if (a instanceof Element && b instanceof Element) { // both are ELEMENT if (a.tagName == b.tagName) { var f = [ a.id, b.id ].smartSort('d'); return a.id == f[0] ? -1 : 1; } var f = [ a.tagName, b.tagName ].smartSort('d'); return a.tagName == f[0] ? -1 : 1; } if (a instanceof Date || b instanceof Date) return a instanceof Date ? 1 : -1; if (a instanceof Array || b instanceof Array) return a instanceof Array ? -1 : 1; var f = Object.keys(a), g = Object.keys(b), h = f.concat(g).smartSort('a'); for (var i = 0; i < 20; i++) { var j = f[i], k = g[i]; if (a.hasOwnProperty(j) && b.hasOwnProperty(k)) { if (a[j] instanceof Element && b[k] instanceof Element) { if (a[j].tagName == b[k].tagName) { var l = [ a[j].id, b[k].id ].smartSort('d'); return a[j].id == l[0] ? -1 : 1; } var l = [ a[j].tagName, b[k].tagName ].smartSort('d'); return a[j].tagName == l[0] ? -1 : 1; } if (a[j] instanceof Element || b[k] instanceof Element) return a[j] instanceof Element ? 1 : -1; if (a[j] != b[k]) { var m = [ a[j], b[k] ].smartSort('d'); return a[j] == m[0] ? -1 : 1; } } if (a.hasOwnProperty(j) && a[j] instanceof Element) return 1; if (b.hasOwnProperty(k) && b[k] instanceof Element) return -1; if (!a.hasOwnProperty(j)) return 1; if (!b.hasOwnProperty(j)) return -1; } var m = [ a[Object.keys(a)[0]], b[Object.keys(b)[0]] ].smartSort('d'); return a[Object.keys(a)[0]] == m[0] ? -1 : 1; } var g = [a, b].sort(); return g[0] < g[1]; } Object.defineProperty(Array.prototype, 'smartSort', { value: function() { if (arguments && (!arguments.length || arguments.length == 1 && /^a([sc]{2})?$|^d([esc]{3})?$/i.test(arguments[0]))) return this.sort(!arguments.length || /^a([sc]{2})?$/i.test(arguments[0]) ? smartSortAsc : smartSortDesc); return this.sort(); } }); } 

jsFiddle

smartSort(Array, 'asc|desc')

;;(function() { var dir = void 0; // numbers, strings, booleans, dates, elements, arrays, objects, null|undefined function smartSort(a, b/* , dir */) { // immidiate return for emtpy values if (null == a || void 0 == a || a !== a) return 1; if (null == b || void 0 == b || b !== b) return -1; // make string numbers into real numbers var regNum = new RegExp(/^-?\d+\.?\d*$|^\d*\.?\d+$/); if (regNum.test(a)) a = parseFloat(a); if (regNum.test(b)) b = parseFloat(b); var aType = typeof a, bType = typeof b, cType = aType + bType; var aInstance = Object.prototype.toString.call(a).slice(8, -1), bInstance = Object.prototype.toString.call(b).slice(8, -1), cInstance = aInstance + bInstance; if (/Array/ig.test(aInstance)) a.smartSort(dir); if (/Array/ig.test(bInstance)) b.smartSort(dir); if (aType == bType) { switch (aType || bType) { case 'boolean': return a === b ? 0 : (dir ? (a ? 1 : -1) : (b ? 1 : -1)); case 'number': return a === b ? 0 : (dir ? (a < b ? -1 : 1) : (a > b ? -1 : 1)); case 'string': a = a.valueOf().toLowerCase(); b = b.valueOf().toLowerCase(); return a === b ? 0 : (dir ? (a < b ? -1 : 1) : (a > b ? -1 : 1)); case 'object': if (aInstance == bInstance) { if (/(date){2}/ig.test(cInstance)) { var aValue = a.valueOf(), bValue = b.valueOf(); return aValue === bValue ? 0 : (dir ? (aValue < bValue ? -1 : 1) : (aValue > bValue ? -1 : 1)); } else if (/^(HTML)\w+(Element)$/.test(cInstance)) { if (a.id && b.id) return a.id === b.id ? 0 : (dir ? (a.id < b.id ? -1 : 1) : (a.id > b.id ? -1 : 1)); else if (a.id || b.id) return a.id && !b.id ? 1 : -1; if (a.name && b.name) return a.name === b.name ? 0 : (dir ? (a.name < b.name ? -1 : 1) : (a.name > b.name ? -1 : 1)); else if (a.name || b.name) return a.name && !b.name ? 1 : -1; return a.tagName === b.tagName ? 0 : (dir ? (a.tagName < b.tagName ? -1 : 1) : (a.tagName > b.tagName ? -1 : 1)); } /*TODO: else if (window['jQuery'] && a instanceof jQuery) { } */ else if (/(array){2}/ig.test(cInstance)) { var aFirst = Object.keys(a)[0], bFirst = Object.keys(b)[0]; if (aFirst === bFirst) { aFirst = a[aFirst]; bFirst = b[bFirst]; if (aFirst === bFirst) return 0; var firstSorted = [aFirst, bFirst].smartSort(dir); return aFirst == firstSorted[0] ? 1 : -1; } else return dir ? (aFirst < bFirst ? -1 : 1) : (aFirst > bFirst ? -1 : 1); } else if (/(object){2}/ig.test(cInstance)) { var aFirst = Object.keys(a)[0], bFirst = Object.keys(b)[0]; if (void 0 != aFirst && aFirst === bFirst) { aFirst = a[aFirst]; bFirst = b[bFirst]; if (aFirst === bFirst) return 0; var firstSorted = [aFirst, bFirst].smartSort(dir); return aFirst == firstSorted[0] ? 1 : -1; } else return dir ? (aFirst < bFirst ? -1 : 1) : (aFirst > bFirst ? -1 : 1); if (!window['smartSort']) { window.smartSort = function() { if (arguments) { var a, b; for (var x in arguments) arguments[x] instanceof Array && (a = arguments[x], void 0 == b && (b = "a")), "string" == typeof arguments[x] && (b = /^a([sc]{2})?$/i.test(arguments[x]) ? "a" : "d"); if (a instanceof Array) return a.sort(b == 'a' ? smartSort.asc : smartSort.desc); } return this.sort(); } smartSort.asc = function(a, b) { if (a == null || a == undefined) return 1; if (b == null || b == undefined) return -1; var c = typeof a, d = typeof b, e = c + d; if (/^numbernumber$/ig.test(e)) return a - b; if (/^stringstring$/ig.test(e)) return a > b; if (/(string|number){2}/ig.test(e)) return /string/i.test(c) ? 1 : -1; if (/number/ig.test(e) && /object/ig.test(e)) return /object/i.test(c) ? 1 : -1; if (/string/ig.test(e) && /object/ig.test(e)) return /object/i.test(c) ? 1 : -1; if (/^objectobject$/ig.test(e)) { if (a instanceof Array) a.sort(smartSort.asc); if (b instanceof Array) b.sort(smartSort.asc); if (a instanceof Date && b instanceof Date) return a - b; if (a instanceof Array && b instanceof Array) { var f = Object.keys(a), g = Object.keys(b), h = smartSort(f.concat(g), 'a'); for (var x in h) { var i = h[x]; if (a[i] != b[i]) { var j = smartSort([ a[i], b[i] ], 'a'); return a[i] == j[0] ? -1 : 1; } } var k = smartSort([ a[Object.keys(a)[0]], b[Object.keys(b)[0]] ], 'a'); return a[Object.keys(a)[0]] == k[0] ? -1 : 1; } if (a instanceof Element && b instanceof Element) { if (a.tagName == b.tagName) { var f = smartSort([ a.id, b.id ], 'a'); return a.id == f[0] ? 1 : -1; } var f = smartSort([ a.tagName, b.tagName ], 'a'); return a.tagName == f[0] ? 1 : -1; } if (a instanceof Date || b instanceof Date) return a instanceof Date ? 1 : -1; if (a instanceof Array || b instanceof Array) return a instanceof Array ? -1 : 1; var f = Object.keys(a), g = Object.keys(b), h = smartSort(f.concat(g), 'a'); for (var i = 0; i < 20; i++) { var j = f[i], k = g[i]; if (a.hasOwnProperty(j) && b.hasOwnProperty(k)) { if (a[j] instanceof Element && b[k] instanceof Element) { if (a[j].tagName == b[k].tagName) { var l = smartSort([ a[j].id, b[k].id ], 'a'); return a[j].id == l[0] ? -1 : 1;  } var l = smartSort([ a[j].tagName, b[k].tagName ], 'a'); return a[j].tagName == l[0] ? -1 : 1; } else { // Organize as [DATE, ELEMENT, ARRAY, OBJECT, NAN|NULL|UNDEFINED] if (/Date/ig.test(cInstance)) return /Date/ig.test(aInstance) ? -1 : 1; a[j] instanceof Element || b[k] ifinstanceof (/Element/ig.test(cInstance)) return /a[j] instanceof Element/ig.test(aInstance) ? -1 : -1;   //  quick jQuery check to organize jQuery elements right behind standard elements if (window['jQuery'] && (a instanceof jQuery || ba[j] instanceof!= jQuery)b[k]) return a instanceof jQuery ? -1 : 1;{ ifvar (/Array/ig.test(cInstance))m return= /Array/ig.testsmartSort(aInstance)[ ?a[j], -1b[k] :], 1;'a'); return /object/ig.test(aInstance)a[j] == m[0] ? -1 : 1; }  break; } } else { // Organize as [NUMBER, STRING, BOOLEAN, DATE, ELEMENT, ARRAY, OBJECT, NAN|NULL|UNDEFINED] if (/number/ig.test(cType)) return /number/ig.test(aType) ? -1 : 1; if (/string/ig.test(cType)) return /string/ig.test(aType) ? -1 : 1; if (/boolean/ig.test(cType)) return /boolean/ig.test(aType) ? -1 : 1; if (/object/ig.test(cType)) { // TODO: think up every possible test to ensure this is never reached, as it shouldnt be if (window['console'] && console['log']) { console.log(new Array(50).join('-') + 'H I T' + new Array(50).join('-')); console.log(new Array(50).join('-') + 'H I T' + new Array(50).join('-')); console.log(new Array(50).join('-') + 'H I T' + new Array(50).join('-'));  } if (a instanceof Date.hasOwnProperty(j) ||&& ba[j] instanceof DateElement) return a instanceof Date ? -1 : 1; if (a instanceof Element || b instanceof Element.hasOwnProperty(k) return&& ab[k] instanceof Element) ?return -1 : 1; if (!a instanceof Array || b instanceof Array.hasOwnProperty(j)) return a instanceof Array ? -1 : 1; returnif /object/ig(!b.testhasOwnProperty(aTypej) ? -1) :return 1; } ifvar m = smartSort(/function/ig[ a[Object.testkeys(cType)a) return[0]], /function/igb[Object.testkeys(aTypeb)[0]] ?], -1'a');  : 1;  return a[Object.keys(a)[0]] else== returnm[0] ? 1 : -1; }  var g = [a, b].sort(); return g[0] > g[1];  } smartSort.desc = function(a, b) {   if (Object['defineProperty']a &&== !Array.prototype['smartSort']null || a == undefined) {return 1; Object.definePropertyif (Array.prototypeb == null || b == undefined) return -1; var c = typeof a, 'smartSort'd = typeof b, {e value:= functionc + d; if (/^numbernumber$/ig.test(e)) { return b - a;  if (/^stringstring$/ig.test(e)) return firstb determine> a;  if a(/(string|number){2}/ig.test(e)) specificreturn /string/i.test(c) for? a|asc|d|dsc|desc1 was: passed-1;  in if (/number/ig.test(e) && /object/ig.test(e)) return /object/i.test(c) ? 1 : -1; if (/string/ig.test(e) && /object/ig.test(e)) forreturn /object/i.test(varc) x? in1 arguments: -1; if (/^objectobject$/ig.test(e)) { // both are OBJECT if (a instanceof Array) a.sort(smartSort.desc); if (typeofb arguments[x]instanceof ==Array) 'string'b.sort(smartSort.desc);  && /^a if ([sc]{2}a instanceof Date && b instanceof Date)?$|^d return b - a; if ([e]?[sc]a instanceof Array && b instanceof Array) {2 // both are ARRAY var f = Object.keys(a),3} g = Object.keys(b)?$/i, h = smartSort(f.testconcat(arguments[x]g), 'a');  for (var x in h) { dirvar i = /^ah[x]; if ([sc]{2}a[i] != b[i])?$/i.test { var j = smartSort(arguments[x])[ ?a[i], trueb[i] :], false;'d'); delete arguments[x]; return a[i] == j[0] ? -1 : 1; break;} }  var k = smartSort([ a[Object.keys(a)[0]], b[Object.keys(b)[0]] ], 'd'); return a[Object.keys(a)[0]] == k[0] ? -1 : 1;  }  if (a instanceof Element && b instanceof Element) { //  add extraboth argumentsare toELEMENT  current array for sorting  /*if var(a.tagName arr== =b.tagName) this;{ for (var x in arguments) {  var f = smartSort([ a.id, b.id ], 'd');  // check if direction is set yet, if current item is boolean  return a.id == f[0] ? -1 : 1;  // if not yet set, set it to first found}  given boolean  var f if= smartSort(typeof arguments[x][ ==a.tagName, 'boolean'b.tagName &&], void'd');  0 == dir) dir = arguments[x];  return a.tagName == f[0] ? -1 else: arr.push(arguments[x]);1; } returnif arr.sort(function(a, instanceof Date || b instanceof Date) {return a instanceof Date ? 1 : -1; if (a instanceof Array || b instanceof Array) return smartSorta instanceof Array ? -1 : 1; var f = Object.keys(a),  g = Object.keys(b),   dir h = smartSort(f.concat(g);, }'a'); */   for (var i = 0; i < 20; i++) { // if direction stillvar notj set= f[i], thenk set= tog[i];  true/asc if (a.hasOwnProperty(j) && b.hasOwnProperty(k)) {   if (voida[j] 0instanceof Element && b[k] instanceof Element) {  if (a[j].tagName == dirb[k].tagName) dir{  var l = true;smartSort([ a[j].id, b[k].id ], 'd');    Object return a[j].definePropertyid == l[0] ? -1 : 1; } var l = smartSort(this[ a[j].tagName, "direction"b[k].tagName ], {'d'); enumerable return a[j].tagName == l[0] ? -1 : false,1; value } if (a[j] instanceof Element || b[k] instanceof Element) return a[j] instanceof Element ? 1 : dir-1; if (a[j] != b[k]) { var m = smartSort([ a[j], b[k] ], 'd'); writable return a[j] == m[0] ? -1 : true1;  }  } if (a.hasOwnProperty(j); && a[j] instanceof Element) return 1;   if (b.hasOwnProperty(k) && b[k] instanceof Element) return this-1; if (!a.sorthasOwnProperty(j)) return 1; if (!b.hasOwnProperty(j)) return -1; } var m = smartSort([ a[Object.keys(a)[0]], b[Object.keys(b)[0]] ], 'd'); } return a[Object.keys(a)[0]] == m[0] ? -1 : 1;  } var g = [a, b].sort(); return g[0] < g[1]; } })(); 

jsFiddlejsFiddle

UPDATE Long overdue, mainly cause I forgot about it, here's an updated code that needs some more modifying.

;;(function() { var dir = void 0; // numbers, strings, booleans, dates, elements, arrays, objects, null|undefined function smartSort(a, b/* , dir */) { // immidiate return for emtpy values if (null == a || void 0 == a || a !== a) return 1; if (null == b || void 0 == b || b !== b) return -1; // make string numbers into real numbers var regNum = new RegExp(/^-?\d+\.?\d*$|^\d*\.?\d+$/); if (regNum.test(a)) a = parseFloat(a); if (regNum.test(b)) b = parseFloat(b); var aType = typeof a, bType = typeof b, cType = aType + bType; var aInstance = Object.prototype.toString.call(a).slice(8, -1), bInstance = Object.prototype.toString.call(b).slice(8, -1), cInstance = aInstance + bInstance; if (/Array/ig.test(aInstance)) a.smartSort(dir); if (/Array/ig.test(bInstance)) b.smartSort(dir); if (aType == bType) { switch (aType || bType) { case 'boolean': return a === b ? 0 : (dir ? (a ? 1 : -1) : (b ? 1 : -1)); case 'number': return a === b ? 0 : (dir ? (a < b ? -1 : 1) : (a > b ? -1 : 1)); case 'string': a = a.valueOf().toLowerCase(); b = b.valueOf().toLowerCase(); return a === b ? 0 : (dir ? (a < b ? -1 : 1) : (a > b ? -1 : 1)); case 'object': if (aInstance == bInstance) { if (/(date){2}/ig.test(cInstance)) { var aValue = a.valueOf(), bValue = b.valueOf(); return aValue === bValue ? 0 : (dir ? (aValue < bValue ? -1 : 1) : (aValue > bValue ? -1 : 1)); } else if (/^(HTML)\w+(Element)$/.test(cInstance)) { if (a.id && b.id) return a.id === b.id ? 0 : (dir ? (a.id < b.id ? -1 : 1) : (a.id > b.id ? -1 : 1)); else if (a.id || b.id) return a.id && !b.id ? 1 : -1; if (a.name && b.name) return a.name === b.name ? 0 : (dir ? (a.name < b.name ? -1 : 1) : (a.name > b.name ? -1 : 1)); else if (a.name || b.name) return a.name && !b.name ? 1 : -1; return a.tagName === b.tagName ? 0 : (dir ? (a.tagName < b.tagName ? -1 : 1) : (a.tagName > b.tagName ? -1 : 1)); } /*TODO: else if (window['jQuery'] && a instanceof jQuery) { } */ else if (/(array){2}/ig.test(cInstance)) { var aFirst = Object.keys(a)[0], bFirst = Object.keys(b)[0]; if (aFirst === bFirst) { aFirst = a[aFirst]; bFirst = b[bFirst]; if (aFirst === bFirst) return 0; var firstSorted = [aFirst, bFirst].smartSort(dir); return aFirst == firstSorted[0] ? 1 : -1; } else return dir ? (aFirst < bFirst ? -1 : 1) : (aFirst > bFirst ? -1 : 1); } else if (/(object){2}/ig.test(cInstance)) { var aFirst = Object.keys(a)[0], bFirst = Object.keys(b)[0]; if (void 0 != aFirst && aFirst === bFirst) { aFirst = a[aFirst]; bFirst = b[bFirst]; if (aFirst === bFirst) return 0; var firstSorted = [aFirst, bFirst].smartSort(dir); return aFirst == firstSorted[0] ? 1 : -1; } else return dir ? (aFirst < bFirst ? -1 : 1) : (aFirst > bFirst ? -1 : 1);  } } else { // Organize as [DATE, ELEMENT, ARRAY, OBJECT, NAN|NULL|UNDEFINED] if (/Date/ig.test(cInstance)) return /Date/ig.test(aInstance) ? -1 : 1;  if (/Element/ig.test(cInstance)) return /Element/ig.test(aInstance) ? -1 : 1;   //  quick jQuery check to organize jQuery elements right behind standard elements if (window['jQuery'] && (a instanceof jQuery || b instanceof jQuery)) return a instanceof jQuery ? -1 : 1; if (/Array/ig.test(cInstance)) return /Array/ig.test(aInstance) ? -1 : 1; return /object/ig.test(aInstance) ? -1 : 1; }  break; } } else { // Organize as [NUMBER, STRING, BOOLEAN, DATE, ELEMENT, ARRAY, OBJECT, NAN|NULL|UNDEFINED] if (/number/ig.test(cType)) return /number/ig.test(aType) ? -1 : 1; if (/string/ig.test(cType)) return /string/ig.test(aType) ? -1 : 1; if (/boolean/ig.test(cType)) return /boolean/ig.test(aType) ? -1 : 1; if (/object/ig.test(cType)) { // TODO: think up every possible test to ensure this is never reached, as it shouldnt be if (window['console'] && console['log']) { console.log(new Array(50).join('-') + 'H I T' + new Array(50).join('-')); console.log(new Array(50).join('-') + 'H I T' + new Array(50).join('-')); console.log(new Array(50).join('-') + 'H I T' + new Array(50).join('-'));  } if (a instanceof Date || b instanceof Date) return a instanceof Date ? -1 : 1; if (a instanceof Element || b instanceof Element) return a instanceof Element ? -1 : 1; if (a instanceof Array || b instanceof Array) return a instanceof Array ? -1 : 1; return /object/ig.test(aType) ? -1 : 1; } if (/function/ig.test(cType)) return /function/ig.test(aType) ? -1 : 1;  else return -1; } } if (Object['defineProperty'] && !Array.prototype['smartSort']) { Object.defineProperty(Array.prototype, 'smartSort', { value: function() {  // first determine if a specific string for a|asc|d|dsc|desc was passed in for (var x in arguments) { if (typeof arguments[x] == 'string' && /^a([sc]{2})?$|^d([e]?[sc]{2,3})?$/i.test(arguments[x])) { dir = /^a([sc]{2})?$/i.test(arguments[x]) ? true : false; delete arguments[x]; break; } }   //  add extra arguments to current array for sorting  /* var arr = this; for (var x in arguments) {  // check if direction is set yet, if current item is boolean  // if not yet set, set it to first found given boolean  if (typeof arguments[x] == 'boolean' && void 0 == dir) dir = arguments[x];  else arr.push(arguments[x]); } return arr.sort(function(a, b) { return smartSort(a, b, dir); }); */ // if direction still not set, then set to true/asc if (void 0 == dir) dir = true;    Object.defineProperty(this, "direction", { enumerable: false, value: dir, writable: true }); return this.sort(smartSort); } }); } })(); 

jsFiddle

if (Object['defineProperty'] && !Array.prototype['smartSort']) { var smartSortAsc = function(a, b) { if (a == null || a == undefined) return 1; if (b == null || b == undefined) return -1; var c = typeof a, d = typeof b, e = c + d; if (/^numbernumber$/ig.test(e)) return a - b; if (/^stringstring$/ig.test(e)) return a > b; if (/(string|number){2}/ig.test(e)) return /string/i.test(c) ? 1 : -1; if (/number/ig.test(e) && /object/ig.test(e)) return /object/i.test(c) ? 1 : -1; if (/string/ig.test(e) && /object/ig.test(e)) return /object/i.test(c) ? 1 : -1; if (/^objectobject$/ig.test(e)) { if (a instanceof Array) a.smartSort('a'); if (b instanceof Array) b.smartSort('a'); if (a instanceof Date && b instanceof Date) return a - b; if (a instanceof Array && b instanceof Array) { var f = Object.keys(a), g = Object.keys(b), h = f.concat(g).smartSort('a'); for (var x in h) { var i = h[x]; if (a[i] != b[i]) { var j = [ a[i], b[i] ].smartSort('a'); return a[i] == j[0] ? -1 : 1; } } var k = [ a[Object.keys(a)[0]], b[Object.keys(b)[0]] ].smartSort('a'); return a[Object.keys(a)[0]] == k[0] ? -1 : 1; } if (a instanceof Element && b instanceof Element) { if (a.tagName == b.tagName) { var f = [ a.id, b.id ].smartSort('a'); return a.id == f[0] ? 1 : -1; } var f = [ a.tagName, b.tagName ].smartSort('a'); return a.tagName == f[0] ? 1 : -1; } if (a instanceof Date || b instanceof Date) return a instanceof Date ? 1 : -1; if (a instanceof Array || b instanceof Array) return a instanceof Array ? -1 : 1; var f = Object.keys(a), g = Object.keys(b), h = f.concat(g).smartSort('a'); for (var i = 0; i < 20; i++) { var j = f[i], k = g[i]; if (a.hasOwnProperty(j) && b.hasOwnProperty(k)) { if (a[j] instanceof Element && b[k] instanceof Element) { if (a[j].tagName == b[k].tagName) { var l = [ a[j].id, b[k].id ].smartSort('a'); return a[j].id == l[0] ? -1 : 1; } var l = [ a[j].tagName, b[k].tagName ].smartSort('a'); return a[j].tagName == l[0] ? -1 : 1; } if (a[j] instanceof Element || b[k] instanceof Element) return a[j] instanceof Element ? 1 : -1; if (a[j] != b[k]) { var m = [ a[j], b[k] ].smartSort('a'); return a[j] == m[0] ? -1 : 1; } } if (a.hasOwnProperty(j) && a[j] instanceof Element) return 1; if (b.hasOwnProperty(k) && b[k] instanceof Element) return -1; if (!a.hasOwnProperty(j)) return -1; if (!b.hasOwnProperty(j)) return 1; } var m = [ a[Object.keys(a)[0]], b[Object.keys(b)[0]] ].smartSort('a'); return a[Object.keys(a)[0]] == m[0] ? 1 : -1; } var g = [a, b].sort(); return g[0] > g[1]; } var smartSortDesc = function(a, b) { if (a == null || a == undefined) return 1; if (b == null || b == undefined) return -1; var c = typeof a, d = typeof b, e = c + d; if (/^numbernumber$/ig.test(e)) return b - a; if (/^stringstring$/ig.test(e)) return b > a; if (/(string|number){2}/ig.test(e)) return /string/i.test(c) ? 1 : -1; if (/number/ig.test(e) && /object/ig.test(e)) return /object/i.test(c) ? 1 : -1; if (/string/ig.test(e) && /object/ig.test(e)) return /object/i.test(c) ? 1 : -1; if (/^objectobject$/ig.test(e)) { // both are OBJECT if (a instanceof Array) a.smartSort('d'); if (b instanceof Array) b.smartSort('d'); if (a instanceof Date && b instanceof Date) return b - a; if (a instanceof Array && b instanceof Array) { // both are ARRAY var f = Object.keys(a), g = Object.keys(b), h = f.concat(g).smartSort('a'); for (var x in h) { var i = h[x]; if (a[i] != b[i]) { var j = [ a[i], b[i] ].smartSort('d'); return a[i] == j[0] ? -1 : 1; } } var k = [ a[Object.keys(a)[0]], b[Object.keys(b)[0]] ].smartSort('d'); return a[Object.keys(a)[0]] == k[0] ? -1 : 1; } if (a instanceof Element && b instanceof Element) { // both are ELEMENT if (a.tagName == b.tagName) { var f = [ a.id, b.id ].smartSort('d'); return a.id == f[0] ? -1 : 1; } var f = [ a.tagName, b.tagName ].smartSort('d'); return a.tagName == f[0] ? -1 : 1; } if (a instanceof Date || b instanceof Date) return a instanceof Date ? 1 : -1; if (a instanceof Array || b instanceof Array) return a instanceof Array ? -1 : 1; var f = Object.keys(a), g = Object.keys(b), h = f.concat(g).smartSort('a'); for (var i = 0; i < 20; i++) { var j = f[i], k = g[i]; if (a.hasOwnProperty(j) && b.hasOwnProperty(k)) { if (a[j] instanceof Element && b[k] instanceof Element) { if (a[j].tagName == b[k].tagName) { var l = [ a[j].id, b[k].id ].smartSort('d'); return a[j].id == l[0] ? -1 : 1; } var l = [ a[j].tagName, b[k].tagName ].smartSort('d'); return a[j].tagName == l[0] ? -1 : 1; } if (a[j] instanceof Element || b[k] instanceof Element) return a[j] instanceof Element ? 1 : -1; if (a[j] != b[k]) { var m = [ a[j], b[k] ].smartSort('d'); return a[j] == m[0] ? -1 : 1; } } if (a.hasOwnProperty(j) && a[j] instanceof Element) return 1; if (b.hasOwnProperty(k) && b[k] instanceof Element) return -1; if (!a.hasOwnProperty(j)) return 1; if (!b.hasOwnProperty(j)) return -1; } var m = [ a[Object.keys(a)[0]], b[Object.keys(b)[0]] ].smartSort('d'); return a[Object.keys(a)[0]] == m[0] ? -1 : 1; } var g = [a, b].sort(); return g[0] < g[1]; } Object.defineProperty(Array.prototype, 'smartSort', { value: function() { if (arguments && (!arguments.length || arguments.length == 1 && /^a([sc]{2})?$|^d([esc]{3})?$/i.test(arguments[0]))) return this.sort(!arguments.length || /^a([sc]{2})?$/i.test(arguments[0]) ? smartSortAsc : smartSortDesc); return this.sort(); } }); } 

jsFiddle

smartSort(Array, 'asc|desc')

if (!window['smartSort']) { window.smartSort = function() { if (arguments) { var a, b; for (var x in arguments) arguments[x] instanceof Array && (a = arguments[x], void 0 == b && (b = "a")), "string" == typeof arguments[x] && (b = /^a([sc]{2})?$/i.test(arguments[x]) ? "a" : "d"); if (a instanceof Array) return a.sort(b == 'a' ? smartSort.asc : smartSort.desc); } return this.sort(); } smartSort.asc = function(a, b) { if (a == null || a == undefined) return 1; if (b == null || b == undefined) return -1; var c = typeof a, d = typeof b, e = c + d; if (/^numbernumber$/ig.test(e)) return a - b; if (/^stringstring$/ig.test(e)) return a > b; if (/(string|number){2}/ig.test(e)) return /string/i.test(c) ? 1 : -1; if (/number/ig.test(e) && /object/ig.test(e)) return /object/i.test(c) ? 1 : -1; if (/string/ig.test(e) && /object/ig.test(e)) return /object/i.test(c) ? 1 : -1; if (/^objectobject$/ig.test(e)) { if (a instanceof Array) a.sort(smartSort.asc); if (b instanceof Array) b.sort(smartSort.asc); if (a instanceof Date && b instanceof Date) return a - b; if (a instanceof Array && b instanceof Array) { var f = Object.keys(a), g = Object.keys(b), h = smartSort(f.concat(g), 'a'); for (var x in h) { var i = h[x]; if (a[i] != b[i]) { var j = smartSort([ a[i], b[i] ], 'a'); return a[i] == j[0] ? -1 : 1; } } var k = smartSort([ a[Object.keys(a)[0]], b[Object.keys(b)[0]] ], 'a'); return a[Object.keys(a)[0]] == k[0] ? -1 : 1; } if (a instanceof Element && b instanceof Element) { if (a.tagName == b.tagName) { var f = smartSort([ a.id, b.id ], 'a'); return a.id == f[0] ? 1 : -1; } var f = smartSort([ a.tagName, b.tagName ], 'a'); return a.tagName == f[0] ? 1 : -1; } if (a instanceof Date || b instanceof Date) return a instanceof Date ? 1 : -1; if (a instanceof Array || b instanceof Array) return a instanceof Array ? -1 : 1; var f = Object.keys(a), g = Object.keys(b), h = smartSort(f.concat(g), 'a'); for (var i = 0; i < 20; i++) { var j = f[i], k = g[i]; if (a.hasOwnProperty(j) && b.hasOwnProperty(k)) { if (a[j] instanceof Element && b[k] instanceof Element) { if (a[j].tagName == b[k].tagName) { var l = smartSort([ a[j].id, b[k].id ], 'a'); return a[j].id == l[0] ? -1 : 1;  } var l = smartSort([ a[j].tagName, b[k].tagName ], 'a'); return a[j].tagName == l[0] ? -1 : 1; } if (a[j] instanceof Element || b[k] instanceof Element) return a[j] instanceof Element ? 1 : -1; if (a[j] != b[k]) { var m = smartSort([ a[j], b[k] ], 'a'); return a[j] == m[0] ? -1 : 1; } } if (a.hasOwnProperty(j) && a[j] instanceof Element) return 1; if (b.hasOwnProperty(k) && b[k] instanceof Element) return -1; if (!a.hasOwnProperty(j)) return -1; if (!b.hasOwnProperty(j)) return 1; } var m = smartSort([ a[Object.keys(a)[0]], b[Object.keys(b)[0]] ], 'a');  return a[Object.keys(a)[0]] == m[0] ? 1 : -1; }  var g = [a, b].sort(); return g[0] > g[1];  } smartSort.desc = function(a, b) {   if (a == null || a == undefined) return 1; if (b == null || b == undefined) return -1; var c = typeof a, d = typeof b, e = c + d; if (/^numbernumber$/ig.test(e)) return b - a;  if (/^stringstring$/ig.test(e)) return b > a;  if (/(string|number){2}/ig.test(e)) return /string/i.test(c) ? 1 : -1;   if (/number/ig.test(e) && /object/ig.test(e)) return /object/i.test(c) ? 1 : -1; if (/string/ig.test(e) && /object/ig.test(e)) return /object/i.test(c) ? 1 : -1; if (/^objectobject$/ig.test(e)) { // both are OBJECT if (a instanceof Array) a.sort(smartSort.desc); if (b instanceof Array) b.sort(smartSort.desc);   if (a instanceof Date && b instanceof Date) return b - a; if (a instanceof Array && b instanceof Array) { // both are ARRAY var f = Object.keys(a), g = Object.keys(b), h = smartSort(f.concat(g), 'a');  for (var x in h) { var i = h[x]; if (a[i] != b[i]) { var j = smartSort([ a[i], b[i] ], 'd');  return a[i] == j[0] ? -1 : 1; } }  var k = smartSort([ a[Object.keys(a)[0]], b[Object.keys(b)[0]] ], 'd'); return a[Object.keys(a)[0]] == k[0] ? -1 : 1;  } if (a instanceof Element && b instanceof Element) { // both are ELEMENT  if (a.tagName == b.tagName) { var f = smartSort([ a.id, b.id ], 'd');  return a.id == f[0] ? -1 : 1;  }  var f = smartSort([ a.tagName, b.tagName ], 'd');  return a.tagName == f[0] ? -1 : 1; } if (a instanceof Date || b instanceof Date) return a instanceof Date ? 1 : -1; if (a instanceof Array || b instanceof Array) return a instanceof Array ? -1 : 1; var f = Object.keys(a),  g = Object.keys(b),    h = smartSort(f.concat(g), 'a');   for (var i = 0; i < 20; i++) { var j = f[i], k = g[i];   if (a.hasOwnProperty(j) && b.hasOwnProperty(k)) {   if (a[j] instanceof Element && b[k] instanceof Element) {  if (a[j].tagName == b[k].tagName) {  var l = smartSort([ a[j].id, b[k].id ], 'd');  return a[j].id == l[0] ? -1 : 1; } var l = smartSort([ a[j].tagName, b[k].tagName ], 'd');  return a[j].tagName == l[0] ? -1 : 1;  } if (a[j] instanceof Element || b[k] instanceof Element) return a[j] instanceof Element ? 1 : -1; if (a[j] != b[k]) { var m = smartSort([ a[j], b[k] ], 'd');  return a[j] == m[0] ? -1 : 1;  }  } if (a.hasOwnProperty(j) && a[j] instanceof Element) return 1;   if (b.hasOwnProperty(k) && b[k] instanceof Element) return -1; if (!a.hasOwnProperty(j)) return 1; if (!b.hasOwnProperty(j)) return -1; } var m = smartSort([ a[Object.keys(a)[0]], b[Object.keys(b)[0]] ], 'd');  return a[Object.keys(a)[0]] == m[0] ? -1 : 1;  } var g = [a, b].sort(); return g[0] < g[1]; } } 

jsFiddle

Rollback to Revision 9
Source Link
user10934
user10934
Loading
Rollback to Revision 8
Source Link
Ethan Bierlein
  • 15.9k
  • 4
  • 60
  • 146
Loading
Rollback to Revision 7
Source Link
user10934
user10934
Loading
Rollback to Revision 6
Source Link
Vogel612
  • 25.5k
  • 7
  • 59
  • 141
Loading
Rollback to Revision 5
Source Link
user10934
user10934
Loading
Rollback to Revision 4
Source Link
Ethan Bierlein
  • 15.9k
  • 4
  • 60
  • 146
Loading
deleted 3683 characters in body
Source Link
user10934
user10934
Loading
Tweeted twitter.com/#!/StackCodeReview/status/601610724566298624
deleted 81 characters in body; edited title
Source Link
Jamal
  • 35.2k
  • 13
  • 134
  • 238
Loading
Improved title
Link
Phrancis
  • 20.5k
  • 6
  • 70
  • 155
Loading
added 243 characters in body
Source Link
user10934
user10934
Loading
Source Link
user10934
user10934
Loading