1 var Page =
function(table){
6 this.progressiveLoad =
false;
13 this.displayIndex = 0;
17 this.createElements();
20 Page.prototype.createElements =
function(){
24 this.element = document.createElement(
"span");
25 this.element.classList.add(
"tabulator-paginator");
27 this.pagesElement = document.createElement(
"span");
28 this.pagesElement.classList.add(
"tabulator-pages");
30 button = document.createElement(
"button");
31 button.classList.add(
"tabulator-page");
32 button.setAttribute(
"type",
"button");
33 button.setAttribute(
"role",
"button");
34 button.setAttribute(
"aria-label",
"");
35 button.setAttribute(
"title",
"");
37 this.firstBut = button.cloneNode(
true);
38 this.firstBut.setAttribute(
"data-page",
"first");
40 this.prevBut = button.cloneNode(
true);
41 this.prevBut.setAttribute(
"data-page",
"prev");
43 this.nextBut = button.cloneNode(
true);
44 this.nextBut.setAttribute(
"data-page",
"next");
46 this.lastBut = button.cloneNode(
true);
47 this.lastBut.setAttribute(
"data-page",
"last");
49 if(this.table.options.paginationSizeSelector){
50 this.pageSizeSelect = document.createElement(
"select");
51 this.pageSizeSelect.classList.add(
"tabulator-page-size");
56 Page.prototype.generatePageSizeSelectList =
function(){
59 if(this.pageSizeSelect){
61 if(Array.isArray(
this.table.options.paginationSizeSelector)){
62 pageSizes = this.table.options.paginationSizeSelector;
63 this.pageSizes = pageSizes;
65 if(this.pageSizes.indexOf(
this.size) == -1){
66 pageSizes.unshift(this.size);
70 if(this.pageSizes.indexOf(
this.size) == -1){
73 for (let i = 1; i < 5; i++){
74 pageSizes.push(this.size * i);
77 this.pageSizes = pageSizes;
79 pageSizes = this.pageSizes;
83 while(this.pageSizeSelect.firstChild) this.pageSizeSelect.removeChild(this.pageSizeSelect.firstChild);
85 pageSizes.forEach((item) => {
86 var itemEl = document.createElement(
"option");
88 itemEl.innerHTML = item;
90 this.pageSizeSelect.appendChild(itemEl);
93 this.pageSizeSelect.value = this.size;
98 Page.prototype.initialize =
function(hidden){
103 for(let key in
self.table.options.paginationDataSent){
104 self.paginationDataSentNames[key] =
self.table.options.paginationDataSent[key];
107 for(let key in
self.table.options.paginationDataReceived){
108 self.paginationDataReceivedNames[key] =
self.table.options.paginationDataReceived[key];
114 self.table.modules.localize.bind(
"pagination|first",
function(value){
115 self.firstBut.innerHTML = value;
118 self.table.modules.localize.bind(
"pagination|first_title",
function(value){
119 self.firstBut.setAttribute(
"aria-label", value);
120 self.firstBut.setAttribute(
"title", value);
123 self.table.modules.localize.bind(
"pagination|prev",
function(value){
124 self.prevBut.innerHTML = value;
127 self.table.modules.localize.bind(
"pagination|prev_title",
function(value){
128 self.prevBut.setAttribute(
"aria-label", value);
129 self.prevBut.setAttribute(
"title", value);
132 self.table.modules.localize.bind(
"pagination|next",
function(value){
133 self.nextBut.innerHTML = value;
136 self.table.modules.localize.bind(
"pagination|next_title",
function(value){
137 self.nextBut.setAttribute(
"aria-label", value);
138 self.nextBut.setAttribute(
"title", value);
141 self.table.modules.localize.bind(
"pagination|last",
function(value){
142 self.lastBut.innerHTML = value;
145 self.table.modules.localize.bind(
"pagination|last_title",
function(value){
146 self.lastBut.setAttribute(
"aria-label", value);
147 self.lastBut.setAttribute(
"title", value);
151 self.firstBut.addEventListener(
"click",
function(){
155 self.prevBut.addEventListener(
"click",
function(){
159 self.nextBut.addEventListener(
"click",
function(){
160 self.nextPage().then(()=>{}).
catch(()=>{});
163 self.lastBut.addEventListener(
"click",
function(){
164 self.setPage(
self.max);
167 if(
self.table.options.paginationElement){
168 self.element =
self.table.options.paginationElement;
171 if(this.pageSizeSelect){
172 pageSelectLabel = document.createElement(
"label");
174 self.table.modules.localize.bind(
"pagination|page_size",
function(value){
175 self.pageSizeSelect.setAttribute(
"aria-label", value);
176 self.pageSizeSelect.setAttribute(
"title", value);
177 pageSelectLabel.innerHTML = value;
180 self.element.appendChild(pageSelectLabel);
181 self.element.appendChild(
self.pageSizeSelect);
183 self.pageSizeSelect.addEventListener(
"change",
function(e){
184 self.setPageSize(
self.pageSizeSelect.value)
185 self.setPage(1).then(()=>{}).
catch(()=>{});
190 self.element.appendChild(
self.firstBut);
191 self.element.appendChild(
self.prevBut);
192 self.element.appendChild(
self.pagesElement);
193 self.element.appendChild(
self.nextBut);
194 self.element.appendChild(
self.lastBut);
196 if(!
self.table.options.paginationElement && !hidden){
197 self.table.footerManager.append(
self.element,
self);
201 self.mode =
self.table.options.pagination;
203 self.size =
self.table.options.paginationSize || Math.floor(
self.table.rowManager.getElement().clientHeight / 24);
205 self.count =
self.table.options.paginationButtonCount;
207 self.generatePageSizeSelectList();
210 Page.prototype.initializeProgressive =
function(mode){
211 this.initialize(
true);
212 this.mode =
"progressive_" + mode;
213 this.progressiveLoad =
true;
216 Page.prototype.setDisplayIndex =
function(index){
217 this.displayIndex = index;
220 Page.prototype.getDisplayIndex =
function(){
221 return this.displayIndex;
226 Page.prototype.setMaxRows =
function(rowCount){
230 this.max = Math.ceil(rowCount/this.size);
233 if(this.page > this.max){
234 this.page = this.max;
239 Page.prototype.reset =
function(force){
240 if(this.mode ==
"local" || force){
247 Page.prototype.setMaxPage =
function(max){
253 if(this.page > this.max){
254 this.page = this.max;
260 Page.prototype.setPage =
function(page){
263 return new Promise((resolve, reject)=>{
265 page = parseInt(page);
267 if(page > 0 && page <= this.max){
277 if(
self.table.options.persistence &&
self.table.modExists(
"persistence",
true) &&
self.table.modules.persistence.config.page){
278 self.table.modules.persistence.save(
"page");
282 console.warn(
"Pagination Error - Requested page is out of range of 1 - " + this.max +
":", page);
288 Page.prototype.setPageToRow =
function(row){
290 return new Promise((resolve, reject)=>{
292 var rows = this.table.rowManager.getDisplayRows(this.displayIndex - 1);
293 var index = rows.indexOf(row);
296 var page = Math.ceil((index + 1) / this.size);
306 console.warn(
"Pagination Error - Requested row is not visible");
313 Page.prototype.setPageSize =
function(size){
314 size = parseInt(size);
320 if(this.pageSizeSelect){
322 this.generatePageSizeSelectList();
325 if(this.table.options.persistence &&
this.table.modExists(
"persistence",
true) && this.table.modules.persistence.config.page){
326 this.table.modules.persistence.save(
"page");
332 Page.prototype._setPageButtons =
function(){
335 let leftSize = Math.floor((this.count-1) / 2);
336 let rightSize = Math.ceil((this.count-1) / 2);
337 let min = this.max - this.page + leftSize + 1 < this.count ? this.max-this.count+1: Math.max(this.page-leftSize,1);
338 let max = this.page <= rightSize? Math.min(this.count, this.max) :Math.min(this.page+rightSize, this.max);
340 while(
self.pagesElement.firstChild)
self.pagesElement.removeChild(
self.pagesElement.firstChild);
343 self.firstBut.disabled =
true;
344 self.prevBut.disabled =
true;
346 self.firstBut.disabled =
false;
347 self.prevBut.disabled =
false;
350 if(
self.page ==
self.max){
351 self.lastBut.disabled =
true;
352 self.nextBut.disabled =
true;
354 self.lastBut.disabled =
false;
355 self.nextBut.disabled =
false;
358 for(let i = min; i <= max; i++){
359 if(i>0 && i <=
self.max){
360 self.pagesElement.appendChild(
self._generatePageButton(i));
367 Page.prototype._generatePageButton =
function(page){
369 button = document.createElement(
"button");
371 button.classList.add(
"tabulator-page");
372 if(page ==
self.page){
373 button.classList.add(
"active");
376 button.setAttribute(
"type",
"button");
377 button.setAttribute(
"role",
"button");
378 button.setAttribute(
"aria-label",
"Show Page " + page);
379 button.setAttribute(
"title",
"Show Page " + page);
380 button.setAttribute(
"data-page", page);
381 button.textContent = page;
383 button.addEventListener(
"click",
function(e){
391 Page.prototype.previousPage =
function(){
392 return new Promise((resolve, reject)=>{
403 console.warn(
"Pagination Error - Previous page would be less than page 1:", 0);
410 Page.prototype.nextPage =
function(){
411 return new Promise((resolve, reject)=>{
412 if(this.page < this.max){
422 if(!this.progressiveLoad){
423 console.warn(
"Pagination Error - Next page would be greater than maximum page of " + this.max +
":", this.max + 1);
431 Page.prototype.getPage =
function(){
436 Page.prototype.getPageMax =
function(){
440 Page.prototype.getPageSize =
function(size){
444 Page.prototype.getMode =
function(){
449 Page.prototype.getRows =
function(data){
450 var output, start, end;
452 if(this.mode ==
"local"){
454 start = this.size * (this.page - 1);
455 end = start + parseInt(this.size);
457 this._setPageButtons();
459 for(let i = start; i < end; i++){
461 output.push(data[i]);
468 this._setPageButtons();
470 return data.slice(0);
474 Page.prototype.trigger =
function(){
477 return new Promise((resolve, reject)=>{
481 left = this.table.rowManager.scrollLeft;
483 this.table.rowManager.refreshActiveData(
"page");
484 this.table.rowManager.scrollHorizontal(left);
486 this.table.options.pageLoaded.call(this.table, this.getPage());
491 case "progressive_load":
492 case "progressive_scroll":
493 this.table.modules.ajax.blockActiveRequest();
494 this._getRemotePage()
504 console.warn(
"Pagination Error - no such pagination mode:", this.mode);
510 Page.prototype._getRemotePage =
function(){
512 oldParams, pageParams;
515 return new Promise((resolve, reject)=>{
517 if(!
self.table.modExists(
"ajax",
true)){
522 oldParams = Tabulator.prototype.helpers.deepClone(
self.table.modules.ajax.getParams() || {});
523 pageParams =
self.table.modules.ajax.getParams();
526 pageParams[this.paginationDataSentNames.page] =
self.page;
530 pageParams[this.paginationDataSentNames.size] = this.size;
534 if(this.table.options.ajaxSorting &&
this.table.modExists(
"sort")){
535 let sorters =
self.table.modules.sort.getSort();
537 sorters.forEach(
function(item){
541 pageParams[this.paginationDataSentNames.sorters] = sorters;
545 if(this.table.options.ajaxFiltering &&
this.table.modExists(
"filter")){
546 let filters =
self.table.modules.filter.getFilters(
true,
true);
547 pageParams[this.paginationDataSentNames.filters] = filters;
550 self.table.modules.ajax.setParams(pageParams);
552 self.table.modules.ajax.sendRequest(this.progressiveLoad)
554 self._parseRemoteData(data);
557 .
catch((e)=>{reject()});
559 self.table.modules.ajax.setParams(oldParams);
565 Page.prototype._parseRemoteData =
function(data){
569 if(typeof data[this.paginationDataReceivedNames.last_page] ===
"undefined"){
570 console.warn(
"Remote Pagination Error - Server response missing '" + this.paginationDataReceivedNames.last_page +
"' property");
573 if(data[this.paginationDataReceivedNames.data]){
574 this.max = parseInt(data[this.paginationDataReceivedNames.last_page]) || 1;
576 if(this.progressiveLoad){
578 case "progressive_load":
579 this.table.rowManager.addRows(data[this.paginationDataReceivedNames.data]);
580 if(this.page < this.max){
581 setTimeout(
function(){
582 self.nextPage().then(()=>{}).
catch(()=>{});
583 },
self.table.options.ajaxProgressiveLoadDelay);
587 case "progressive_scroll":
588 data = this.table.rowManager.getData().concat(data[this.paginationDataReceivedNames.data]);
590 this.table.rowManager.setData(data,
true);
592 margin = this.table.options.ajaxProgressiveLoadScrollMargin || (this.table.rowManager.element.clientHeight * 2);
594 if(
self.table.rowManager.element.scrollHeight <= (
self.table.rowManager.element.clientHeight + margin)){
595 self.nextPage().then(()=>{}).
catch(()=>{});
600 left = this.table.rowManager.scrollLeft;
602 this.table.rowManager.setData(data[this.paginationDataReceivedNames.data]);
604 this.table.rowManager.scrollHorizontal(left);
606 this.table.columnManager.scrollHorizontal(left);
608 this.table.options.pageLoaded.call(this.table, this.getPage());
612 console.warn(
"Remote Pagination Error - Server response missing '" + this.paginationDataReceivedNames.data +
"' property");
621 Page.prototype.footerRedraw =
function(){
622 var footer = this.table.footerManager.element;
624 if((Math.ceil(footer.clientWidth) - footer.scrollWidth) < 0){
625 this.pagesElement.style.display =
'none';
627 this.pagesElement.style.display =
'';
629 if((Math.ceil(footer.clientWidth) - footer.scrollWidth) < 0){
630 this.pagesElement.style.display =
'none';
636 Page.prototype.paginationDataSentNames = {
647 Page.prototype.paginationDataReceivedNames = {
648 "current_page":
"current_page",
649 "last_page":
"last_page",
653 Tabulator.prototype.registerModule(
"page", Page);