From d8ed1e7b7dc3965355a8aaa34e8e2cb9fd7c5d74 Mon Sep 17 00:00:00 2001 From: Jo-Philipp Wich Date: Thu, 24 Feb 2022 16:48:00 +0100 Subject: [PATCH] luci-base: form.js: add column sorting to TableSections and GridSections Add ability to reorder TableSection and GridSection rows by clicking on column headers. Signed-off-by: Jo-Philipp Wich --- .../htdocs/luci-static/resources/form.js | 68 ++++++++++++++++++- 1 file changed, 66 insertions(+), 2 deletions(-) diff --git a/modules/luci-base/htdocs/luci-static/resources/form.js b/modules/luci-base/htdocs/luci-static/resources/form.js index 23cc0b1cb5..c17f8ff0ca 100644 --- a/modules/luci-base/htdocs/luci-static/resources/form.js +++ b/modules/luci-base/htdocs/luci-static/resources/form.js @@ -2615,7 +2615,8 @@ var CBITableSection = CBITypedSection.extend(/** @lends LuCI.form.TableSection.p if (has_titles) { var trEl = E('tr', { 'class': 'tr cbi-section-table-titles ' + anon_class, - 'data-title': (!this.anonymous || this.sectiontitle) ? _('Name') : null + 'data-title': (!this.anonymous || this.sectiontitle) ? _('Name') : null, + 'click': this.sortable ? ui.createHandlerFn(this, 'handleSort') : null }); for (var i = 0, opt; i < max_cols && (opt = this.children[i]) != null; i++) { @@ -2624,7 +2625,8 @@ var CBITableSection = CBITypedSection.extend(/** @lends LuCI.form.TableSection.p trEl.appendChild(E('th', { 'class': 'th cbi-section-table-cell', - 'data-widget': opt.__name__ + 'data-widget': opt.__name__, + 'data-sortable-row': this.sortable ? '' : null })); if (opt.width != null) @@ -3034,6 +3036,68 @@ var CBITableSection = CBITypedSection.extend(/** @lends LuCI.form.TableSection.p .catch(function() {}); }, + /** @private */ + handleSort: function(ev) { + if (!ev.target.matches('th[data-sortable-row]')) + return; + + var th = ev.target, + descending = (th.getAttribute('data-sort-direction') == 'desc'), + config_name = this.uciconfig || this.map.config, + index = 0, + list = []; + + ev.currentTarget.querySelectorAll('th').forEach(function(other_th, i) { + if (other_th !== th) + other_th.removeAttribute('data-sort-direction'); + else + index = i; + }); + + ev.currentTarget.parentNode.querySelectorAll('tr.cbi-section-table-row').forEach(L.bind(function(tr, i) { + var sid = tr.getAttribute('data-sid'), + opt = tr.childNodes[index].getAttribute('data-name'), + val = this.cfgvalue(sid, opt); + + tr.querySelectorAll('.flash').forEach(function(n) { + n.classList.remove('flash') + }); + + list.push([ + ui.Table.prototype.deriveSortKey((val != null) ? val.trim() : ''), + tr + ]); + }, 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; + }); + + window.requestAnimationFrame(L.bind(function() { + var ref_sid, cur_sid; + + for (var i = 0; i < list.length; i++) { + list[i][1].childNodes[index].classList.add('flash'); + th.parentNode.parentNode.appendChild(list[i][1]); + + cur_sid = list[i][1].getAttribute('data-sid'); + + if (ref_sid) + this.map.data.move(config_name, cur_sid, ref_sid, true); + + ref_sid = cur_sid; + } + + th.setAttribute('data-sort-direction', descending ? 'asc' : 'desc'); + }, this)); + }, + /** * Add further options to the per-section instanced modal popup. * -- 2.30.2