Add natural sort option to tree view.

This commit is contained in:
Lars Jung 2015-04-05 22:20:22 +02:00
parent f723bcd7bb
commit e9ac5b46d8
4 changed files with 89 additions and 61 deletions

View file

@ -0,0 +1,71 @@
modulejs.define('core/util', [], function () {
function regularCmpFn(val1, val2) {
if (val1 < val2) {
return -1;
}
if (val1 > val2) {
return 1;
}
return 0;
}
// Natural Sort algorithm for Javascript - Version 0.7 - Released under MIT license
// Author: Jim Palmer (based on chunking idea from Dave Koelle)
//
// Modified to make it work with h5ai
function naturalCmpFn(val1, val2) {
var re = /(^-?[0-9]+(\.?[0-9]*)[df]?e?[0-9]?$|^0x[0-9a-f]+$|[0-9]+)/gi;
var sre = /(^[ ]*|[ ]*$)/g;
var dre = /(^([\w ]+,?[\w ]+)?[\w ]+,?[\w ]+\d+:\d+(:\d+)?[\w ]?|^\d{1,4}[\/\-]\d{1,4}[\/\-]\d{1,4}|^\w+, \w+ \d+, \d{4})/;
var hre = /^0x[0-9a-f]+$/i;
var ore = /^0/;
// convert all to strings strip whitespace
var x = ('' + val1).replace(sre, '');
var y = ('' + val2).replace(sre, '');
// chunk/tokenize
var xN = x.replace(re, '\0$1\0').replace(/\0$/,'').replace(/^\0/,'').split('\0');
var yN = y.replace(re, '\0$1\0').replace(/\0$/,'').replace(/^\0/,'').split('\0');
// numeric, hex or date detection
var xD = parseInt(x.match(hre), 10) || (xN.length !== 1 && x.match(dre) && Date.parse(x));
var yD = parseInt(y.match(hre), 10) || xD && y.match(dre) && Date.parse(y) || null;
var oFxNcL, oFyNcL;
// first try and sort Hex codes or Dates
if (yD) {
if (xD < yD) {
return -1;
} else if (xD > yD) {
return 1;
}
}
// natural sorting through split numeric strings and default strings
for(var cLoc=0, numS=Math.max(xN.length, yN.length); cLoc < numS; cLoc += 1) {
// find floats not starting with '0', string or 0 if not defined (Clint Priest)
oFxNcL = !(xN[cLoc] || '').match(ore) && parseFloat(xN[cLoc]) || xN[cLoc] || 0;
oFyNcL = !(yN[cLoc] || '').match(ore) && parseFloat(yN[cLoc]) || yN[cLoc] || 0;
// handle numeric vs string comparison - number < string - (Kyle Adams)
if (isNaN(oFxNcL) !== isNaN(oFyNcL)) { return (isNaN(oFxNcL)) ? 1 : -1; }
// rely on string comparison if different types - i.e. '02' < 2 != '02' < '2'
else if (typeof oFxNcL !== typeof oFyNcL) {
oFxNcL += '';
oFyNcL += '';
}
if (oFxNcL < oFyNcL) {
return -1;
}
if (oFxNcL > oFyNcL) {
return 1;
}
}
return 0;
}
return {
regularCmpFn: regularCmpFn,
naturalCmpFn: naturalCmpFn
};
});

View file

@ -1,4 +1,4 @@
modulejs.define('ext/sort', ['_', '$', 'core/settings', 'core/resource', 'core/event', 'core/store'], function (_, $, allsettings, resource, event, store) {
modulejs.define('ext/sort', ['_', '$', 'core/settings', 'core/resource', 'core/event', 'core/store', 'core/util'], function (_, $, allsettings, resource, event, store, util) {
var settings = _.extend({
enabled: false,
@ -58,57 +58,6 @@ modulejs.define('ext/sort', ['_', '$', 'core/settings', 'core/resource', 'core/e
};
// Natural Sort algorithm for Javascript - Version 0.7 - Released under MIT license
// Author: Jim Palmer (based on chunking idea from Dave Koelle)
//
// Modified to make it work with h5ai
function naturalCmpFn(val1, val2) {
var re = /(^-?[0-9]+(\.?[0-9]*)[df]?e?[0-9]?$|^0x[0-9a-f]+$|[0-9]+)/gi;
var sre = /(^[ ]*|[ ]*$)/g;
var dre = /(^([\w ]+,?[\w ]+)?[\w ]+,?[\w ]+\d+:\d+(:\d+)?[\w ]?|^\d{1,4}[\/\-]\d{1,4}[\/\-]\d{1,4}|^\w+, \w+ \d+, \d{4})/;
var hre = /^0x[0-9a-f]+$/i;
var ore = /^0/;
// convert all to strings strip whitespace
var x = ('' + val1).replace(sre, '');
var y = ('' + val2).replace(sre, '');
// chunk/tokenize
var xN = x.replace(re, '\0$1\0').replace(/\0$/,'').replace(/^\0/,'').split('\0');
var yN = y.replace(re, '\0$1\0').replace(/\0$/,'').replace(/^\0/,'').split('\0');
// numeric, hex or date detection
var xD = parseInt(x.match(hre), 10) || (xN.length !== 1 && x.match(dre) && Date.parse(x));
var yD = parseInt(y.match(hre), 10) || xD && y.match(dre) && Date.parse(y) || null;
var oFxNcL, oFyNcL;
// first try and sort Hex codes or Dates
if (yD) {
if (xD < yD) {
return -1;
} else if (xD > yD) {
return 1;
}
}
// natural sorting through split numeric strings and default strings
for(var cLoc=0, numS=Math.max(xN.length, yN.length); cLoc < numS; cLoc += 1) {
// find floats not starting with '0', string or 0 if not defined (Clint Priest)
oFxNcL = !(xN[cLoc] || '').match(ore) && parseFloat(xN[cLoc]) || xN[cLoc] || 0;
oFyNcL = !(yN[cLoc] || '').match(ore) && parseFloat(yN[cLoc]) || yN[cLoc] || 0;
// handle numeric vs string comparison - number < string - (Kyle Adams)
if (isNaN(oFxNcL) !== isNaN(oFyNcL)) { return (isNaN(oFxNcL)) ? 1 : -1; }
// rely on string comparison if different types - i.e. '02' < 2 != '02' < '2'
else if (typeof oFxNcL !== typeof oFyNcL) {
oFxNcL += '';
oFyNcL += '';
}
if (oFxNcL < oFyNcL) {
return -1;
}
if (oFxNcL > oFyNcL) {
return 1;
}
}
return 0;
}
function cmpFn(getValue, reverse, ignorecase, natural) {
return function (item1, item2) {
@ -133,12 +82,7 @@ modulejs.define('ext/sort', ['_', '$', 'core/settings', 'core/resource', 'core/e
}
}
if (natural) {
res = naturalCmpFn(val1, val2);
} else {
res = val1 < val2 ? -1 : (val1 > val2 ? 1 : 0);
}
res = natural ? util.naturalCmpFn(val1, val2) : util.regularCmpFn(val1, val2);
return reverse ? -res : res;
};
}

View file

@ -1,9 +1,10 @@
modulejs.define('ext/tree', ['_', '$', 'core/settings', 'core/resource', 'core/store', 'core/event', 'core/location'], function (_, $, allsettings, resource, store, event, location) {
modulejs.define('ext/tree', ['_', '$', 'core/settings', 'core/resource', 'core/store', 'core/event', 'core/location', 'core/util'], function (_, $, allsettings, resource, store, event, location, util) {
var settings = _.extend({
enabled: false,
show: true,
maxSubfolders: 50
maxSubfolders: 50,
naturalSort: false
}, allsettings.tree);
var template =
'<div class="item">' +
@ -25,6 +26,14 @@ modulejs.define('ext/tree', ['_', '$', 'core/settings', 'core/resource', 'core/s
var storekey = 'ext/tree';
function cmpFn(item1, item2) {
var val1 = item1.label;
var val2 = item2.label;
return settings.natural ? util.naturalCmpFn(val1, val2) : util.regularCmpFn(val1, val2);
}
function update(item) {
var $html = $(template);
@ -66,6 +75,8 @@ modulejs.define('ext/tree', ['_', '$', 'core/settings', 'core/resource', 'core/s
// does it have subfolders?
if (subfolders.length) {
subfolders.sort(cmpFn);
var $ul = $('<ul class="content"/>').appendTo($html);
var counter = 0;
_.each(subfolders, function (e) {

View file

@ -327,10 +327,12 @@ Options
- show: boolean, initial visible to first time users
- maxSubfolders: number, max number of subfolders to show in tree
- naturalSort: boolean, use natural sort order for folders
*/
"tree": {
"enabled": true,
"show": true,
"maxSubfolders": 50
"maxSubfolders": 50,
"naturalSort": false
}
}