UNPKG

tabulator-tables

Version:

Interactive table generation JavaScript library

730 lines (562 loc) 18.7 kB
/* Tabulator v4.9.3 (c) Oliver Folkerd */ var Page = function Page(table) { this.table = table; //hold Tabulator object this.mode = "local"; this.progressiveLoad = false; this.size = 0; this.page = 1; this.count = 5; this.max = 1; this.displayIndex = 0; //index in display pipeline this.initialLoad = true; this.pageSizes = []; this.dataReceivedNames = {}; this.dataSentNames = {}; this.createElements(); }; Page.prototype.createElements = function () { var button; this.element = document.createElement("span"); this.element.classList.add("tabulator-paginator"); this.pagesElement = document.createElement("span"); this.pagesElement.classList.add("tabulator-pages"); button = document.createElement("button"); button.classList.add("tabulator-page"); button.setAttribute("type", "button"); button.setAttribute("role", "button"); button.setAttribute("aria-label", ""); button.setAttribute("title", ""); this.firstBut = button.cloneNode(true); this.firstBut.setAttribute("data-page", "first"); this.prevBut = button.cloneNode(true); this.prevBut.setAttribute("data-page", "prev"); this.nextBut = button.cloneNode(true); this.nextBut.setAttribute("data-page", "next"); this.lastBut = button.cloneNode(true); this.lastBut.setAttribute("data-page", "last"); if (this.table.options.paginationSizeSelector) { this.pageSizeSelect = document.createElement("select"); this.pageSizeSelect.classList.add("tabulator-page-size"); } }; Page.prototype.generatePageSizeSelectList = function () { var _this = this; var pageSizes = []; if (this.pageSizeSelect) { if (Array.isArray(this.table.options.paginationSizeSelector)) { pageSizes = this.table.options.paginationSizeSelector; this.pageSizes = pageSizes; if (this.pageSizes.indexOf(this.size) == -1) { pageSizes.unshift(this.size); } } else { if (this.pageSizes.indexOf(this.size) == -1) { pageSizes = []; for (var i = 1; i < 5; i++) { pageSizes.push(this.size * i); } this.pageSizes = pageSizes; } else { pageSizes = this.pageSizes; } } while (this.pageSizeSelect.firstChild) { this.pageSizeSelect.removeChild(this.pageSizeSelect.firstChild); }pageSizes.forEach(function (item) { var itemEl = document.createElement("option"); itemEl.value = item; if (item === true) { _this.table.modules.localize.bind("pagination|all", function (value) { itemEl.innerHTML = value; }); } else { itemEl.innerHTML = item; } _this.pageSizeSelect.appendChild(itemEl); }); this.pageSizeSelect.value = this.size; } }; //setup pageination Page.prototype.initialize = function (hidden) { var self = this, pageSelectLabel, testElRow, testElCell; //update param names this.dataSentNames = Object.assign({}, this.paginationDataSentNames); this.dataSentNames = Object.assign(this.dataSentNames, this.table.options.paginationDataSent); this.dataReceivedNames = Object.assign({}, this.paginationDataReceivedNames); this.dataReceivedNames = Object.assign(this.dataReceivedNames, this.table.options.paginationDataReceived); //build pagination element //bind localizations self.table.modules.localize.bind("pagination|first", function (value) { self.firstBut.innerHTML = value; }); self.table.modules.localize.bind("pagination|first_title", function (value) { self.firstBut.setAttribute("aria-label", value); self.firstBut.setAttribute("title", value); }); self.table.modules.localize.bind("pagination|prev", function (value) { self.prevBut.innerHTML = value; }); self.table.modules.localize.bind("pagination|prev_title", function (value) { self.prevBut.setAttribute("aria-label", value); self.prevBut.setAttribute("title", value); }); self.table.modules.localize.bind("pagination|next", function (value) { self.nextBut.innerHTML = value; }); self.table.modules.localize.bind("pagination|next_title", function (value) { self.nextBut.setAttribute("aria-label", value); self.nextBut.setAttribute("title", value); }); self.table.modules.localize.bind("pagination|last", function (value) { self.lastBut.innerHTML = value; }); self.table.modules.localize.bind("pagination|last_title", function (value) { self.lastBut.setAttribute("aria-label", value); self.lastBut.setAttribute("title", value); }); //click bindings self.firstBut.addEventListener("click", function () { self.setPage(1).then(function () {}).catch(function () {}); }); self.prevBut.addEventListener("click", function () { self.previousPage().then(function () {}).catch(function () {}); }); self.nextBut.addEventListener("click", function () { self.nextPage().then(function () {}).catch(function () {}); }); self.lastBut.addEventListener("click", function () { self.setPage(self.max).then(function () {}).catch(function () {}); }); if (self.table.options.paginationElement) { self.element = self.table.options.paginationElement; } if (this.pageSizeSelect) { pageSelectLabel = document.createElement("label"); self.table.modules.localize.bind("pagination|page_size", function (value) { self.pageSizeSelect.setAttribute("aria-label", value); self.pageSizeSelect.setAttribute("title", value); pageSelectLabel.innerHTML = value; }); self.element.appendChild(pageSelectLabel); self.element.appendChild(self.pageSizeSelect); self.pageSizeSelect.addEventListener("change", function (e) { self.setPageSize(self.pageSizeSelect.value == "true" ? true : self.pageSizeSelect.value); self.setPage(1).then(function () {}).catch(function () {}); }); } //append to DOM self.element.appendChild(self.firstBut); self.element.appendChild(self.prevBut); self.element.appendChild(self.pagesElement); self.element.appendChild(self.nextBut); self.element.appendChild(self.lastBut); if (!self.table.options.paginationElement && !hidden) { self.table.footerManager.append(self.element, self); } //set default values self.mode = self.table.options.pagination; if (self.table.options.paginationSize) { self.size = self.table.options.paginationSize; } else { testElRow = document.createElement("div"); testElRow.classList.add("tabulator-row"); testElRow.style.visibility = hidden; testElCell = document.createElement("div"); testElCell.classList.add("tabulator-cell"); testElCell.innerHTML = "Page Row Test"; testElRow.appendChild(testElCell); self.table.rowManager.getTableElement().appendChild(testElRow); self.size = Math.floor(self.table.rowManager.getElement().clientHeight / testElRow.offsetHeight); self.table.rowManager.getTableElement().removeChild(testElRow); } // self.page = self.table.options.paginationInitialPage || 1; self.count = self.table.options.paginationButtonCount; self.generatePageSizeSelectList(); }; Page.prototype.initializeProgressive = function (mode) { this.initialize(true); this.mode = "progressive_" + mode; this.progressiveLoad = true; }; Page.prototype.setDisplayIndex = function (index) { this.displayIndex = index; }; Page.prototype.getDisplayIndex = function () { return this.displayIndex; }; //calculate maximum page from number of rows Page.prototype.setMaxRows = function (rowCount) { if (!rowCount) { this.max = 1; } else { this.max = this.size === true ? 1 : Math.ceil(rowCount / this.size); } if (this.page > this.max) { this.page = this.max; } }; //reset to first page without triggering action Page.prototype.reset = function (force, columnsChanged) { if (this.mode == "local" || force) { this.page = 1; } if (columnsChanged) { this.initialLoad = true; } return true; }; //set the maxmum page Page.prototype.setMaxPage = function (max) { max = parseInt(max); this.max = max || 1; if (this.page > this.max) { this.page = this.max; this.trigger(); } }; //set current page number Page.prototype.setPage = function (page) { var _this2 = this; var self = this; switch (page) { case "first": return this.setPage(1); break; case "prev": return this.previousPage(); break; case "next": return this.nextPage(); break; case "last": return this.setPage(this.max); break; } return new Promise(function (resolve, reject) { page = parseInt(page); if (page > 0 && page <= _this2.max || _this2.mode !== "local") { _this2.page = page; _this2.trigger().then(function () { resolve(); }).catch(function () { reject(); }); if (self.table.options.persistence && self.table.modExists("persistence", true) && self.table.modules.persistence.config.page) { self.table.modules.persistence.save("page"); } } else { console.warn("Pagination Error - Requested page is out of range of 1 - " + _this2.max + ":", page); reject(); } }); }; Page.prototype.setPageToRow = function (row) { var _this3 = this; return new Promise(function (resolve, reject) { var rows = _this3.table.rowManager.getDisplayRows(_this3.displayIndex - 1); var index = rows.indexOf(row); if (index > -1) { var page = _this3.size === true ? 1 : Math.ceil((index + 1) / _this3.size); _this3.setPage(page).then(function () { resolve(); }).catch(function () { reject(); }); } else { console.warn("Pagination Error - Requested row is not visible"); reject(); } }); }; Page.prototype.setPageSize = function (size) { if (size !== true) { size = parseInt(size); } if (size > 0) { this.size = size; } if (this.pageSizeSelect) { // this.pageSizeSelect.value = size; this.generatePageSizeSelectList(); } if (this.table.options.persistence && this.table.modExists("persistence", true) && this.table.modules.persistence.config.page) { this.table.modules.persistence.save("page"); } }; //setup the pagination buttons Page.prototype._setPageButtons = function () { var self = this; var leftSize = Math.floor((this.count - 1) / 2); var rightSize = Math.ceil((this.count - 1) / 2); var min = this.max - this.page + leftSize + 1 < this.count ? this.max - this.count + 1 : Math.max(this.page - leftSize, 1); var max = this.page <= rightSize ? Math.min(this.count, this.max) : Math.min(this.page + rightSize, this.max); while (self.pagesElement.firstChild) { self.pagesElement.removeChild(self.pagesElement.firstChild); }if (self.page == 1) { self.firstBut.disabled = true; self.prevBut.disabled = true; } else { self.firstBut.disabled = false; self.prevBut.disabled = false; } if (self.page == self.max) { self.lastBut.disabled = true; self.nextBut.disabled = true; } else { self.lastBut.disabled = false; self.nextBut.disabled = false; } for (var i = min; i <= max; i++) { if (i > 0 && i <= self.max) { self.pagesElement.appendChild(self._generatePageButton(i)); } } this.footerRedraw(); }; Page.prototype._generatePageButton = function (page) { var self = this, button = document.createElement("button"); button.classList.add("tabulator-page"); if (page == self.page) { button.classList.add("active"); } button.setAttribute("type", "button"); button.setAttribute("role", "button"); self.table.modules.localize.bind("pagination|page_title", function (value) { button.setAttribute("aria-label", value + " " + page); button.setAttribute("title", value + " " + page); }); button.setAttribute("data-page", page); button.textContent = page; button.addEventListener("click", function (e) { self.setPage(page).then(function () {}).catch(function () {}); }); return button; }; //previous page Page.prototype.previousPage = function () { var _this4 = this; return new Promise(function (resolve, reject) { if (_this4.page > 1) { _this4.page--; _this4.trigger().then(function () { resolve(); }).catch(function () { reject(); }); if (_this4.table.options.persistence && _this4.table.modExists("persistence", true) && _this4.table.modules.persistence.config.page) { _this4.table.modules.persistence.save("page"); } } else { console.warn("Pagination Error - Previous page would be less than page 1:", 0); reject(); } }); }; //next page Page.prototype.nextPage = function () { var _this5 = this; return new Promise(function (resolve, reject) { if (_this5.page < _this5.max) { _this5.page++; _this5.trigger().then(function () { resolve(); }).catch(function () { reject(); }); if (_this5.table.options.persistence && _this5.table.modExists("persistence", true) && _this5.table.modules.persistence.config.page) { _this5.table.modules.persistence.save("page"); } } else { if (!_this5.progressiveLoad) { console.warn("Pagination Error - Next page would be greater than maximum page of " + _this5.max + ":", _this5.max + 1); } reject(); } }); }; //return current page number Page.prototype.getPage = function () { return this.page; }; //return max page number Page.prototype.getPageMax = function () { return this.max; }; Page.prototype.getPageSize = function (size) { return this.size; }; Page.prototype.getMode = function () { return this.mode; }; //return appropriate rows for current page Page.prototype.getRows = function (data) { var output, start, end; if (this.mode == "local") { output = []; if (this.size === true) { start = 0; end = data.length; } else { start = this.size * (this.page - 1); end = start + parseInt(this.size); } this._setPageButtons(); for (var i = start; i < end; i++) { if (data[i]) { output.push(data[i]); } } return output; } else { this._setPageButtons(); return data.slice(0); } }; Page.prototype.trigger = function () { var _this6 = this; var left; return new Promise(function (resolve, reject) { switch (_this6.mode) { case "local": left = _this6.table.rowManager.scrollLeft; _this6.table.rowManager.refreshActiveData("page"); _this6.table.rowManager.scrollHorizontal(left); _this6.table.options.pageLoaded.call(_this6.table, _this6.getPage()); resolve(); break; case "remote": case "progressive_load": case "progressive_scroll": _this6.table.modules.ajax.blockActiveRequest(); _this6._getRemotePage().then(function () { resolve(); }).catch(function () { reject(); }); break; default: console.warn("Pagination Error - no such pagination mode:", _this6.mode); reject(); } }); }; Page.prototype._getRemotePage = function () { var _this7 = this; var self = this, oldParams, pageParams; return new Promise(function (resolve, reject) { if (!self.table.modExists("ajax", true)) { reject(); } //record old params and restore after request has been made oldParams = Tabulator.prototype.helpers.deepClone(self.table.modules.ajax.getParams() || {}); pageParams = self.table.modules.ajax.getParams(); //configure request params pageParams[_this7.dataSentNames.page] = self.page; //set page size if defined if (_this7.size) { pageParams[_this7.dataSentNames.size] = _this7.size; } //set sort data if defined if (_this7.table.options.ajaxSorting && _this7.table.modExists("sort")) { var sorters = self.table.modules.sort.getSort(); sorters.forEach(function (item) { delete item.column; }); pageParams[_this7.dataSentNames.sorters] = sorters; } //set filter data if defined if (_this7.table.options.ajaxFiltering && _this7.table.modExists("filter")) { var filters = self.table.modules.filter.getFilters(true, true); pageParams[_this7.dataSentNames.filters] = filters; } self.table.modules.ajax.setParams(pageParams); self.table.modules.ajax.sendRequest(_this7.progressiveLoad).then(function (data) { self._parseRemoteData(data); resolve(); }).catch(function (e) { reject(); }); self.table.modules.ajax.setParams(oldParams); }); }; Page.prototype._parseRemoteData = function (data) { var self = this, left, data, margin; if (typeof data[this.dataReceivedNames.last_page] === "undefined") { console.warn("Remote Pagination Error - Server response missing '" + this.dataReceivedNames.last_page + "' property"); } if (data[this.dataReceivedNames.data]) { this.max = parseInt(data[this.dataReceivedNames.last_page]) || 1; if (this.progressiveLoad) { switch (this.mode) { case "progressive_load": if (this.page == 1) { this.table.rowManager.setData(data[this.dataReceivedNames.data], false, this.initialLoad && this.page == 1); } else { this.table.rowManager.addRows(data[this.dataReceivedNames.data]); } if (this.page < this.max) { setTimeout(function () { self.nextPage().then(function () {}).catch(function () {}); }, self.table.options.ajaxProgressiveLoadDelay); } break; case "progressive_scroll": data = this.table.rowManager.getData().concat(data[this.dataReceivedNames.data]); this.table.rowManager.setData(data, true, this.initialLoad && this.page == 1); margin = this.table.options.ajaxProgressiveLoadScrollMargin || this.table.rowManager.element.clientHeight * 2; if (self.table.rowManager.element.scrollHeight <= self.table.rowManager.element.clientHeight + margin) { self.nextPage().then(function () {}).catch(function () {}); } break; } } else { left = this.table.rowManager.scrollLeft; this.table.rowManager.setData(data[this.dataReceivedNames.data], false, this.initialLoad && this.page == 1); this.table.rowManager.scrollHorizontal(left); this.table.columnManager.scrollHorizontal(left); this.table.options.pageLoaded.call(this.table, this.getPage()); } this.initialLoad = false; } else { console.warn("Remote Pagination Error - Server response missing '" + this.dataReceivedNames.data + "' property"); } }; //handle the footer element being redrawn Page.prototype.footerRedraw = function () { var footer = this.table.footerManager.element; if (Math.ceil(footer.clientWidth) - footer.scrollWidth < 0) { this.pagesElement.style.display = 'none'; } else { this.pagesElement.style.display = ''; if (Math.ceil(footer.clientWidth) - footer.scrollWidth < 0) { this.pagesElement.style.display = 'none'; } } }; //set the paramter names for pagination requests Page.prototype.paginationDataSentNames = { "page": "page", "size": "size", "sorters": "sorters", // "sort_dir":"sort_dir", "filters": "filters" // "filter_value":"filter_value", // "filter_type":"filter_type", }; //set the property names for pagination responses Page.prototype.paginationDataReceivedNames = { "current_page": "current_page", "last_page": "last_page", "data": "data" }; Tabulator.prototype.registerModule("page", Page);