From 46cadeb6385f21be1324e3a03c48fef9f611232a Mon Sep 17 00:00:00 2001 From: aalimaslam <133842400+aalimaslam-mm@users.noreply.github.com> Date: Sun, 6 Aug 2023 15:08:57 +0530 Subject: [PATCH] optimize --- src/internal.js | 1029 ++++++++++++++++++++--------------------------- 1 file changed, 443 insertions(+), 586 deletions(-) diff --git a/src/internal.js b/src/internal.js index 9b9bba4..c9094ac 100644 --- a/src/internal.js +++ b/src/internal.js @@ -31,11 +31,7 @@ function findFooterAndHeaderItems(selector) return $.merge(footer, header); } -function getParams(context) -{ - return (context) ? $.extend({}, this.cachedParams, { ctx: context }) : - this.cachedParams; -} +const getParams = (context)=> (context) ? $.extend({}, this.cachedParams, { ctx: context }) : this.cachedParams; function getRequest() { @@ -51,14 +47,10 @@ function getRequest() return this.options.requestHandler($.extend(true, request, post)); } -function getCssSelector(css) -{ - return "." + $.trim(css).replace(/\s+/gm, "."); -} +const getCssSelector = (css)=> "." + $.trim(css).replace(/\s+/gm, "."); -function getUrl() -{ - var url = this.options.url; +const getUrl = ()=>{ + const url = this.options.url; return ($.isFunction(url)) ? url() : url; } @@ -85,63 +77,48 @@ function highlightAppendedRows(rows) // todo: implement } } - -function isVisible(column) -{ - return column.visible; -} - -function loadColumns() -{ - var that = this, - firstHeadRow = this.element.find("thead > tr").first(), - sorted = false; - - /*jshint -W018*/ - firstHeadRow.children().each(function () - { - var $this = $(this), - data = $this.data(), - column = { - id: data.columnId, - identifier: that.identifier == null && data.identifier || false, - converter: that.options.converters[data.converter || data.type] || that.options.converters["string"], - text: $this.text(), - align: data.align || "left", - headerAlign: data.headerAlign || "left", - cssClass: data.cssClass || "", - headerCssClass: data.headerCssClass || "", - formatter: that.options.formatters[data.formatter] || null, - order: (!sorted && (data.order === "asc" || data.order === "desc")) ? data.order : null, - searchable: !(data.searchable === false), // default: true - sortable: !(data.sortable === false), // default: true - visible: !(data.visible === false), // default: true - visibleInSelection: !(data.visibleInSelection === false), // default: true - width: ($.isNumeric(data.width)) ? data.width + "px" : - (typeof(data.width) === "string") ? data.width : null - }; +const isVisible = (column)=> column.visible; + +function loadColumns() { + const that = this; + const firstHeadRow = this.element.find("thead > tr").first(); + + firstHeadRow.children().each(function () { + const $this = $(this); + const data = $this.data(); + const column = { + id: data.columnId, + identifier: that.identifier == null && data.identifier || false, + converter: that.options.converters[data.converter || data.type] || that.options.converters["string"], + text: $this.text(), + align: data.align || "left", + headerAlign: data.headerAlign || "left", + cssClass: data.cssClass || "", + headerCssClass: data.headerCssClass || "", + formatter: that.options.formatters[data.formatter] || null, + order: data.order != null ? data.order : null, + searchable: data.searchable !== false, // default: true + sortable: data.sortable !== false, // default: true + visible: data.visible !== false, // default: true + visibleInSelection: data.visibleInSelection !== false, // default: true + width: data.width || null + }; that.columns.push(column); - if (column.order != null) - { - that.sortDictionary[column.id] = column.order; - } // Prevents multiple identifiers - if (column.identifier) - { + if (column.identifier) { that.identifier = column.id; that.converter = column.converter; } - // ensures that only the first order will be applied in case of multi sorting is disabled - if (!that.options.multiSort && column.order !== null) - { - sorted = true; + // Update the sortDictionary + if (column.order != null) { + that.sortDictionary[column.id] = column.order; } }); - /*jshint +W018*/ } + /* response = { current: 1, @@ -152,24 +129,23 @@ response = { } */ -function loadData() -{ - var that = this; +function loadData() { + const that = this; + const options = this.options; + const searchPhrase = this.searchPhrase; + const current = this.current; this.element._bgBusyAria(true).trigger("load" + namespace); showLoading.call(this); - function containsPhrase(row) - { - var column, - searchPattern = new RegExp(that.searchPhrase, (that.options.caseSensitive) ? "g" : "gi"); + function containsPhrase(row) { + const columns = that.columns; + const searchPattern = new RegExp(searchPhrase, options.caseSensitive ? "g" : "gi"); - for (var i = 0; i < that.columns.length; i++) - { - column = that.columns[i]; + for (let i = 0; i < columns.length; i++) { + const column = columns[i]; if (column.searchable && column.visible && - column.converter.to(row[column.id]).search(searchPattern) > -1) - { + column.converter.to(row[column.id]).search(searchPattern) > -1) { return true; } } @@ -177,13 +153,11 @@ function loadData() return false; } - function update(rows, total) - { + function update(rows, total) { that.currentRows = rows; setTotals.call(that, total); - if (!that.options.keepSelection) - { + if (!options.keepSelection) { that.selectedRows = []; } @@ -194,87 +168,80 @@ function loadData() that.element._bgBusyAria(false).trigger("loaded" + namespace); } - if (this.options.ajax) - { - var request = getRequest.call(this), - url = getUrl.call(this); + if (options.ajax) { + const request = getRequest.call(this); + const url = getUrl.call(this); - if (url == null || typeof url !== "string" || url.length === 0) - { - throw new Error("Url setting must be a none empty string or a function that returns one."); + if (!url || typeof url !== "string" || url.length === 0) { + throw new Error("Url setting must be a non-empty string or a function that returns one."); } // aborts the previous ajax request if not already finished or failed - if (this.xqr) - { + if (this.xqr) { this.xqr.abort(); } - var settings = { + const ajaxSettings = $.extend({}, options.ajaxSettings, { url: url, data: request, - success: function(response) - { + success: function (response) { that.xqr = null; - if (typeof (response) === "string") - { + if (typeof response === "string") { response = $.parseJSON(response); } - response = that.options.responseHandler(response); + response = options.responseHandler(response); that.current = response.current; update(response.rows, response.total); }, - error: function (jqXHR, textStatus, errorThrown) - { + error: function (jqXHR, textStatus, errorThrown) { that.xqr = null; - if (textStatus !== "abort") - { + if (textStatus !== "abort") { renderNoResultsRow.call(that); // overrides loading mask that.element._bgBusyAria(false).trigger("loaded" + namespace); } } - }; - settings = $.extend(this.options.ajaxSettings, settings); + }); - this.xqr = $.ajax(settings); - } - else - { - var rows = (this.searchPhrase.length > 0) ? this.rows.where(containsPhrase) : this.rows, + this.xqr = $.ajax(ajaxSettings); + } else { + let rows = this.rows; + let total = rows.length; + + if (searchPhrase.length > 0) { + rows = rows.where(containsPhrase); total = rows.length; - if (this.rowCount !== -1) - { - rows = rows.page(this.current, this.rowCount); } - // todo: improve the following comment + if (this.rowCount !== -1) { + rows = rows.page(current, this.rowCount); + } + // setTimeout decouples the initialization so that adding event handlers happens before - window.setTimeout(function () { update(rows, total); }, 10); + setTimeout(function () { update(rows, total); }, 10); } } -function loadRows() -{ - if (!this.options.ajax) - { - var that = this, - rows = this.element.find("tbody > tr"); - rows.each(function () - { - var $this = $(this), - cells = $this.children("td"), - row = {}; +function loadRows() { + if (!this.options.ajax) { + const that = this; + const rows = this.element.find("tbody > tr"); + const rowsData = rows.map(function () { + const cells = $(this).children("td"); + const row = {}; - $.each(that.columns, function (i, column) - { + that.columns.forEach(function (column, i) { row[column.id] = column.converter.from(cells.eq(i).text()); }); + return row; + }).get(); + + rowsData.forEach(function (row) { appendRow.call(that, row); }); @@ -283,67 +250,60 @@ function loadRows() } } + function setTotals(total) { this.total = total; - this.totalPages = (this.rowCount === -1) ? 1 : - Math.ceil(this.total / this.rowCount); + this.totalPages = (this.rowCount === -1) ? 1 : Math.ceil(this.total / this.rowCount); } -function prepareTable() -{ - var tpl = this.options.templates, - wrapper = (this.element.parent().hasClass(this.options.css.responsiveTable)) ? - this.element.parent() : this.element; +function prepareTable() { + const tpl = this.options.templates; + const wrapper = this.element.parent().hasClass(this.options.css.responsiveTable) + ? this.element.parent() : this.element; this.element.addClass(this.options.css.table); - // checks whether there is an tbody element; otherwise creates one - if (this.element.children("tbody").length === 0) - { + // Create tbody element if it doesn't exist + if (!this.element.children("tbody").length) { this.element.append(tpl.body); } - if (this.options.navigation & 1) - { - this.header = $(tpl.header.resolve(getParams.call(this, { id: this.element._bgId() + "-header" }))); + if (this.options.navigation & 1) { + const headerId = this.element._bgId() + "-header"; + this.header = $(tpl.header.resolve(getParams.call(this, { id: headerId }))); wrapper.before(this.header); } - if (this.options.navigation & 2) - { - this.footer = $(tpl.footer.resolve(getParams.call(this, { id: this.element._bgId() + "-footer" }))); + if (this.options.navigation & 2) { + const footerId = this.element._bgId() + "-footer"; + this.footer = $(tpl.footer.resolve(getParams.call(this, { id: footerId }))); wrapper.after(this.footer); } } -function renderActions() -{ - if (this.options.navigation !== 0) - { - var css = this.options.css, - selector = getCssSelector(css.actions), - actionItems = findFooterAndHeaderItems.call(this, selector); - if (actionItems.length > 0) - { - var that = this, - tpl = this.options.templates, - actions = $(tpl.actions.resolve(getParams.call(this))); +function renderActions() { + if (this.options.navigation !== 0) { + const { css, templates, labels, ajax } = this.options; + const selector = getCssSelector(css.actions); + const actionItems = findFooterAndHeaderItems.call(this, selector); + + if (actionItems.length > 0) { + const actions = $(templates.actions.resolve(getParams.call(this))); // Refresh Button - if (this.options.ajax) - { - var refreshIcon = tpl.icon.resolve(getParams.call(this, { iconCss: css.iconRefresh })), - refresh = $(tpl.actionButton.resolve(getParams.call(this, - { content: refreshIcon, text: this.options.labels.refresh }))) - .on("click" + namespace, function (e) - { - // todo: prevent multiple fast clicks (fast click detection) - e.stopPropagation(); - that.current = 1; - loadData.call(that); - }); + if (ajax) { + const refreshIcon = $(templates.icon.resolve(getParams.call(this, { iconCss: css.iconRefresh }))); + const refresh = $(templates.actionButton.resolve(getParams.call(this, + { content: refreshIcon, text: labels.refresh }))) + .on("click" + namespace, function (e) { + // todo: prevent multiple fast clicks (fast click detection) + e.stopPropagation(); + that.current = 1; + loadData.call(that); + }); + actions.append(refresh); } @@ -358,121 +318,106 @@ function renderActions() } } -function renderColumnSelection(actions) -{ - if (this.options.columnSelection && this.columns.length > 1) - { - var that = this, - css = this.options.css, - tpl = this.options.templates, - icon = tpl.icon.resolve(getParams.call(this, { iconCss: css.iconColumns })), - dropDown = $(tpl.actionDropDown.resolve(getParams.call(this, { content: icon }))), - selector = getCssSelector(css.dropDownItem), - checkboxSelector = getCssSelector(css.dropDownItemCheckbox), - itemsSelector = getCssSelector(css.dropDownMenuItems); - - $.each(this.columns, function (i, column) - { - if (column.visibleInSelection) - { - var item = $(tpl.actionDropDownCheckboxItem.resolve(getParams.call(that, - { name: column.id, label: column.text, checked: column.visible }))) - .on("click" + namespace, selector, function (e) - { - e.stopPropagation(); - - var $this = $(this), - checkbox = $this.find(checkboxSelector); - if (!checkbox.prop("disabled")) - { - column.visible = checkbox.prop("checked"); - var enable = that.columns.where(isVisible).length > 1; - $this.parents(itemsSelector).find(selector + ":has(" + checkboxSelector + ":checked)") - ._bgEnableAria(enable).find(checkboxSelector)._bgEnableField(enable); - - that.element.find("tbody").empty(); // Fixes an column visualization bug - renderTableHeader.call(that); - loadData.call(that); - } - }); - dropDown.find(getCssSelector(css.dropDownMenuItems)).append(item); + +function renderColumnSelection(actions) { + if (this.options.columnSelection && this.columns.length > 1) { + const { css, templates } = this.options; + const icon = $(templates.icon.resolve(getParams.call(this, { iconCss: css.iconColumns }))); + const dropDown = $(templates.actionDropDown.resolve(getParams.call(this, { content: icon }))); + const checkboxSelector = getCssSelector(css.dropDownItemCheckbox); + + this.columns.forEach(column => { + if (column.visibleInSelection) { + const item = $(`
  • + +
  • `); + + item.on("click" + namespace, checkboxSelector, function (e) { + e.stopPropagation(); + const checkbox = $(this); + if (!checkbox.prop("disabled")) { + column.visible = checkbox.prop("checked"); + const enable = that.columns.filter(col => col.visible).length > 1; + checkbox.closest(`.${css.dropDownMenuItems}`) + .find(checkboxSelector + ":checked").prop("disabled", !enable); + + that.element.find("tbody").empty(); // Fixes a column visualization bug + renderTableHeader.call(that); + loadData.call(that); + } + }); + + dropDown.find(`.${css.dropDownMenuItems}`).append(item); } }); + actions.append(dropDown); } } -function renderInfos() -{ - if (this.options.navigation !== 0) - { - var selector = getCssSelector(this.options.css.infos), - infoItems = findFooterAndHeaderItems.call(this, selector); - - if (infoItems.length > 0) - { - var end = (this.current * this.rowCount), - infos = $(this.options.templates.infos.resolve(getParams.call(this, { - end: (this.total === 0 || end === -1 || end > this.total) ? this.total : end, - start: (this.total === 0) ? 0 : (end - this.rowCount + 1), - total: this.total - }))); + +function renderInfos() { + if (this.options.navigation !== 0) { + const selector = getCssSelector(this.options.css.infos); + const infoItems = findFooterAndHeaderItems.call(this, selector); + + if (infoItems.length > 0) { + const end = this.total === 0 || this.current * this.rowCount > this.total ? this.total : this.current * this.rowCount; + const start = this.total === 0 ? 0 : end - this.rowCount + 1; + const infos = $(this.options.templates.infos.resolve(getParams.call(this, { + end: end, + start: start, + total: this.total + }))); replacePlaceHolder.call(this, infoItems, infos); } } } -function renderNoResultsRow() -{ - var tbody = this.element.children("tbody").first(), - tpl = this.options.templates, - count = this.columns.where(isVisible).length; - if (this.selection) - { - count = count + 1; - } +function renderNoResultsRow() { + const tbody = this.element.children("tbody").first(); + const tpl = this.options.templates; + const visibleColumns = this.columns.filter(column => column.visible); + const count = this.selection ? visibleColumns.length + 1 : visibleColumns.length; + tbody.html(tpl.noResults.resolve(getParams.call(this, { columns: count }))); } -function renderPagination() -{ - if (this.options.navigation !== 0) - { - var selector = getCssSelector(this.options.css.pagination), - paginationItems = findFooterAndHeaderItems.call(this, selector)._bgShowAria(this.rowCount !== -1); - - if (this.rowCount !== -1 && paginationItems.length > 0) - { - var tpl = this.options.templates, - current = this.current, - totalPages = this.totalPages, - pagination = $(tpl.pagination.resolve(getParams.call(this))), - offsetRight = totalPages - current, - offsetLeft = (this.options.padding - current) * -1, - startWith = ((offsetRight >= this.options.padding) ? - Math.max(offsetLeft, 1) : - Math.max((offsetLeft - this.options.padding + offsetRight), 1)), - maxCount = this.options.padding * 2 + 1, - count = (totalPages >= maxCount) ? maxCount : totalPages; + +function renderPagination() { + if (this.options.navigation !== 0 && this.rowCount !== -1) { + const selector = getCssSelector(this.options.css.pagination); + const paginationItems = findFooterAndHeaderItems.call(this, selector)._bgShowAria(); + + if (paginationItems.length > 0) { + const tpl = this.options.templates; + const current = this.current; + const totalPages = this.totalPages; + const pagination = $(tpl.pagination.resolve(getParams.call(this))); + const maxCount = this.options.padding * 2 + 1; + const count = Math.min(totalPages, maxCount); + + const startWith = Math.max(current - this.options.padding, 1); + const endWith = Math.min(startWith + maxCount - 1, totalPages); renderPaginationItem.call(this, pagination, "first", "«", "first") ._bgEnableAria(current > 1); renderPaginationItem.call(this, pagination, "prev", "<", "prev") ._bgEnableAria(current > 1); - for (var i = 0; i < count; i++) - { - var pos = i + startWith; + for (let pos = startWith; pos <= endWith; pos++) { renderPaginationItem.call(this, pagination, pos, pos, "page-" + pos) - ._bgEnableAria()._bgSelectAria(pos === current); + ._bgSelectAria(pos === current); } - if (count === 0) - { - renderPaginationItem.call(this, pagination, 1, 1, "page-" + 1) - ._bgEnableAria(false)._bgSelectAria(); + if (count === 0) { + renderPaginationItem.call(this, pagination, 1, 1, "page-" + 1); } renderPaginationItem.call(this, pagination, "next", ">", "next") @@ -485,251 +430,198 @@ function renderPagination() } } -function renderPaginationItem(list, page, text, markerCss) -{ - var that = this, - tpl = this.options.templates, - css = this.options.css, - values = getParams.call(this, { css: markerCss, text: text, page: page }), - item = $(tpl.paginationItem.resolve(values)) - .on("click" + namespace, getCssSelector(css.paginationButton), function (e) - { - e.stopPropagation(); - e.preventDefault(); - var $this = $(this), - parent = $this.parent(); - if (!parent.hasClass("active") && !parent.hasClass("disabled")) - { - var commandList = { - first: 1, - prev: that.current - 1, - next: that.current + 1, - last: that.totalPages - }; - var command = $this.data("page"); - that.current = commandList[command] || command; - loadData.call(that); - } - $this.trigger("blur"); - }); +function renderPaginationItem(list, page, text, markerCss) { + const { templates, css } = this.options; + const values = getParams.call(this, { css: markerCss, text: text, page: page }); + const item = $(templates.paginationItem.resolve(values)); + const $paginationButton = item.find(getCssSelector(css.paginationButton)); list.append(item); + + $paginationButton.on("click" + namespace, function (e) { + e.stopPropagation(); + e.preventDefault(); + + const $this = $(this); + const parent = $this.parent(); + if (!parent.hasClass("active") && !parent.hasClass("disabled")) { + const commandList = { + first: 1, + prev: this.current - 1, + next: this.current + 1, + last: this.totalPages + }; + const command = $this.data("page"); + this.current = commandList[command] || command; + loadData.call(this); + } + $this.trigger("blur"); + }.bind(this)); + return item; } -function renderRowCountSelection(actions) -{ - var that = this, - rowCountList = this.options.rowCount; - function getText(value) - { - return (value === -1) ? that.options.labels.all : value; +function renderRowCountSelection(actions) { + const { css, templates, rowCount } = this.options; + + function getText(value) { + return value === -1 ? this.options.labels.all : value; } - if ($.isArray(rowCountList)) - { - var css = this.options.css, - tpl = this.options.templates, - dropDown = $(tpl.actionDropDown.resolve(getParams.call(this, { content: getText(this.rowCount) }))), - menuSelector = getCssSelector(css.dropDownMenu), - menuTextSelector = getCssSelector(css.dropDownMenuText), - menuItemsSelector = getCssSelector(css.dropDownMenuItems), - menuItemSelector = getCssSelector(css.dropDownItemButton); - - $.each(rowCountList, function (index, value) - { - var item = $(tpl.actionDropDownItem.resolve(getParams.call(that, - { text: getText(value), action: value }))) - ._bgSelectAria(value === that.rowCount) - .on("click" + namespace, menuItemSelector, function (e) - { - e.preventDefault(); - - var $this = $(this), - newRowCount = $this.data("action"); - if (newRowCount !== that.rowCount) - { - // todo: sophisticated solution needed for calculating which page is selected - that.current = 1; // that.rowCount === -1 ---> All - that.rowCount = newRowCount; - $this.parents(menuItemsSelector).children().each(function () - { - var $item = $(this), - currentRowCount = $item.find(menuItemSelector).data("action"); - $item._bgSelectAria(currentRowCount === newRowCount); - }); - $this.parents(menuSelector).find(menuTextSelector).text(getText(newRowCount)); - loadData.call(that); - } - }); - dropDown.find(menuItemsSelector).append(item); - }); + if ($.isArray(rowCount)) { + const dropDown = $(templates.actionDropDown.resolve(getParams.call(this, { content: getText(this.rowCount) }))); + const menuItems = rowCount.map(value => { + return templates.actionDropDownItem + .resolve(getParams.call(this, { text: getText(value), action: value })) + ._bgSelectAria(value === this.rowCount); + }).join(''); + + dropDown.find(getCssSelector(css.dropDownMenuItems)).append(menuItems); + + dropDown.on("click" + namespace, getCssSelector(css.dropDownItemButton), function (e) { + e.preventDefault(); + + const newRowCount = $(this).data("action"); + if (newRowCount !== this.rowCount) { + this.current = 1; // this.rowCount === -1 ---> All + this.rowCount = newRowCount; + const menuItems = dropDown.find(getCssSelector(css.dropDownItemButton)); + menuItems.each(function () { + const $item = $(this); + const currentRowCount = $item.data("action"); + $item._bgSelectAria(currentRowCount === newRowCount); + }); + + dropDown.find(getCssSelector(css.dropDownMenuText)).text(getText(newRowCount)); + + loadData.call(this); + } + }.bind(this)); + actions.append(dropDown); } } -function renderRows(rows) -{ - if (rows.length > 0) - { - var that = this, - css = this.options.css, - tpl = this.options.templates, - tbody = this.element.children("tbody").first(), - allRowsSelected = true, - html = ""; - - $.each(rows, function (index, row) - { - var cells = "", - rowAttr = " data-row-id=\"" + ((that.identifier == null) ? index : row[that.identifier]) + "\"", - rowCss = ""; - - if (that.selection) - { - var selected = ($.inArray(row[that.identifier], that.selectedRows) !== -1), - selectBox = tpl.select.resolve(getParams.call(that, - { type: "checkbox", value: row[that.identifier], checked: selected })); - cells += tpl.cell.resolve(getParams.call(that, { content: selectBox, css: css.selectCell })); - allRowsSelected = (allRowsSelected && selected); - if (selected) - { +function renderRows(rows) { + if (rows.length > 0) { + const { css, templates } = this.options; + const tbody = this.element.children("tbody").first(); + let html = ""; + + function createCell(column, row) { + if (column.visible) { + const value = $.isFunction(column.formatter) ? column.formatter.call(this, column, row) : column.converter.to(row[column.id]); + const cssClass = column.cssClass.length > 0 ? " " + column.cssClass : ""; + const content = value == null || value === "" ? " " : value; + const cellCss = ((column.align === "right") ? css.right : (column.align === "center") ? css.center : css.left) + cssClass; + const cellStyle = column.width == null ? "" : "width:" + column.width + ";"; + return templates.cell.resolve(getParams.call(this, { content, css: cellCss, style: cellStyle })); + } + return ""; + } + + $.each(rows, function (index, row) { + let cells = ""; + let rowAttr = " data-row-id=\"" + ((this.identifier == null) ? index : row[this.identifier]) + "\""; + let rowCss = ""; + + if (this.selection) { + const selected = $.inArray(row[this.identifier], this.selectedRows) !== -1; + const selectBox = templates.select.resolve(getParams.call(this, { type: "checkbox", value: row[this.identifier], checked: selected })); + cells += templates.cell.resolve(getParams.call(this, { content: selectBox, css: css.selectCell })); + if (selected) { rowCss += css.selected; rowAttr += " aria-selected=\"true\""; } } - var status = row.status != null && that.options.statusMapping[row.status]; - if (status) - { + const status = row.status != null && this.options.statusMapping[row.status]; + if (status) { rowCss += status; } - $.each(that.columns, function (j, column) - { - if (column.visible) - { - var value = ($.isFunction(column.formatter)) ? - column.formatter.call(that, column, row) : - column.converter.to(row[column.id]), - cssClass = (column.cssClass.length > 0) ? " " + column.cssClass : ""; - cells += tpl.cell.resolve(getParams.call(that, { - content: (value == null || value === "") ? " " : value, - css: ((column.align === "right") ? css.right : (column.align === "center") ? - css.center : css.left) + cssClass, - style: (column.width == null) ? "" : "width:" + column.width + ";" })); - } - }); + cells += this.columns.map(column => createCell.call(this, column, row)).join(""); - if (rowCss.length > 0) - { + if (rowCss.length > 0) { rowAttr += " class=\"" + rowCss + "\""; } - html += tpl.row.resolve(getParams.call(that, { attr: rowAttr, cells: cells })); + html += templates.row.resolve(getParams.call(this, { attr: rowAttr, cells })); }); - // sets or clears multi selectbox state - that.element.find("thead " + getCssSelector(that.options.css.selectBox)) - .prop("checked", allRowsSelected); + // sets or clears multi-selectbox state + this.element.find("thead " + getCssSelector(css.selectBox)) + .prop("checked", rows.length > 0 && rows.every(row => $.inArray(row[this.identifier], this.selectedRows) !== -1)); tbody.html(html); - registerRowEvents.call(this, tbody); - } - else - { + } else { renderNoResultsRow.call(this); } } -function registerRowEvents(tbody) -{ - var that = this, - selectBoxSelector = getCssSelector(this.options.css.selectBox); - if (this.selection) - { +function registerRowEvents(tbody) { + const { css, rowSelect } = this.options; + const selectBoxSelector = getCssSelector(css.selectBox); + + if (this.selection) { tbody.off("click" + namespace, selectBoxSelector) - .on("click" + namespace, selectBoxSelector, function(e) - { + .on("click" + namespace, selectBoxSelector, function (e) { e.stopPropagation(); - var $this = $(this), - id = that.converter.from($this.val()); + const $this = $(this); + const id = that.converter.from($this.val()); + const isChecked = $this.prop("checked"); - if ($this.prop("checked")) - { - that.select([id]); - } - else - { - that.deselect([id]); - } + that[isChecked ? "select" : "deselect"]([id]); }); } tbody.off("click" + namespace, "> tr") - .on("click" + namespace, "> tr", function(e) - { + .on("click" + namespace, "> tr", function (e) { e.stopPropagation(); - var $this = $(this), - id = (that.identifier == null) ? $this.data("row-id") : - that.converter.from($this.data("row-id") + ""), - row = (that.identifier == null) ? that.currentRows[id] : - that.currentRows.first(function (item) { return item[that.identifier] === id; }); - - if (that.selection && that.options.rowSelect) - { - if ($this.hasClass(that.options.css.selected)) - { - that.deselect([id]); - } - else - { - that.select([id]); - } + const $this = $(this); + const id = (that.identifier == null) ? $this.data("row-id") : that.converter.from(`${$this.data("row-id")}`); + const row = (that.identifier == null) ? that.currentRows[id] : + that.currentRows.first((item) => item[that.identifier] === id); + + if (that.selection && rowSelect) { + $this.toggleClass(css.selected); + that[$this.hasClass(css.selected) ? "select" : "deselect"]([id]); } that.element.trigger("click" + namespace, [that.columns, row]); }); } -function renderSearchField() -{ - if (this.options.navigation !== 0) - { - var css = this.options.css, - selector = getCssSelector(css.search), - searchItems = findFooterAndHeaderItems.call(this, selector); - - if (searchItems.length > 0) - { - var that = this, - tpl = this.options.templates, - timer = null, // fast keyup detection - currentValue = "", - searchFieldSelector = getCssSelector(css.searchField), - search = $(tpl.search.resolve(getParams.call(this))), - searchField = (search.is(searchFieldSelector)) ? search : - search.find(searchFieldSelector); - - searchField.on("keyup" + namespace, function (e) - { + +function renderSearchField() { + if (this.options.navigation !== 0) { + const css = this.options.css; + const selector = getCssSelector(css.search); + const searchItems = findFooterAndHeaderItems.call(this, selector); + + if (searchItems.length > 0) { + const tpl = this.options.templates; + let timer = null; // fast keyup detection + let currentValue = ""; + const searchFieldSelector = getCssSelector(css.searchField); + const search = $(tpl.search.resolve(getParams.call(this))); + const searchField = search.is(searchFieldSelector) ? search : search.find(searchFieldSelector); + + searchField.on("keyup" + namespace, function (e) { e.stopPropagation(); - var newValue = $(this).val(); - if (currentValue !== newValue || (e.which === 13 && newValue !== "")) - { + const newValue = $(this).val(); + if (currentValue !== newValue || (e.which === 13 && newValue !== "")) { currentValue = newValue; - if (e.which === 13 || newValue.length === 0 || newValue.length >= that.options.searchSettings.characters) - { + if (e.which === 13 || newValue.length === 0 || newValue.length >= this.options.searchSettings.characters) { window.clearTimeout(timer); - timer = window.setTimeout(function () - { - executeSearch.call(that, newValue); - }, that.options.searchSettings.delay); + timer = window.setTimeout(() => { + executeSearch.call(this, newValue); + }, this.options.searchSettings.delay); } } }); @@ -739,132 +631,119 @@ function renderSearchField() } } -function executeSearch(phrase) -{ - if (this.searchPhrase !== phrase) - { + +function executeSearch(phrase){ + if(this.searchPhrase === phrase) return; this.current = 1; this.searchPhrase = phrase; loadData.call(this); - } } -function renderTableHeader() -{ - var that = this, - headerRow = this.element.find("thead > tr"), - css = this.options.css, - tpl = this.options.templates, - html = "", - sorting = this.options.sorting; - - if (this.selection) - { - var selectBox = (this.options.multiSelect) ? - tpl.select.resolve(getParams.call(that, { type: "checkbox", value: "all" })) : ""; - html += tpl.rawHeaderCell.resolve(getParams.call(that, { content: selectBox, - css: css.selectCell })); +function renderTableHeader() { + const that = this; + const css = this.options.css; + const tpl = this.options.templates; + const headerRow = this.element.find("thead > tr"); + const sorting = this.options.sorting; + const selectBoxSelector = getCssSelector(css.selectBox); + const sortingSelector = getCssSelector(css.sortable); + + let html = ""; + + function createHeaderCell(column) { + if (!column.visible) return ""; + + const sortOrder = that.sortDictionary[column.id]; + const iconCss = (sorting && sortOrder && sortOrder === "asc") ? css.iconUp : + (sorting && sortOrder && sortOrder === "desc") ? css.iconDown : ""; + const icon = tpl.icon.resolve(getParams.call(that, { iconCss })); + const align = column.headerAlign; + const cssClass = column.headerCssClass.length > 0 ? " " + column.headerCssClass : ""; + + return tpl.headerCell.resolve(getParams.call(that, { + column: column, + icon: icon, + sortable: sorting && column.sortable && css.sortable || "", + css: ((align === "right") ? css.right : (align === "center") ? + css.center : css.left) + cssClass, + style: column.width == null ? "" : "width:" + column.width + ";", + })); } - $.each(this.columns, function (index, column) - { - if (column.visible) - { - var sortOrder = that.sortDictionary[column.id], - iconCss = ((sorting && sortOrder && sortOrder === "asc") ? css.iconUp : - (sorting && sortOrder && sortOrder === "desc") ? css.iconDown : ""), - icon = tpl.icon.resolve(getParams.call(that, { iconCss: iconCss })), - align = column.headerAlign, - cssClass = (column.headerCssClass.length > 0) ? " " + column.headerCssClass : ""; - html += tpl.headerCell.resolve(getParams.call(that, { - column: column, icon: icon, sortable: sorting && column.sortable && css.sortable || "", - css: ((align === "right") ? css.right : (align === "center") ? - css.center : css.left) + cssClass, - style: (column.width == null) ? "" : "width:" + column.width + ";" })); - } - }); + if (this.selection) { + const selectBox = (this.options.multiSelect) ? tpl.select.resolve(getParams.call(that, { + type: "checkbox", + value: "all", + })) : ""; + + html += tpl.rawHeaderCell.resolve(getParams.call(that, { + content: selectBox, + css: css.selectCell, + })); + } + + html += this.columns.filter(column => column.visible).map(createHeaderCell).join(""); headerRow.html(html); - if (sorting) - { - var sortingSelector = getCssSelector(css.sortable); + attachSortingClickHandler(); + + if (this.selection && this.options.multiSelect) { + attachSelectBoxClickHandler(); + } + + function attachSortingClickHandler() { headerRow.off("click" + namespace, sortingSelector) - .on("click" + namespace, sortingSelector, function (e) - { + .on("click" + namespace, sortingSelector, function (e) { e.preventDefault(); - setTableHeaderSortDirection.call(that, $(this)); - sortRows.call(that); - loadData.call(that); + setTableHeaderSortDirection($(this)); + sortRows(); + loadData(); }); } - // todo: create a own function for that piece of code - if (this.selection && this.options.multiSelect) - { - var selectBoxSelector = getCssSelector(css.selectBox); + function attachSelectBoxClickHandler() { headerRow.off("click" + namespace, selectBoxSelector) - .on("click" + namespace, selectBoxSelector, function(e) - { + .on("click" + namespace, selectBoxSelector, function (e) { e.stopPropagation(); - if ($(this).prop("checked")) - { + if ($(this).prop("checked")) { that.select(); - } - else - { + } else { that.deselect(); } }); } } -function setTableHeaderSortDirection(element) -{ - var css = this.options.css, - iconSelector = getCssSelector(css.icon), - columnId = element.data("column-id") || element.parents("th").first().data("column-id"), - sortOrder = this.sortDictionary[columnId], - icon = element.find(iconSelector); +function setTableHeaderSortDirection(element) { + const { css } = this.options; + const iconSelector = getCssSelector(css.icon); + const columnId = element.data("column-id") || element.parents("th").first().data("column-id"); + const sortOrder = this.sortDictionary[columnId]; + const icon = element.find(iconSelector); - if (!this.options.multiSort) - { - element.parents("tr").first().find(iconSelector).removeClass(css.iconDown + " " + css.iconUp); + if (!this.options.multiSort) { + element.parents("tr").first().find(iconSelector).removeClass(`${css.iconDown} ${css.iconUp}`); this.sortDictionary = {}; } - if (sortOrder && sortOrder === "asc") - { + if (sortOrder === "asc") { this.sortDictionary[columnId] = "desc"; icon.removeClass(css.iconUp).addClass(css.iconDown); - } - else if (sortOrder && sortOrder === "desc") - { - if (this.options.multiSort) - { - var newSort = {}; - for (var key in this.sortDictionary) - { - if (key !== columnId) - { - newSort[key] = this.sortDictionary[key]; - } + } else if (sortOrder === "desc" && this.options.multiSort) { + const newSort = {}; + for (const key in this.sortDictionary) { + if (key !== columnId) { + newSort[key] = this.sortDictionary[key]; } - this.sortDictionary = newSort; - icon.removeClass(css.iconDown); } - else - { - this.sortDictionary[columnId] = "asc"; - icon.removeClass(css.iconDown).addClass(css.iconUp); - } - } - else - { - this.sortDictionary[columnId] = "asc"; - icon.addClass(css.iconUp); + this.sortDictionary = newSort; + icon.removeClass(css.iconDown); + } else { + this.sortDictionary[columnId] = sortOrder ? "asc" : "asc"; + icon.toggleClass(css.iconUp, !sortOrder).toggleClass(css.iconDown, sortOrder); } } @@ -877,72 +756,50 @@ function replacePlaceHolder(placeholder, element) }); } -function showLoading() -{ - var that = this; - - window.setTimeout(function() - { - if (that.element._bgAria("busy") === "true") - { - var tpl = that.options.templates, - thead = that.element.children("thead").first(), - tbody = that.element.children("tbody").first(), - firstCell = tbody.find("tr > td").first(), - padding = (that.element.height() - thead.height()) - (firstCell.height() + 20), - count = that.columns.where(isVisible).length; - - if (that.selection) - { - count = count + 1; - } - tbody.html(tpl.loading.resolve(getParams.call(that, { columns: count }))); - if (that.rowCount !== -1 && padding > 0) - { - tbody.find("tr > td").css("padding", "20px 0 " + padding + "px"); +function showLoading() { + const { element, options } = this; + const tpl = options.templates; + const thead = element.children("thead").first(); + const tbody = element.children("tbody").first(); + const firstCell = tbody.find("tr > td").first(); + const isVisible = (col) => col.visible !== false; + const columnsCount = this.columns.filter(isVisible).length + (this.selection ? 1 : 0); + + window.setTimeout(function () { + if (element._bgAria("busy") === "true") { + const padding = element.height() - thead.height() - (firstCell.height() + 20); + + tbody.empty().append(tpl.loading.resolve(getParams.call(this, { columns: columnsCount }))); + if (padding > 0) { + tbody.find("tr > td").css("padding", `20px 0 ${padding}px`); } } - }, 250); + }.bind(this), 250); } +function sortRows() { + const sortArray = []; -function sortRows() -{ - var sortArray = []; + function sort(x, y, current = 0) { + const item = sortArray[current]; + const sortOrder = item.order === "asc" ? 1 : -1; - function sort(x, y, current) - { - current = current || 0; - var next = current + 1, - item = sortArray[current]; - - function sortOrder(value) - { - return (item.order === "asc") ? value : value * -1; - } - - return (x[item.id] > y[item.id]) ? sortOrder(1) : - (x[item.id] < y[item.id]) ? sortOrder(-1) : - (sortArray.length > next) ? sort(x, y, next) : 0; + if (x[item.id] > y[item.id]) return sortOrder; + if (x[item.id] < y[item.id]) return -sortOrder; + return sortArray.length > current + 1 ? sort(x, y, current + 1) : 0; } - if (!this.options.ajax) - { - var that = this; - - for (var key in this.sortDictionary) - { - if (this.options.multiSort || sortArray.length === 0) - { + if (!this.options.ajax) { + for (const key in this.sortDictionary) { + if (this.options.multiSort || sortArray.length === 0) { sortArray.push({ id: key, - order: this.sortDictionary[key] + order: this.sortDictionary[key], }); } } - if (sortArray.length > 0) - { - this.rows.sort(sort); + if (sortArray.length > 0) { + this.rows.sort((x, y) => sort(x, y)); } } -} \ No newline at end of file +}