From 3081f667f7caad53a05359d2b5f76d5b91a94ad7 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sun, 30 Sep 2018 00:29:29 +0200 Subject: [PATCH] Add simple sorting for tables --- UI/Component/Form.js | 5 +- UI/Component/Table.js | 104 +++++++++++++++++++++++++++++++++++++----- UI/UIManager.js | 2 +- Utils/UiUtils.js | 10 +++- Utils/oLib.js | 5 +- Views/FormView.js | 6 ++- Views/TableView.js | 56 +++++++++++------------ 7 files changed, 142 insertions(+), 46 deletions(-) diff --git a/UI/Component/Form.js b/UI/Component/Form.js index 3a9cf4e..31e310f 100644 --- a/UI/Component/Form.js +++ b/UI/Component/Form.js @@ -78,8 +78,9 @@ length = !forms ? 0 : forms.length; for (let i = 0; i < length; ++i) { - if (typeof forms[i].getAttribute('id') !== 'undefined' && forms[i].getAttribute('id') !== null && typeof this.ignore[forms[i].getAttribute('id')] === 'undefined') { - this.bindForm(forms[i].getAttribute('id')); + let formId = forms[i].getAttribute('id'); + if (typeof formId !== 'undefined' && formId !== null && typeof this.ignore[formId] === 'undefined') { + this.bindForm(formId); } } } diff --git a/UI/Component/Table.js b/UI/Component/Table.js index 276197d..c9b9481 100644 --- a/UI/Component/Table.js +++ b/UI/Component/Table.js @@ -18,9 +18,11 @@ * * @since 1.0.0 */ - constructor(responseManager) + constructor(app) { - this.responseManager = responseManager; + this.app = app; + this.tables = {}; + this.ignore = {}; }; /** @@ -34,33 +36,113 @@ */ bind (id) { - if (typeof id !== 'undefined') { - const e = document.getElementById(id); - - if (e) { - this.bindElement(e); - } + if (typeof id !== 'undefined' && typeof this.ignore[id] === 'undefined') { + this.bindTable(id); } else { const tables = document.getElementsByTagName('table'), length = !tables ? 0 : tables.length; for (let i = 0; i < length; ++i) { - this.bindElement(tables[i]); + let tableId = tables[i].getAttribute('id'); + if (typeof tableId !== 'undefined' && tableId !== null && typeof this.ignore[tableId] === 'undefined') { + this.bindTable(tableId); + } } } }; + /** + * Unbind table + * + * @param {string} id Table Id + * + * @since 1.0.0 + */ + unbind (id) + { + + }; + /** * Bind & rebind UI element. * - * @param {Object} [e] Element id + * @param {Object} [id] Element id * * @method * * @since 1.0.0 */ - bindElement (e) + bindTable (id) { + if (typeof id === 'undefined' || !id) { + jsOMS.Log.Logger.instance.info('A table doesn\'t have an ID.'); + return; + } + + const self = this; + this.tables[id] = new jsOMS.Views.TableView(id); + + this.unbind(id); + + // todo: sorting: increasing / decreasing only if icons are available + // todo: filtering: equals (alphanumeric), greater, greater equals, lesser, lesser equals, contains, doesn't contain, excel like selection of elements. Amount of filtering options unlimited. + // cell value should be data-value="" and cell name should be data-name="" and cell content should be data-content="". + // if no value is defined than data-value = cell content. if no name is defined then data-name = cell content. if no content is defined then data-content = cell content. + + const sorting = this.tables[id].getSorting(); + let length = sorting.length; + + for (let i = 0; i < length; ++i) { + sorting[i].addEventListener('click', function (event) + { + jsOMS.preventAll(event); + + const table = document.getElementById(id), + rows = table.rows, + rowLength = rows.length, + cellId = this.closest('td').cellIndex; + + let j, row1, row2, content1, content2, + order = false, + shouldSwitch = false; + + do { + order = false; + + for (j = 1; j < rowLength - 1; ++j) { + shouldSwitch = false; + row1 = rows[j].getElementsByTagName('td')[cellId]; + row2 = rows[j + 1].getElementsByTagName('td')[cellId]; + content1 = row1.getAttribute('data-content') !== null ? row1.getAttribute('data-content') : row1.textContent; + content2 = row2.getAttribute('data-content') !== null ? row2.getAttribute('data-content') : row2.textContent; + + if (jsOMS.hasClass(this, 'sort-asc') && content1 > content2) { + shouldSwitch = true; + break; + } else if (jsOMS.hasClass(this, 'sort-desc') && content1 < content2) { + shouldSwitch = true; + break; + } + } + + if (shouldSwitch) { + rows[j].parentNode.insertBefore(rows[j + 1], rows[j]); + order = true; + } + } while (order); + }); + } + + const filters = this.tables[id].getFilter(); + length = filters.length; + + for (let i = 0; i < length; ++i) { + filters[i].addEventListener('click', function (event) + { + jsOMS.preventAll(event); + // filter algorithm here + }); + } }; } }(window.jsOMS = window.jsOMS || {})); diff --git a/UI/UIManager.js b/UI/UIManager.js index 8e41dc0..ca3a4dd 100644 --- a/UI/UIManager.js +++ b/UI/UIManager.js @@ -26,7 +26,7 @@ this.app = app; this.formManager = new jsOMS.UI.Component.Form(this.app); this.tabManager = new jsOMS.UI.Component.Tab(this.app.responseManager); - this.tableManager = new jsOMS.UI.Component.Table(this.app.responseManager); + this.tableManager = new jsOMS.UI.Component.Table(this.app); this.actionManager = new jsOMS.UI.ActionManager(this.app); this.dragNDrop = new jsOMS.UI.DragNDrop(this.app); this.generalUI = new jsOMS.UI.GeneralUI(); diff --git a/Utils/UiUtils.js b/Utils/UiUtils.js index 2ec9a5d..ac02deb 100644 --- a/Utils/UiUtils.js +++ b/Utils/UiUtils.js @@ -28,7 +28,10 @@ */ jsOMS.hasClass = function (ele, cls) { - return typeof ele !== 'undefined' && ele !== null && typeof ele.className !== 'undefined' && ele.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)')); + return typeof ele !== 'undefined' + && ele !== null + && typeof ele.className !== 'undefined' + && ele.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)')) !== null; }; /** @@ -106,7 +109,10 @@ jsOMS.ready = function (func) { // TODO: IE problems? + Maybe interactive + loaded can cause problems since elements might not be loaded yet?!!?!!?! - if (document.readyState === 'complete' || document.readyState === 'loaded' || document.readyState === 'interactive') { + if (document.readyState === 'complete' + || document.readyState === 'loaded' + || document.readyState === 'interactive' + ) { func(); } else { document.addEventListener("DOMContentLoaded", function (event) diff --git a/Utils/oLib.js b/Utils/oLib.js index b2b3b42..adb5f20 100644 --- a/Utils/oLib.js +++ b/Utils/oLib.js @@ -150,7 +150,10 @@ */ jsOMS.hasClass = function (ele, cls) { - return typeof ele !== 'undefined' && ele !== null && typeof ele.className !== 'undefined' && ele.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)')); + return typeof ele !== 'undefined' + && ele !== null + && typeof ele.className !== 'undefined' + && ele.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)')) !== null; }; /** diff --git a/Views/FormView.js b/Views/FormView.js index b7bcb91..877c830 100644 --- a/Views/FormView.js +++ b/Views/FormView.js @@ -92,7 +92,11 @@ */ getSubmit () { - return document.querySelectorAll('#' + this.id + ' input[type=submit], button[form=' + this.id + '][type=submit], #' + this.id + ' button[type=submit]'); + return document.querySelectorAll( + '#' + this.id + ' input[type=submit],' + + ' button[form=' + this.id + '][type=submit],' + + ' #' + this.id + ' button[type=submit]' + ); }; /** diff --git a/Views/TableView.js b/Views/TableView.js index 6fb6c18..349e420 100644 --- a/Views/TableView.js +++ b/Views/TableView.js @@ -1,40 +1,40 @@ (function (jsOMS) { "use strict"; - jsOMS.TableView = class { - constructor () { - this.table = null; + jsOMS.Autoloader.defineNamespace('jsOMS.Views'); + + jsOMS.Views.TableView = class { + constructor (id) { + this.id = id; + + this.bind(); + }; + + bind () + { + const e = document.getElementById(this.id); }; /** - * None, Pagination, Infinite + * Get sorting elements + * + * @return {Object} + * + * @since 1.0.0 */ - setExtensible () { - + getSorting() + { + return document.querySelectorAll( + '#' + this.id + ' thead .sort-asc,' + + ' #' + this.id + ' thead .sort-desc' + ); }; - add (element) { - - }; - - addCollection (collection) { - - }; - - remove (id) { - - }; - - get (id) { - - }; - - filter (id) { - - }; - - request (filter) { - + getFilter() + { + return document.querySelectorAll( + '#' + this.id + ' thead .filter' + ); }; } }(window.jsOMS = window.jsOMS || {}));