Software: Apache. PHP/5.6.40-67+ubuntu20.04.1+deb.sury.org+1 uname -a: Linux hosting1.erectacloud.it 5.4.0-182-generic #202-Ubuntu SMP Fri Apr 26 12:29:36 UTC uid=5229(web473) gid=5117(client172) groups=5117(client172),5002(sshusers) Safe-mode: OFF (not secure) /var/www/clients/client172/web473/web/aps/xcrud/plugins/tabulator-master/src/js/ drwxr-xr-x |
Viewing file: row_manager.js (40.91 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) | var RowManager = function(table){ this.table = table; this.element = this.createHolderElement(); //containing element this.tableElement = this.createTableElement(); //table element this.columnManager = null; //hold column manager object this.height = 0; //hold height of table element this.firstRender = false; //handle first render this.renderMode = "classic"; //current rendering mode this.rows = []; //hold row data objects this.activeRows = []; //rows currently available to on display in the table this.activeRowsCount = 0; //count of active rows this.displayRows = []; //rows currently on display in the table this.displayRowsCount = 0; //count of display rows this.scrollTop = 0; this.scrollLeft = 0; this.vDomRowHeight = 20; //approximation of row heights for padding this.vDomTop = 0; //hold position for first rendered row in the virtual DOM this.vDomBottom = 0; //hold possition for last rendered row in the virtual DOM this.vDomScrollPosTop = 0; //last scroll position of the vDom top; this.vDomScrollPosBottom = 0; //last scroll position of the vDom bottom; this.vDomTopPad = 0; //hold value of padding for top of virtual DOM this.vDomBottomPad = 0; //hold value of padding for bottom of virtual DOM this.vDomMaxRenderChain = 90; //the maximum number of dom elements that can be rendered in 1 go this.vDomWindowBuffer = 0; //window row buffer before removing elements, to smooth scrolling this.vDomWindowMinTotalRows = 20; //minimum number of rows to be generated in virtual dom (prevent buffering issues on tables with tall rows) this.vDomWindowMinMarginRows = 5; //minimum number of rows to be generated in virtual dom margin this.vDomTopNewRows = []; //rows to normalize after appending to optimize render speed this.vDomBottomNewRows = []; //rows to normalize after appending to optimize render speed }; //////////////// Setup Functions ///////////////// RowManager.prototype.createHolderElement = function (){ var el = document.createElement("div"); el.classList.add("tabulator-tableHolder"); el.setAttribute("tabindex", 0); return el; }; RowManager.prototype.createTableElement = function (){ var el = document.createElement("div"); el.classList.add("tabulator-table"); return el; }; //return containing element RowManager.prototype.getElement = function(){ return this.element; }; //return table element RowManager.prototype.getTableElement = function(){ return this.tableElement; }; //return position of row in table RowManager.prototype.getRowPosition = function(row, active){ if(active){ return this.activeRows.indexOf(row); }else{ return this.rows.indexOf(row); } }; //link to column manager RowManager.prototype.setColumnManager = function(manager){ this.columnManager = manager; }; RowManager.prototype.initialize = function(){ var self = this; self.setRenderMode(); //initialize manager self.element.appendChild(self.tableElement); self.firstRender = true; //scroll header along with table body self.element.addEventListener("scroll", function(){ var left = self.element.scrollLeft; //handle horizontal scrolling if(self.scrollLeft != left){ self.columnManager.scrollHorizontal(left); if(self.table.options.groupBy){ self.table.modules.groupRows.scrollHeaders(left); } if(self.table.modExists("columnCalcs")){ self.table.modules.columnCalcs.scrollHorizontal(left); } } self.scrollLeft = left; }); //handle virtual dom scrolling if(this.renderMode === "virtual"){ self.element.addEventListener("scroll", function(){ var top = self.element.scrollTop; var dir = self.scrollTop > top; //handle verical scrolling if(self.scrollTop != top){ self.scrollTop = top; self.scrollVertical(dir); if(self.table.options.ajaxProgressiveLoad == "scroll"){ self.table.modules.ajax.nextPage(self.element.scrollHeight - self.element.clientHeight - top); } }else{ self.scrollTop = top; } }); } }; ////////////////// Row Manipulation ////////////////// RowManager.prototype.findRow = function(subject){ var self = this; if(typeof subject == "object"){ if(subject instanceof Row){ //subject is row element return subject; }else if(subject instanceof RowComponent){ //subject is public row component return subject._getSelf() || false; }else if(typeof HTMLElement !== "undefined" && subject instanceof HTMLElement){ //subject is a HTML element of the row let match = self.rows.find(function(row){ return row.element === subject; }); return match || false; } }else if(typeof subject == "undefined" || subject === null){ return false; }else{ //subject should be treated as the index of the row let match = self.rows.find(function(row){ return row.data[self.table.options.index] == subject; }); return match || false; } //catch all for any other type of input return false; }; RowManager.prototype.getRowFromDataObject = function(data){ var match = this.rows.find(function(row){ return row.data === data; }); return match || false; }; RowManager.prototype.getRowFromPosition = function(position, active){ if(active){ return this.activeRows[position]; }else{ return this.rows[position]; } }; RowManager.prototype.scrollToRow = function(row, position, ifVisible){ var rowIndex = this.getDisplayRows().indexOf(row), rowEl = row.getElement(), rowTop, offset = 0; return new Promise((resolve, reject) => { if(rowIndex > -1){ if(typeof position === "undefined"){ position = this.table.options.scrollToRowPosition; } if(typeof ifVisible === "undefined"){ ifVisible = this.table.options.scrollToRowIfVisible; } if(position === "nearest"){ switch(this.renderMode){ case"classic": rowTop = Tabulator.prototype.helpers.elOffset(rowEl).top; position = Math.abs(this.element.scrollTop - rowTop) > Math.abs(this.element.scrollTop + this.element.clientHeight - rowTop) ? "bottom" : "top"; break; case"virtual": position = Math.abs(this.vDomTop - rowIndex) > Math.abs(this.vDomBottom - rowIndex) ? "bottom" : "top"; break; } } //check row visibility if(!ifVisible){ if(Tabulator.prototype.helpers.elVisible(rowEl)){ offset = Tabulator.prototype.helpers.elOffset(rowEl).top - Tabulator.prototype.helpers.elOffset(this.element).top; if(offset > 0 && offset < this.element.clientHeight - rowEl.offsetHeight){ return false; } } } //scroll to row switch(this.renderMode){ case"classic": this.element.scrollTop = Tabulator.prototype.helpers.elOffset(rowEl).top - Tabulator.prototype.helpers.elOffset(this.element).top + this.element.scrollTop; break; case"virtual": this._virtualRenderFill(rowIndex, true); break; } //align to correct position switch(position){ case "middle": case "center": if(this.element.scrollHeight - this.element.scrollTop == this.element.clientHeight){ this.element.scrollTop = this.element.scrollTop + (rowEl.offsetTop - this.element.scrollTop) - ((this.element.scrollHeight - rowEl.offsetTop) / 2); }else{ this.element.scrollTop = this.element.scrollTop - (this.element.clientHeight / 2); } break; case "bottom": if(this.element.scrollHeight - this.element.scrollTop == this.element.clientHeight){ this.element.scrollTop = this.element.scrollTop - (this.element.scrollHeight - rowEl.offsetTop) + rowEl.offsetHeight; }else{ this.element.scrollTop = this.element.scrollTop - this.element.clientHeight + rowEl.offsetHeight; } break; } resolve(); }else{ console.warn("Scroll Error - Row not visible"); reject("Scroll Error - Row not visible"); } }); }; ////////////////// Data Handling ////////////////// RowManager.prototype.setData = function(data, renderInPosition){ var self = this; return new Promise((resolve, reject)=>{ if(renderInPosition && this.getDisplayRows().length){ if(self.table.options.pagination){ self._setDataActual(data, true); }else{ this.reRenderInPosition(function(){ self._setDataActual(data); }); } }else{ if(this.table.options.autoColumns){ this.table.columnManager.generateColumnsFromRowData(data); } this.resetScroll(); this._setDataActual(data); } resolve(); }); }; RowManager.prototype._setDataActual = function(data, renderInPosition){ var self = this; self.table.options.dataLoading.call(this.table, data); this._wipeElements(); if(this.table.options.history && this.table.modExists("history")){ this.table.modules.history.clear(); } if(Array.isArray(data)){ if(this.table.modExists("selectRow")){ this.table.modules.selectRow.clearSelectionData(); } if(this.table.options.reactiveData && this.table.modExists("reactiveData", true)){ this.table.modules.reactiveData.watchData(data); } data.forEach(function(def, i){ if(def && typeof def === "object"){ var row = new Row(def, self); self.rows.push(row); }else{ console.warn("Data Loading Warning - Invalid row data detected and ignored, expecting object but received:", def); } }); self.table.options.dataLoaded.call(this.table, data); self.refreshActiveData(false, false, renderInPosition); }else{ console.error("Data Loading Error - Unable to process data due to invalid data type \nExpecting: array \nReceived: ", typeof data, "\nData: ", data); } }; RowManager.prototype._wipeElements = function(){ this.rows.forEach(function(row){ row.wipe(); }); if(this.table.options.groupBy && this.table.modExists("groupRows")){ this.table.modules.groupRows.wipe(); } this.rows = []; } RowManager.prototype.deleteRow = function(row, blockRedraw){ var allIndex = this.rows.indexOf(row), activeIndex = this.activeRows.indexOf(row); if(activeIndex > -1){ this.activeRows.splice(activeIndex, 1); } if(allIndex > -1){ this.rows.splice(allIndex, 1); } this.setActiveRows(this.activeRows); this.displayRowIterator(function(rows){ var displayIndex = rows.indexOf(row); if(displayIndex > -1){ rows.splice(displayIndex, 1); } }); if(!blockRedraw){ this.reRenderInPosition(); } this.table.options.rowDeleted.call(this.table, row.getComponent()); this.table.options.dataEdited.call(this.table, this.getData()); if(this.table.options.groupBy && this.table.modExists("groupRows")){ this.table.modules.groupRows.updateGroupRows(true); }else if(this.table.options.pagination && this.table.modExists("page")){ this.refreshActiveData(false, false, true); }else{ if(this.table.options.pagination && this.table.modExists("page")){ this.refreshActiveData("page"); } } }; RowManager.prototype.addRow = function(data, pos, index, blockRedraw){ var row = this.addRowActual(data, pos, index, blockRedraw); if(this.table.options.history && this.table.modExists("history")){ this.table.modules.history.action("rowAdd", row, {data:data, pos:pos, index:index}); } return row; }; //add multiple rows RowManager.prototype.addRows = function(data, pos, index){ var self = this, length = 0, rows = []; return new Promise((resolve, reject) => { pos = this.findAddRowPos(pos); if(!Array.isArray(data)){ data = [data]; } length = data.length - 1; if((typeof index == "undefined" && pos) || (typeof index !== "undefined" && !pos)){ data.reverse(); } data.forEach(function(item, i){ var row = self.addRow(item, pos, index, true); rows.push(row); }); if(this.table.options.groupBy && this.table.modExists("groupRows")){ this.table.modules.groupRows.updateGroupRows(true); }else if(this.table.options.pagination && this.table.modExists("page")){ this.refreshActiveData(false, false, true); }else{ this.reRenderInPosition(); } //recalc column calculations if present if(this.table.modExists("columnCalcs")){ this.table.modules.columnCalcs.recalc(this.table.rowManager.activeRows); } resolve(rows); }); }; RowManager.prototype.findAddRowPos = function(pos){ if(typeof pos === "undefined"){ pos = this.table.options.addRowPos; } if(pos === "pos"){ pos = true; } if(pos === "bottom"){ pos = false; } return pos; }; RowManager.prototype.addRowActual = function(data, pos, index, blockRedraw){ var row = data instanceof Row ? data : new Row(data || {}, this), top = this.findAddRowPos(pos), dispRows; if(!index && this.table.options.pagination && this.table.options.paginationAddRow == "page"){ dispRows = this.getDisplayRows(); if(top){ if(dispRows.length){ index = dispRows[0]; }else{ if(this.activeRows.length){ index = this.activeRows[this.activeRows.length-1]; top = false; } } }else{ if(dispRows.length){ index = dispRows[dispRows.length - 1]; top = dispRows.length < this.table.modules.page.getPageSize() ? false : true; } } } if(index){ index = this.findRow(index); } if(this.table.options.groupBy && this.table.modExists("groupRows")){ this.table.modules.groupRows.assignRowToGroup(row); var groupRows = row.getGroup().rows; if(groupRows.length > 1){ if(!index || (index && groupRows.indexOf(index) == -1)){ if(top){ if(groupRows[0] !== row){ index = groupRows[0]; this._moveRowInArray(row.getGroup().rows, row, index, !top); } }else{ if(groupRows[groupRows.length -1] !== row){ index = groupRows[groupRows.length -1]; this._moveRowInArray(row.getGroup().rows, row, index, !top); } } }else{ this._moveRowInArray(row.getGroup().rows, row, index, !top); } } } if(index){ let allIndex = this.rows.indexOf(index), activeIndex = this.activeRows.indexOf(index); this.displayRowIterator(function(rows){ var displayIndex = rows.indexOf(index); if(displayIndex > -1){ rows.splice((top ? displayIndex : displayIndex + 1), 0, row); } }); if(activeIndex > -1){ this.activeRows.splice((top ? activeIndex : activeIndex + 1), 0, row); } if(allIndex > -1){ this.rows.splice((top ? allIndex : allIndex + 1), 0, row); } }else{ if(top){ this.displayRowIterator(function(rows){ rows.unshift(row); }); this.activeRows.unshift(row); this.rows.unshift(row); }else{ this.displayRowIterator(function(rows){ rows.push(row); }); this.activeRows.push(row); this.rows.push(row); } } this.setActiveRows(this.activeRows); this.table.options.rowAdded.call(this.table, row.getComponent()); this.table.options.dataEdited.call(this.table, this.getData()); if(!blockRedraw){ this.reRenderInPosition(); } return row; }; RowManager.prototype.moveRow = function(from, to, after){ if(this.table.options.history && this.table.modExists("history")){ this.table.modules.history.action("rowMove", from, {pos:this.getRowPosition(from), to:to, after:after}); } this.moveRowActual(from, to, after); this.table.options.rowMoved.call(this.table, from.getComponent()); }; RowManager.prototype.moveRowActual = function(from, to, after){ var self = this; this._moveRowInArray(this.rows, from, to, after); this._moveRowInArray(this.activeRows, from, to, after); this.displayRowIterator(function(rows){ self._moveRowInArray(rows, from, to, after); }); if(this.table.options.groupBy && this.table.modExists("groupRows")){ var toGroup = to.getGroup(); var fromGroup = from.getGroup(); if(toGroup === fromGroup){ this._moveRowInArray(toGroup.rows, from, to, after); }else{ if(fromGroup){ fromGroup.removeRow(from); } toGroup.insertRow(from, to, after); } } }; RowManager.prototype._moveRowInArray = function(rows, from, to, after){ var fromIndex, toIndex, start, end; if(from !== to){ fromIndex = rows.indexOf(from); if (fromIndex > -1) { rows.splice(fromIndex, 1); toIndex = rows.indexOf(to); if (toIndex > -1) { if(after){ rows.splice(toIndex+1, 0, from); }else{ rows.splice(toIndex, 0, from); } }else{ rows.splice(fromIndex, 0, from); } } //restyle rows if(rows === this.getDisplayRows()){ start = fromIndex < toIndex ? fromIndex : toIndex; end = toIndex > fromIndex ? toIndex : fromIndex +1; for(let i = start; i <= end; i++){ if(rows[i]){ this.styleRow(rows[i], i); } } } } }; RowManager.prototype.clearData = function(){ this.setData([]); }; RowManager.prototype.getRowIndex = function(row){ return this.findRowIndex(row, this.rows); }; RowManager.prototype.getDisplayRowIndex = function(row){ var index = this.getDisplayRows().indexOf(row); return index > -1 ? index : false; }; RowManager.prototype.nextDisplayRow = function(row, rowOnly){ var index = this.getDisplayRowIndex(row), nextRow = false; if(index !== false && index < this.displayRowsCount -1){ nextRow = this.getDisplayRows()[index+1]; } if(nextRow && (!(nextRow instanceof Row) || nextRow.type != "row")){ return this.nextDisplayRow(nextRow, rowOnly); } return nextRow; }; RowManager.prototype.prevDisplayRow = function(row, rowOnly){ var index = this.getDisplayRowIndex(row), prevRow = false; if(index){ prevRow = this.getDisplayRows()[index-1]; } if(prevRow && (!(prevRow instanceof Row) || prevRow.type != "row")){ return this.prevDisplayRow(prevRow, rowOnly); } return prevRow; }; RowManager.prototype.findRowIndex = function(row, list){ var rowIndex; row = this.findRow(row); if(row){ rowIndex = list.indexOf(row); if(rowIndex > -1){ return rowIndex; } } return false; }; RowManager.prototype.getData = function(active, transform){ var self = this, output = []; var rows = active ? self.activeRows : self.rows; rows.forEach(function(row){ output.push(row.getData(transform || "data")); }); return output; }; RowManager.prototype.getComponents = function(active){ var self = this, output = []; var rows = active ? self.activeRows : self.rows; rows.forEach(function(row){ output.push(row.getComponent()); }); return output; } RowManager.prototype.getDataCount = function(active){ return active ? this.activeRows.length : this.rows.length; }; RowManager.prototype._genRemoteRequest = function(){ var self = this, table = self.table, options = table.options, params = {}; if(table.modExists("page")){ //set sort data if defined if(options.ajaxSorting){ let sorters = self.table.modules.sort.getSort(); sorters.forEach(function(item){ delete item.column; }); params[self.table.modules.page.paginationDataSentNames.sorters] = sorters; } //set filter data if defined if(options.ajaxFiltering){ let filters = self.table.modules.filter.getFilters(true, true); params[self.table.modules.page.paginationDataSentNames.filters] = filters; } self.table.modules.ajax.setParams(params, true); } table.modules.ajax.sendRequest() .then((data)=>{ self.setData(data); }) .catch((e)=>{}); }; //choose the path to refresh data after a filter update RowManager.prototype.filterRefresh = function(){ var table = this.table, options = table.options, left = this.scrollLeft; if(options.ajaxFiltering){ if(options.pagination == "remote" && table.modExists("page")){ table.modules.page.reset(true); table.modules.page.setPage(1).then(()=>{}).catch(()=>{}); }else if(options.ajaxProgressiveLoad){ table.modules.ajax.loadData().then(()=>{}).catch(()=>{}); }else{ //assume data is url, make ajax call to url to get data this._genRemoteRequest(); } }else{ this.refreshActiveData("filter"); } this.scrollHorizontal(left); }; //choose the path to refresh data after a sorter update RowManager.prototype.sorterRefresh = function(loadOrignalData){ var table = this.table, options = this.table.options, left = this.scrollLeft; if(options.ajaxSorting){ if((options.pagination == "remote" || options.progressiveLoad) && table.modExists("page")){ table.modules.page.reset(true); table.modules.page.setPage(1).then(()=>{}).catch(()=>{}); }else if(options.ajaxProgressiveLoad){ table.modules.ajax.loadData().then(()=>{}).catch(()=>{}); }else{ //assume data is url, make ajax call to url to get data this._genRemoteRequest(); } }else{ this.refreshActiveData(loadOrignalData ? "filter" : "sort"); } this.scrollHorizontal(left); }; RowManager.prototype.scrollHorizontal = function(left){ this.scrollLeft = left; this.element.scrollLeft = left; if(this.table.options.groupBy){ this.table.modules.groupRows.scrollHeaders(left); } if(this.table.modExists("columnCalcs")){ this.table.modules.columnCalcs.scrollHorizontal(left); } }; //set active data set RowManager.prototype.refreshActiveData = function(stage, skipStage, renderInPosition){ var self = this, table = this.table, displayIndex; if(self.table.modExists("edit")){ self.table.modules.edit.cancelEdit(); } if(!stage){ stage = "all"; } if(table.options.selectable && !table.options.selectablePersistence && table.modExists("selectRow")){ table.modules.selectRow.deselectRows(); } //cascade through data refresh stages switch(stage){ case "all": case "filter": if(!skipStage){ if(table.modExists("filter")){ self.setActiveRows(table.modules.filter.filter(self.rows)); }else{ self.setActiveRows(self.rows.slice(0)); } }else{ skipStage = false; } case "sort": if(!skipStage){ if(table.modExists("sort")){ table.modules.sort.sort(this.activeRows); } }else{ skipStage = false; } //generic stage to allow for pipeline trigger after the data manipulation stage case "display": this.resetDisplayRows(); case "freeze": if(!skipStage){ if(this.table.modExists("frozenRows")){ if(table.modules.frozenRows.isFrozen()){ if(!table.modules.frozenRows.getDisplayIndex()){ table.modules.frozenRows.setDisplayIndex(this.getNextDisplayIndex()); } displayIndex = table.modules.frozenRows.getDisplayIndex(); displayIndex = self.setDisplayRows(table.modules.frozenRows.getRows(this.getDisplayRows(displayIndex - 1)), displayIndex); if(displayIndex !== true){ table.modules.frozenRows.setDisplayIndex(displayIndex); } } } }else{ skipStage = false; } case "group": if(!skipStage){ if(table.options.groupBy && table.modExists("groupRows")){ if(!table.modules.groupRows.getDisplayIndex()){ table.modules.groupRows.setDisplayIndex(this.getNextDisplayIndex()); } displayIndex = table.modules.groupRows.getDisplayIndex(); displayIndex = self.setDisplayRows(table.modules.groupRows.getRows(this.getDisplayRows(displayIndex - 1)), displayIndex); if(displayIndex !== true){ table.modules.groupRows.setDisplayIndex(displayIndex); } } }else{ skipStage = false; } case "tree": if(!skipStage){ if(table.options.dataTree && table.modExists("dataTree")){ if(!table.modules.dataTree.getDisplayIndex()){ table.modules.dataTree.setDisplayIndex(this.getNextDisplayIndex()); } displayIndex = table.modules.dataTree.getDisplayIndex(); displayIndex = self.setDisplayRows(table.modules.dataTree.getRows(this.getDisplayRows(displayIndex - 1)), displayIndex); if(displayIndex !== true){ table.modules.dataTree.setDisplayIndex(displayIndex); } } }else{ skipStage = false; } if(table.options.pagination && table.modExists("page") && !renderInPosition){ if(table.modules.page.getMode() == "local"){ table.modules.page.reset(); } } case "page": if(!skipStage){ if(table.options.pagination && table.modExists("page")){ if(!table.modules.page.getDisplayIndex()){ table.modules.page.setDisplayIndex(this.getNextDisplayIndex()); } displayIndex = table.modules.page.getDisplayIndex(); if(table.modules.page.getMode() == "local"){ table.modules.page.setMaxRows(this.getDisplayRows(displayIndex - 1).length); } displayIndex = self.setDisplayRows(table.modules.page.getRows(this.getDisplayRows(displayIndex - 1)), displayIndex); if(displayIndex !== true){ table.modules.page.setDisplayIndex(displayIndex); } } }else{ skipStage = false; } } if(Tabulator.prototype.helpers.elVisible(self.element)){ if(renderInPosition){ self.reRenderInPosition(); }else{ self.renderTable(); if(table.options.layoutColumnsOnNewData){ self.table.columnManager.redraw(true); } } } if(table.modExists("columnCalcs")){ table.modules.columnCalcs.recalc(this.activeRows); } }; RowManager.prototype.setActiveRows = function(activeRows){ this.activeRows = activeRows; this.activeRowsCount = this.activeRows.length; }; //reset display rows array RowManager.prototype.resetDisplayRows = function(){ this.displayRows = []; this.displayRows.push(this.activeRows.slice(0)); this.displayRowsCount = this.displayRows[0].length; if(this.table.modExists("frozenRows")){ this.table.modules.frozenRows.setDisplayIndex(0); } if(this.table.options.groupBy && this.table.modExists("groupRows")){ this.table.modules.groupRows.setDisplayIndex(0); } if(this.table.options.pagination && this.table.modExists("page")){ this.table.modules.page.setDisplayIndex(0); } }; RowManager.prototype.getNextDisplayIndex = function(){ return this.displayRows.length; }; //set display row pipeline data RowManager.prototype.setDisplayRows = function(displayRows, index){ var output = true; if(index && typeof this.displayRows[index] != "undefined"){ this.displayRows[index] = displayRows; output = true; }else{ this.displayRows.push(displayRows) output = index = this.displayRows.length -1; } if(index == this.displayRows.length -1){ this.displayRowsCount = this.displayRows[this.displayRows.length -1].length; } return output; }; RowManager.prototype.getDisplayRows = function(index){ if(typeof index == "undefined"){ return this.displayRows.length ? this.displayRows[this.displayRows.length -1] : []; }else{ return this.displayRows[index] || []; } }; RowManager.prototype.getVisibleRows = function(viewable){ var topEdge = this.element.scrollTop, bottomEdge = this.element.clientHeight + topEdge, topFound = false, topRow = 0, bottomRow = 0, rows = this.getDisplayRows(); if(viewable){ this.getDisplayRows(); for(var i = this.vDomTop; i <= this.vDomBottom; i++){ if(rows[i]){ if(!topFound){ if((topEdge - rows[i].getElement().offsetTop) >= 0){ topRow = i; }else{ topFound = true; } }else{ if(bottomEdge - rows[i].getElement().offsetTop >= 0){ bottomRow = i; }else{ break; } } } } }else{ topRow = this.vDomTop; bottomRow = this.vDomBottom; } return rows.slice(topRow, bottomRow + 1); }; //repeat action accross display rows RowManager.prototype.displayRowIterator = function(callback){ this.displayRows.forEach(callback); this.displayRowsCount = this.displayRows[this.displayRows.length -1].length; }; //return only actual rows (not group headers etc) RowManager.prototype.getRows = function(){ return this.rows; }; ///////////////// Table Rendering ///////////////// //trigger rerender of table in current position RowManager.prototype.reRenderInPosition = function(callback){ if(this.getRenderMode() == "virtual"){ var scrollTop = this.element.scrollTop; var topRow = false; var topOffset = false; var left = this.scrollLeft; var rows = this.getDisplayRows(); for(var i = this.vDomTop; i <= this.vDomBottom; i++){ if(rows[i]){ var diff = scrollTop - rows[i].getElement().offsetTop; if(topOffset === false || Math.abs(diff) < topOffset){ topOffset = diff; topRow = i; }else{ break; } } } if(callback){ callback(); } this._virtualRenderFill((topRow === false ? this.displayRowsCount - 1 : topRow), true, topOffset || 0); this.scrollHorizontal(left); }else{ this.renderTable(); if(callback){ callback(); } } }; RowManager.prototype.setRenderMode = function(){ if((this.table.element.clientHeight || this.table.options.height) && this.table.options.virtualDom){ this.renderMode = "virtual"; }else{ this.renderMode = "classic"; } }; RowManager.prototype.getRenderMode = function(){ return this.renderMode; }; RowManager.prototype.renderTable = function(){ var self = this; self.table.options.renderStarted.call(this.table); self.element.scrollTop = 0; switch(self.renderMode){ case "classic": self._simpleRender(); break; case "virtual": self._virtualRenderFill(); break; } if(self.firstRender){ if(self.displayRowsCount){ self.firstRender = false; self.table.modules.layout.layout(); }else{ self.renderEmptyScroll(); } } if(self.table.modExists("frozenColumns")){ self.table.modules.frozenColumns.layout(); } if(!self.displayRowsCount){ if(self.table.options.placeholder){ if(this.renderMode){ self.table.options.placeholder.setAttribute("tabulator-render-mode", this.renderMode); } self.getElement().appendChild(self.table.options.placeholder); } } self.table.options.renderComplete.call(this.table); }; //simple render on heightless table RowManager.prototype._simpleRender = function(){ this._clearVirtualDom(); if(this.displayRowsCount){ this.checkClassicModeGroupHeaderWidth(); }else{ this.renderEmptyScroll(); } }; RowManager.prototype.checkClassicModeGroupHeaderWidth = function(){ var self = this, element = this.tableElement, onlyGroupHeaders = true; self.getDisplayRows().forEach(function(row, index){ self.styleRow(row, index); element.appendChild(row.getElement()); row.initialize(true); if(row.type !== "group"){ onlyGroupHeaders = false; } }); if(onlyGroupHeaders){ element.style.minWidth = self.table.columnManager.getWidth() + "px"; }else{ element.style.minWidth = ""; } }; //show scrollbars on empty table div RowManager.prototype.renderEmptyScroll = function(){ this.tableElement.style.minWidth = this.table.columnManager.getWidth() + "px"; this.tableElement.style.minHeight = "1px"; this.tableElement.style.visibility = "hidden"; }; RowManager.prototype._clearVirtualDom = function(){ var element = this.tableElement; if(this.table.options.placeholder && this.table.options.placeholder.parentNode){ this.table.options.placeholder.parentNode.removeChild(this.table.options.placeholder); } // element.children.detach(); while(element.firstChild) element.removeChild(element.firstChild); element.style.paddingTop = ""; element.style.paddingBottom = ""; element.style.minWidth = ""; element.style.minHeight = ""; element.style.visibility = ""; this.scrollTop = 0; this.scrollLeft = 0; this.vDomTop = 0; this.vDomBottom = 0; this.vDomTopPad = 0; this.vDomBottomPad = 0; }; RowManager.prototype.styleRow = function(row, index){ var rowEl = row.getElement(); if(index % 2){ rowEl.classList.add("tabulator-row-even"); rowEl.classList.remove("tabulator-row-odd"); }else{ rowEl.classList.add("tabulator-row-odd"); rowEl.classList.remove("tabulator-row-even"); } }; //full virtual render RowManager.prototype._virtualRenderFill = function(position, forceMove, offset){ var self = this, element = self.tableElement, holder = self.element, topPad = 0, rowsHeight = 0, topPadHeight = 0, i = 0, onlyGroupHeaders = true, rows = self.getDisplayRows(); position = position || 0; offset = offset || 0; if(!position){ self._clearVirtualDom(); }else{ while(element.firstChild) element.removeChild(element.firstChild); //check if position is too close to bottom of table let heightOccupied = (self.displayRowsCount - position + 1) * self.vDomRowHeight; if(heightOccupied < self.height){ position -= Math.ceil((self.height - heightOccupied ) / self.vDomRowHeight); if(position < 0){ position = 0; } } //calculate initial pad topPad = Math.min(Math.max(Math.floor(self.vDomWindowBuffer / self.vDomRowHeight), self.vDomWindowMinMarginRows), position); position -= topPad; } if(self.displayRowsCount && Tabulator.prototype.helpers.elVisible(self.element)){ self.vDomTop = position; self.vDomBottom = position -1; while ((rowsHeight <= self.height + self.vDomWindowBuffer || i < self.vDomWindowMinTotalRows) && self.vDomBottom < self.displayRowsCount -1){ var index = self.vDomBottom + 1, row = rows[index], rowHeight = 0; self.styleRow(row, index); element.appendChild(row.getElement()); if(!row.initialized){ row.initialize(true); }else{ if(!row.heightInitialized){ row.normalizeHeight(true); } } rowHeight = row.getHeight(); if(i < topPad){ topPadHeight += rowHeight; }else{ rowsHeight += rowHeight; } if(rowHeight > this.vDomWindowBuffer){ this.vDomWindowBuffer = rowHeight * 2; } if(row.type !== "group"){ onlyGroupHeaders = false; } self.vDomBottom ++; i++; } if(!position){ this.vDomTopPad = 0; //adjust rowheight to match average of rendered elements self.vDomRowHeight = Math.floor((rowsHeight + topPadHeight) / i); self.vDomBottomPad = self.vDomRowHeight * (self.displayRowsCount - self.vDomBottom -1); self.vDomScrollHeight = topPadHeight + rowsHeight + self.vDomBottomPad - self.height; }else{ self.vDomTopPad = !forceMove ? self.scrollTop - topPadHeight : (self.vDomRowHeight * this.vDomTop) + offset; self.vDomBottomPad = self.vDomBottom == self.displayRowsCount-1 ? 0 : Math.max(self.vDomScrollHeight - self.vDomTopPad - rowsHeight - topPadHeight, 0); } element.style.paddingTop = self.vDomTopPad + "px"; element.style.paddingBottom = self.vDomBottomPad + "px"; if(forceMove){ this.scrollTop = self.vDomTopPad + (topPadHeight) + offset - (this.element.scrollWidth > this.element.clientWidth ? this.element.offsetHeight - this.element.clientHeight : 0); } this.scrollTop = Math.min(this.scrollTop, this.element.scrollHeight - this.height); //adjust for horizontal scrollbar if present (and not at top of table) if(this.element.scrollWidth > this.element.offsetWidth && forceMove){ this.scrollTop += this.element.offsetHeight - this.element.clientHeight; } this.vDomScrollPosTop = this.scrollTop; this.vDomScrollPosBottom = this.scrollTop; holder.scrollTop = this.scrollTop; element.style.minWidth = onlyGroupHeaders ? self.table.columnManager.getWidth() + "px" : ""; if(self.table.options.groupBy){ if(self.table.modules.layout.getMode() != "fitDataFill" && self.displayRowsCount == self.table.modules.groupRows.countGroups()){ self.tableElement.style.minWidth = self.table.columnManager.getWidth(); } } }else{ this.renderEmptyScroll(); } }; //handle vertical scrolling RowManager.prototype.scrollVertical = function(dir){ var topDiff = this.scrollTop - this.vDomScrollPosTop; var bottomDiff = this.scrollTop - this.vDomScrollPosBottom; var margin = this.vDomWindowBuffer * 2; if(-topDiff > margin || bottomDiff > margin){ //if big scroll redraw table; var left = this.scrollLeft; this._virtualRenderFill(Math.floor((this.element.scrollTop / this.element.scrollHeight) * this.displayRowsCount)); this.scrollHorizontal(left); }else{ if(dir){ //scrolling up if(topDiff < 0){ this._addTopRow(-topDiff); } if(bottomDiff < 0){ //hide bottom row if needed if(this.vDomScrollHeight - this.scrollTop > this.vDomWindowBuffer){ this._removeBottomRow(-bottomDiff); } } }else{ //scrolling down if(topDiff >= 0){ //hide top row if needed if(this.scrollTop > this.vDomWindowBuffer){ this._removeTopRow(topDiff); } } if(bottomDiff >= 0){ this._addBottomRow(bottomDiff); } } } }; RowManager.prototype._addTopRow = function(topDiff, i=0){ var table = this.tableElement, rows = this.getDisplayRows(); if(this.vDomTop){ let index = this.vDomTop -1, topRow = rows[index], topRowHeight = topRow.getHeight() || this.vDomRowHeight; //hide top row if needed if(topDiff >= topRowHeight){ this.styleRow(topRow, index); table.insertBefore(topRow.getElement(), table.firstChild); if(!topRow.initialized || !topRow.heightInitialized){ this.vDomTopNewRows.push(topRow); if(!topRow.heightInitialized){ topRow.clearCellHeight(); } } topRow.initialize(); this.vDomTopPad -= topRowHeight; if(this.vDomTopPad < 0){ this.vDomTopPad = index * this.vDomRowHeight; } if(!index){ this.vDomTopPad = 0; } table.style.paddingTop = this.vDomTopPad + "px"; this.vDomScrollPosTop -= topRowHeight; this.vDomTop--; } topDiff = -(this.scrollTop - this.vDomScrollPosTop); if(topRow.getHeight() > this.vDomWindowBuffer){ this.vDomWindowBuffer = topRow.getHeight() * 2; } if(i < this.vDomMaxRenderChain && this.vDomTop && topDiff >= (rows[this.vDomTop -1].getHeight() || this.vDomRowHeight)){ this._addTopRow(topDiff, i+1); }else{ this._quickNormalizeRowHeight(this.vDomTopNewRows); } } }; RowManager.prototype._removeTopRow = function(topDiff){ var table = this.tableElement, topRow = this.getDisplayRows()[this.vDomTop], topRowHeight = topRow.getHeight() || this.vDomRowHeight; if(topDiff >= topRowHeight){ var rowEl = topRow.getElement(); rowEl.parentNode.removeChild(rowEl); this.vDomTopPad += topRowHeight; table.style.paddingTop = this.vDomTopPad + "px"; this.vDomScrollPosTop += this.vDomTop ? topRowHeight : topRowHeight + this.vDomWindowBuffer; this.vDomTop++; topDiff = this.scrollTop - this.vDomScrollPosTop; this._removeTopRow(topDiff); } }; RowManager.prototype._addBottomRow = function(bottomDiff, i=0){ var table = this.tableElement, rows = this.getDisplayRows(); if(this.vDomBottom < this.displayRowsCount -1){ let index = this.vDomBottom + 1, bottomRow = rows[index], bottomRowHeight = bottomRow.getHeight() || this.vDomRowHeight; //hide bottom row if needed if(bottomDiff >= bottomRowHeight){ this.styleRow(bottomRow, index); table.appendChild(bottomRow.getElement()); if(!bottomRow.initialized || !bottomRow.heightInitialized){ this.vDomBottomNewRows.push(bottomRow); if(!bottomRow.heightInitialized){ bottomRow.clearCellHeight(); } } bottomRow.initialize(); this.vDomBottomPad -= bottomRowHeight; if(this.vDomBottomPad < 0 || index == this.displayRowsCount -1){ this.vDomBottomPad = 0; } table.style.paddingBottom = this.vDomBottomPad + "px"; this.vDomScrollPosBottom += bottomRowHeight; this.vDomBottom++; } bottomDiff = this.scrollTop - this.vDomScrollPosBottom; if(bottomRow.getHeight() > this.vDomWindowBuffer){ this.vDomWindowBuffer = bottomRow.getHeight() * 2; } if(i < this.vDomMaxRenderChain && this.vDomBottom < this.displayRowsCount -1 && bottomDiff >= (rows[this.vDomBottom + 1].getHeight() || this.vDomRowHeight)){ this._addBottomRow(bottomDiff, i+1); }else{ this._quickNormalizeRowHeight(this.vDomBottomNewRows); } } }; RowManager.prototype._removeBottomRow = function(bottomDiff){ var table = this.tableElement, bottomRow = this.getDisplayRows()[this.vDomBottom], bottomRowHeight = bottomRow.getHeight() || this.vDomRowHeight; if(bottomDiff >= bottomRowHeight){ var rowEl = bottomRow.getElement(); if(rowEl.parentNode){ rowEl.parentNode.removeChild(rowEl); } this.vDomBottomPad += bottomRowHeight; if(this.vDomBottomPad < 0){ this.vDomBottomPad = 0; } table.style.paddingBottom = this.vDomBottomPad + "px"; this.vDomScrollPosBottom -= bottomRowHeight; this.vDomBottom--; bottomDiff = -(this.scrollTop - this.vDomScrollPosBottom); this._removeBottomRow(bottomDiff); } }; RowManager.prototype._quickNormalizeRowHeight = function(rows){ rows.forEach(function(row){ row.calcHeight(); }); rows.forEach(function(row){ row.setCellHeight(); }); rows.length = 0; }; //normalize height of active rows RowManager.prototype.normalizeHeight = function(){ this.activeRows.forEach(function(row){ row.normalizeHeight(); }); }; //adjust the height of the table holder to fit in the Tabulator element RowManager.prototype.adjustTableSize = function(){ if(this.renderMode === "virtual"){ this.height = this.element.clientHeight; this.vDomWindowBuffer = this.table.options.virtualDomBuffer || this.height; let otherHeight = this.columnManager.getElement().offsetHeight + (this.table.footerManager && !this.table.footerManager.external ? this.table.footerManager.getElement().offsetHeight : 0); this.element.style.minHeight = "calc(100% - " + otherHeight + "px)"; this.element.style.height = "calc(100% - " + otherHeight + "px)"; this.element.style.maxHeight = "calc(100% - " + otherHeight + "px)"; } }; //renitialize all rows RowManager.prototype.reinitialize = function(){ this.rows.forEach(function(row){ row.reinitialize(); }); }; //redraw table RowManager.prototype.redraw = function (force){ var pos = 0, left = this.scrollLeft; this.adjustTableSize(); this.table.tableWidth = this.table.element.clientWidth; if(!force){ if(this.renderMode == "classic"){ if(this.table.options.groupBy){ this.refreshActiveData("group", false, false); }else{ this._simpleRender(); } }else{ this.reRenderInPosition(); this.scrollHorizontal(left); } if(!this.displayRowsCount){ if(this.table.options.placeholder){ this.getElement().appendChild(this.table.options.placeholder); } } }else{ this.renderTable(); } }; RowManager.prototype.resetScroll = function(){ this.element.scrollLeft = 0; this.element.scrollTop = 0; if(this.table.browser === "ie"){ var event = document.createEvent("Event"); event.initEvent("scroll", false, true); this.element.dispatchEvent(event); }else{ this.element.dispatchEvent(new Event('scroll')); } }; |
:: Command execute :: | |
--[ c99shell v.2.1 [PHP 7 Update] [1.12.2019] maintained by KaizenLouie and updated by cermmik | C99Shell Github (MySQL update) | Generation time: 0.0091 ]-- |