From 37422e891a47f15659356ce75b6f6cce831e0041 Mon Sep 17 00:00:00 2001 From: Jo-Philipp Wich Date: Wed, 27 Jul 2022 17:19:08 +0200 Subject: [PATCH] luci-base: revise array sorting Refactor various sort operations throughout luci-base to use the new L.naturalCompare() comparator function. This primarily ensures that embedded numbers are sorted numerically and not in a lexicographical way. It also simplifies some code as a side effect. Ref: #5899 Signed-off-by: Jo-Philipp Wich --- .../htdocs/luci-static/resources/form.js | 12 ++--- .../htdocs/luci-static/resources/network.js | 52 +++++-------------- .../luci-static/resources/tools/widgets.js | 2 +- .../htdocs/luci-static/resources/ui.js | 25 +++------ 4 files changed, 25 insertions(+), 66 deletions(-) diff --git a/modules/luci-base/htdocs/luci-static/resources/form.js b/modules/luci-base/htdocs/luci-static/resources/form.js index aae8b3684a..2d540420bc 100644 --- a/modules/luci-base/htdocs/luci-static/resources/form.js +++ b/modules/luci-base/htdocs/luci-static/resources/form.js @@ -74,7 +74,7 @@ var CBIJSONConfig = baseclass.extend({ if (indexA != indexB) return (indexA - indexB); - return (a > b); + return L.naturalCompare(a, b); }, this)); for (var i = 0; i < section_ids.length; i++) @@ -3080,13 +3080,9 @@ var CBITableSection = CBITypedSection.extend(/** @lends LuCI.form.TableSection.p }, this)); list.sort(function(a, b) { - if (a[0] < b[0]) - return descending ? 1 : -1; - - if (a[0] > b[0]) - return descending ? -1 : 1; - - return 0; + return descending + ? -L.naturalCompare(a[0], b[0]) + : L.naturalCompare(a[0], b[0]); }); window.requestAnimationFrame(L.bind(function() { diff --git a/modules/luci-base/htdocs/luci-static/resources/network.js b/modules/luci-base/htdocs/luci-static/resources/network.js index 864cbba52c..e0013c8ec0 100644 --- a/modules/luci-base/htdocs/luci-static/resources/network.js +++ b/modules/luci-base/htdocs/luci-static/resources/network.js @@ -101,15 +101,6 @@ var _init = null, _protocols = {}, _protospecs = {}; -function strcmp(a, b) { - if (a > b) - return 1; - else if (a < b) - return -1; - else - return 0; -} - function getProtocolHandlers(cache) { return callNetworkProtoHandlers().then(function(protos) { /* Register "none" protocol */ @@ -485,10 +476,7 @@ function initNetworkState(refresh) { } ports.sort(function(a, b) { - if (a.role != b.role) - return (a.role < b.role) ? -1 : 1; - - return (a.index - b.index); + return L.naturalCompare(a.role, b.role) || L.naturalCompare(a.index, b.index); }); for (var i = 0, port; (port = ports[i]) != null; i++) { @@ -562,18 +550,14 @@ function ifnameOf(obj) { } function networkSort(a, b) { - return strcmp(a.getName(), b.getName()); + return L.naturalCompare(a.getName(), b.getName()); } function deviceSort(a, b) { - var typeWeigth = { wifi: 2, alias: 3 }, - weightA = typeWeigth[a.getType()] || 1, - weightB = typeWeigth[b.getType()] || 1; - - if (weightA != weightB) - return weightA - weightB; + var typeWeigth = { wifi: 2, alias: 3 }; - return strcmp(a.getName(), b.getName()); + return L.naturalCompare(typeWeigth[a.getType()] || 1, typeWeigth[b.getType()] || 1) || + L.naturalCompare(a.getName(), b.getName()); } function formatWifiEncryption(enc) { @@ -1441,7 +1425,7 @@ Network = baseclass.extend(/** @lends LuCI.network.prototype */ { rv.push(this.lookupWifiNetwork(wifiIfaces[i]['.name'])); rv.sort(function(a, b) { - return strcmp(a.getID(), b.getID()); + return L.naturalCompare(a.getID(), b.getID()); }); return rv; @@ -1539,10 +1523,7 @@ Network = baseclass.extend(/** @lends LuCI.network.prototype */ { } rv.sort(function(a, b) { - if (a.metric != b.metric) - return (a.metric - b.metric); - - return strcmp(a.interface, b.interface); + return L.naturalCompare(a.metric, b.metric) || L.naturalCompare(a.interface, b.interface); }); return rv; @@ -1990,7 +1971,7 @@ Hosts = baseclass.extend(/** @lends LuCI.network.Hosts.prototype */ { } return rv.sort(function(a, b) { - return strcmp(a[0], b[0]); + return L.naturalCompare(a[0], b[0]); }); } }); @@ -3419,19 +3400,10 @@ WifiDevice = baseclass.extend(/** @lends LuCI.network.WifiDevice.prototype */ { if (this.ubus('dev', 'iwinfo', 'type') == 'wl') type = 'Broadcom'; - var hwmodes = this.getHWModes(), - modestr = ''; - - hwmodes.sort(function(a, b) { - if (a.length != b.length) - return a.length - b.length; - - return strcmp(a, b); - }); - - modestr = hwmodes.join(''); - - return '%s 802.11%s Wireless Controller (%s)'.format(type || 'Generic', modestr, this.getName()); + return '%s 802.11%s Wireless Controller (%s)'.format( + type || 'Generic', + this.getHWModes().sort(L.naturalCompare).join(''), + this.getName()); }, /** diff --git a/modules/luci-base/htdocs/luci-static/resources/tools/widgets.js b/modules/luci-base/htdocs/luci-static/resources/tools/widgets.js index ae17d8197d..14948bbf0f 100644 --- a/modules/luci-base/htdocs/luci-static/resources/tools/widgets.js +++ b/modules/luci-base/htdocs/luci-static/resources/tools/widgets.js @@ -537,7 +537,7 @@ var CBIDeviceSelect = form.ListValue.extend({ } if (!this.nocreate) { - var keys = Object.keys(checked).sort(); + var keys = Object.keys(checked).sort(L.naturalCompare); for (var i = 0; i < keys.length; i++) { if (choices.hasOwnProperty(keys[i])) diff --git a/modules/luci-base/htdocs/luci-static/resources/ui.js b/modules/luci-base/htdocs/luci-static/resources/ui.js index 2c4a9bf395..ef6e334216 100644 --- a/modules/luci-base/htdocs/luci-static/resources/ui.js +++ b/modules/luci-base/htdocs/luci-static/resources/ui.js @@ -777,7 +777,7 @@ var UISelect = UIElement.extend(/** @lends LuCI.ui.Select.prototype */ { keys = Object.keys(this.choices); if (this.options.sort === true) - keys.sort(); + keys.sort(L.naturalCompare); else if (Array.isArray(this.options.sort)) keys = this.options.sort; @@ -1056,7 +1056,7 @@ var UIDropdown = UIElement.extend(/** @lends LuCI.ui.Dropdown.prototype */ { var keys = Object.keys(this.choices); if (this.options.sort === true) - keys.sort(); + keys.sort(L.naturalCompare); else if (Array.isArray(this.options.sort)) keys = this.options.sort; @@ -2859,13 +2859,8 @@ var UIFileUpload = UIElement.extend(/** @lends LuCI.ui.FileUpload.prototype */ { rows = E('ul'); list.sort(function(a, b) { - var isDirA = (a.type == 'directory'), - isDirB = (b.type == 'directory'); - - if (isDirA != isDirB) - return isDirA < isDirB; - - return a.name > b.name; + return L.naturalCompare(a.type == 'directory', b.type == 'directory') || + L.naturalCompare(a.name, b.name); }); for (var i = 0; i < list.length; i++) { @@ -3152,7 +3147,7 @@ var UIMenu = baseclass.singleton(/** @lends LuCI.ui.menu.prototype */ { if (wA != wB) return wA - wB; - return a.name > b.name; + return L.naturalCompare(a.name, b.name); }); } }); @@ -3220,13 +3215,9 @@ var UITable = baseclass.extend(/** @lends LuCI.ui.table.prototype */ { }, this)); list.sort(function(a, b) { - if (a[0] < b[0]) - return sorting[1] ? 1 : -1; - - if (a[0] > b[0]) - return sorting[1] ? -1 : 1; - - return 0; + return sorting[1] + ? -L.naturalCompare(a[0], b[0]) + : L.naturalCompare(a[0], b[0]); }); data.length = 0; -- 2.30.2