Clean sort code.
This commit is contained in:
parent
73e74bb887
commit
8485905901
4 changed files with 51 additions and 78 deletions
|
@ -345,7 +345,7 @@
|
|||
"column": 0,
|
||||
"reverse": false,
|
||||
"ignorecase": true,
|
||||
"natural": false,
|
||||
"natural": true,
|
||||
"folders": 0
|
||||
},
|
||||
|
||||
|
@ -390,7 +390,7 @@
|
|||
"enabled": true,
|
||||
"show": true,
|
||||
"maxSubfolders": 50,
|
||||
"naturalSort": false,
|
||||
"naturalSort": true,
|
||||
"ignorecase": true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,51 +13,25 @@ const settings = Object.assign({
|
|||
folders: 0
|
||||
}, allsettings.sort);
|
||||
const storekey = 'ext/sort';
|
||||
const template = '<img src="' + resource.image('sort') + '" class="sort" alt="sort order"/>';
|
||||
const template = `<img src="${resource.image('sort')}" class="sort" alt="sort order"/>`;
|
||||
|
||||
const getTypeOrder = item => item.isFolder() ? settings.folders : 1;
|
||||
const columnProps = {0: 'label', 1: 'time', 2: 'size'};
|
||||
const columnClasses = {0: 'label', 1: 'date', 2: 'size'};
|
||||
|
||||
|
||||
const getType = item => {
|
||||
const $item = dom(item);
|
||||
const cmpFn = (prop, reverse, ignorecase, natural) => {
|
||||
return (el1, el2) => {
|
||||
const item1 = el1._item;
|
||||
const item2 = el2._item;
|
||||
|
||||
if ($item.hasCls('folder-parent')) {
|
||||
return 0;
|
||||
}
|
||||
if ($item.hasCls('folder')) {
|
||||
if (settings.folders === 1) {
|
||||
return 2;
|
||||
} else if (settings.folders === 2) {
|
||||
return 3;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return 2;
|
||||
};
|
||||
|
||||
const columnGetters = {
|
||||
0: el => el._item.label,
|
||||
1: el => el._item.time,
|
||||
2: el => el._item.size
|
||||
};
|
||||
const columnClasses = {
|
||||
0: 'label',
|
||||
1: 'date',
|
||||
2: 'size'
|
||||
};
|
||||
|
||||
|
||||
const cmpFn = (getValue, reverse, ignorecase, natural) => {
|
||||
return (item1, item2) => {
|
||||
let res;
|
||||
let val1;
|
||||
let val2;
|
||||
|
||||
res = getType(item1) - getType(item2);
|
||||
let res = getTypeOrder(item1) - getTypeOrder(item2);
|
||||
if (res !== 0) {
|
||||
return res;
|
||||
}
|
||||
|
||||
val1 = getValue(item1);
|
||||
val2 = getValue(item2);
|
||||
let val1 = item1[prop];
|
||||
let val2 = item2[prop];
|
||||
|
||||
if (isNaN(val1) || isNaN(val2)) {
|
||||
val1 = String(val1);
|
||||
|
@ -77,14 +51,14 @@ const cmpFn = (getValue, reverse, ignorecase, natural) => {
|
|||
const sortItems = (column, reverse) => {
|
||||
const $headers = dom('#items li.header a');
|
||||
const $header = dom('#items li.header a.' + columnClasses[column]);
|
||||
const fn = cmpFn(columnGetters[column], reverse, settings.ignorecase, column === 0 && settings.natural);
|
||||
const fn = cmpFn(columnProps[column], reverse, settings.ignorecase, settings.natural);
|
||||
|
||||
store.put(storekey, {column, reverse});
|
||||
|
||||
$headers.rmCls('ascending').rmCls('descending');
|
||||
$header.addCls(reverse ? 'descending' : 'ascending');
|
||||
|
||||
dom(toArray(dom('#items .item')).sort(fn)).appTo('#items');
|
||||
dom(toArray(dom('#items .item:not(.folder-parent)')).sort(fn)).appTo('#items');
|
||||
};
|
||||
|
||||
const onContentChanged = () => {
|
||||
|
@ -101,11 +75,11 @@ const addToggles = () => {
|
|||
each(columnClasses, (cls, idx) => {
|
||||
const pos = idx === '0' ? 'app' : 'pre';
|
||||
$header
|
||||
.find('a.' + cls)[pos](template)
|
||||
.on('click', ev => {
|
||||
sortItems(idx, dom(ev.currentTarget).hasCls('ascending'));
|
||||
ev.preventDefault();
|
||||
});
|
||||
.find('a.' + cls)[pos](template)
|
||||
.on('click', ev => {
|
||||
sortItems(idx, dom(ev.currentTarget).hasCls('ascending'));
|
||||
ev.preventDefault();
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
@ -66,7 +66,7 @@ const cmpItems = (item1, item2) => {
|
|||
val2 = val2.toLowerCase();
|
||||
}
|
||||
|
||||
return settings.natural ? naturalCmp(val1, val2) : regularCmp(val1, val2);
|
||||
return settings.naturalSort ? naturalCmp(val1, val2) : regularCmp(val1, val2);
|
||||
};
|
||||
|
||||
const update = item => {
|
||||
|
|
|
@ -3,58 +3,57 @@
|
|||
|
||||
// Modified to make it work with h5ai
|
||||
|
||||
|
||||
const re = /(^-?[0-9]+(\.?[0-9]*)[df]?e?[0-9]?$|^0x[0-9a-f]+$|[0-9]+)/gi;
|
||||
const reStrip = /(^[ ]*|[ ]*$)/g;
|
||||
const dre = /(^([\w ]+,?[\w ]+)?[\w ]+,?[\w ]+\d+:\d+(:\d+)?[\w ]?|^\d{1,4}[\/\-]\d{1,4}[\/\-]\d{1,4}|^\w+, \w+ \d+, \d{4})/;
|
||||
const reToken = /(^([+\-]?(?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][+\-]?\d+)?)?$|^0x[0-9a-f]+$|\d+)/gi;
|
||||
const reDate = /(^([\w ]+,?[\w ]+)?[\w ]+,?[\w ]+\d+:\d+(:\d+)?[\w ]?|^\d{1,4}[\/\-]\d{1,4}[\/\-]\d{1,4}|^\w+, \w+ \d+, \d{4})/;
|
||||
const reHex = /^0x[0-9a-f]+$/i;
|
||||
const reLeadingZero = /^0/;
|
||||
|
||||
/* eslint-disable complexity */
|
||||
const naturalCmp = (val1, val2) => {
|
||||
const naturalCmp = (a, b) => {
|
||||
// convert all to strings strip whitespace
|
||||
const x = String(val1).replace(reStrip, '');
|
||||
const y = String(val2).replace(reStrip, '');
|
||||
// chunk/tokenize
|
||||
const xN = x.replace(re, '\0$1\0').replace(/\0$/, '').replace(/^\0/, '').split('\0');
|
||||
const yN = y.replace(re, '\0$1\0').replace(/\0$/, '').replace(/^\0/, '').split('\0');
|
||||
// numeric, hex or date detection
|
||||
const xD = parseInt(x.match(reHex), 10) || xN.length !== 1 && x.match(dre) && Date.parse(x);
|
||||
const yD = parseInt(y.match(reHex), 10) || xD && y.match(dre) && Date.parse(y) || null;
|
||||
const x = String(a).trim();
|
||||
const y = String(b).trim();
|
||||
|
||||
let oFxNcL;
|
||||
let oFyNcL;
|
||||
// chunk/tokenize
|
||||
const xTokens = x.replace(reToken, '\0$1\0').replace(/\0$/, '').replace(/^\0/, '').split('\0');
|
||||
const yTokens = y.replace(reToken, '\0$1\0').replace(/\0$/, '').replace(/^\0/, '').split('\0');
|
||||
|
||||
// first try and sort Hex codes or Dates
|
||||
if (yD) {
|
||||
if (xD < yD) {
|
||||
const xDate = parseInt(x.match(reHex), 16) || xTokens.length !== 1 && x.match(reDate) && Date.parse(x);
|
||||
const yDate = parseInt(y.match(reHex), 16) || xDate && y.match(reDate) && Date.parse(y) || null;
|
||||
if (yDate) {
|
||||
if (xDate < yDate) {
|
||||
return -1;
|
||||
} else if (xD > yD) {
|
||||
}
|
||||
if (xDate > yDate) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// natural sorting through split numeric strings and default strings
|
||||
for (let cLoc = 0, numS = Math.max(xN.length, yN.length); cLoc < numS; cLoc += 1) {
|
||||
for (let idx = 0, len = Math.max(xTokens.length, yTokens.length); idx < len; idx += 1) {
|
||||
// find floats not starting with '0', string or 0 if not defined (Clint Priest)
|
||||
oFxNcL = !(xN[cLoc] || '').match(reLeadingZero) && parseFloat(xN[cLoc]) || xN[cLoc] || 0;
|
||||
oFyNcL = !(yN[cLoc] || '').match(reLeadingZero) && parseFloat(yN[cLoc]) || yN[cLoc] || 0;
|
||||
let xToken = !(xTokens[idx] || '').match(reLeadingZero) && parseFloat(xTokens[idx]) || xTokens[idx] || 0;
|
||||
let yToken = !(yTokens[idx] || '').match(reLeadingZero) && parseFloat(yTokens[idx]) || yTokens[idx] || 0;
|
||||
|
||||
// handle numeric vs string comparison - number < string - (Kyle Adams)
|
||||
if (isNaN(oFxNcL) !== isNaN(oFyNcL)) {
|
||||
return isNaN(oFxNcL) ? 1 : -1;
|
||||
} else if (typeof oFxNcL !== typeof oFyNcL) {
|
||||
// rely on string comparison if different types - i.e. '02' < 2 != '02' < '2'
|
||||
oFxNcL = String(oFxNcL);
|
||||
oFxNcL = String(oFxNcL);
|
||||
if (isNaN(xToken) !== isNaN(yToken)) {
|
||||
return isNaN(xToken) ? 1 : -1;
|
||||
}
|
||||
if (oFxNcL < oFyNcL) {
|
||||
|
||||
// rely on string comparison if different types - i.e. '02' < 2 != '02' < '2'
|
||||
if (typeof xToken !== typeof yToken) {
|
||||
xToken = String(xToken);
|
||||
yToken = String(yToken);
|
||||
}
|
||||
|
||||
if (xToken < yToken) {
|
||||
return -1;
|
||||
}
|
||||
if (oFxNcL > oFyNcL) {
|
||||
if (xToken > yToken) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
};
|
||||
/* eslint-enable */
|
||||
|
|
Loading…
Add table
Reference in a new issue