'use strict'; var total_recordss =0; //changes done by Soumya var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; /* Tabulator v3.5.3 (c) Oliver Folkerd */ /* * This file is part of the Tabulator package. * * (c) Oliver Folkerd * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * * Full Documentation & Demos can be found at: http://olifolkerd.github.io/tabulator/ * */ (function (factory) { "use strict"; if (typeof define === 'function' && define.amd) { define(['jquery'], factory); } else if (typeof module !== 'undefined' && module.exports) { module.exports = factory(require('jquery')); } else { factory(jQuery); } })(function ($, undefined) { (function () { 'use strict'; // https://tc39.github.io/ecma262/#sec-array.prototype.findIndex if (!Array.prototype.findIndex) { Object.defineProperty(Array.prototype, 'findIndex', { value: function value(predicate) { // 1. Let O be ? ToObject(this value). if (this == null) { throw new TypeError('"this" is null or not defined'); } var o = Object(this); // 2. Let len be ? ToLength(? Get(O, "length")). var len = o.length >>> 0; // 3. If IsCallable(predicate) is false, throw a TypeError exception. if (typeof predicate !== 'function') { throw new TypeError('predicate must be a function'); } // 4. If thisArg was supplied, let T be thisArg; else let T be undefined. var thisArg = arguments[1]; // 5. Let k be 0. var k = 0; // 6. Repeat, while k < len while (k < len) { // a. Let Pk be ! ToString(k). // b. Let kValue be ? Get(O, Pk). // c. Let testResult be ToBoolean(? Call(predicate, T, « kValue, k, O »)). // d. If testResult is true, return k. var kValue = o[k]; if (predicate.call(thisArg, kValue, k, o)) { return k; } // e. Increase k by 1. k++; } // 7. Return -1. return -1; } }); } // https://tc39.github.io/ecma262/#sec-array.prototype.find if (!Array.prototype.find) { Object.defineProperty(Array.prototype, 'find', { value: function value(predicate) { // 1. Let O be ? ToObject(this value). if (this == null) { throw new TypeError('"this" is null or not defined'); } var o = Object(this); // 2. Let len be ? ToLength(? Get(O, "length")). var len = o.length >>> 0; // 3. If IsCallable(predicate) is false, throw a TypeError exception. if (typeof predicate !== 'function') { throw new TypeError('predicate must be a function'); } // 4. If thisArg was supplied, let T be thisArg; else let T be undefined. var thisArg = arguments[1]; // 5. Let k be 0. var k = 0; // 6. Repeat, while k < len while (k < len) { // a. Let Pk be ! ToString(k). // b. Let kValue be ? Get(O, Pk). // c. Let testResult be ToBoolean(? Call(predicate, T, « kValue, k, O »)). // d. If testResult is true, return kValue. var kValue = o[k]; if (predicate.call(thisArg, kValue, k, o)) { return kValue; } // e. Increase k by 1. k++; } // 7. Return undefined. return undefined; } }); } var ColumnManager = function ColumnManager(table) { this.table = table; //hold parent table this.headersElement = $("
"); this.element = $("
"); //containing element this.rowManager = null; //hold row manager object this.columns = []; // column definition object this.columnsByIndex = []; //columns by index this.columnsByField = []; //columns by field this.scrollLeft = 0; this.element.prepend(this.headersElement); }; ////////////// Setup Functions ///////////////// //link to row manager ColumnManager.prototype.setRowManager = function (manager) { this.rowManager = manager; }; //return containing element ColumnManager.prototype.getElement = function () { return this.element; }; //return header containing element ColumnManager.prototype.getHeadersElement = function () { return this.headersElement; }; //scroll horizontally to match table body ColumnManager.prototype.scrollHorizontal = function (left) { var hozAdjust = 0, scrollWidth = this.element[0].scrollWidth - this.table.element.innerWidth(); this.element.scrollLeft(left); //adjust for vertical scrollbar moving table when present if (left > scrollWidth) { hozAdjust = left - scrollWidth; this.element.css("margin-left", -hozAdjust); } else { this.element.css("margin-left", 0); } //keep frozen columns fixed in position //this._calcFrozenColumnsPos(hozAdjust + 3); this.scrollLeft = left; if (this.table.extExists("frozenColumns")) { this.table.extensions.frozenColumns.layout(); } }; ///////////// Column Setup Functions ///////////// ColumnManager.prototype.setColumns = function (cols, row) { var self = this; self.headersElement.empty(); self.columns = []; self.columnsByIndex = []; self.columnsByField = []; //reset frozen columns if (self.table.extExists("frozenColumns")) { self.table.extensions.frozenColumns.reset(); } cols.forEach(function (def, i) { self._addColumn(def); }); self._reIndexColumns(); if (self.table.options.responsiveLayout && self.table.extExists("responsiveLayout", true)) { self.table.extensions.responsiveLayout.initialize(); } self.redraw(true); }; ColumnManager.prototype._addColumn = function (definition, before, nextToColumn) { var column = new Column(definition, this); var index = nextToColumn ? this.findColumnIndex(nextToColumn) : nextToColumn; if (nextToColumn && index > -1) { var parentIndex = this.columns.indexOf(nextToColumn.getTopColumn()); if (before) { this.columns.splice(parentIndex, 0, column); nextToColumn.getElement().before(column.getElement()); } else { this.columns.splice(parentIndex + 1, 0, column); nextToColumn.getElement().after(column.getElement()); } } else { if (before) { this.columns.unshift(column); this.headersElement.prepend(column.getElement()); } else { this.columns.push(column); this.headersElement.append(column.getElement()); } } return column; }; ColumnManager.prototype.registerColumnField = function (col) { if (col.definition.field) { this.columnsByField[col.definition.field] = col; } }; ColumnManager.prototype.registerColumnPosition = function (col) { this.columnsByIndex.push(col); }; ColumnManager.prototype._reIndexColumns = function () { this.columnsByIndex = []; this.columns.forEach(function (column) { column.reRegisterPosition(); }); }; //ensure column headers take up the correct amount of space in column groups ColumnManager.prototype._verticalAlignHeaders = function () { var self = this; self.columns.forEach(function (column) { column.clearVerticalAlign(); }); self.columns.forEach(function (column) { column.verticalAlign(self.table.options.columnVertAlign); }); self.rowManager.adjustTableSize(); }; //////////////// Column Details ///////////////// ColumnManager.prototype.findColumn = function (subject) { var self = this; if ((typeof subject === 'undefined' ? 'undefined' : _typeof(subject)) == "object") { if (subject instanceof Column) { //subject is column element return subject; } else if (subject instanceof ColumnComponent) { //subject is public column component return subject._getSelf() || false; } else if (subject instanceof jQuery) { //subject is a jquery element of the column header var match = self.columns.find(function (column) { return column.element === subject; }); return match || false; } } else { //subject should be treated as the field name of the column return this.columnsByField[subject] || false; } //catch all for any other type of input return false; }; ColumnManager.prototype.getColumnByField = function (field) { return this.columnsByField[field]; }; ColumnManager.prototype.getColumnByIndex = function (index) { return this.columnsByIndex[index]; }; ColumnManager.prototype.getColumns = function () { return this.columns; }; ColumnManager.prototype.findColumnIndex = function (column) { return this.columnsByIndex.findIndex(function (col) { return column === col; }); }; //return all columns that are not groups ColumnManager.prototype.getRealColumns = function () { return this.columnsByIndex; }; //travers across columns and call action ColumnManager.prototype.traverse = function (callback) { var self = this; self.columnsByIndex.forEach(function (column, i) { callback(column, i); }); }; //get defintions of actual columns ColumnManager.prototype.getDefinitions = function (active) { var self = this, output = []; self.columnsByIndex.forEach(function (column) { if (!active || active && column.visible) { output.push(column.getDefinition()); } }); return output; }; //get full nested definition tree ColumnManager.prototype.getDefinitionTree = function () { var self = this, output = []; self.columns.forEach(function (column) { output.push(column.getDefinition(true)); }); return output; }; ColumnManager.prototype.getComponents = function (structured) { var self = this, output = [], columns = structured ? self.columns : self.columnsByIndex; columns.forEach(function (column) { output.push(column.getComponent()); }); return output; }; ColumnManager.prototype.getWidth = function () { var width = 0; this.columnsByIndex.forEach(function (column) { if (column.visible) { width += column.getWidth(); } }); return width; }; ColumnManager.prototype.moveColumn = function (from, to, after) { this._moveColumnInArray(this.columns, from, to, after); this._moveColumnInArray(this.columnsByIndex, from, to, after, true); if (this.table.options.responsiveLayout && this.table.extExists("responsiveLayout", true)) { this.table.extensions.responsiveLayout.initialize(); } if (this.table.options.columnMoved) { this.table.options.columnMoved(from.getComponent(), this.table.columnManager.getComponents()); } if (this.table.options.persistentLayout && this.table.extExists("persistence", true)) { this.table.extensions.persistence.save("columns"); } }; ColumnManager.prototype._moveColumnInArray = function (columns, from, to, after, updateRows) { var fromIndex = columns.indexOf(from), toIndex; if (fromIndex > -1) { columns.splice(fromIndex, 1); toIndex = columns.indexOf(to); if (toIndex > -1) { if (after) { toIndex = toIndex + 1; } } else { toIndex = fromIndex; } columns.splice(toIndex, 0, from); if (updateRows) { this.table.rowManager.rows.forEach(function (row) { if (row.cells.length) { var cell = row.cells.splice(fromIndex, 1)[0]; row.cells.splice(toIndex, 0, cell); } }); } } }; ColumnManager.prototype.scrollToColumn = function (column, position, ifVisible) { var left = 0, offset = 0, adjust = 0; if (typeof position === "undefined") { position = this.table.options.scrollToColumnPosition; } if (typeof ifVisible === "undefined") { ifVisible = this.table.options.scrollToColumnIfVisible; } if (column.visible) { //align to correct position switch (position) { case "middle": case "center": adjust = -this.element[0].clientWidth / 2; break; case "right": adjust = column.element.innerWidth() - this.headersElement.innerWidth(); break; } //check column visibility if (!ifVisible) { offset = column.element.position().left; if (offset > 0 && offset + column.element.outerWidth() < this.element[0].clientWidth) { return false; } } //calculate scroll position left = column.element.position().left + this.element.scrollLeft() + adjust; left = Math.max(Math.min(left, this.table.rowManager.element[0].scrollWidth - this.table.rowManager.element[0].clientWidth), 0); this.table.rowManager.scrollHorizontal(left); this.scrollHorizontal(left); return true; } else { console.warn("Scroll Error - Column not visible"); return false; } }; //////////////// Cell Management ///////////////// ColumnManager.prototype.generateCells = function (row) { var self = this; var cells = []; self.columnsByIndex.forEach(function (column) { cells.push(column.generateCell(row)); }); return cells; }; //////////////// Column Management ///////////////// ColumnManager.prototype.getFlexBaseWidth = function () { var self = this, totalWidth = self.table.element.innerWidth(), //table element width fixedWidth = 0; //adjust for vertical scrollbar if present if (self.rowManager.element[0].scrollHeight > self.rowManager.element.innerHeight()) { totalWidth -= self.rowManager.element[0].offsetWidth - self.rowManager.element[0].clientWidth; } this.columnsByIndex.forEach(function (column) { var width, minWidth, colWidth; if (column.visible) { width = column.definition.width || 0; minWidth = typeof column.minWidth == "undefined" ? self.table.options.columnMinWidth : parseInt(column.minWidth); if (typeof width == "string") { if (width.indexOf("%") > -1) { colWidth = totalWidth / 100 * parseInt(width); } else { colWidth = parseInt(width); } } else { colWidth = width; } fixedWidth += colWidth > minWidth ? colWidth : minWidth; } }); return fixedWidth; }; ColumnManager.prototype.addColumn = function (definition, before, nextToColumn) { var column = this._addColumn(definition, before, nextToColumn); this._reIndexColumns(); if (this.table.options.responsiveLayout && this.table.extExists("responsiveLayout", true)) { this.table.extensions.responsiveLayout.initialize(); } if (this.table.extExists("columnCalcs")) { this.table.extensions.columnCalcs.recalc(this.table.rowManager.activeRows); } this.redraw(); if (this.table.extensions.layout.getMode() != "fitColumns") { column.reinitializeWidth(); } this._verticalAlignHeaders(); this.table.rowManager.reinitialize(); }; //remove column from system ColumnManager.prototype.deregisterColumn = function (column) { var field = column.getField(), index; //remove from field list if (field) { delete this.columnsByField[field]; } //remove from index list index = this.columnsByIndex.indexOf(column); if (index > -1) { this.columnsByIndex.splice(index, 1); } //remove from column list index = this.columns.indexOf(column); if (index > -1) { this.columns.splice(index, 1); } if (this.table.options.responsiveLayout && this.table.extExists("responsiveLayout", true)) { this.table.extensions.responsiveLayout.initialize(); } this.redraw(); }; //redraw columns ColumnManager.prototype.redraw = function (force) { if (force) { if (this.element.is(":visible")) { this._verticalAlignHeaders(); } this.table.rowManager.resetScroll(); this.table.rowManager.reinitialize(); } if (this.table.extensions.layout.getMode() == "fitColumns") { this.table.extensions.layout.layout(); } else { if (force) { this.table.extensions.layout.layout(); } else { if (this.table.options.responsiveLayout && this.table.extExists("responsiveLayout", true)) { this.table.extensions.responsiveLayout.update(); } } } if (this.table.extExists("frozenColumns")) { this.table.extensions.frozenColumns.layout(); } if (this.table.extExists("columnCalcs")) { this.table.extensions.columnCalcs.recalc(this.table.rowManager.activeRows); } if (force) { if (this.table.options.persistentLayout && this.table.extExists("persistence", true)) { this.table.extensions.persistence.save("columns"); } if (this.table.extExists("columnCalcs")) { this.table.extensions.columnCalcs.redraw(); } } this.table.footerManager.redraw(); }; //public column object var ColumnComponent = function ColumnComponent(column) { this.column = column; this.type = "ColumnComponent"; }; ColumnComponent.prototype.getElement = function () { return this.column.getElement(); }; ColumnComponent.prototype.getDefinition = function () { return this.column.getDefinition(); }; ColumnComponent.prototype.getField = function () { return this.column.getField(); }; ColumnComponent.prototype.getCells = function () { var cells = []; this.column.cells.forEach(function (cell) { cells.push(cell.getComponent()); }); return cells; }; ColumnComponent.prototype.getVisibility = function () { return this.column.visible; }; ColumnComponent.prototype.show = function () { if (this.column.isGroup) { this.column.columns.forEach(function (column) { column.show(); }); } else { this.column.show(); } }; ColumnComponent.prototype.hide = function () { if (this.column.isGroup) { this.column.columns.forEach(function (column) { column.hide(); }); } else { this.column.hide(); } }; ColumnComponent.prototype.toggle = function () { if (this.column.visible) { this.hide(); } else { this.show(); } }; ColumnComponent.prototype.delete = function () { this.column.delete(); }; ColumnComponent.prototype.getSubColumns = function () { var output = []; if (this.column.columns.length) { this.column.columns.forEach(function (column) { output.push(column.getComponent()); }); } return output; }; ColumnComponent.prototype.getParentColumn = function () { return this.column.parent instanceof Column ? this.column.parent.getComponent() : false; }; ColumnComponent.prototype._getSelf = function () { return this.column; }; ColumnComponent.prototype.scrollTo = function () { this.column.table.columManager.scrollToColumn(this.column); }; var Column = function Column(def, parent) { var self = this; this.table = parent.table; this.definition = def; //column definition this.parent = parent; //hold parent object this.type = "column"; //type of element this.columns = []; //child columns this.cells = []; //cells bound to this column this.element = $("
"); //column header element this.contentElement = false; this.groupElement = $("
"); //column group holder element this.isGroup = false; this.tooltip = false; //hold column tooltip this.hozAlign = ""; //horizontal text alignment //multi dimentional filed handling this.field = ""; this.fieldStructure = ""; this.getFieldValue = ""; this.setFieldValue = ""; this.setField(this.definition.field); this.extensions = {}; //hold extension variables; this.cellEvents = { cellClick: false, cellDblClick: false, cellContext: false, cellTap: false, cellDblTap: false, cellTapHold: false }; this.width = null; //column width this.minWidth = null; //column minimum width this.widthFixed = false; //user has specified a width for this column this.visible = true; //default visible state //initialize column if (def.columns) { this.isGroup = true; def.columns.forEach(function (def, i) { var newCol = new Column(def, self); self.attachColumn(newCol); }); self.checkColumnVisibility(); } else { parent.registerColumnField(this); } if (def.rowHandle && this.table.options.movableRows !== false && this.table.extExists("moveRow")) { this.table.extensions.moveRow.setHandle(true); } this._mapDepricatedFunctionality(); this._buildHeader(); }; //////////////// Setup Functions ///////////////// Column.prototype._mapDepricatedFunctionality = function (field) { if (this.definition.tooltipHeader) { console.warn("The%c tooltipHeader%c column definition property has been depricated and will be removed in version 4.0, use %c headerTooltip%c instead.", "font-weight:bold;", "font-weight:regular;", "font-weight:bold;", "font-weight:regular;"); if (typeof this.definition.headerTooltip == "undefined") { this.definition.headerTooltip = this.definition.tooltipHeader; } } }; Column.prototype.setField = function (field) { this.field = field; this.fieldStructure = field ? field.split(".") : []; this.getFieldValue = this.fieldStructure.length > 1 ? this._getNestedData : this._getFlatData; this.setFieldValue = this.fieldStructure.length > 1 ? this._setNesteData : this._setFlatData; }; //register column position with column manager Column.prototype.registerColumnPosition = function (column) { this.parent.registerColumnPosition(column); }; //register column position with column manager Column.prototype.registerColumnField = function (column) { this.parent.registerColumnField(column); }; //trigger position registration Column.prototype.reRegisterPosition = function () { if (this.isGroup) { this.columns.forEach(function (column) { column.reRegisterPosition(); }); } else { this.registerColumnPosition(this); } }; Column.prototype.setTooltip = function () { var self = this, def = self.definition; //set header tooltips var tooltip = def.headerTooltip || def.tooltip === false ? def.headerTooltip : self.table.options.tooltipsHeader; if (tooltip) { if (tooltip === true) { if (def.field) { self.table.extensions.localize.bind("columns|" + def.field, function (value) { self.element.attr("title", value || def.title); }); } else { self.element.attr("title", def.title); } } else { if (typeof tooltip == "function") { tooltip = tooltip(self.getComponent()); if (tooltip === false) { tooltip = ""; } } self.element.attr("title", tooltip); } } else { self.element.attr("title", ""); } }; //build header element Column.prototype._buildHeader = function () { var self = this, def = self.definition, dblTap, tapHold, tap; self.element.empty(); self.contentElement = self._buildColumnHeaderContent(); self.element.append(self.contentElement); if (self.isGroup) { self._buildGroupHeader(); } else { self._buildColumnHeader(); } self.setTooltip(); //set resizable handles if (self.table.options.resizableColumns && self.table.extExists("resizeColumns")) { self.table.extensions.resizeColumns.initializeColumn("header", self, self.element); } //set resizable handles if (def.headerFilter && self.table.extExists("filter") && self.table.extExists("edit")) { if (typeof def.headerFilterPlaceholder !== "undefined" && def.field) { self.table.extensions.localize.setHeaderFilterColumnPlaceholder(def.field, def.headerFilterPlaceholder); } self.table.extensions.filter.initializeColumn(self); } //set resizable handles if (self.table.extExists("frozenColumns")) { self.table.extensions.frozenColumns.initializeColumn(self); } //set movable column if (self.table.options.movableColumns && !self.isGroup && self.table.extExists("moveColumn")) { self.table.extensions.moveColumn.initializeColumn(self); } //set calcs column if ((def.topCalc || def.bottomCalc) && self.table.extExists("columnCalcs")) { self.table.extensions.columnCalcs.initializeColumn(self); } //update header tooltip on mouse enter self.element.on("mouseenter", function (e) { self.setTooltip(); }); //setup header click event bindings if (typeof def.headerClick == "function") { self.element.on("click", function (e) { def.headerClick(e, self.getComponent()); }); } if (typeof def.headerDblClick == "function") { self.element.on("dblclick", function (e) { def.headerDblClick(e, self.getComponent()); }); } if (typeof def.headerContext == "function") { self.element.on("contextmenu", function (e) { def.headerContext(e, self.getComponent()); }); } //setup header tap event bindings if (typeof def.headerTap == "function") { tap = false; self.element.on("touchstart", function (e) { tap = true; }); self.element.on("touchend", function (e) { if (tap) { def.headerTap(e, self.getComponent()); } tap = false; }); } if (typeof def.headerDblTap == "function") { dblTap = null; self.element.on("touchend", function (e) { if (dblTap) { clearTimeout(dblTap); dblTap = null; def.headerDblTap(e, self.getComponent()); } else { dblTap = setTimeout(function () { clearTimeout(dblTap); dblTap = null; }, 300); } }); } if (typeof def.headerTapHold == "function") { tapHold = null; self.element.on("touchstart", function (e) { clearTimeout(tapHold); tapHold = setTimeout(function () { clearTimeout(tapHold); tapHold = null; tap = false; def.headerTapHold(e, self.getComponent()); }, 1000); }); self.element.on("touchend", function (e) { clearTimeout(tapHold); tapHold = null; }); } //store column cell click event bindings if (typeof def.cellClick == "function") { self.cellEvents.cellClick = def.cellClick; } if (typeof def.cellDblClick == "function") { self.cellEvents.cellDblClick = def.cellDblClick; } if (typeof def.cellContext == "function") { self.cellEvents.cellContext = def.cellContext; } //setup column cell tap event bindings if (typeof def.cellTap == "function") { self.cellEvents.cellTap = def.cellTap; } if (typeof def.cellDblTap == "function") { self.cellEvents.cellDblTap = def.cellDblTap; } if (typeof def.cellTapHold == "function") { self.cellEvents.cellTapHold = def.cellTapHold; } //setup column cell edit callbacks if (typeof def.cellEdited == "function") { self.cellEvents.cellEdited = def.cellEdited; } if (typeof def.cellEditing == "function") { self.cellEvents.cellEditing = def.cellEditing; } if (typeof def.cellEditCancelled == "function") { self.cellEvents.cellEditCancelled = def.cellEditCancelled; } }; //build header element for header Column.prototype._buildColumnHeader = function () { var self = this, def = self.definition, table = self.table, sortable; //set column sorter if (table.extExists("sort")) { table.extensions.sort.initializeColumn(self, self.contentElement); } //set column formatter if (table.extExists("format")) { table.extensions.format.initializeColumn(self); } //set column editor if (typeof def.editor != "undefined" && table.extExists("edit")) { table.extensions.edit.initializeColumn(self); } //set colum validator if (typeof def.validator != "undefined" && table.extExists("validate")) { table.extensions.validate.initializeColumn(self); } //set column mutator if (table.extExists("mutator")) { table.extensions.mutator.initializeColumn(self); } //set column accessor if (table.extExists("accessor")) { table.extensions.accessor.initializeColumn(self); } //set respoviveLayout if (_typeof(table.options.responsiveLayout) && table.extExists("responsiveLayout")) { table.extensions.responsiveLayout.initializeColumn(self); } //set column visibility if (typeof def.visible != "undefined") { if (def.visible) { self.show(true); } else { self.hide(true); } } //asign additional css classes to column header if (def.cssClass) { self.element.addClass(def.cssClass); } if (def.field) { this.element.attr("tabulator-field", def.field); } //set min width if present self.setMinWidth(typeof def.minWidth == "undefined" ? self.table.options.columnMinWidth : def.minWidth); self.reinitializeWidth(); //set tooltip if present self.tooltip = self.definition.tooltip || self.definition.tooltip === false ? self.definition.tooltip : self.table.options.tooltips; //set orizontal text alignment self.hozAlign = typeof self.definition.align == "undefined" ? "" : self.definition.align; }; Column.prototype._buildColumnHeaderContent = function () { var self = this, def = self.definition, table = self.table; var contentElement = $("
"); contentElement.append(self._buildColumnHeaderTitle()); return contentElement; }; //build title element of column Column.prototype._buildColumnHeaderTitle = function () { var self = this, def = self.definition, table = self.table, title; var titleHolderElement = $("
"); if (def.editableTitle) { var titleElement = $(""); titleElement.on("click", function (e) { e.stopPropagation(); $(this).focus(); }); titleElement.on("change", function () { var newTitle = $(this).val(); def.title = newTitle; table.options.columnTitleChanged(self.getComponent()); }); titleHolderElement.append(titleElement); if (def.field) { table.extensions.localize.bind("columns|" + def.field, function (text) { titleElement.val(text || def.title || " "); }); } else { titleElement.val(def.title || " "); } } else { if (def.field) { table.extensions.localize.bind("columns|" + def.field, function (text) { self._formatColumnHeaderTitle(titleHolderElement, text || def.title || " "); }); } else { self._formatColumnHeaderTitle(titleHolderElement, def.title || " "); } } return titleHolderElement; }; Column.prototype._formatColumnHeaderTitle = function (el, title) { var formatter, contents; if (this.definition.titleFormatter && this.table.extExists("format")) { formatter = this.table.extensions.format.getFormatter(this.definition.titleFormatter); contents = formatter.call(this.table.extensions.format, { getValue: function getValue() { return title; }, getElement: function getElement() { return el; } }, this.definition.titleFormatterParams || {}); el.append(contents); } else { el.html(title); } }; //build header element for column group Column.prototype._buildGroupHeader = function () { var self = this, def = self.definition, table = self.table; self.element.addClass("tabulator-col-group").attr("role", "columngroup").attr("aria-title", def.title); self.element.append(self.groupElement); }; //flat field lookup Column.prototype._getFlatData = function (data) { return data[this.field]; }; //nested field lookup Column.prototype._getNestedData = function (data) { var dataObj = data, structure = this.fieldStructure, length = structure.length, output; for (var i = 0; i < length; i++) { dataObj = dataObj[structure[i]]; output = dataObj; if (!dataObj) { break; } } return output; }; //flat field set Column.prototype._setFlatData = function (data, value) { data[this.field] = value; }; //nested field set Column.prototype._setNesteData = function (data, value) { var dataObj = data, structure = this.fieldStructure, length = structure.length; for (var i = 0; i < length; i++) { if (i == length - 1) { dataObj[structure[i]] = value; } else { if (!dataObj[structure[i]]) { dataObj[structure[i]] = {}; } dataObj = dataObj[structure[i]]; } } }; //attach column to this group Column.prototype.attachColumn = function (column) { var self = this; if (self.groupElement) { self.columns.push(column); self.groupElement.append(column.getElement()); } else { console.warn("Column Warning - Column being attached to another column instead of column group"); } }; //vertically align header in column Column.prototype.verticalAlign = function (alignment) { //calculate height of column header and group holder element var parentHeight = this.parent.isGroup ? this.parent.getGroupElement().innerHeight() : this.parent.getHeadersElement().innerHeight(); this.element.css("height", parentHeight); if (this.isGroup) { this.groupElement.css("min-height", parentHeight - this.contentElement.outerHeight()); } //vertically align cell contents if (!this.isGroup && alignment !== "top") { if (alignment === "bottom") { this.element.css({ "padding-top": this.element.innerHeight() - this.contentElement.outerHeight() }); } else { this.element.css({ "padding-top": (this.element.innerHeight() - this.contentElement.outerHeight()) / 2 }); } } this.columns.forEach(function (column) { column.verticalAlign(alignment); }); }; //clear vertical alignmenet Column.prototype.clearVerticalAlign = function () { this.element.css("padding-top", ""); this.element.css("height", ""); this.element.css("min-height", ""); this.columns.forEach(function (column) { column.clearVerticalAlign(); }); }; //// Retreive Column Information //// //return column header element Column.prototype.getElement = function () { return this.element; }; //return colunm group element Column.prototype.getGroupElement = function () { return this.groupElement; }; //return field name Column.prototype.getField = function () { return this.field; }; //return the first column in a group Column.prototype.getFirstColumn = function () { if (!this.isGroup) { return this; } else { if (this.columns.length) { return this.columns[0].getFirstColumn(); } else { return false; } } }; //return the last column in a group Column.prototype.getLastColumn = function () { if (!this.isGroup) { return this; } else { if (this.columns.length) { return this.columns[this.columns.length - 1].getLastColumn(); } else { return false; } } }; //return all columns in a group Column.prototype.getColumns = function () { return this.columns; }; //return all columns in a group Column.prototype.getCells = function () { return this.cells; }; //retreive the top column in a group of columns Column.prototype.getTopColumn = function () { if (this.parent.isGroup) { return this.parent.getTopColumn(); } else { return this; } }; //return column definition object Column.prototype.getDefinition = function (updateBranches) { var colDefs = []; if (this.isGroup && updateBranches) { this.columns.forEach(function (column) { colDefs.push(column.getDefinition(true)); }); this.definition.columns = colDefs; } return this.definition; }; //////////////////// Actions //////////////////// Column.prototype.checkColumnVisibility = function () { var visible = false; this.columns.forEach(function (column) { if (column.visible) { visible = true; } }); if (visible) { this.show(); this.parent.table.options.columnVisibilityChanged(this.getComponent(), false); } else { this.hide(); } }; //show column Column.prototype.show = function (silent, responsiveToggle) { if (!this.visible) { this.visible = true; this.element.css({ "display": "" }); this.table.columnManager._verticalAlignHeaders(); if (this.parent.isGroup) { this.parent.checkColumnVisibility(); } this.cells.forEach(function (cell) { cell.show(); }); if (this.table.options.persistentLayout && this.table.extExists("responsiveLayout", true)) { this.table.extensions.persistence.save("columns"); } if (!responsiveToggle && this.table.options.responsiveLayout && this.table.extExists("responsiveLayout", true)) { this.table.extensions.responsiveLayout.updateColumnVisibility(this, this.visible); } if (!silent) { this.table.options.columnVisibilityChanged(this.getComponent(), true); } } }; //hide column Column.prototype.hide = function (silent, responsiveToggle) { if (this.visible) { this.visible = false; this.element.css({ "display": "none" }); this.table.columnManager._verticalAlignHeaders(); if (this.parent.isGroup) { this.parent.checkColumnVisibility(); } this.cells.forEach(function (cell) { cell.hide(); }); if (this.table.options.persistentLayout && this.table.extExists("persistence", true)) { this.table.extensions.persistence.save("columns"); } if (!responsiveToggle && this.table.options.responsiveLayout && this.table.extExists("responsiveLayout", true)) { this.table.extensions.responsiveLayout.updateColumnVisibility(this, this.visible); } if (!silent) { this.table.options.columnVisibilityChanged(this.getComponent(), false); } } }; Column.prototype.matchChildWidths = function () { var childWidth = 0; if (this.contentElement && this.columns.length) { this.columns.forEach(function (column) { childWidth += column.getWidth(); }); this.contentElement.css("max-width", childWidth - 1); } }; Column.prototype.setWidth = function (width) { this.widthFixed = true; this.setWidthActual(width); }; Column.prototype.setWidthActual = function (width) { if (isNaN(width)) { width = Math.floor(this.table.element.innerWidth() / 100 * parseInt(width)); } width = Math.max(this.minWidth, width); this.width = width; this.element.css("width", width || ""); if (!this.isGroup) { this.cells.forEach(function (cell) { cell.setWidth(width); }); } if (this.parent.isGroup) { this.parent.matchChildWidths(); } //set resizable handles if (this.table.extExists("frozenColumns")) { this.table.extensions.frozenColumns.layout(); } }; Column.prototype.checkCellHeights = function () { var rows = []; this.cells.forEach(function (cell) { if (cell.row.heightInitialized) { if (cell.row.element[0].offsetParent !== null) { rows.push(cell.row); cell.row.clearCellHeight(); } else { cell.row.heightInitialized = false; } } }); rows.forEach(function (row) { row.calcHeight(); }); rows.forEach(function (row) { row.setCellHeight(); }); }; Column.prototype.getWidth = function () { return this.element.outerWidth(); }; Column.prototype.getHeight = function () { return this.element.outerHeight(); }; Column.prototype.setMinWidth = function (minWidth) { this.minWidth = minWidth; this.element.css("min-width", minWidth || ""); this.cells.forEach(function (cell) { cell.setMinWidth(minWidth); }); }; Column.prototype.delete = function () { if (this.isGroup) { this.columns.forEach(function (column) { column.delete(); }); } var cellCount = this.cells.length; for (var i = 0; i < cellCount; i++) { this.cells[0].delete(); } this.element.detach(); this.table.columnManager.deregisterColumn(this); }; //////////////// Cell Management ///////////////// //generate cell for this column Column.prototype.generateCell = function (row) { var self = this; var cell = new Cell(self, row); this.cells.push(cell); return cell; }; Column.prototype.reinitializeWidth = function (force) { this.widthFixed = false; //set width if present if (typeof this.definition.width !== "undefined" && !force) { this.setWidth(this.definition.width); } //hide header filters to prevent them altering column width if (this.table.extExists("filter")) { this.table.extensions.filter.hideHeaderFilterElements(); } this.fitToData(); //show header filters again after layout is complete if (this.table.extExists("filter")) { this.table.extensions.filter.showHeaderFilterElements(); } }; //set column width to maximum cell width Column.prototype.fitToData = function () { var self = this; if (!this.widthFixed) { this.element.css("width", ""); self.cells.forEach(function (cell) { cell.setWidth(""); }); } var maxWidth = this.element.outerWidth(); if (!self.width || !this.widthFixed) { self.cells.forEach(function (cell) { var width = cell.getWidth(); if (width > maxWidth) { maxWidth = width; } }); if (maxWidth) { self.setWidthActual(maxWidth + 1); } } }; Column.prototype.deleteCell = function (cell) { var index = this.cells.indexOf(cell); if (index > -1) { this.cells.splice(index, 1); } }; //////////////// Event Bindings ///////////////// //////////////// Object Generation ///////////////// Column.prototype.getComponent = function () { return new ColumnComponent(this); }; var RowManager = function RowManager(table) { this.table = table; this.element = $("
"); //containing element this.tableElement = $("
"); //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 = 50; //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 ///////////////// //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.append(self.tableElement); self.firstRender = true; //scroll header along with table body self.element.scroll(function () { var left = self.element[0].scrollLeft; //handle horizontal scrolling if (self.scrollLeft != left) { self.columnManager.scrollHorizontal(left); if (self.table.options.groupBy) { self.table.extensions.groupRows.scrollHeaders(left); } if (self.table.extExists("columnCalcs")) { self.table.extensions.columnCalcs.scrollHorizontal(left); } } self.scrollLeft = left; }); //handle virtual dom scrolling if (this.renderMode === "virtual") { self.element.scroll(function () { var top = self.element[0].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.extensions.ajax.nextPage(self.element[0].scrollHeight - self.element[0].clientHeight - top); } } else { self.scrollTop = top; } }); } }; ////////////////// Row Manipulation ////////////////// RowManager.prototype.findRow = function (subject) { var self = this; if ((typeof subject === 'undefined' ? 'undefined' : _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 (subject instanceof jQuery) { //subject is a jquery element of the row var 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 var _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.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), offset = 0; 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": position = Math.abs(this.element.scrollTop() - row.element.position().top) > Math.abs(this.element.scrollTop() + this.element[0].clientHeight - row.element.position().top) ? "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 (row.element.is(":visible")) { offset = row.element.offset().top - this.element.offset().top; if (offset > 0 && offset < this.element[0].clientHeight - row.element.outerHeight()) { return false; } } } //scroll to row switch (this.renderMode) { case "classic": this.element.scrollTop(row.element.offset().top - this.element.offset().top + this.element.scrollTop()); break; case "virtual": this._virtualRenderFill(rowIndex, true); break; } //align to correct position switch (position) { case "middle": case "center": this.element.scrollTop(this.element.scrollTop() - this.element[0].clientHeight / 2); break; case "bottom": this.element.scrollTop(this.element.scrollTop() - this.element[0].clientHeight + row.getElement().outerHeight()); break; } return true; } else { console.warn("Scroll Error - Row not visible"); return false; } }; ////////////////// Data Handling ////////////////// RowManager.prototype.setData = function (data, renderInPosition) { var self = this; if (renderInPosition && this.getDisplayRows().length) { if (self.table.options.pagination) { self._setDataActual(data, true); } else { this.reRenderInPosition(function () { self._setDataActual(data); }); } } else { this.resetScroll(); this._setDataActual(data); } }; RowManager.prototype._setDataActual = function (data, renderInPosition) { var self = this; self.table.options.dataLoading(data); self.rows.forEach(function (row) { row.wipe(); }); self.rows = []; if (this.table.options.history && this.table.extExists("history")) { this.table.extensions.history.clear(); } if (Array.isArray(data)) { if (this.table.extExists("selectRow")) { this.table.extensions.selectRow.clearSelectionData(); } data.forEach(function (def, i) { if (def && (typeof def === 'undefined' ? 'undefined' : _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 receved:", def); } }); self.table.options.dataLoaded(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 === 'undefined' ? 'undefined' : _typeof(data), "\nData: ", data); } }; RowManager.prototype.deleteRow = function (row) { 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); } }); this.reRenderInPosition(); this.table.options.rowDeleted(row.getComponent()); this.table.options.dataEdited(this.getData()); if (this.table.options.groupBy && this.table.extExists("groupRows")) { this.table.extensions.groupRows.updateGroupRows(true); } else if (this.table.options.pagination && this.table.extExists("page")) { this.refreshActiveData(false, false, true); } else { if (this.table.options.pagination && this.table.extExists("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.extExists("history")) { this.table.extensions.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 = []; 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.extExists("groupRows")) { this.table.extensions.groupRows.updateGroupRows(true); } else if (this.table.options.pagination && this.table.extExists("page")) { this.refreshActiveData(false, false, true); } else { this.reRenderInPosition(); } //recalc column calculations if present if (this.table.extExists("columnCalcs")) { this.table.extensions.columnCalcs.recalc(this.table.rowManager.activeRows); } return 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 = 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.extensions.page.getPageSize() ? false : true; } } } if (index) { index = this.findRow(index); } if (this.table.options.groupBy && this.table.extExists("groupRows")) { this.table.extensions.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) { var 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(row.getComponent()); this.table.options.dataEdited(this.getData()); if (!blockRedraw) { this.reRenderInPosition(); } return row; }; RowManager.prototype.moveRow = function (from, to, after) { if (this.table.options.history && this.table.extExists("history")) { this.table.extensions.history.action("rowMove", from, { pos: this.getRowPosition(from), to: to, after: after }); }; this.moveRowActual(from, to, after); this.table.options.rowMoved(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.extExists("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 (var 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.getHtml = function (active) { var data = this.getData(active), columns = [], header = "", body = "", table = ""; //build header row this.table.columnManager.getColumns().forEach(function (column) { var def = column.getDefinition(); if (column.visible && !def.hideInHtml) { header += '' + (def.title || "") + ''; columns.push(column); } }); //build body rows data.forEach(function (rowData) { var row = ""; columns.forEach(function (column) { var value = column.getFieldValue(rowData); if (typeof value === "undefined" || value === null) { value = ":"; } row += '' + value + ''; }); body += '' + row + ''; }); //build table table = '\n\n \t\t\t\t\n\n \t\t\t\t' + header + '\n\n \t\t\t\t\n\n \t\t\t\t' + body + '\n\n \t\t\t\t
'; return table; }; 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.rows.length : this.activeRows.length; }; RowManager.prototype._genRemoteRequest = function () { var self = this, table = self.table, options = table.options, params = {}; if (table.extExists("page")) { //set sort data if defined if (options.ajaxSorting) { var sorters = self.table.extensions.sort.getSort(); sorters.forEach(function (item) { delete item.column; }); params[self.table.extensions.page.paginationDataSentNames.sorters] = sorters; } //set filter data if defined if (options.ajaxFiltering) { var filters = self.table.extensions.filter.getFilters(true, true); params[self.table.extensions.page.paginationDataSentNames.filters] = filters; } self.table.extensions.ajax.setParams(params, true); } table.extensions.ajax.sendRequest(function (data) { self.setData(data); }); }; //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.extExists("page")) { table.extensions.page.reset(true); table.extensions.page.setPage(1); } 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 () { var table = this.table, options = this.table.options, left = this.scrollLeft; if (options.ajaxSorting) { if (options.pagination == "remote" && table.extExists("page")) { table.extensions.page.reset(true); table.extensions.page.setPage(1); } else { //assume data is url, make ajax call to url to get data this._genRemoteRequest(); } } else { this.refreshActiveData("sort"); } this.scrollHorizontal(left); }; RowManager.prototype.scrollHorizontal = function (left) { this.scrollLeft = left; this.element.scrollLeft(left); if (this.table.options.groupBy) { this.table.extensions.groupRows.scrollHeaders(left); } if (this.table.extExists("columnCalcs")) { this.table.extensions.columnCalcs.scrollHorizontal(left); } }; //set active data set RowManager.prototype.refreshActiveData = function (stage, skipStage, renderInPosition) { var self = this, table = this.table, displayIndex; if (!stage) { stage = "all"; } if (table.options.selectable && !table.options.selectablePersistence && table.extExists("selectRow")) { table.extensions.selectRow.deselectRows(); } //cascade through data refresh stages switch (stage) { case "all": case "filter": if (!skipStage) { if (table.extExists("filter")) { self.setActiveRows(table.extensions.filter.filter(self.rows)); } else { self.setActiveRows(self.rows.slice(0)); } } else { skipStage = false; } case "sort": if (!skipStage) { if (table.extExists("sort")) { table.extensions.sort.sort(); } } 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.extExists("frozenRows")) { if (table.extensions.frozenRows.isFrozen()) { if (!table.extensions.frozenRows.getDisplayIndex()) { table.extensions.frozenRows.setDisplayIndex(this.getNextDisplayIndex()); } displayIndex = table.extensions.frozenRows.getDisplayIndex(); displayIndex = self.setDisplayRows(table.extensions.frozenRows.getRows(this.getDisplayRows(displayIndex - 1)), displayIndex); if (displayIndex !== true) { table.extensions.frozenRows.setDisplayIndex(displayIndex); } } } } else { skipStage = false; } case "group": if (!skipStage) { if (table.options.groupBy && table.extExists("groupRows")) { if (!table.extensions.groupRows.getDisplayIndex()) { table.extensions.groupRows.setDisplayIndex(this.getNextDisplayIndex()); } displayIndex = table.extensions.groupRows.getDisplayIndex(); displayIndex = self.setDisplayRows(table.extensions.groupRows.getRows(this.getDisplayRows(displayIndex - 1)), displayIndex); if (displayIndex !== true) { table.extensions.groupRows.setDisplayIndex(displayIndex); } } } else { skipStage = false; } if (table.options.pagination && table.extExists("page") && !renderInPosition) { if (table.extensions.page.getMode() == "local") { table.extensions.page.reset(); } } case "page": if (!skipStage) { if (table.options.pagination && table.extExists("page")) { if (!table.extensions.page.getDisplayIndex()) { table.extensions.page.setDisplayIndex(this.getNextDisplayIndex()); } displayIndex = table.extensions.page.getDisplayIndex(); if (table.extensions.page.getMode() == "local") { table.extensions.page.setMaxRows(this.getDisplayRows(displayIndex - 1).length); } displayIndex = self.setDisplayRows(table.extensions.page.getRows(this.getDisplayRows(displayIndex - 1)), displayIndex); if (displayIndex !== true) { table.extensions.page.setDisplayIndex(displayIndex); } } } else { skipStage = false; } } if (self.element.is(":visible")) { if (renderInPosition) { self.reRenderInPosition(); } else { self.renderTable(); if (table.options.layoutColumnsOnNewData) { self.table.columnManager.redraw(true); } } } if (table.extExists("columnCalcs")) { table.extensions.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.extExists("frozenRows")) { this.table.extensions.frozenRows.setDisplayIndex(0); } if (this.table.options.groupBy && this.table.extExists("groupRows")) { this.table.extensions.groupRows.setDisplayIndex(0); } if (this.table.options.pagination && this.table.extExists("page")) { this.table.extensions.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] || []; } }; //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().position().top; 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(); } }; RowManager.prototype.setRenderMode = function () { if ((this.table.element.innerHeight() || 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(); 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.extensions.layout.layout(); } else { self.renderEmptyScroll(); } } if (self.table.extExists("frozenColumns")) { self.table.extensions.frozenColumns.layout(); } if (!self.displayRowsCount) { if (self.table.options.placeholder) { if (this.renderMode) { self.table.options.placeholder.attr("tabulator-render-mode", this.renderMode); } self.getElement().append(self.table.options.placeholder); } } self.table.options.renderComplete(); }; //simple render on heightless table RowManager.prototype._simpleRender = function () { var self = this, element = this.tableElement; self._clearVirtualDom(); if (self.displayRowsCount) { var onlyGroupHeaders = true; self.getDisplayRows().forEach(function (row, index) { self.styleRow(row, index); element.append(row.getElement()); row.initialize(true); if (row.type !== "group") { onlyGroupHeaders = false; } }); if (onlyGroupHeaders) { self.tableElement.css({ "min-width": self.table.columnManager.getWidth() }); } } else { self.renderEmptyScroll(); } }; //show scrollbars on empty table div RowManager.prototype.renderEmptyScroll = function () { var self = this; self.tableElement.css({ "min-width": self.table.columnManager.getWidth(), "min-height": "1px", "visibility": "hidden" }); }; RowManager.prototype._clearVirtualDom = function () { var element = this.tableElement; if (this.table.options.placeholder) { this.table.options.placeholder.detach(); } element.children().detach(); element.css({ "padding-top": "", "padding-bottom": "", "min-width": "", "min-height": "", "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) { if (index % 2) { row.element.addClass("tabulator-row-even").removeClass("tabulator-row-odd"); } else { row.element.addClass("tabulator-row-odd").removeClass("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, rows = self.getDisplayRows(); position = position || 0; offset = offset || 0; if (!position) { self._clearVirtualDom(); } else { element.children().detach(); //check if position is too close to bottom of table var heightOccpied = (self.displayRowsCount - position + 1) * self.vDomRowHeight; if (heightOccpied < self.height) { position -= Math.ceil((self.height - heightOccpied) / 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 && self.element.is(":visible")) { 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]; self.styleRow(row, index); element.append(row.getElement()); if (!row.initialized) { row.initialize(true); } else { if (!row.heightInitialized) { row.normalizeHeight(true); } } if (i < topPad) { topPadHeight += row.getHeight(); } else { rowsHeight += row.getHeight(); } 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[0].style.paddingTop = self.vDomTopPad + "px"; element[0].style.paddingBottom = self.vDomBottomPad + "px"; if (forceMove) { this.scrollTop = self.vDomTopPad + topPadHeight + offset; } this.scrollTop = Math.min(this.scrollTop, this.element[0].scrollHeight - this.height); //adjust for horizontal scrollbar if present if (this.element[0].scrollWidth > this.element[0].offsetWidt) { this.scrollTop += this.element[0].offsetHeight - this.element[0].clientHeight; } this.vDomScrollPosTop = this.scrollTop; this.vDomScrollPosBottom = this.scrollTop; holder.scrollTop(this.scrollTop); if (self.table.options.groupBy) { if (self.table.extensions.layout.getMode() != "fitDataFill" && self.displayRowsCount == self.table.extensions.groupRows.countGroups()) { self.tableElement.css({ "min-width": 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[0].scrollTop / this.element[0].scrollHeight * this.displayRowsCount)); this.scrollHorizontal(left); } else { if (dir) { //scrolling up if (topDiff < 0) { this._addTopRow(-topDiff); } if (topDiff < 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) { var i = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; var table = this.tableElement, rows = this.getDisplayRows(); if (this.vDomTop) { var 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.prepend(topRow.getElement()); 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[0].style.paddingTop = this.vDomTopPad + "px"; this.vDomScrollPosTop -= topRowHeight; this.vDomTop--; } topDiff = -(this.scrollTop - this.vDomScrollPosTop); 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) { topRow.element.detach(); this.vDomTopPad += topRowHeight; table[0].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) { var i = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; var table = this.tableElement, rows = this.getDisplayRows(); if (this.vDomBottom < this.displayRowsCount - 1) { var 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.append(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[0].style.paddingBottom = this.vDomBottomPad + "px"; this.vDomScrollPosBottom += bottomRowHeight; this.vDomBottom++; } bottomDiff = this.scrollTop - this.vDomScrollPosBottom; 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) { bottomRow.element.detach(); this.vDomBottomPad += bottomRowHeight; if (this.vDomBottomPad < 0) { this.vDomBottomPad == 0; } table[0].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 () { var self = this; self.activeRows.forEach(function (row) { row.normalizeHeight(); }); }; //adjust the height of the table holder to fit in the Tabulator element RowManager.prototype.adjustTableSize = function () { var self = this; if (this.renderMode === "virtual") { self.height = self.element.innerHeight(); self.vDomWindowBuffer = self.table.options.virtualDomBuffer || self.height; var otherHeight = self.columnManager.getElement().outerHeight() + (self.table.footerManager ? self.table.footerManager.getElement().outerHeight() : 0); // otherHeight+=27; //height of title bar //changes done by Soumya otherHeight+=36; //height of title bar //changes done by Soumya self.element.css({ "min-height": "calc(100% - " + otherHeight + "px)", "height": "calc(100% - " + otherHeight + "px)", "max-height": "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(); if (!force) { if (self.renderMode == "classic") { if (self.table.options.groupBy) { self.refreshActiveData("group", false, false); } else { this._simpleRender(); } } else { this.reRenderInPosition(); this.scrollHorizontal(left); } if (!this.displayRowsCount) { if (this.table.options.placeholder) { this.getElement().append(this.table.options.placeholder); } } } else { this.renderTable(); } }; RowManager.prototype.resetScroll = function () { this.element.scrollLeft(0); this.element.scrollTop(0); this.element.scroll(); }; //public row object var RowComponent = function RowComponent(row) { this.row = row; }; RowComponent.prototype.getData = function (transform) { return this.row.getData(transform); }; RowComponent.prototype.getElement = function () { return this.row.getElement(); }; RowComponent.prototype.getCells = function () { var cells = []; this.row.getCells().forEach(function (cell) { cells.push(cell.getComponent()); }); return cells; }; RowComponent.prototype.getCell = function (column) { return this.row.getCell(column).getComponent(); }; RowComponent.prototype.getIndex = function () { return this.row.getData("data")[this.row.table.options.index]; }; RowComponent.prototype.getPosition = function (active) { return this.row.table.rowManager.getRowPosition(this.row, active); }; RowComponent.prototype.delete = function () { this.row.delete(); }; RowComponent.prototype.scrollTo = function () { this.row.table.rowManager.scrollToRow(this.row); }; RowComponent.prototype.update = function (data) { this.row.updateData(data); }; RowComponent.prototype.normalizeHeight = function () { this.row.normalizeHeight(true); }; RowComponent.prototype.select = function () { this.row.table.extensions.selectRow.selectRows(this.row); }; RowComponent.prototype.deselect = function () { this.row.table.extensions.selectRow.deselectRows(this.row); }; RowComponent.prototype.toggleSelect = function () { this.row.table.extensions.selectRow.toggleRow(this.row); }; RowComponent.prototype._getSelf = function () { return this.row; }; RowComponent.prototype.freeze = function () { if (this.row.table.extExists("frozenRows", true)) { this.row.table.extensions.frozenRows.freezeRow(this.row); } }; RowComponent.prototype.unfreeze = function () { if (this.row.table.extExists("frozenRows", true)) { this.row.table.extensions.frozenRows.unfreezeRow(this.row); } }; RowComponent.prototype.reformat = function () { return this.row.reinitialize(); }; RowComponent.prototype.getGroup = function () { return this.row.getGroup().getComponent(); }; var Row = function Row(data, parent) { this.table = parent.table; this.parent = parent; this.data = {}; this.type = "row"; //type of element this.element = $("
"); this.extensions = {}; //hold extension variables; this.cells = []; this.height = 0; //hold element height this.outerHeight = 0; //holde lements outer height this.initialized = false; //element has been rendered this.heightInitialized = false; //element has resized cells to fit this.setData(data); this.generateElement(); }; Row.prototype.getElement = function () { return this.element; }; Row.prototype.generateElement = function () { var self = this, dblTap, tapHold, tap; //set row selection characteristics if (self.table.options.selectable !== false && self.table.extExists("selectRow")) { self.table.extensions.selectRow.initializeRow(this); } //setup movable rows if (self.table.options.movableRows !== false && self.table.extExists("moveRow")) { self.table.extensions.moveRow.initializeRow(this); } //handle row click events if (self.table.options.rowClick) { self.element.on("click", function (e) { self.table.options.rowClick(e, self.getComponent()); }); } if (self.table.options.rowDblClick) { self.element.on("dblclick", function (e) { self.table.options.rowDblClick(e, self.getComponent()); }); } if (self.table.options.rowContext) { self.element.on("contextmenu", function (e) { self.table.options.rowContext(e, self.getComponent()); }); } if (self.table.options.rowTap) { tap = false; self.element.on("touchstart", function (e) { tap = true; }); self.element.on("touchend", function (e) { if (tap) { self.table.options.rowTap(e, self.getComponent()); } tap = false; }); } if (self.table.options.rowDblTap) { dblTap = null; self.element.on("touchend", function (e) { if (dblTap) { clearTimeout(dblTap); dblTap = null; self.table.options.rowDblTap(e, self.getComponent()); } else { dblTap = setTimeout(function () { clearTimeout(dblTap); dblTap = null; }, 300); } }); } if (self.table.options.rowTapHold) { tapHold = null; self.element.on("touchstart", function (e) { clearTimeout(tapHold); tapHold = setTimeout(function () { clearTimeout(tapHold); tapHold = null; tap = false; self.table.options.rowTapHold(e, self.getComponent()); }, 1000); }); self.element.on("touchend", function (e) { clearTimeout(tapHold); tapHold = null; }); } }; Row.prototype.generateCells = function () { this.cells = this.table.columnManager.generateCells(this); }; //functions to setup on first render Row.prototype.initialize = function (force) { var self = this; if (!self.initialized || force) { self.deleteCells(); self.element.empty(); //handle frozen cells if (this.table.extExists("frozenColumns")) { this.table.extensions.frozenColumns.layoutRow(this); } this.generateCells(); self.cells.forEach(function (cell) { self.element.append(cell.getElement()); }); if (force) { self.normalizeHeight(); } //setup movable rows if (self.table.options.responsiveLayout === "collapse" && self.table.extExists("responsiveLayout")) { self.table.extensions.responsiveLayout.layoutRow(this); } if (self.table.options.rowFormatter) { self.table.options.rowFormatter(self.getComponent()); } //set resizable handles if (self.table.options.resizableRows && self.table.extExists("resizeRows")) { self.table.extensions.resizeRows.initializeRow(self); } self.initialized = true; } }; Row.prototype.reinitializeHeight = function () { this.heightInitialized = false; if (this.element[0].offsetParent !== null) { this.normalizeHeight(true); } }; Row.prototype.reinitialize = function () { this.initialized = false; this.heightInitialized = false; this.height = 0; if (this.element[0].offsetParent !== null) { this.initialize(true); } }; //get heights when doing bulk row style calcs in virtual DOM Row.prototype.calcHeight = function () { var maxHeight = 0, minHeight = this.element[0].clientHeight; this.cells.forEach(function (cell) { var height = cell.getHeight(); if (height > maxHeight) { maxHeight = height; } }); this.height = Math.max(maxHeight, minHeight); this.outerHeight = this.element[0].offsetHeight; }; //set of cells Row.prototype.setCellHeight = function () { var height = this.height; this.cells.forEach(function (cell) { cell.setHeight(height); }); this.heightInitialized = true; }; Row.prototype.clearCellHeight = function () { this.cells.forEach(function (cell) { cell.clearHeight(); }); }; //normalize the height of elements in the row Row.prototype.normalizeHeight = function (force) { if (force) { this.clearCellHeight(); } this.calcHeight(); this.setCellHeight(); }; Row.prototype.setHeight = function (height) { this.height = height; this.setCellHeight(); }; //set height of rows Row.prototype.setHeight = function (height, force) { if (this.height != height || force) { this.height = height; this.setCellHeight(); // this.outerHeight = this.element.outerHeight(); this.outerHeight = this.element[0].offsetHeight; } }; //return rows outer height Row.prototype.getHeight = function () { return this.outerHeight; }; //return rows outer Width Row.prototype.getWidth = function () { return this.element.outerWidth(); }; //////////////// Cell Management ///////////////// Row.prototype.deleteCell = function (cell) { var index = this.cells.indexOf(cell); if (index > -1) { this.cells.splice(index, 1); } }; //////////////// Data Management ///////////////// Row.prototype.setData = function (data) { var self = this; if (self.table.extExists("mutator")) { self.data = self.table.extensions.mutator.transformRow(data, "data"); } else { self.data = data; } }; //update the rows data Row.prototype.updateData = function (data) { var self = this; if (typeof data === "string") { data = JSON.parse(data); } //mutate incomming data if needed if (self.table.extExists("mutator")) { data = self.table.extensions.mutator.transformRow(data, "data"); } //set data for (var attrname in data) { self.data[attrname] = data[attrname]; } //update affected cells only for (var attrname in data) { var cell = this.getCell(attrname); if (cell) { if (cell.getValue() != data[attrname]) { cell.setValueProcessData(data[attrname]); } } } //Partial reinitialization if visible if (this.element.is(":visible")) { self.normalizeHeight(); if (self.table.options.rowFormatter) { self.table.options.rowFormatter(self.getComponent()); } } else { this.initialized = false; this.height = 0; } //self.reinitialize(); self.table.options.rowUpdated(self.getComponent()); }; Row.prototype.getData = function (transform) { var self = this; if (transform) { if (self.table.extExists("accessor")) { return self.table.extensions.accessor.transformRow(self.data, transform); } } else { return this.data; } }; Row.prototype.getCell = function (column) { var match = false, column = this.table.columnManager.findColumn(column); match = this.cells.find(function (cell) { return cell.column === column; }); return match; }, Row.prototype.getCellIndex = function (findCell) { return this.cells.findIndex(function (cell) { return cell === findCell; }); }, Row.prototype.findNextEditableCell = function (index) { var nextCell = false; if (index < this.cells.length - 1) { for (var i = index + 1; i < this.cells.length; i++) { var cell = this.cells[i]; if (cell.column.extensions.edit && cell.getElement().is(":visible")) { var allowEdit = true; if (typeof cell.column.extensions.edit.check == "function") { allowEdit = cell.column.extensions.edit.check(cell.getComponent()); } if (allowEdit) { nextCell = cell; break; } } } } return nextCell; }, Row.prototype.findPrevEditableCell = function (index) { var prevCell = false; if (index > 0) { for (var i = index - 1; i >= 0; i--) { var cell = this.cells[i], allowEdit = true; if (cell.column.extensions.edit && cell.getElement().is(":visible")) { if (typeof cell.column.extensions.edit.check == "function") { allowEdit = cell.column.extensions.edit.check(cell.getComponent()); } if (allowEdit) { prevCell = cell; break; } } } } return prevCell; }, Row.prototype.getCells = function () { return this.cells; }, ///////////////////// Actions ///////////////////// Row.prototype.delete = function () { var index = this.table.rowManager.getRowIndex(this); this.deleteActual(); if (this.table.options.history && this.table.extExists("history")) { if (index) { index = this.table.rowManager.rows[index - 1]; } this.table.extensions.history.action("rowDelete", this, { data: this.getData(), pos: !index, index: index }); }; }; Row.prototype.deleteActual = function () { var index = this.table.rowManager.getRowIndex(this); //deselect row if it is selected if (this.table.extExists("selectRow")) { this.table.extensions.selectRow._deselectRow(this.row, true); } this.table.rowManager.deleteRow(this); this.deleteCells(); //remove from group if (this.extensions.group) { this.extensions.group.removeRow(this); } //recalc column calculations if present if (this.table.extExists("columnCalcs")) { if (this.table.options.groupBy && this.table.extExists("groupRows")) { this.table.extensions.columnCalcs.recalcRowGroup(this); } else { this.table.extensions.columnCalcs.recalc(this.table.rowManager.activeRows); } } }; Row.prototype.deleteCells = function () { var cellCount = this.cells.length; for (var i = 0; i < cellCount; i++) { this.cells[0].delete(); } }; Row.prototype.wipe = function () { this.deleteCells(); this.element.children().each(function () { $(this).remove(); }); this.element.empty(); this.element.remove(); }; Row.prototype.getGroup = function () { return this.extensions.group || false; }; //////////////// Object Generation ///////////////// Row.prototype.getComponent = function () { return new RowComponent(this); }; //public row object var CellComponent = function CellComponent(cell) { this.cell = cell; }; CellComponent.prototype.getValue = function () { return this.cell.getValue(); }; CellComponent.prototype.getOldValue = function () { return this.cell.getOldValue(); }; CellComponent.prototype.getElement = function () { return $(this.cell.getElement()); }; CellComponent.prototype.getRow = function () { return this.cell.row.getComponent(); }; CellComponent.prototype.getData = function () { return this.cell.row.getData(); }; CellComponent.prototype.getField = function () { return this.cell.column.getField(); }; CellComponent.prototype.getColumn = function () { return this.cell.column.getComponent(); }; CellComponent.prototype.setValue = function (value, mutate) { if (typeof mutate == "undefined") { mutate = true; } this.cell.setValue(value, mutate); }; CellComponent.prototype.restoreOldValue = function () { this.cell.setValueActual(this.cell.getOldValue()); }; CellComponent.prototype.edit = function (force) { return this.cell.edit(force); }; CellComponent.prototype.cancelEdit = function () { this.cell.cancelEdit(force); }; CellComponent.prototype.nav = function () { return this.cell.nav(); }; CellComponent.prototype.checkHeight = function () { this.cell.checkHeight(); }; CellComponent.prototype._getSelf = function () { return this.cell; }; var Cell = function Cell(column, row) { this.table = column.table; this.column = column; this.row = row; // this.element = $("
"); this.element = null; this.value = null; this.oldValue = null; this.height = null; this.width = null; this.minWidth = null; this.build(); }; //////////////// Setup Functions ///////////////// //generate element Cell.prototype.build = function () { this.generateElement(); this.setWidth(this.column.width); this._configureCell(); this.setValueActual(this.column.getFieldValue(this.row.data)); }; Cell.prototype.generateElement = function () { this.element = document.createElement('div'); this.element.className = "tabulator-cell"; this.element.setAttribute("role", "gridcell"); this.element = $(this.element); }; Cell.prototype._configureCell = function () { var self = this, cellEvents = self.column.cellEvents, element = self.element, field = this.column.getField(), dblTap, tapHold, tap; //set text alignment element[0].style.textAlign = self.column.hozAlign; if (field) { element.attr("tabulator-field", field); } if (self.column.definition.cssClass) { element.addClass(self.column.definition.cssClass); } //set event bindings if (cellEvents.cellClick || self.table.options.cellClick) { self.element.on("click", function (e) { var component = self.getComponent(); if (cellEvents.cellClick) { cellEvents.cellClick(e, component); } if (self.table.options.cellClick) { self.table.options.cellClick(e, component); } }); } if (cellEvents.cellDblClick || this.table.options.cellDblClick) { self.element.on("dblclick", function (e) { var component = self.getComponent(); if (cellEvents.cellDblClick) { cellEvents.cellDblClick(e, component); } if (self.table.options.cellDblClick) { self.table.options.cellDblClick(e, component); } }); } if (cellEvents.cellContext || this.table.options.cellContext) { self.element.on("contextmenu", function (e) { var component = self.getComponent(); if (cellEvents.cellContext) { cellEvents.cellContext(e, component); } if (self.table.options.cellContext) { self.table.options.cellContext(e, component); } }); } if (this.table.options.tooltipGenerationMode === "hover") { //update tooltip on mouse enter self.element.on("mouseenter", function (e) { self._generateTooltip(); }); } if (cellEvents.cellTap || this.table.options.cellTap) { tap = false; self.element.on("touchstart", function (e) { tap = true; }); self.element.on("touchend", function (e) { if (tap) { var component = self.getComponent(); if (cellEvents.cellTap) { cellEvents.cellTap(e, component); } if (self.table.options.cellTap) { self.table.options.cellTap(e, component); } } tap = false; }); } if (cellEvents.cellDblTap || this.table.options.cellDblTap) { dblTap = null; self.element.on("touchend", function (e) { if (dblTap) { clearTimeout(dblTap); dblTap = null; var component = self.getComponent(); if (cellEvents.cellDblTap) { cellEvents.cellDblTap(e, component); } if (self.table.options.cellDblTap) { self.table.options.cellDblTap(e, component); } } else { dblTap = setTimeout(function () { clearTimeout(dblTap); dblTap = null; }, 300); } }); } if (cellEvents.cellTapHold || this.table.options.cellTapHold) { tapHold = null; self.element.on("touchstart", function (e) { clearTimeout(tapHold); tapHold = setTimeout(function () { clearTimeout(tapHold); tapHold = null; tap = false; var component = self.getComponent(); if (cellEvents.cellTapHold) { cellEvents.cellTapHold(e, component); } if (self.table.options.cellTapHold) { self.table.options.cellTapHold(e, component); } }, 1000); }); self.element.on("touchend", function (e) { clearTimeout(tapHold); tapHold = null; }); } if (self.column.extensions.edit) { self.table.extensions.edit.bindEditor(self); } if (self.column.definition.rowHandle && self.table.options.movableRows !== false && self.table.extExists("moveRow")) { self.table.extensions.moveRow.initializeCell(self); } //hide cell if not visible if (!self.column.visible) { self.hide(); } }; //generate cell contents Cell.prototype._generateContents = function () { var self = this; if (self.table.extExists("format")) { self.element.html(self.table.extensions.format.formatValue(self)); } else { self.element.html(self.value); } }; //generate tooltip text Cell.prototype._generateTooltip = function () { var self = this; var tooltip = self.column.tooltip; if (tooltip) { if (tooltip === true) { tooltip = self.value; } else if (typeof tooltip == "function") { tooltip = tooltip(self.getComponent()); if (tooltip === false) { tooltip = ""; } } self.element[0].setAttribute("title", tooltip); } else { self.element[0].setAttribute("title", ""); } }; //////////////////// Getters //////////////////// Cell.prototype.getElement = function () { return this.element; }; Cell.prototype.getValue = function () { return this.value; }; Cell.prototype.getOldValue = function () { return this.oldValue; }; //////////////////// Actions //////////////////// Cell.prototype.setValue = function (value, mutate) { var changed = this.setValueProcessData(value, mutate), component; if (changed) { if (this.table.options.history && this.table.extExists("history")) { this.table.extensions.history.action("cellEdit", this, { oldValue: this.oldValue, newValue: this.value }); }; component = this.getComponent(); if (this.column.cellEvents.cellEdited) { this.column.cellEvents.cellEdited(component); } this.table.options.cellEdited(component); this.table.options.dataEdited(this.table.rowManager.getData()); } if (this.table.extExists("columnCalcs")) { if (this.column.definition.topCalc || this.column.definition.bottomCalc) { if (this.table.options.groupBy && this.table.extExists("groupRows")) { this.table.extensions.columnCalcs.recalcRowGroup(this.row); } else { this.table.extensions.columnCalcs.recalc(this.table.rowManager.activeRows); } } } }; Cell.prototype.setValueProcessData = function (value, mutate) { var changed = false; if (this.value != value) { changed = true; if (mutate) { if (this.column.extensions.mutate) { value = this.table.extensions.mutator.transformCell(this, value); } } } this.setValueActual(value); return changed; }; Cell.prototype.setValueActual = function (value) { this.oldValue = this.value; this.value = value; this.column.setFieldValue(this.row.data, value); this._generateContents(); this._generateTooltip(); //set resizable handles if (this.table.options.resizableColumns && this.table.extExists("resizeColumns")) { this.table.extensions.resizeColumns.initializeColumn("cell", this.column, this.element); } //handle frozen cells if (this.table.extExists("frozenColumns")) { this.table.extensions.frozenColumns.layoutElement(this.element, this.column); } }; Cell.prototype.setWidth = function (width) { this.width = width; // this.element.css("width", width || ""); this.element[0].style.width = width ? width + "px" : ""; }; Cell.prototype.getWidth = function () { return this.width || this.element.outerWidth(); }; Cell.prototype.setMinWidth = function (minWidth) { this.minWidth = minWidth; this.element[0].style.minWidth = minWidth ? minWidth + "px" : ""; }; Cell.prototype.checkHeight = function () { var height = this.element.css("height"); this.row.reinitializeHeight(); }; Cell.prototype.clearHeight = function () { this.element[0].style.height = ""; }; Cell.prototype.setHeight = function (height) { this.height = height; this.element[0].style.height = height ? height + "px" : ""; }; Cell.prototype.getHeight = function () { return this.height || this.element.outerHeight(); }; Cell.prototype.show = function () { this.element[0].style.display = ""; }; Cell.prototype.hide = function () { this.element[0].style.display = "none"; }; Cell.prototype.edit = function (force) { if (this.table.extExists("edit", true)) { return this.table.extensions.edit.editCell(this, false, force); } }; Cell.prototype.cancelEdit = function () { if (this.table.extExists("edit", true)) { var editing = this.table.extensions.edit.getCurrentCell(); if (editing && editing._getSelf() === this) { this.table.extensions.edit.cancelEdit(); } else { console.warn("Cancel Editor Error - This cell is not currently being edited "); } } }; Cell.prototype.delete = function () { this.element.detach(); this.column.deleteCell(this); this.row.deleteCell(this); }; //////////////// Navigation ///////////////// Cell.prototype.nav = function () { var self = this, nextCell = false, index = this.row.getCellIndex(this); return { next: function next() { var nextCell = this.right(), nextRow; if (!nextCell) { nextRow = self.table.rowManager.nextDisplayRow(self.row, true); if (nextRow) { nextCell = nextRow.findNextEditableCell(-1); if (nextCell) { nextCell.edit(); return true; } } } else { return true; } return false; }, prev: function prev() { var nextCell = this.left(), prevRow; if (!nextCell) { prevRow = self.table.rowManager.prevDisplayRow(self.row, true); if (prevRow) { nextCell = prevRow.findPrevEditableCell(prevRow.cells.length); if (nextCell) { nextCell.edit(); return true; } } } else { return true; } return false; }, left: function left() { nextCell = self.row.findPrevEditableCell(index); if (nextCell) { nextCell.edit(); return true; } else { return false; } }, right: function right() { nextCell = self.row.findNextEditableCell(index); if (nextCell) { nextCell.edit(); return true; } else { return false; } }, up: function up() { var nextRow = self.table.rowManager.prevDisplayRow(self.row, true); if (nextRow) { nextRow.cells[index].edit(); } }, down: function down() { var nextRow = self.table.rowManager.nextDisplayRow(self.row, true); if (nextRow) { nextRow.cells[index].edit(); } } }; }; Cell.prototype.getIndex = function () { this.row.getCellIndex(this); }; //////////////// Object Generation ///////////////// Cell.prototype.getComponent = function () { return new CellComponent(this); }; var FooterManager = function FooterManager(table) { this.table = table; this.active = false; this.element = $(""); //containing element this.links = []; this._initialize(); }; FooterManager.prototype._initialize = function (element) { if (this.table.options.footerElement) { this.element = this.table.options.footerElement; } }; FooterManager.prototype.getElement = function () { return this.element; }; FooterManager.prototype.append = function (element, parent) { this.activate(parent); this.element.append(element); this.table.rowManager.adjustTableSize(); }; FooterManager.prototype.prepend = function (element, parent) { this.activate(parent); this.element.prepend(element); this.table.rowManager.adjustTableSize(); }; FooterManager.prototype.remove = function (element) { element.remove(); this.deactivate(); }; FooterManager.prototype.deactivate = function (force) { if (this.element.is(":empty") || force) { this.element.remove(); this.active = false; } // this.table.rowManager.adjustTableSize(); }; FooterManager.prototype.activate = function (parent) { if (!this.active) { this.active = true; this.table.element.append(this.getElement()); this.table.element.show(); } if (parent) { this.links.push(parent); } }; FooterManager.prototype.redraw = function () { this.links.forEach(function (link) { link.footerRedraw(); }); }; window.Tabulator = { columnManager: null, // hold Column Manager rowManager: null, //hold Row Manager footerManager: null, //holder Footer Manager browser: "", //hold current browser type browserSlow: false, //handle reduced functionality for slower browsers //setup options options: { height: false, //height of tabulator layout: "fitData", ///layout type "fitColumns" | "fitData" layoutColumnsOnNewData: false, //update column widths on setData fitColumns: false, //DEPRICATED - fit colums to width of screen; columnMinWidth: 40, //minimum global width for a column columnVertAlign: "top", //vertical alignment of column headers resizableColumns: true, //resizable columns resizableRows: false, //resizable rows autoResize: true, //auto resize table columns: [], //store for colum header info data: [], //default starting data tooltips: false, //Tool tip value tooltipsHeader: false, //Tool tip for headers tooltipGenerationMode: "load", //when to generate tooltips initialSort: false, //initial sorting criteria footerElement: false, //hold footer element index: "id", //filed for row index keybindings: [], //array for keybindings clipboard: false, //enable clipboard clipboardCopySelector: "active", //method of chosing which data is coppied to the clipboard clipboardCopyFormatter: "table", //convert data to a clipboard string clipboardCopyHeader: true, //include table headers in copt clipboardPasteParser: "table", //convert pasted clipboard data to rows clipboardPasteAction: "insert", //how to insert pasted data into the table clipboardCopied: function clipboardCopied() {}, //data has been copied to the clipboard clipboardPasted: function clipboardPasted() {}, //data has been pasted into the table clipboardPasteError: function clipboardPasteError() {}, //data has not successfully been pasted into the table downloadDataFormatter: false, //function to manipulate table data before it is downloaded downloadReady: function downloadReady(data, blob) { return blob; }, //function to manipulate download data downloadComplete: false, //function to manipulate download data addRowPos: "bottom", //position to insert blank rows, top|bottom selectable: "highlight", //highlight rows on hover selectableRollingSelection: true, //roll selection once maximum number of selectable rows is reached selectablePersistence: true, // maintain selection when table view is updated selectableCheck: function selectableCheck(data, row) { return true; }, //check wheather row is selectable headerFilterPlaceholder: false, //placeholder text to display in header filters history: false, //enable edit history locale: false, //current system language langs: {}, virtualDom: true, //enable DOM virtualization persistentLayout: false, //store column layout in memory persistentSort: false, //store sorting in memory persistentFilter: false, //store filters in memory persistenceID: "", //key for persistent storage persistenceMode: true, //mode for storing persistence information persistentLayoutID: "", //DEPRICATED - key for persistent storage; responsiveLayout: false, //responsive layout flags responsiveLayoutCollapseStartOpen: true, //start showing collapsed data responsiveLayoutCollapseUseFormatters: true, //responsive layout collapse formatter responsiveLayoutCollapseFormatter: false, //responsive layout collapse formatter pagination: false, //set pagination type paginationSize: false, //set number of rows to a page paginationButtonCount: 5, // set count of page button paginationElement: false, //element to hold pagination numbers paginationDataSent: {}, //pagination data sent to the server paginationDataReceived: {}, //pagination data received from the server paginator: false, //pagination url string builder paginationAddRow: "page", //add rows on table or page ajaxURL: false, //url for ajax loading ajaxParams: {}, //params for ajax loading ajaxConfig: "get", //ajax request type ajaxLoader: true, //show loader ajaxLoaderLoading: false, //loader element ajaxLoaderError: false, //loader element ajaxFiltering: false, ajaxSorting: false, ajaxProgressiveLoad: false, //progressive loading ajaxProgressiveLoadDelay: 0, //delay between requests ajaxProgressiveLoadScrollMargin: 0, //margin before scroll begins groupBy: false, //enable table grouping and set field to group by groupStartOpen: true, //starting state of group groupHeader: false, //header generation function movableColumns: false, //enable movable columns movableRows: false, //enable movable rows movableRowsConnectedTables: false, //tables for movable rows to be connected to movableRowsSender: false, movableRowsReceiver: "insert", movableRowsSendingStart: function movableRowsSendingStart() {}, movableRowsSent: function movableRowsSent() {}, movableRowsSentFailed: function movableRowsSentFailed() {}, movableRowsSendingStop: function movableRowsSendingStop() {}, movableRowsReceivingStart: function movableRowsReceivingStart() {}, movableRowsReceived: function movableRowsReceived() {}, movableRowsReceivedFailed: function movableRowsReceivedFailed() {}, movableRowsReceivingStop: function movableRowsReceivingStop() {}, scrollToRowPosition: "top", scrollToRowIfVisible: true, scrollToColumnPosition: "left", scrollToColumnIfVisible: true, rowFormatter: false, placeholder: false, //table building callbacks tableBuilding: function tableBuilding() {}, tableBuilt: function tableBuilt() {}, //render callbacks renderStarted: function renderStarted() {}, renderComplete: function renderComplete() {}, //row callbacks rowClick: false, rowDblClick: false, rowContext: false, rowTap: false, rowDblTap: false, rowTapHold: false, rowAdded: function rowAdded() {}, rowDeleted: function rowDeleted() {}, rowMoved: function rowMoved() {}, rowUpdated: function rowUpdated() {}, rowSelectionChanged: function rowSelectionChanged() {}, rowSelected: function rowSelected() {}, rowDeselected: function rowDeselected() {}, rowResized: function rowResized() {}, //cell callbacks //row callbacks cellClick: false, cellDblClick: false, cellContext: false, cellTap: false, cellDblTap: false, cellTapHold: false, cellEditing: function cellEditing() {}, cellEdited: function cellEdited() {}, cellEditCancelled: function cellEditCancelled() {}, //column callbacks columnMoved: false, columnResized: function columnResized() {}, columnTitleChanged: function columnTitleChanged() {}, columnVisibilityChanged: function columnVisibilityChanged() {}, //HTML iport callbacks htmlImporting: function htmlImporting() {}, htmlImported: function htmlImported() {}, //data callbacks dataLoading: function dataLoading() {}, dataLoaded: function dataLoaded() {}, dataEdited: function dataEdited() {}, //ajax callbacks ajaxRequesting: function ajaxRequesting() {}, ajaxResponse: false, ajaxError: function ajaxError() {}, //filtering callbacks dataFiltering: false, dataFiltered: false, //sorting callbacks dataSorting: function dataSorting() {}, dataSorted: function dataSorted() {}, //grouping callbacks groupToggleElement: "arrow", groupClosedShowCalcs: false, dataGrouping: function dataGrouping() {}, dataGrouped: false, groupVisibilityChanged: function groupVisibilityChanged() {}, groupClick: false, groupDblClick: false, groupContext: false, groupTap: false, groupDblTap: false, groupTapHold: false, columnCalcs: true, // default title //changes done by Soumya gridTitle: ' ', //changes done by Soumya //default value //changes done by Soumya columnVisibility:false, //changes done by Soumya //pagination callbacks pageLoaded: function pageLoaded() {}, //localization callbacks localized: function localized() {}, //validation has failed validationFailed: function validationFailed() {}, //history callbacks historyUndo: function historyUndo() {}, historyRedo: function historyRedo() {} }, //convert depricated functionality to new functions _mapDepricatedFunctionality: function _mapDepricatedFunctionality() { if (this.options.fitColumns) { this.options.layout = "fitColumns"; console.warn("The%c fitColumns:true%c option has been depricated and will be removed in version 4.0, use %c layout:'fitColumns'%c instead.", "font-weight:bold;", "font-weight:regular;", "font-weight:bold;", "font-weight:regular;"); } if (this.options.persistentLayoutID) { this.options.persistenceID = this.options.persistentLayoutID; console.warn("The%c persistentLayoutID%c option has been depricated and will be removed in version 4.0, use %c persistenceID%c instead.", "font-weight:bold;", "font-weight:regular;", "font-weight:bold;", "font-weight:regular;"); } if (this.options.persistentLayout === "cookie" || this.options.persistentLayout === "local") { this.options.persistenceMode = this.options.persistentLayout; this.options.persistentLayout = true; console.warn("Setting the persistent storage mode on the%c persistentLayout%c option has been depricated and will be removed in version 4.0, use %c persistenceMode%c instead.", "font-weight:bold;", "font-weight:regular;", "font-weight:bold;", "font-weight:regular;"); } if (this.options.downloadDataMutator) { this.options.downloadDataFormatter = this.options.downloadDataMutator; console.warn("The%c downloadDataMutator%c option has been depricated and will be removed in version 4.0, use %cdownloadDataFormatter%c instead.", "font-weight:bold;", "font-weight:regular;", "font-weight:bold;", "font-weight:regular;"); } }, //constructor _create: function _create() { var self = this, element = this.element; self._clearObjectPointers(); self._mapDepricatedFunctionality(); self.bindExtensions(); if (element.is("table")) { if (this.extExists("htmlTableImport", true)) { self.extensions.htmlTableImport.parseTable(); } } else { self.columnManager = new ColumnManager(self); self.rowManager = new RowManager(self); self.footerManager = new FooterManager(self); self.columnManager.setRowManager(self.rowManager); self.rowManager.setColumnManager(self.columnManager); self._buildElement(); //load initial data set this._loadInitialData(); } }, //clear pointers to objects in default config object _clearObjectPointers: function _clearObjectPointers() { this.options.columns = this.options.columns.slice(0); this.options.data = this.options.data.slice(0); }, //build tabulator element _buildElement: function _buildElement() { var element = this.element, ext = this.extensions, options = this.options; options.tableBuilding(); element.addClass("tabulator").attr("role", "grid").empty(); //set table height if (options.height) { options.height = isNaN(options.height) ? options.height : options.height + "px"; this.element.css({ "height": options.height }); } this.rowManager.initialize(); this._detectBrowser(); if (this.extExists("layout", true)) { ext.layout.initialize(options.layout); } //set localization if (options.headerFilterPlaceholder !== false) { ext.localize.setHeaderFilterPlaceholder(options.headerFilterPlaceholder); } for (var locale in options.langs) { ext.localize.installLang(locale, options.langs[locale]); } ext.localize.setLocale(options.locale); //configure placeholder element if (typeof options.placeholder == "string") { options.placeholder = $("
" + options.placeholder + "
"); } //build table elements element.append('
'+options.gridTitle+'
'); //changes done by Soumya element.append(this.columnManager.getElement()); element.append(this.rowManager.getElement()); if (options.footerElement) { this.footerManager.activate(); } if ((options.persistentLayout || options.persistentSort || options.persistentFilter) && this.extExists("persistence", true)) { ext.persistence.initialize(options.persistenceMode, options.persistenceID); } if (options.persistentLayout && this.extExists("persistence", true)) { options.columns = ext.persistence.load("columns", options.columns); } if (options.movableRows && this.extExists("moveRow")) { ext.moveRow.initialize(); } if (this.extExists("columnCalcs")) { ext.columnCalcs.initialize(); } this.columnManager.setColumns(options.columns); if (this.extExists("frozenRows")) { this.extensions.frozenRows.initialize(); } if ((options.persistentSort || options.initialSort) && this.extExists("sort", true)) { var sorters = []; if (options.persistentSort && this.extExists("persistence", true)) { sorters = ext.persistence.load("sort"); if (sorters === false && options.initialSort) { sorters = options.initialSort; } } else if (options.initialSort) { sorters = options.initialSort; } ext.sort.setSort(sorters); } if (options.persistentFilter && this.extExists("persistence", true)) { var filters = ext.persistence.load("filter"); if (filters !== false) { this.setFilter(filters); } } if (this.extExists("ajax")) { ext.ajax.initialize(); } if (options.pagination && this.extExists("page", true)) { ext.page.initialize(); } if (options.groupBy && this.extExists("groupRows", true)) { ext.groupRows.initialize(); } if (this.extExists("keybindings")) { ext.keybindings.initialize(); } if (this.extExists("selectRow")) { ext.selectRow.clearSelectionData(true); } if (options.autoResize && this.extExists("resizeTable")) { ext.resizeTable.initialize(); } if (this.extExists("clipboard")) { ext.clipboard.initialize(); } options.tableBuilt(); }, _loadInitialData: function _loadInitialData() { var self = this; if (self.options.pagination && self.extExists("page")) { self.extensions.page.reset(true); if (self.options.pagination == "local") { if (self.options.data.length) { self.rowManager.setData(self.options.data); } else { if (self.options.ajaxURL && self.extExists("ajax")) { self.extensions.ajax.loadData(); } else { self.rowManager.setData(self.options.data); } } } else { self.extensions.page.setPage(1); } } else { if (self.options.data.length) { self.rowManager.setData(self.options.data); } else { if (self.options.ajaxURL && self.extExists("ajax")) { self.extensions.ajax.loadData(); } else { self.rowManager.setData(self.options.data); } } } }, //set options _setOption: function _setOption(option, value) { console.error("Options Error - Tabulator does not allow options to be set after initialization unless there is a function defined for that purpose"); }, //deconstructor _destroy: function _destroy() { var element = this.element; //clear row data this.rowManager.rows.forEach(function (row) { row.wipe(); }); this.rowManager.rows = []; this.rowManager.activeRows = []; this.rowManager.displayRows = []; //clear event bindings if (this.options.autoResize && this.extExists("resizeTable")) { this.extensions.resizeTable.clearBindings(); } if (this.extExists("keybindings")) { this.extensions.keybindings.clearBindings(); } //clear DOM element.empty(); element.removeClass("tabulator"); }, _detectBrowser: function _detectBrowser() { var ua = navigator.userAgent; if (ua.indexOf("Trident") > -1) { this.browser = "ie"; this.browserSlow = true; } else if (ua.indexOf("Edge") > -1) { this.browser = "edge"; this.browserSlow = true; } else if (ua.indexOf("Firefox") > -1) { this.browser = "firefox"; this.browserSlow = false; } else { this.browser = "other"; this.browserSlow = false; } }, ////////////////// Data Handling ////////////////// //load data setData: function setData(data, params, config) { if (this.extExists("ajax")) { this.extensions.ajax.blockActiveRequest(); } this._setData(data, params, config); }, _setData: function _setData(data, params, config, inPosition) { var self = this; if (typeof data === "string") { if (data.indexOf("{") == 0 || data.indexOf("[") == 0) { //data is a json encoded string self.rowManager.setData(JSON.parse(data), inPosition); } else { if (self.extExists("ajax", true)) { if (params) { self.extensions.ajax.setParams(params); } if (config) { self.extensions.ajax.setConfig(config); } self.extensions.ajax.setUrl(data); if (self.options.pagination == "remote" && self.extExists("page", true)) { self.extensions.page.reset(true); self.extensions.page.setPage(1); } else { //assume data is url, make ajax call to url to get data self.extensions.ajax.loadData(inPosition); } } } } else { if (data) { //asume data is already an object self.rowManager.setData(data, inPosition); } else { //no data provided, check if ajaxURL is present; if (self.extExists("ajax") && self.extensions.ajax.getUrl) { if (self.options.pagination == "remote" && self.extExists("page", true)) { self.extensions.page.reset(true); self.extensions.page.setPage(1); } else { self.extensions.ajax.loadData(inPosition); } } else { //empty data self.rowManager.setData([], inPosition); } } } }, //clear data clearData: function clearData() { if (this.extExists("ajax")) { this.extensions.ajax.blockActiveRequest(); } this.rowManager.clearData(); }, //get table data array getData: function getData(active) { return this.rowManager.getData(active); }, //get table data array count getDataCount: function getDataCount(active) { return this.rowManager.getDataCount(active); }, //get table html getHtml: function getHtml(active) { return this.rowManager.getHtml(active); }, //retrieve Ajax URL getAjaxUrl: function getAjaxUrl() { if (this.extExists("ajax", true)) { return this.extensions.ajax.getUrl(); } }, //replace data, keeping table in position with same sort replaceData: function replaceData(data, params, config) { if (this.extExists("ajax")) { this.extensions.ajax.blockActiveRequest(); } this._setData(data, params, config, true); }, //update table data updateData: function updateData(data) { var self = this; if (this.extExists("ajax")) { this.extensions.ajax.blockActiveRequest(); } if (typeof data === "string") { data = JSON.parse(data); } if (data) { data.forEach(function (item) { var row = self.rowManager.findRow(item[self.options.index]); if (row) { row.updateData(item); } }); } else { console.warn("Update Error - No data provided"); } }, addData: function addData(data, pos, index) { var rows = [], output = []; if (this.extExists("ajax")) { this.extensions.ajax.blockActiveRequest(); } if (typeof data === "string") { data = JSON.parse(data); } if (data) { rows = this.rowManager.addRows(data, pos, index); rows.forEach(function (row) { output.push(row.getComponent()); }); return output; } else { console.warn("Update Error - No data provided"); } }, //update table data updateOrAddData: function updateOrAddData(data) { var self = this; var rows = []; if (this.extExists("ajax")) { this.extensions.ajax.blockActiveRequest(); } if (typeof data === "string") { data = JSON.parse(data); } if (data) { data.forEach(function (item) { var row = self.rowManager.findRow(item[self.options.index]); if (row) { row.updateData(item); rows.push(row.getComponent()); } else { rows.push(self.rowManager.addRows(item)[0].getComponent()); } }); return rows; } else { console.warn("Update Error - No data provided"); } }, //get row object getRow: function getRow(index) { var row = this.rowManager.findRow(index); if (row) { return row.getComponent(); } else { console.warn("Find Error - No matching row found:", index); return false; } }, //get row object getRowFromPosition: function getRowFromPosition(position, active) { var row = this.rowManager.getRowFromPosition(position, active); if (row) { return row.getComponent(); } else { console.warn("Find Error - No matching row found:", position); return false; } }, //delete row from table deleteRow: function deleteRow(index) { var row = this.rowManager.findRow(index); if (row) { row.delete(); return true; } else { console.warn("Delete Error - No matching row found:", index); return false; } }, //add row to table addRow: function addRow(data, pos, index) { var row; if (typeof data === "string") { data = JSON.parse(data); } row = this.rowManager.addRows(data, pos, index)[0]; //recalc column calculations if present if (this.extExists("columnCalcs")) { this.extensions.columnCalcs.recalc(this.rowManager.activeRows); } return row.getComponent(); }, //update a row if it exitsts otherwise create it updateOrAddRow: function updateOrAddRow(index, data) { var row = this.rowManager.findRow(index); if (typeof data === "string") { data = JSON.parse(data); } if (row) { row.updateData(data); } else { row = this.rowManager.addRows(data)[0]; //recalc column calculations if present if (this.extExists("columnCalcs")) { this.extensions.columnCalcs.recalc(this.rowManager.activeRows); } } return row.getComponent(); }, //update row data updateRow: function updateRow(index, data) { var row = this.rowManager.findRow(index); if (typeof data === "string") { data = JSON.parse(data); } if (row) { row.updateData(data); return row.getComponent(); } else { console.warn("Update Error - No matching row found:", index); return false; } }, //scroll to row in DOM scrollToRow: function scrollToRow(index, position, ifVisible) { var row = this.rowManager.findRow(index); if (row) { return this.rowManager.scrollToRow(row, position, ifVisible); } else { console.warn("Scroll Error - No matching row found:", index); return false; } }, getRows: function getRows(active) { return this.rowManager.getComponents(active); }, //get position of row in table getRowPosition: function getRowPosition(index, active) { var row = this.rowManager.findRow(index); if (row) { return this.rowManager.getRowPosition(row, active); } else { console.warn("Position Error - No matching row found:", index); return false; } }, //copy table data to clipboard copyToClipboard: function copyToClipboard(selector, selectorParams, formatter, formatterParams) { if (this.extExists("clipboard", true)) { this.extensions.clipboard.copy(selector, selectorParams, formatter, formatterParams); } }, /////////////// Column Functions /////////////// setColumns: function setColumns(definition) { this.columnManager.setColumns(definition); }, getColumns: function getColumns(structured) { return this.columnManager.getComponents(structured); }, getColumnDefinitions: function getColumnDefinitions() { return this.columnManager.getDefinitionTree(); }, getColumnLayout: function getColumnLayout() { if (this.extExists("persistence", true)) { return this.extensions.persistence.parseColumns(this.columnManager.getColumns()); } }, setColumnLayout: function setColumnLayout(layout) { if (this.extExists("persistence", true)) { this.columnManager.setColumns(this.extensions.persistence.mergeDefinition(this.options.columns, layout)); return true; } return false; }, showColumn: function showColumn(field) { var column = this.columnManager.findColumn(field); if (column) { column.show(); if (this.options.responsiveLayout && this.extExists("responsiveLayout", true)) { this.extensions.responsiveLayout.update(); } } else { console.warn("Column Show Error - No matching column found:", field); return false; } }, hideColumn: function hideColumn(field) { var column = this.columnManager.findColumn(field); if (column) { column.hide(); if (this.options.responsiveLayout && this.extExists("responsiveLayout", true)) { this.extensions.responsiveLayout.update(); } } else { console.warn("Column Hide Error - No matching column found:", field); return false; } }, toggleColumn: function toggleColumn(field) { var column = this.columnManager.findColumn(field); if (column) { if (column.visible) { column.hide(); } else { column.show(); } } else { console.warn("Column Visibility Toggle Error - No matching column found:", field); return false; } }, addColumn: function addColumn(definition, before, field) { var column = this.columnManager.findColumn(field); this.columnManager.addColumn(definition, before, column); }, deleteColumn: function deleteColumn(field) { var column = this.columnManager.findColumn(field); if (column) { column.delete(); } else { console.warn("Column Delete Error - No matching column found:", field); return false; } }, //scroll to column in DOM scrollToColumn: function scrollToColumn(field, position, ifVisible) { var column = this.columnManager.findColumn(field); if (column) { return this.columnManager.scrollToColumn(column, position, ifVisible); } else { console.warn("Scroll Error - No matching column found:", field); return false; } }, //////////// Localization Functions //////////// setLocale: function setLocale(locale) { this.extensions.localize.setLocale(locale); }, getLocale: function getLocale() { return this.extensions.localize.getLocale(); }, getLang: function getLang(locale) { return this.extensions.localize.getLang(locale); }, //////////// General Public Functions //////////// //redraw list without updating data redraw: function redraw(force) { this.columnManager.redraw(force); this.rowManager.redraw(force); }, setHeight: function setHeight(height) { this.options.height = isNaN(height) ? height : height + "px"; this.element.css({ "height": this.options.height }); this.rowManager.redraw(); }, ///////////////////// Sorting //////////////////// //trigger sort setSort: function setSort(sortList, dir) { if (this.extExists("sort", true)) { this.extensions.sort.setSort(sortList, dir); this.rowManager.sorterRefresh(); } }, getSort: function getSort() { if (this.extExists("sort", true)) { console.warn("The%c getSort%c function has been depricated and will be removed in version 4.0, use %c getSorters%c instead.", "font-weight:bold;", "font-weight:regular;", "font-weight:bold;", "font-weight:regular;"); return this.getSorters(); } }, getSorters: function getSorters() { if (this.extExists("sort", true)) { return this.extensions.sort.getSort(); } }, clearSort: function clearSort() { if (this.extExists("sort", true)) { this.extensions.sort.clear(); this.rowManager.sorterRefresh(); } }, ///////////////////// Filtering //////////////////// //set standard filters setFilter: function setFilter(field, type, value) { if (this.extExists("filter", true)) { this.extensions.filter.setFilter(field, type, value); this.rowManager.filterRefresh(); } }, //add filter to array addFilter: function addFilter(field, type, value) { if (this.extExists("filter", true)) { this.extensions.filter.addFilter(field, type, value); this.rowManager.filterRefresh(); } }, //get all filters getFilter: function getFilter(all) { console.warn("The%c getFilter%c function has been depricated and will be removed in version 4.0, use %c getFilters%c instead.", "font-weight:bold;", "font-weight:regular;", "font-weight:bold;", "font-weight:regular;"); this.getFilters(all); }, getFilters: function getFilters(all) { if (this.extExists("filter", true)) { return this.extensions.filter.getFilters(all); } }, setHeaderFilterFocus: function setHeaderFilterFocus(field) { if (this.extExists("filter", true)) { var column = this.columnManager.findColumn(field); if (column) { this.extensions.filter.setHeaderFilterFocus(column); } else { console.warn("Column Filter Focus Error - No matching column found:", field); return false; } } }, setHeaderFilterValue: function setHeaderFilterValue(field, value) { if (this.extExists("filter", true)) { var column = this.columnManager.findColumn(field); if (column) { this.extensions.filter.setHeaderFilterValue(column, value); } else { console.warn("Column Filter Error - No matching column found:", field); return false; } } }, getHeaderFilters: function getHeaderFilters() { if (this.extExists("filter", true)) { return this.extensions.filter.getHeaderFilters(); } }, //remove filter from array removeFilter: function removeFilter(field, type, value) { if (this.extExists("filter", true)) { this.extensions.filter.removeFilter(field, type, value); this.rowManager.filterRefresh(); } }, //clear filters clearFilter: function clearFilter(all) { if (this.extExists("filter", true)) { this.extensions.filter.clearFilter(all); this.rowManager.filterRefresh(); } }, //clear header filters clearHeaderFilter: function clearHeaderFilter() { if (this.extExists("filter", true)) { this.extensions.filter.clearHeaderFilter(); this.rowManager.filterRefresh(); } }, ///////////////////// Filtering //////////////////// selectRow: function selectRow(rows) { if (this.extExists("selectRow", true)) { this.extensions.selectRow.selectRows(rows); } }, deselectRow: function deselectRow(rows) { if (this.extExists("selectRow", true)) { this.extensions.selectRow.deselectRows(rows); } }, toggleSelectRow: function toggleSelectRow(row) { if (this.extExists("selectRow", true)) { this.extensions.selectRow.toggleRow(row); } }, getSelectedRows: function getSelectedRows() { if (this.extExists("selectRow", true)) { return this.extensions.selectRow.getSelectedRows(); } }, getSelectedData: function getSelectedData() { if (this.extExists("selectRow", true)) { return this.extensions.selectRow.getSelectedData(); } }, //////////// Pagination Functions //////////// setMaxPage: function setMaxPage(max) { if (this.options.pagination && this.extExists("page")) { this.extensions.page.setMaxPage(max); } else { return false; } }, setPage: function setPage(page) { if (this.options.pagination && this.extExists("page")) { this.extensions.page.setPage(page); } else { return false; } }, setPageSize: function setPageSize(size) { if (this.options.pagination && this.extExists("page")) { this.extensions.page.setPageSize(size); this.extensions.page.setPage(1); } else { return false; } }, getPageSize: function getPageSize() { if (this.options.pagination && this.extExists("page", true)) { return this.extensions.page.getPageSize(); } }, previousPage: function previousPage() { if (this.options.pagination && this.extExists("page")) { this.extensions.page.previousPage(); } else { return false; } }, nextPage: function nextPage() { if (this.options.pagination && this.extExists("page")) { this.extensions.page.nextPage(); } else { return false; } }, getPage: function getPage() { if (this.options.pagination && this.extExists("page")) { return this.extensions.page.getPage(); } else { return false; } }, getPageMax: function getPageMax() { if (this.options.pagination && this.extExists("page")) { return this.extensions.page.getPageMax(); } else { return false; } }, ///////////////// Grouping Functions /////////////// setGroupBy: function setGroupBy(groups) { if (this.extExists("groupRows", true)) { this.options.groupBy = groups; this.extensions.groupRows.initialize(); this.rowManager.refreshActiveData("display"); } else { return false; } }, setGroupStartOpen: function setGroupStartOpen(values) { if (this.extExists("groupRows", true)) { this.options.groupStartOpen = values; this.extensions.groupRows.initialize(); if (this.options.groupBy) { this.rowManager.refreshActiveData("group"); } else { console.warn("Grouping Update - cant refresh view, no groups have been set"); } } else { return false; } }, setGroupHeader: function setGroupHeader(values) { if (this.extExists("groupRows", true)) { this.options.groupHeader = values; this.extensions.groupRows.initialize(); if (this.options.groupBy) { this.rowManager.refreshActiveData("group"); } else { console.warn("Grouping Update - cant refresh view, no groups have been set"); } } else { return false; } }, getGroups: function getGroups(values) { if (this.extExists("groupRows", true)) { return this.extensions.groupRows.getGroups(); } else { return false; } }, ///////////////// Column Calculation Functions /////////////// getCalcResults: function getCalcResults() { if (this.extExists("columnCalcs", true)) { return this.extensions.columnCalcs.getResults(); } else { return false; } }, /////////////// Navigation Management ////////////// navigatePrev: function navigatePrev() { var cell = false; if (this.extExists("edit", true)) { cell = this.extensions.edit.currentCell; if (cell) { e.preventDefault(); return cell.nav().prev(); } } return false; }, navigateNext: function navigateNext() { var cell = false; if (this.extExists("edit", true)) { cell = this.extensions.edit.currentCell; if (cell) { e.preventDefault(); return cell.nav().next(); } } return false; }, navigateLeft: function navigateLeft() { var cell = false; if (this.extExists("edit", true)) { cell = this.extensions.edit.currentCell; if (cell) { e.preventDefault(); return cell.nav().left(); } } return false; }, navigateRight: function navigateRight() { var cell = false; if (this.extExists("edit", true)) { cell = this.extensions.edit.currentCell; if (cell) { e.preventDefault(); return cell.nav().right(); } } return false; }, navigateUp: function navigateUp() { var cell = false; if (this.extExists("edit", true)) { cell = this.extensions.edit.currentCell; if (cell) { e.preventDefault(); return cell.nav().up(); } } return false; }, navigateDown: function navigateDown() { var cell = false; if (this.extExists("edit", true)) { cell = this.extensions.edit.currentCell; if (cell) { e.preventDefault(); return cell.nav().dpwn(); } } return false; }, /////////////// History Management ////////////// undo: function undo() { if (this.options.history && this.extExists("history", true)) { return this.extensions.history.undo(); } else { return false; } }, redo: function redo() { if (this.options.history && this.extExists("history", true)) { return this.extensions.history.redo(); } else { return false; } }, /////////////// Download Management ////////////// download: function download(type, filename, options) { if (this.extExists("download", true)) { this.extensions.download.download(type, filename, options); } }, /////////// Inter Table Communications /////////// tableComms: function tableComms(table, extension, action, data) { this.extensions.comms.receive(table, extension, action, data); }, ////////////// Extension Management ////////////// //object to hold extensions extensions: {}, extensionBindings: {}, //extend extension extendExtension: function extendExtension(name, property, values) { if (this.extensionBindings[name]) { var source = this.extensionBindings[name].prototype[property]; if (source) { if ((typeof values === 'undefined' ? 'undefined' : _typeof(values)) == "object") { for (var key in values) { source[key] = values[key]; } } else { console.warn("Extension Error - Invalid value type, it must be an object"); } } else { console.warn("Extension Error - property does not exist:", property); } } else { console.warn("Extension Error - extension does not exist:", name); } }, //add extension to tabulator registerExtension: function registerExtension(name, extension) { var self = this; this.extensionBindings[name] = extension; }, //ensure that extensions are bound to instantiated function bindExtensions: function bindExtensions() { var self = this; this.extensions = {}; for (var name in self.extensionBindings) { self.extensions[name] = new self.extensionBindings[name](self); } }, //Check for plugin extExists: function extExists(plugin, required) { if (this.extensions[plugin]) { return true; } else { if (required) { console.error("Tabulator Plugin Not Installed: " + plugin); } return false; } } }; var Layout = function Layout(table) { this.table = table; this.mode = null; }; //initialize layout system Layout.prototype.initialize = function (layout) { if (this.modes[layout]) { this.mode = layout; } else { console.warn("Layout Error - invalid mode set, defaulting to 'fitData' : " + layout); this.mode = 'fitData'; } this.table.element.attr("tabulator-layout", this.mode); }; Layout.prototype.getMode = function () { return this.mode; }; //trigger table layout Layout.prototype.layout = function () { this.modes[this.mode].call(this, this.table.columnManager.columnsByIndex); }; //layout render functions Layout.prototype.modes = { //resize columns to fit data the contain "fitData": function fitData(columns) { columns.forEach(function (column) { column.reinitializeWidth(); }); if (this.table.options.responsiveLayout && this.table.extExists("responsiveLayout", true)) { this.table.extensions.responsiveLayout.update(); } }, //resize columns to fit data the contain "fitDataFill": function fitDataFill(columns) { columns.forEach(function (column) { column.reinitializeWidth(); }); if (this.table.options.responsiveLayout && this.table.extExists("responsiveLayout", true)) { this.table.extensions.responsiveLayout.update(); } }, //resize columns to fit "fitColumns": function fitColumns(columns) { var self = this; var totalWidth = self.table.element.innerWidth(); //table element width var fixedWidth = 0; //total width of columns with a defined width var flexWidth = 0; //total width available to flexible columns var flexGrowUnits = 0; //total number of widthGrow blocks accross all columns var flexColWidth = 0; //desired width of flexible columns var flexColumns = []; //array of flexible width columns var fixedShrinkColumns = []; //array of fixed width columns that can shrink var flexShrinkUnits = 0; //total number of widthShrink blocks accross all columns var overflowWidth = 0; //horizontal overflow width var gapFill = 0; //number of pixels to be added to final column to close and half pixel gaps function calcWidth(width) { var colWidth; if (typeof width == "string") { if (width.indexOf("%") > -1) { colWidth = totalWidth / 100 * parseInt(width); } else { colWidth = parseInt(width); } } else { colWidth = width; } return colWidth; } //ensure columns resize to take up the correct amount of space function scaleColumns(columns, freeSpace, colWidth, shrinkCols) { var oversizeCols = [], oversizeSpace = 0, remainingSpace = 0, nextColWidth = 0, gap = 0, changeUnits = 0, undersizeCols = []; function calcGrow(col) { return colWidth * (col.column.definition.widthGrow || 1); } function calcShrink(col) { return calcWidth(col.width) - colWidth * (col.column.definition.widthShrink || 0); } columns.forEach(function (col, i) { var width = shrinkCols ? calcShrink(col) : calcGrow(col); if (col.column.minWidth >= width) { oversizeCols.push(col); } else { undersizeCols.push(col); changeUnits += shrinkCols ? col.column.definition.widthShrink || 1 : col.column.definition.widthGrow || 1; } }); if (oversizeCols.length) { oversizeCols.forEach(function (col) { oversizeSpace += shrinkCols ? col.width - col.column.minWidth : col.column.minWidth; col.width = col.column.minWidth; }); remainingSpace = freeSpace - oversizeSpace; nextColWidth = changeUnits ? Math.floor(remainingSpace / changeUnits) : remainingSpace; gap = remainingSpace - nextColWidth * changeUnits; gap += scaleColumns(undersizeCols, remainingSpace, nextColWidth, shrinkCols); } else { gap = changeUnits ? freeSpace - Math.floor(freeSpace / changeUnits) * changeUnits : freeSpace; undersizeCols.forEach(function (column) { column.width = shrinkCols ? calcShrink(column) : calcGrow(column); }); } return gap; } if (this.table.options.responsiveLayout && this.table.extExists("responsiveLayout", true)) { this.table.extensions.responsiveLayout.update(); } //adjust for vertical scrollbar if present if (this.table.rowManager.element[0].scrollHeight > this.table.rowManager.element.innerHeight()) { totalWidth -= this.table.rowManager.element[0].offsetWidth - this.table.rowManager.element[0].clientWidth; } columns.forEach(function (column) { var width, minWidth, colWidth; if (column.visible) { width = column.definition.width; minWidth = parseInt(column.minWidth); if (width) { colWidth = calcWidth(width); fixedWidth += colWidth > minWidth ? colWidth : minWidth; if (column.definition.widthShrink) { fixedShrinkColumns.push({ column: column, width: colWidth > minWidth ? colWidth : minWidth }); flexShrinkUnits += column.definition.widthShrink; } } else { flexColumns.push({ column: column, width: 0 }); flexGrowUnits += column.definition.widthGrow || 1; } } }); //calculate available space flexWidth = totalWidth - fixedWidth; //calculate correct column size flexColWidth = Math.floor(flexWidth / flexGrowUnits); //generate column widths var gapFill = scaleColumns(flexColumns, flexWidth, flexColWidth, false); //increase width of last column to account for rounding errors if (flexColumns.length && gapFill > 0) { flexColumns[flexColumns.length - 1].width += +gapFill; } //caculate space for columns to be shrunk into flexColumns.forEach(function (col) { flexWidth -= col.width; }); overflowWidth = Math.abs(gapFill) + flexWidth; //shrink oversize columns if there is no available space if (overflowWidth > 0 && flexShrinkUnits) { gapFill = scaleColumns(fixedShrinkColumns, overflowWidth, Math.floor(overflowWidth / flexShrinkUnits), true); } //decrease width of last column to account for rounding errors if (fixedShrinkColumns.length) { fixedShrinkColumns[fixedShrinkColumns.length - 1].width -= gapFill; } flexColumns.forEach(function (col) { col.column.setWidth(col.width); }); fixedShrinkColumns.forEach(function (col) { col.column.setWidth(col.width); }); } }; Tabulator.registerExtension("layout", Layout); var Localize = function Localize(table) { this.table = table; //hold Tabulator object this.locale = "default"; //current locale this.lang = false; //current language this.bindings = {}; //update events to call when locale is changed }; //set header placehoder Localize.prototype.setHeaderFilterPlaceholder = function (placeholder) { this.langs.default.headerFilters.default = placeholder; }; //set header filter placeholder by column Localize.prototype.setHeaderFilterColumnPlaceholder = function (column, placeholder) { this.langs.default.headerFilters.columns[column] = placeholder; if (this.lang && !this.lang.headerFilters.columns[column]) { this.lang.headerFilters.columns[column] = placeholder; } }; //setup a lang description object Localize.prototype.installLang = function (locale, lang) { if (this.langs[locale]) { this._setLangProp(this.langs[locale], lang); } else { this.langs[locale] = lang; } }; Localize.prototype._setLangProp = function (lang, values) { for (var key in values) { if (lang[key] && _typeof(lang[key]) == "object") { this._setLangProp(lang[key], values[key]); } else { lang[key] = values[key]; } } }; //set current locale Localize.prototype.setLocale = function (desiredLocale) { var self = this; desiredLocale = desiredLocale || "default"; //fill in any matching languge values function traverseLang(trans, path) { for (var prop in trans) { if (_typeof(trans[prop]) == "object") { if (!path[prop]) { path[prop] = {}; } traverseLang(trans[prop], path[prop]); } else { path[prop] = trans[prop]; } } } //determing correct locale to load if (desiredLocale === true && navigator.language) { //get local from system desiredLocale = navigator.language.toLowerCase(); } if (desiredLocale) { //if locale is not set, check for matching top level locale else use default if (!self.langs[desiredLocale]) { var prefix = desiredLocale.split("-")[0]; if (self.langs[prefix]) { console.warn("Localization Error - Exact matching locale not found, using closest match: ", desiredLocale, prefix); desiredLocale = prefix; } else { console.warn("Localization Error - Matching locale not found, using default: ", desiredLocale); desiredLocale = "default"; } } } self.locale = desiredLocale; //load default lang template self.lang = $.extend(true, {}, self.langs.default); if (desiredLocale != "default") { traverseLang(self.langs[desiredLocale], self.lang); } self.table.options.localized(self.locale, self.lang); self._executeBindings(); }; //get current locale Localize.prototype.getLocale = function (locale) { return self.locale; }; //get lang object for given local or current if none provided Localize.prototype.getLang = function (locale) { return locale ? this.langs[locale] : this.lang; }; //get text for current locale Localize.prototype.getText = function (path, value) { var path = value ? path + "|" + value : path, pathArray = path.split("|"), text = this._getLangElement(pathArray, this.locale); // if(text === false){ // console.warn("Localization Error - Matching localized text not found for given path: ", path); // } return text || ""; }; //traverse langs object and find localized copy Localize.prototype._getLangElement = function (path, locale) { var self = this; var root = self.lang; path.forEach(function (level) { var rootPath; if (root) { rootPath = root[level]; if (typeof rootPath != "undefined") { root = rootPath; } else { root = false; } } }); return root; }; //set update binding Localize.prototype.bind = function (path, callback) { if (!this.bindings[path]) { this.bindings[path] = []; } this.bindings[path].push(callback); callback(this.getText(path), this.lang); }; //itterate through bindings and trigger updates Localize.prototype._executeBindings = function () { var self = this; var _loop = function _loop(path) { self.bindings[path].forEach(function (binding) { binding(self.getText(path), self.lang); }); }; for (var path in self.bindings) { _loop(path); } }; //Localized text listings Localize.prototype.langs = { "default": { //hold default locale text "groups": { "item": "item", "items": "items" }, "columns": {}, "ajax": { "loading": "Loading", "error": "Error" }, "pagination": { "first": "<<", //changes done by Soumya "first_title": "First Page", "last": ">>", //changes done by Soumya "last_title": "Last Page", "prev": "<", //changes done by Soumya "prev_title": "Prev Page", "next": ">", //changes done by Soumya "next_title": "Next Page" }, "headerFilters": { "default": "Search", //changes done by Soumya "columns": {} } } }; Tabulator.registerExtension("localize", Localize); var Comms = function Comms(table) { this.table = table; }; Comms.prototype.getConnections = function (selectors) { var self = this, connections = [], connection; if (Array.isArray(selectors)) { connections = selectors; } else { connection = typeof selectors == "string" ? $(selectors) : selectors; connection.each(function () { if (self.table.element[0] !== this) { connections.push($(this)); } }); } return connections; }; Comms.prototype.send = function (selectors, extension, action, data) { var self = this, connections = this.getConnections(selectors); connections.forEach(function (connection) { connection.tabulator("tableComms", self.table.element, extension, action, data); }); if (!connections.length && selectors) { console.warn("Table Connection Error - No tables matching selector found", selectors); } }; Comms.prototype.receive = function (table, extension, action, data) { if (this.table.extExists(extension)) { return this.table.extensions[extension].commsReceived(table, action, data); } else { console.warn("Inter-table Comms Error - no such extension:", extension); } }; Tabulator.registerExtension("comms", Comms); var Accessor = function Accessor(table) { this.table = table; //hold Tabulator object this.allowedTypes = ["", "data", "download", "clipboard"]; //list of accessor types }; //initialize column accessor Accessor.prototype.initializeColumn = function (column) { var self = this, match = false, config = {}; this.allowedTypes.forEach(function (type) { var key = "accessor" + (type.charAt(0).toUpperCase() + type.slice(1)), accessor; if (column.definition[key]) { accessor = self.lookupAccessor(column.definition[key]); if (accessor) { match = true; config[key] = { accessor: accessor, params: column.definition[key + "Params"] || {} }; } } }); if (match) { column.extensions.accessor = config; } }, Accessor.prototype.lookupAccessor = function (value) { var accessor = false; //set column accessor switch (typeof value === 'undefined' ? 'undefined' : _typeof(value)) { case "string": if (this.accessors[value]) { accessor = this.accessors[value]; } else { console.warn("Accessor Error - No such accessor found, ignoring: ", value); } break; case "function": accessor = value; break; } return accessor; }; //apply accessor to row Accessor.prototype.transformRow = function (dataIn, type) { var self = this, key = "accessor" + (type.charAt(0).toUpperCase() + type.slice(1)); //clone data object with deep copy to isolate internal data from returned result var data = $.extend(true, {}, dataIn || {}); self.table.columnManager.traverse(function (column) { var value, accessor; if (column.extensions.accessor) { accessor = column.extensions.accessor[key] || column.extensions.accessor.accessor || false; if (accessor) { value = column.getFieldValue(data); if (value != "undefined") { column.setFieldValue(data, accessor.accessor(value, data, type, accessor.params, column.getComponent())); } } } }); return data; }, //default accessors Accessor.prototype.accessors = {}; Tabulator.registerExtension("accessor", Accessor); var Ajax = function Ajax(table) { this.table = table; //hold Tabulator object this.config = false; //hold config object for ajax request this.url = ""; //request URL this.params = false; //request parameters this.loaderElement = $("
"); //loader message div this.msgElement = $(""); //message element this.loadingElement = false; this.errorElement = false; this.progressiveLoad = false; this.loading = false; this.requestOrder = 0; //prevent requests comming out of sequence if overridden by another load request }; //initialize setup options Ajax.prototype.initialize = function () { this.loaderElement.append(this.msgElement); if (this.table.options.ajaxLoaderLoading) { this.loadingElement = this.table.options.ajaxLoaderLoading; } if (this.table.options.ajaxLoaderError) { this.errorElement = this.table.options.ajaxLoaderError; } if (this.table.options.ajaxParams) { this.setParams(this.table.options.ajaxParams); } if (this.table.options.ajaxConfig) { this.setConfig(this.table.options.ajaxConfig); } if (this.table.options.ajaxURL) { this.setUrl(this.table.options.ajaxURL); } if (this.table.options.ajaxProgressiveLoad) { if (this.table.options.pagination) { this.progressiveLoad = false; console.error("Progressive Load Error - Pagination and progressive load cannot be used at the same time"); } else { if (this.table.extExists("page")) { this.progressiveLoad = this.table.options.ajaxProgressiveLoad; this.table.extensions.page.initializeProgressive(this.progressiveLoad); } else { console.error("Pagination plugin is required for progressive ajax loading"); } } } }; //set ajax params Ajax.prototype.setParams = function (params, update) { if (update) { this.params = this.params || {}; for (var key in params) { this.params[key] = params[key]; } } else { this.params = params; } }; Ajax.prototype.getParams = function () { return this.params || {}; }; //load config object Ajax.prototype.setConfig = function (config) { this._loadDefaultConfig(); if (typeof config == "string") { this.config.type = config; } else { for (var key in config) { this.config[key] = config[key]; } } }; //create config object from default Ajax.prototype._loadDefaultConfig = function (force) { var self = this; if (!self.config || force) { self.config = {}; //load base config from defaults for (var key in self.defaultConfig) { self.config[key] = self.defaultConfig[key]; } } }; //set request url Ajax.prototype.setUrl = function (url) { this.url = url; }; //get request url Ajax.prototype.getUrl = function () { return this.url; }; //lstandard loading function Ajax.prototype.loadData = function (inPosition) { var self = this; if (this.progressiveLoad) { this._loadDataProgressive(); } else { this._loadDataStandard(inPosition); } }; Ajax.prototype.nextPage = function (diff) { var margin; if (!this.loading) { margin = this.table.options.ajaxProgressiveLoadScrollMargin || this.table.rowManager.element[0].clientHeight * 2; if (diff < margin) { this.table.extensions.page.nextPage(); } } }; Ajax.prototype.blockActiveRequest = function () { this.requestOrder++; }; Ajax.prototype._loadDataProgressive = function () { this.table.rowManager.setData([]); this.table.extensions.page.setPage(1); }; Ajax.prototype._loadDataStandard = function (inPosition) { var self = this; this.sendRequest(function (data) { self.table.rowManager.setData(data, inPosition); }, inPosition); }; //send ajax request Ajax.prototype.sendRequest = function (callback, silent) { var self = this, requestNo; if (self.url) { self.requestOrder++; requestNo = self.requestOrder; self._loadDefaultConfig(); self.config.url = self.url; if (self.params) { self.config.data = self.params; } if (self.table.options.ajaxRequesting(self.url, self.params) !== false) { self.loading = true; if (!silent) { self.showLoader(); } $.ajax(self.config).done(function (data) { if (requestNo === self.requestOrder) { if (self.table.options.ajaxResponse) { data = self.table.options.ajaxResponse(self.url, self.params, data); } callback(data); } else { console.warn("Ajax Response Blocked - An active ajax request was blocked by an attempt to change table data while the request was being made"); } self.hideLoader(); self.loading = false; }).fail(function (xhr, textStatus, errorThrown) { console.error("Ajax Load Error - Connection Error: " + xhr.status, errorThrown); self.table.options.ajaxError(xhr, textStatus, errorThrown); self.showError(); setTimeout(function () { self.hideLoader(); }, 3000); self.loading = false; }); } } else { console.warn("Ajax Load Error - No URL Set"); return false; } }; Ajax.prototype.showLoader = function () { var shouldLoad = typeof this.table.options.ajaxLoader === "function" ? this.table.options.ajaxLoader() : this.table.options.ajaxLoader; if (shouldLoad) { this.loaderElement.detach(); this.msgElement.empty().removeClass("tabulator-error").addClass("tabulator-loading"); if (this.loadingElement) { this.msgElement.append(this.loadingElement); } else { this.msgElement.append(this.table.extensions.localize.getText("ajax|loading")); } this.table.element.append(this.loaderElement); } }; Ajax.prototype.showError = function () { this.loaderElement.detach(); this.msgElement.empty().removeClass("tabulator-loading").addClass("tabulator-error"); if (this.errorElement) { this.msgElement.append(this.errorElement); } else { this.msgElement.append(this.table.extensions.localize.getText("ajax|error")); } this.table.element.append(this.loaderElement); }; Ajax.prototype.hideLoader = function () { this.loaderElement.detach(); }; //default ajax config object Ajax.prototype.defaultConfig = { url: "", type: "GET", async: true, dataType: "json", success: function success(data) {} }; Tabulator.registerExtension("ajax", Ajax); var ColumnCalcs = function ColumnCalcs(table) { this.table = table; //hold Tabulator object this.topCalcs = []; this.botCalcs = []; this.genColumn = false; this.topElement = $("
"); this.botElement = $("
"); this.topRow = false; this.botRow = false; this.topInitialized = false; this.botInitialized = false; this.initialize(); }; ColumnCalcs.prototype.initialize = function () { this.genColumn = new Column({ field: "value" }, this); }; //dummy functions to handle being mock column manager ColumnCalcs.prototype.registerColumnField = function () {}; //initialize column calcs ColumnCalcs.prototype.initializeColumn = function (column) { var def = column.definition; var config = { topCalcParams: def.topCalcParams || {}, botCalcParams: def.bottomCalcParams || {} }; if (def.topCalc) { switch (_typeof(def.topCalc)) { case "string": if (this.calculations[def.topCalc]) { config.topCalc = this.calculations[def.topCalc]; } else { console.warn("Column Calc Error - No such calculation found, ignoring: ", def.topCalc); } break; case "function": config.topCalc = def.topCalc; break; } if (config.topCalc) { column.extensions.columnCalcs = config; this.topCalcs.push(column); if (this.table.options.columnCalcs != "group") { this.initializeTopRow(); } } } if (def.bottomCalc) { switch (_typeof(def.bottomCalc)) { case "string": if (this.calculations[def.bottomCalc]) { config.botCalc = this.calculations[def.bottomCalc]; } else { console.warn("Column Calc Error - No such calculation found, ignoring: ", def.bottomCalc); } break; case "function": config.botCalc = def.bottomCalc; break; } if (config.botCalc) { column.extensions.columnCalcs = config; this.botCalcs.push(column); if (this.table.options.columnCalcs != "group") { this.initializeBottomRow(); } } } }; ColumnCalcs.prototype.removeCalcs = function () { var changed = false; if (this.topInitialized) { this.topInitialized = false; this.topElement.remove(); changed = true; } if (this.botInitialized) { this.botInitialized = false; this.table.footerManager.remove(this.botElement); changed = true; } if (changed) { this.table.rowManager.adjustTableSize(); } }; ColumnCalcs.prototype.initializeTopRow = function () { if (!this.topInitialized) { this.table.columnManager.headersElement.after(this.topElement); this.topInitialized = true; } }; ColumnCalcs.prototype.initializeBottomRow = function () { if (!this.botInitialized) { this.table.footerManager.prepend(this.botElement); this.botInitialized = true; } }; ColumnCalcs.prototype.scrollHorizontal = function (left) { var hozAdjust = 0, scrollWidth = this.table.columnManager.element[0].scrollWidth - this.table.element.innerWidth(); if (this.botInitialized) { this.botRow.getElement().css("margin-left", -left); } }; ColumnCalcs.prototype.recalc = function (rows) { var data, row; if (this.topInitialized || this.botInitialized) { data = this.rowsToData(rows); if (this.topInitialized) { row = this.generateRow("top", this.rowsToData(rows)); this.topRow = row; this.topElement.empty(); this.topElement.append(row.getElement()); row.initialize(true); } if (this.botInitialized) { row = this.generateRow("bottom", this.rowsToData(rows)); this.botRow = row; this.botElement.empty(); this.botElement.append(row.getElement()); row.initialize(true); } this.table.rowManager.adjustTableSize(); //set resizable handles if (this.table.extExists("frozenColumns")) { this.table.extensions.frozenColumns.layout(); } } }; ColumnCalcs.prototype.recalcRowGroup = function (row) { this.recalcGroup(this.table.extensions.groupRows.getRowGroup(row)); }; ColumnCalcs.prototype.recalcGroup = function (group) { var data, rowData; if (group) { if (group.calcs) { if (group.calcs.bottom) { data = this.rowsToData(group.rows); rowData = this.generateRowData("bottom", data); group.calcs.bottom.updateData(rowData); group.calcs.bottom.reinitialize(); } if (group.calcs.top) { data = this.rowsToData(group.rows); rowData = this.generateRowData("top", data); group.calcs.top.updateData(rowData); group.calcs.top.reinitialize(); } } } }; //generate top stats row ColumnCalcs.prototype.generateTopRow = function (rows) { return this.generateRow("top", this.rowsToData(rows)); }; //generate bottom stats row ColumnCalcs.prototype.generateBottomRow = function (rows) { return this.generateRow("bottom", this.rowsToData(rows)); }; ColumnCalcs.prototype.rowsToData = function (rows) { var data = []; rows.forEach(function (row) { data.push(row.getData()); }); return data; }; //generate stats row ColumnCalcs.prototype.generateRow = function (pos, data) { var self = this, rowData = this.generateRowData(pos, data), row = new Row(rowData, this); row.getElement().addClass("tabulator-calcs").addClass("tabulator-calcs-" + pos); row.type = "calc"; row.generateCells = function () { var cells = []; self.table.columnManager.columnsByIndex.forEach(function (column) { if (column.visible) { //set field name of mock column self.genColumn.setField(column.getField()); self.genColumn.hozAlign = column.hozAlign; if (column.definition[pos + "CalcFormatter"] && self.table.extExists("format")) { self.genColumn.extensions.format = { formatter: self.table.extensions.format.getFormatter(column.definition[pos + "CalcFormatter"]), params: column.definition[pos + "CalcFormatterParams"] }; } else { self.genColumn.extensions.format = { formatter: self.table.extensions.format.getFormatter("plaintext"), params: {} }; } //generate cell and assign to correct column var cell = new Cell(self.genColumn, row); cell.column = column; cell.setWidth(column.width); column.cells.push(cell); cells.push(cell); } }); this.cells = cells; }; return row; }; //generate stats row ColumnCalcs.prototype.generateRowData = function (pos, data) { var rowData = {}, calcs = pos == "top" ? this.topCalcs : this.botCalcs, type = pos == "top" ? "topCalc" : "botCalc"; calcs.forEach(function (column) { var values = []; if (column.extensions.columnCalcs && column.extensions.columnCalcs[type]) { data.forEach(function (item) { values.push(column.getFieldValue(item)); }); column.setFieldValue(rowData, column.extensions.columnCalcs[type](values, data, column.extensions.columnCalcs[type + "Params"])); } }); return rowData; }; ColumnCalcs.prototype.hasTopCalcs = function () { return !!this.topCalcs.length; }, ColumnCalcs.prototype.hasBottomCalcs = function () { return !!this.botCalcs.length; }, //handle table redraw ColumnCalcs.prototype.redraw = function () { if (this.topRow) { this.topRow.normalizeHeight(true); } if (this.botRow) { this.botRow.normalizeHeight(true); } }; //return the calculated ColumnCalcs.prototype.getResults = function () { var self = this, results = {}, groups; if (this.table.options.groupBy && this.table.extExists("groupRows")) { groups = this.table.extensions.groupRows.getGroups(); groups.forEach(function (group) { results[group.getKey()] = self.getGroupResults(group); }); } else { results = { top: this.topRow ? this.topRow.getData() : {}, bottom: this.botRow ? this.botRow.getData() : {} }; } return results; }; //get results from a group ColumnCalcs.prototype.getGroupResults = function (group) { var self = this, groupObj = group._getSelf(), subGroups = group.getSubGroups(), subGroupResults = {}, results = {}; subGroups.forEach(function (subgroup) { subGroupResults[subgroup.getKey()] = self.getGroupResults(subgroup); }); results = { top: groupObj.calcs.top ? groupObj.calcs.top.getData() : {}, bottom: groupObj.calcs.bottom ? groupObj.calcs.bottom.getData() : {}, groups: subGroupResults }; return results; }; //default calculations ColumnCalcs.prototype.calculations = { "avg": function avg(values, data, calcParams) { var output = 0, precision = typeof calcParams.precision !== "undefined" ? calcParams.precision : 2; if (values.length) { output = values.reduce(function (sum, value) { value = Number(value); return sum + value; }); output = output / values.length; output = precision !== false ? output.toFixed(precision) : output; } return parseFloat(output).toString(); }, "max": function max(values, data, calcParams) { var output = null, precision = typeof calcParams.precision !== "undefined" ? calcParams.precision : false; values.forEach(function (value) { value = Number(value); if (value > output || output === null) { output = value; } }); return output !== null ? precision !== false ? output.toFixed(precision) : output : ""; }, "min": function min(values, data, calcParams) { var output = null, precision = typeof calcParams.precision !== "undefined" ? calcParams.precision : false; values.forEach(function (value) { value = Number(value); if (value < output || output === null) { output = value; } }); return output !== null ? precision !== false ? output.toFixed(precision) : output : ""; }, "sum": function sum(values, data, calcParams) { var output = 0, precision = typeof calcParams.precision !== "undefined" ? calcParams.precision : false; if (values.length) { values.forEach(function (value) { value = Number(value); output += !isNaN(value) ? Number(value) : 0; }); } return precision !== false ? output.toFixed(precision) : output; }, "concat": function concat(values, data, calcParams) { var output = 0; if (values.length) { output = values.reduce(function (sum, value) { return String(sum) + String(value); }); } return output; }, "count": function count(values, data, calcParams) { var output = 0; if (values.length) { values.forEach(function (value) { if (value) { output++; } }); } return output; } }; Tabulator.registerExtension("columnCalcs", ColumnCalcs); var Clipboard = function Clipboard(table) { this.table = table; this.mode = true; this.copySelector = false; this.copySelectorParams = {}; this.copyFormatter = false; this.copyFormatterParams = {}; this.pasteParser = function () {}; this.pasteAction = function () {}; this.blocked = true; //block copy actions not originating from this command }; Clipboard.prototype.initialize = function () { var self = this; this.mode = this.table.options.clipboard; if (this.mode === true || this.mode === "copy") { this.table.element.on("copy", function (e) { var data; if (!self.blocked) { e.preventDefault(); data = self.generateContent(); if (window.clipboardData && window.clipboardData.setData) { window.clipboardData.setData('Text', data); } else if (e.clipboardData && e.clipboardData.setData) { e.clipboardData.setData('text/plain', data); } else if (e.originalEvent && e.originalEvent.clipboardData.setData) { e.originalEvent.clipboardData.setData('text/plain', data); } self.table.options.clipboardCopied(data); self.reset(); } }); } if (this.mode === true || this.mode === "paste") { this.table.element.on("paste", function (e) { self.paste(e); }); } this.setPasteParser(this.table.options.clipboardPasteParser); this.setPasteAction(this.table.options.clipboardPasteAction); }; Clipboard.prototype.reset = function () { this.blocked = false; this.originalSelectionText = ""; }; Clipboard.prototype.setPasteAction = function (action) { switch (typeof action === 'undefined' ? 'undefined' : _typeof(action)) { case "string": this.pasteAction = this.pasteActions[action]; if (!this.pasteAction) { console.warn("Clipboard Error - No such paste action found:", action); } break; case "function": this.pasteAction = action; break; } }; Clipboard.prototype.setPasteParser = function (parser) { switch (typeof parser === 'undefined' ? 'undefined' : _typeof(parser)) { case "string": this.pasteParser = this.pasteParsers[parser]; if (!this.pasteParser) { console.warn("Clipboard Error - No such paste parser found:", parser); } break; case "function": this.pasteParser = parser; break; } }; Clipboard.prototype.paste = function (e) { var data, rowData, rows; if (this.checkPaseOrigin(e)) { data = this.getPasteData(e); rowData = this.pasteParser.call(this, data); if (rowData) { e.preventDefault(); if (this.table.extExists("mutator")) { rowData = this.mutateData(rowData); } rows = this.pasteAction.call(this, rowData); this.table.options.clipboardPasted(data, rowData, rows); } else { this.table.options.clipboardPasteError(data); } } }; Clipboard.prototype.mutateData = function (data) { var self = this, output = []; if (Array.isArray(data)) { data.forEach(function (row) { output.push(self.table.extensions.mutator.transformRow(row, "clipboard")); }); } else { output = data; } return output; }; Clipboard.prototype.checkPaseOrigin = function (e) { var valid = true; if (e.target.tagName != "DIV" || this.table.extensions.edit.currentCell) { valid = false; } return valid; }; Clipboard.prototype.getPasteData = function (e) { var data = undefined; if (window.clipboardData && window.clipboardData.getData) { data = window.clipboardData.getData('Text'); } else if (e.clipboardData && e.clipboardData.getData) { data = e.clipboardData.getData('text/plain'); } else if (e.originalEvent && e.originalEvent.clipboardData.getData) { data = e.originalEvent.clipboardData.getData('text/plain'); } return data; }; Clipboard.prototype.copy = function (selector, selectorParams, formatter, formatterParams, internal) { var range, sel; this.blocked = false; if (this.mode === true || this.mode === "copy") { if (typeof window.getSelection != "undefined" && typeof document.createRange != "undefined") { range = document.createRange(); range.selectNodeContents(this.table.element[0]); sel = window.getSelection(); if (sel.toString() && internal) { selector = "userSelection"; formatter = "raw"; this.copySelectorParams = sel.toString(); } sel.removeAllRanges(); sel.addRange(range); } else if (typeof document.selection != "undefined" && typeof document.body.createTextRange != "undefined") { textRange = document.body.createTextRange(); textRange.moveToElementText(this.table.element[0]); textRange.select(); } this.setSelector(selector); this.copySelectorParams = typeof selectorParams != "undefined" && selectorParams != null ? selectorParams : this.table.options.clipboardCopyHeader; this.setFormatter(formatter); this.copyFormatterParams = typeof formatterParams != "undefined" && formatterParams != null ? formatterParams : {}; document.execCommand('copy'); if (sel) { sel.removeAllRanges(); } } }; Clipboard.prototype.setSelector = function (selector) { selector = selector || this.table.options.clipboardCopySelector; switch (typeof selector === 'undefined' ? 'undefined' : _typeof(selector)) { case "string": if (this.copySelectors[selector]) { this.copySelector = this.copySelectors[selector]; } else { console.warn("Clipboard Error - No such selector found:", selector); } break; case "function": this.copySelector = selector; break; } }; Clipboard.prototype.setFormatter = function (formatter) { formatter = formatter || this.table.options.clipboardCopyFormatter; switch (typeof formatter === 'undefined' ? 'undefined' : _typeof(formatter)) { case "string": if (this.copyFormatters[formatter]) { this.copyFormatter = this.copyFormatters[formatter]; } else { console.warn("Clipboard Error - No such formatter found:", formatter); } break; case "function": this.copyFormatter = formatter; break; } }; Clipboard.prototype.generateContent = function () { var data = this.copySelector.call(this, this.copySelectorParams); return this.copyFormatter.call(this, data, this.copyFormatterParams); }; Clipboard.prototype.rowsToData = function (rows, params) { var columns = this.table.columnManager.columnsByIndex, headers = [], data = []; if (params) { columns.forEach(function (column) { headers.push(column.definition.title); }); data.push(headers); } rows.forEach(function (row) { var rowArray = [], rowData = row.getData("clipboard"); columns.forEach(function (column) { var value = column.getFieldValue(rowData); rowArray.push(value); }); data.push(rowArray); }); return data; }; Clipboard.prototype.copySelectors = { userSelection: function userSelection(params) { return params; }, selected: function selected(params) { var rows = []; if (this.table.extExists("selectRow", true)) { rows = this.table.extensions.selectRow.getSelectedRows(); } return this.rowsToData(rows, params); }, table: function table(params) { return this.rowsToData(this.table.rowManager.getComponents(), params); }, active: function active(params) { return this.rowsToData(this.table.rowManager.getComponents(true), params); } }; Clipboard.prototype.copyFormatters = { raw: function raw(data, params) { return data; }, table: function table(data, params) { var output = []; data.forEach(function (row) { row.forEach(function (value) { if (typeof value == "undefined") { value = ""; } value = typeof value == "undefined" || value === null ? "" : value.toString(); if (value.match(/\r|\n/)) { value = value.split('"').join('""'); value = '"' + value + '"'; } }); output.push(row.join("\t")); }); return output.join("\n"); } }; Clipboard.prototype.pasteParsers = { table: function table(clipboard) { var data = [], success = false, headerFindSuccess = true, columns = this.table.columnManager.columns, columnMap = [], rows = []; //get data from clipboard into array of columns and rows. clipboard = clipboard.split("\n"); clipboard.forEach(function (row) { data.push(row.split("\t")); }); if (data.length && !(data.length === 1 && data[0].length < 2)) { success = true; //check if headers are present by title data[0].forEach(function (value) { var column = columns.find(function (column) { return value.trim() && column.definition.title.trim() === value.trim(); }); if (column) { columnMap.push(column); } else { headerFindSuccess = false; } }); //check if column headers are present by field if (!headerFindSuccess) { headerFindSuccess = true; columnMap = []; data[0].forEach(function (value) { var column = columns.find(function (column) { return value.trim() && column.field.trim() === value.trim(); }); if (column) { columnMap.push(column); } else { headerFindSuccess = false; } }); if (!headerFindSuccess) { columnMap = this.table.columnManager.columnsByIndex; } } //remove header row if found if (headerFindSuccess) { data.shift(); } data.forEach(function (item) { var row = {}; item.forEach(function (value, i) { if (columnMap[i]) { row[columnMap[i].field] = value; } }); rows.push(row); }); return rows; } else { return false; } } }; Clipboard.prototype.pasteActions = { replace: function replace(rows) { return this.table.setData(rows); }, update: function update(rows) { return this.table.updateOrAddData(rows); }, insert: function insert(rows) { return this.table.addData(rows); } }; Tabulator.registerExtension("clipboard", Clipboard); var Download = function Download(table) { this.table = table; //hold Tabulator object this.fields = {}; //hold filed multi dimension arrays this.columnsByIndex = []; //hold columns in their order in the table this.columnsByField = {}; //hold columns with lookup by field name }; //trigger file download Download.prototype.download = function (type, filename, options, interceptCallback) { var self = this, downloadFunc = false; function buildLink(data, mime) { if (interceptCallback) { interceptCallback(data); } else { self.triggerDownload(data, mime, type, filename); } } if (typeof type == "function") { downloadFunc = type; } else { if (self.downloaders[type]) { downloadFunc = self.downloaders[type]; } else { console.warn("Download Error - No such download type found: ", type); } } this.processColumns(); if (downloadFunc) { downloadFunc.call(this, self.processDefinitions(), self.processData(), options || {}, buildLink); } }; Download.prototype.processColumns = function () { var self = this; self.columnsByIndex = []; self.columnsByField = {}; self.table.columnManager.columnsByIndex.forEach(function (column) { if (column.field && column.visible && column.definition.download !== false) { self.columnsByIndex.push(column); self.columnsByField[column.field] = column; } }); }; Download.prototype.processDefinitions = function () { var self = this, processedDefinitions = []; self.columnsByIndex.forEach(function (column) { var definition = column.definition; if (column.download !== false) { //isolate definiton from defintion object var def = {}; for (var key in definition) { def[key] = definition[key]; } if (typeof definition.downloadTitle != "undefined") { def.title = definition.downloadTitle; } processedDefinitions.push(def); } }); return processedDefinitions; }; Download.prototype.processData = function () { var self = this, data = self.table.rowManager.getData(true, "download"); //bulk data processing if (typeof self.table.options.downloadDataFormatter == "function") { data = self.table.options.downloadDataFormatter(data); } return data; }; Download.prototype.triggerDownload = function (data, mime, type, filename) { var element = document.createElement('a'), blob = new Blob([data], { type: mime }), filename = filename || "Tabulator." + (typeof type === "function" ? "txt" : type); blob = this.table.options.downloadReady(data, blob); if (blob) { if (navigator.msSaveOrOpenBlob) { navigator.msSaveOrOpenBlob(blob, filename); } else { element.setAttribute('href', window.URL.createObjectURL(blob)); //set file title element.setAttribute('download', filename); //trigger download element.style.display = 'none'; document.body.appendChild(element); element.click(); //remove temporary link element document.body.removeChild(element); } if (this.table.options.downloadComplete) { this.table.options.downloadComplete(); } } }; //nested field lookup Download.prototype.getFieldValue = function (field, data) { var column = this.columnsByField[field]; if (column) { return column.getFieldValue(data); } return false; }; Download.prototype.commsReceived = function (table, action, data) { switch (action) { case "intercept": this.download(data.type, "", data.options, data.intercept); break; } }; //downloaders Download.prototype.downloaders = { csv: function csv(columns, data, options, setFileContents) { var self = this, titles = [], fields = [], delimiter = options && options.delimiter ? options.delimiter : ",", fileContents; //get field lists columns.forEach(function (column) { if (column.field) { titles.push('"' + String(column.title).split('"').join('""') + '"'); fields.push(column.field); } }); //generate header row fileContents = [titles.join(delimiter)]; //generate each row of the table data.forEach(function (row) { var rowData = []; fields.forEach(function (field) { var value = self.getFieldValue(field, row); switch (typeof value === 'undefined' ? 'undefined' : _typeof(value)) { case "object": value = JSON.stringify(value); break; case "undefined": case "null": value = ""; break; default: value = value; } //escape uotation marks rowData.push('"' + String(value).split('"').join('""') + '"'); }); fileContents.push(rowData.join(delimiter)); }); setFileContents(fileContents.join("\n"), "text/csv"); }, json: function json(columns, data, options, setFileContents) { var fileContents = JSON.stringify(data, null, '\t'); setFileContents(fileContents, "application/json"); }, pdf: function pdf(columns, data, options, setFileContents) { var self = this, fields = [], header = [], body = [], table = "", autoTableParams = options && options.autoTable ? options.autoTable : {}, title = options && options.title ? options.title : "", orientation = options && options.orientation == "portrait" ? "p" : "l"; //build column headers columns.forEach(function (column) { if (column.field) { header.push(column.title || ""); fields.push(column.field); } }); //build table rows data.forEach(function (row) { var rowData = []; fields.forEach(function (field) { var value = self.getFieldValue(field, row); switch (typeof value === 'undefined' ? 'undefined' : _typeof(value)) { case "object": value = JSON.stringify(value); break; case "undefined": case "null": value = ""; break; default: value = value; } rowData.push(value); }); body.push(rowData); }); var doc = new jsPDF(orientation, 'pt'); //set document to landscape, better for most tables if (title) { autoTableParams.addPageContent = function (data) { doc.text(title, 40, 30); }; } doc.autoTable(header, body, autoTableParams); setFileContents(doc.output("arraybuffer"), "application/pdf"); }, xlsx: function xlsx(columns, data, options, setFileContents) { var self = this, sheetName = options.sheetName || "Sheet1", workbook = { SheetNames: [], Sheets: {} }, output; function generateSheet() { var titles = [], fields = [], rows = [], worksheet; //convert rows to worksheet function rowsToSheet() { var sheet = {}; var range = { s: { c: 0, r: 0 }, e: { c: fields.length, r: rows.length } }; XLSX.utils.sheet_add_aoa(sheet, rows); sheet['!ref'] = XLSX.utils.encode_range(range); return sheet; } //get field lists columns.forEach(function (column) { if (column.field) { titles.push(column.title); fields.push(column.field); } }); rows.push(titles); //generate each row of the table data.forEach(function (row) { var rowData = []; fields.forEach(function (field) { rowData.push(self.getFieldValue(field, row)); }); rows.push(rowData); }); worksheet = rowsToSheet(); return worksheet; } if (options.sheetOnly) { setFileContents(generateSheet()); return; } if (options.sheets) { for (var sheet in options.sheets) { if (options.sheets[sheet] === true) { workbook.SheetNames.push(sheet); workbook.Sheets[sheet] = generateSheet(); } else { workbook.SheetNames.push(sheet); this.table.extensions.comms.send(options.sheets[sheet], "download", "intercept", { type: "xlsx", options: { sheetOnly: true }, intercept: function intercept(data) { workbook.Sheets[sheet] = data; } }); } } } else { workbook.SheetNames.push(sheetName); workbook.Sheets[sheetName] = generateSheet(); } //convert workbook to binary array function s2ab(s) { var buf = new ArrayBuffer(s.length); var view = new Uint8Array(buf); for (var i = 0; i != s.length; ++i) { view[i] = s.charCodeAt(i) & 0xFF; }return buf; } output = XLSX.write(workbook, { bookType: 'xlsx', bookSST: true, type: 'binary' }); setFileContents(s2ab(output), "application/octet-stream"); } }; Tabulator.registerExtension("download", Download); var Edit = function Edit(table) { this.table = table; //hold Tabulator object this.currentCell = false; //hold currently editing cell this.mouseClick = false; //hold mousedown state to prevent click binding being overriden by editor opening this.recursionBlock = false; //prevent focus recursion this.invalidEdit = false; }; //initialize column editor Edit.prototype.initializeColumn = function (column) { var self = this, config = { editor: false, blocked: false, check: column.definition.editable, params: column.definition.editorParams || {} }; //set column editor switch (_typeof(column.definition.editor)) { case "string": if (self.editors[column.definition.editor]) { config.editor = self.editors[column.definition.editor]; } else { console.warn("Editor Error - No such editor found: ", column.definition.editor); } break; case "function": config.editor = column.definition.editor; break; case "boolean": if (column.definition.editor === true) { if (typeof column.definition.formatter !== "function") { if (self.editors[column.definition.formatter]) { config.editor = self.editors[column.definition.formatter]; } else { config.editor = self.editors["input"]; } } else { console.warn("Editor Error - Cannot auto lookup editor for a custom formatter: ", column.definition.formatter); } } break; } if (config.editor) { column.extensions.edit = config; } }; Edit.prototype.getCurrentCell = function () { return this.currentCell ? this.currentCell.getComponent() : false; }; Edit.prototype.clearEditor = function () { var cell = this.currentCell; this.invalidEdit = false; if (cell) { this.currentCell = false; cell.getElement().removeClass("tabulator-validation-fail"); cell.getElement().removeClass("tabulator-editing").empty(); cell.row.getElement().removeClass("tabulator-row-editing"); } }; Edit.prototype.cancelEdit = function () { if (this.currentCell) { var cell = this.currentCell; var component = this.currentCell.getComponent(); this.clearEditor(); cell.setValueActual(cell.getValue()); if (cell.column.cellEvents.cellEditCancelled) { cell.column.cellEvents.cellEditCancelled(component); } this.table.options.cellEditCancelled(component); } }; //return a formatted value for a cell Edit.prototype.bindEditor = function (cell) { var self = this, element = cell.getElement(); element.attr("tabindex", 0); element.on("click", function (e) { if (!$(this).hasClass("tabulator-editing")) { $(this).focus(); } }); element.on("mousedown", function (e) { self.mouseClick = true; }); element.on("focus", function (e) { if (!self.recursionBlock) { self.edit(cell, e, false); } }); }; Edit.prototype.focusCellNoEvent = function (cell) { this.recursionBlock = true; cell.getElement().focus(); this.recursionBlock = false; }; Edit.prototype.editCell = function (cell, forceEdit) { this.focusCellNoEvent(cell); this.edit(cell, false, forceEdit); }; Edit.prototype.edit = function (cell, e, forceEdit) { var self = this, allowEdit = true, rendered = function rendered() {}, element = cell.getElement(), cellEditor, component; //prevent editing if another cell is refusing to leave focus (eg. validation fail) if (this.currentCell) { if (!this.invalidEdit) { this.cancelEdit(); } else { return; } return; } //handle successfull value change function success(value) { if (self.currentCell === cell) { var valid = true; if (cell.column.extensions.validate && self.table.extExists("validate")) { valid = self.table.extensions.validate.validate(cell.column.extensions.validate, cell.getComponent(), value); } if (valid === true) { self.clearEditor(); cell.setValue(value, true); } else { self.invalidEdit = true; cell.getElement().addClass("tabulator-validation-fail"); self.focusCellNoEvent(cell); rendered(); self.table.options.validationFailed(cell.getComponent(), value, valid); } } else { console.warn("Edit Success Error - cannot call success on a cell that is no longer being edited"); } }; //handle aborted edit function cancel() { if (self.currentCell === cell) { self.cancelEdit(); } else { console.warn("Edit Success Error - cannot call cancel on a cell that is no longer being edited"); } }; function onRendered(callback) { rendered = callback; } if (!cell.column.extensions.edit.blocked) { if (e) { e.stopPropagation(); } switch (_typeof(cell.column.extensions.edit.check)) { case "function": allowEdit = cell.column.extensions.edit.check(cell.getComponent()); break; case "boolean": allowEdit = cell.column.extensions.edit.check; break; } if (allowEdit || forceEdit) { self.cancelEdit(); self.currentCell = cell; component = cell.getComponent(); if (this.mouseClick) { this.mouseClick = false; if (cell.column.cellEvents.cellClick) { cell.column.cellEvents.cellClick(component); } } if (cell.column.cellEvents.cellEditing) { cell.column.cellEvents.cellEditing(component); } self.table.options.cellEditing(component); cellEditor = cell.column.extensions.edit.editor.call(self, component, onRendered, success, cancel, cell.column.extensions.edit.params); //if editor returned, add to DOM, if false, abort edit if (cellEditor !== false) { element.addClass("tabulator-editing"); cell.row.getElement().addClass("tabulator-row-editing"); element.empty(); element.append(cellEditor); //trigger onRendered Callback rendered(); //prevent editing from triggering rowClick event element.children().click(function (e) { e.stopPropagation(); }); } else { element.blur(); return false; } return true; } else { this.mouseClick = false; element.blur(); return false; } } else { this.mouseClick = false; element.blur(); return false; } }; //default data editors Edit.prototype.editors = { //input element input: function input(cell, onRendered, success, cancel, editorParams) { //create and style input var input = $(""); input.css({ "padding": "4px", "width": "100%", "box-sizing": "border-box" }).val(cell.getValue()); onRendered(function () { input.focus(); input.css("height", "100%"); }); //submit new value on blur input.on("change blur", function (e) { if (input.val() != cell.getValue()) { success(input.val()); } else { cancel(); } }); //submit new value on enter input.on("keydown", function (e) { if (e.keyCode == 13) { success(input.val()); } if (e.keyCode == 27) { cancel(); } }); return input; }, //resizable text area element textarea: function textarea(cell, onRendered, success, cancel, editorParams) { var self = this, cellValue = cell.getValue(), value = String(typeof cellValue == "null" || typeof cellValue == "undefined" ? "" : cellValue), count = (value.match(/(?:\r\n|\r|\n)/g) || []).length + 1, input = $(""), scrollHeight = 0; //create and style input input.css({ "display": "block", "height": "100%", "width": "100%", "padding": "2px", "box-sizing": "border-box", "white-space": "pre-wrap", "resize": "none" }).val(value); onRendered(function () { input.focus(); input.css("height", "100%"); }); //submit new value on blur input.on("change blur", function (e) { if (input.val() != cell.getValue()) { success(input.val()); setTimeout(function () { cell.getRow().normalizeHeight(); }, 300); } else { cancel(); } }); input.on("keyup", function () { input.css({ "height": "" }); var heightNow = input[0].scrollHeight; input.css({ "height": heightNow }); if (heightNow != scrollHeight) { scrollHeight = heightNow; cell.getRow().normalizeHeight(); } }); input.on("keydown", function (e) { if (e.keyCode == 27) { cancel(); } }); return input; }, //input element with type of number number: function number(cell, onRendered, success, cancel, editorParams) { var max = typeof editorParams.max != "undefined" ? "max='" + editorParams.max + "'" : ""; var min = typeof editorParams.min != "undefined" ? "min='" + editorParams.min + "'" : ""; var step = "step='" + (typeof editorParams.step != "undefined" ? editorParams.step : 1) + "'"; var input = $(""); //create and style input input.css({ "padding": "4px", "width": "100%", "box-sizing": "border-box" }).val(cell.getValue()); onRendered(function () { input.css("height", "100%"); setTimeout(function () { input.focus(); }, 10); }); //submit new value on blur input.on("blur", function (e) { var value = input.val(); if (!isNaN(value)) { value = Number(value); } if (value != cell.getValue()) { success(value); } else { cancel(); } }); //submit new value on enter input.on("keydown", function (e) { var value; if (e.keyCode == 13) { value = input.val(); if (!isNaN(value)) { value = Number(value); } success(value); } if (e.keyCode == 27) { cancel(); } }); return input; }, //input element with type of number range: function range(cell, onRendered, success, cancel, editorParams) { var max = "max='" + (typeof editorParams.max != "undefined" ? editorParams.max : 10) + "'"; var min = "min='" + (typeof editorParams.min != "undefined" ? editorParams.min : 0) + "'"; var step = "step='" + (typeof editorParams.step != "undefined" ? editorParams.step : 1) + "'"; var input = $(""); //create and style input input.css({ "padding": "4px", "width": "100%", "box-sizing": "border-box" }).val(cell.getValue()); onRendered(function () { input.css("height", "100%"); setTimeout(function () { input.focus(); }, 10); }); //submit new value on blur input.on("blur", function (e) { var value = input.val(); if (!isNaN(value)) { value = Number(value); } if (value != cell.getValue()) { success(value); } else { cancel(); } }); //submit new value on enter input.on("keydown", function (e) { var value; if (e.keyCode == 13) { value = input.val(); if (!isNaN(value)) { value = Number(value); } success(value); } if (e.keyCode == 27) { cancel(); } }); return input; }, //select select: function select(cell, onRendered, success, cancel, editorParams) { //create and style select var select = $(""); var isArray = Array.isArray(editorParams); if (typeof editorParams == "function") { editorParams = editorParams(cell); isArray = Array.isArray(editorParams); } function optionAppend(element, label, value, disabled) { var option = $("").attr("value", value).text(label); if (disabled) { option.prop("disabled", true); } element.append(option); } function processOption(element, option) { var groupEl; if (option.options) { groupEl = $("").attr("label", option.label); option.options.forEach(function (item) { processOption(groupEl, item); }); element.append(groupEl); } else { optionAppend(element, typeof option.label == "undefined" ? option.value : option.label, typeof option.value == "undefined" ? option.label : option.value, option.disabled); } } if (!isArray && (typeof editorParams === 'undefined' ? 'undefined' : _typeof(editorParams)) === "object") { for (var key in editorParams) { optionAppend(select, editorParams[key], key); } } else if (isArray) { editorParams.forEach(function (item) { processOption(select, item); }); } select.css({ "padding": "4px", "width": "100%", "box-sizing": "border-box", "font-family": "" }).val(cell.getValue()); onRendered(function () { select.focus().click(); }); //submit new value on blur select.on("change blur", function (e) { success(select.val()); }); //submit new value on enter select.on("keydown", function (e) { if (e.keyCode === 13) { success(select.val()); } }); return select; }, //start rating star: function star(cell, onRendered, success, cancel, editorParams) { var element = cell.getElement(), value = cell.getValue(), maxStars = $("svg", element).length || 5, size = $("svg:first", element).attr("width") || 14, stars = $("
"), starActive = $(''), starInactive = $(''); //change number of active stars var starChange = function starChange(element) { if ($(".tabulator-star-active", element.closest("div")).length != element.prevAll("svg").length + 1) { element.prevAll("svg").replaceWith(starActive.clone()); element.nextAll("svg").replaceWith(starInactive.clone()); element.replaceWith(starActive.clone()); } }; value = parseInt(value) < maxStars ? parseInt(value) : maxStars; for (var i = 1; i <= maxStars; i++) { var nextStar = i <= value ? starActive : starInactive; stars.append(nextStar.clone()); } stars.on("mouseover", "svg", function (e) { e.stopPropagation(); starChange($(this)); }); stars.on("mouseover", function (e) { $("svg", $(this)).replaceWith(starInactive.clone()); }); stars.on("click", function (e) { success(0); }); stars.on("click", "svg", function (e) { e.stopPropagation(); success($(this).prevAll("svg").length + 1); }); element.css({ "white-space": "nowrap", "overflow": "hidden", "text-overflow": "ellipsis" }); element.on("blur", function () { cancel(); }); //allow key based navigation element.on("keydown", function (e) { switch (e.keyCode) { case 39: //right arrow starChange($(".tabulator-star-inactive:first", stars)); break; case 37: //left arrow var prevstar = $(".tabulator-star-active:last", stars).prev("svg"); if (prevstar.length) { starChange(prevstar); } else { $("svg", stars).replaceWith(starInactive.clone()); } break; case 13: //enter success($(".tabulator-star-active", stars).length); break; case 27: //escape cancel(); break; } }); return stars; }, //draggable progress bar progress: function progress(cell, onRendered, success, cancel, editorParams) { var element = cell.getElement(), max = $("div", element).data("max"), min = $("div", element).data("min"), percent = (max - min) / 100, value = cell.getValue() || 0, handle = $("
"), bar; var newVal = function newVal() { var calcVal = percent * Math.round(bar.outerWidth() / (element.width() / 100)) + min; success(calcVal); element.attr("aria-valuenow", calcVal).attr("aria-label", value); }; //make sure value is in range value = parseFloat(value) <= max ? parseFloat(value) : max; value = parseFloat(value) >= min ? parseFloat(value) : min; //workout percentage value = 100 - Math.round((value - min) / percent); bar = $("
"), element.css({ padding: "0 4px" }); element.attr("aria-valuemin", min).attr("aria-valuemax", max); bar.append(handle); handle.on("mousedown", function (e) { bar.data("mouseDrag", e.screenX); bar.data("mouseDragWidth", bar.outerWidth()); }); handle.on("mouseover", function () { $(this).css({ cursor: "ew-resize" }); }); element.on("mousemove", function (e) { if (bar.data("mouseDrag")) { bar.css({ width: bar.data("mouseDragWidth") + (e.screenX - bar.data("mouseDrag")) }); } }); element.on("mouseup", function (e) { if (bar.data("mouseDrag")) { e.stopPropagation(); e.stopImmediatePropagation(); bar.data("mouseDragOut", true); bar.data("mouseDrag", false); bar.data("mouseDragWidth", false); newVal(); } }); //allow key based navigation element.on("keydown", function (e) { switch (e.keyCode) { case 39: //right arrow bar.css({ "width": bar.width() + element.width() / 100 }); break; case 37: //left arrow bar.css({ "width": bar.width() - element.width() / 100 }); break; case 13: //enter newVal(); break; case 27: //escape cancel(); break; } }); element.on("blur", function () { cancel(); }); return bar; }, //checkbox tickCross: function tickCross(cell, onRendered, success, cancel, editorParams) { var value = cell.getValue(), input = $(""); //create and style input input.css({ "margin-top": "5px", "box-sizing": "border-box" }).val(value); if (this.table.browser != "firefox") { //prevent blur issue on mac firefox onRendered(function () { input.focus(); }); } if (value === true || value === "true" || value === "True" || value === 1) { input.prop("checked", true); } else { input.prop("checked", false); } //submit new value on blur input.on("change blur", function (e) { success(input.is(":checked")); }); //submit new value on enter input.on("keydown", function (e) { if (e.keyCode == 13) { success(input.is(":checked")); } if (e.keyCode == 27) { cancel(); } }); return input; }, //checkbox tick: function tick(cell, onRendered, success, cancel, editorParams) { var value = cell.getValue(), input = $(""); //create and style input input.css({ "margin-top": "5px", "box-sizing": "border-box" }).val(value); if (this.table.browser != "firefox") { //prevent blur issue on mac firefox onRendered(function () { input.focus(); }); } if (value === true || value === "true" || value === "True" || value === 1) { input.prop("checked", true); } else { input.prop("checked", false); } //submit new value on blur input.on("change blur", function (e) { success(input.is(":checked")); }); //submit new value on enter input.on("keydown", function (e) { if (e.keyCode == 13) { success(input.is(":checked")); } if (e.keyCode == 27) { cancel(); } }); return input; } }; Tabulator.registerExtension("edit", Edit); var Filter = function Filter(table) { this.table = table; //hold Tabulator object this.filterList = []; //hold filter list this.headerFilters = {}; //hold column filters this.headerFilterElements = []; //hold header filter elements for manipulation this.changed = false; //has filtering changed since last render }; //initialize column header filter Filter.prototype.initializeColumn = function (column) { var self = this, field = column.getField(), filterElement, editor, editorElement, cellWrapper, typingTimer, tagType, attrType; //handle successfull value change function success(value) { var filterType = tagType == "input" && attrType == "text" || tagType == "textarea" ? "partial" : "match", type = "", filterFunc; if (value) { switch (_typeof(column.definition.headerFilterFunc)) { case "string": if (self.filters[column.definition.headerFilterFunc]) { type = column.definition.headerFilterFunc; filterFunc = function filterFunc(data) { return self.filters[column.definition.headerFilterFunc](value, column.getFieldValue(data)); }; } else { console.warn("Header Filter Error - Matching filter function not found: ", column.definition.headerFilterFunc); } break; case "function": filterFunc = function filterFunc(data) { return column.definition.headerFilterFunc(value, column.getFieldValue(data), data, column.definition.headerFilterFuncParams || {}); }; type = filterFunc; break; } if (!filterFunc) { switch (filterType) { case "partial": filterFunc = function filterFunc(data) { return String(column.getFieldValue(data)).toLowerCase().indexOf(String(value).toLowerCase()) > -1; }; type = "like"; break; default: filterFunc = function filterFunc(data) { return column.getFieldValue(data) == value; }; type = "="; } } self.headerFilters[field] = { value: value, func: filterFunc, type: type }; } else { delete self.headerFilters[field]; } self.changed = true; self.table.rowManager.filterRefresh(); }; column.extensions.filter = { success: success }; //handle aborted edit function cancel() {}; if (field) { filterElement = $("
"); //set column editor switch (_typeof(column.definition.headerFilter)) { case "string": if (self.table.extensions.edit.editors[column.definition.headerFilter]) { editor = self.table.extensions.edit.editors[column.definition.headerFilter]; } else { console.warn("Filter Error - Cannot build header filter, No such editor found: ", column.definition.editor); } break; case "function": editor = column.definition.headerFilter; break; case "boolean": if (column.extensions.edit && column.extensions.edit.editor) { editor = column.extensions.edit.editor; } else { if (column.definition.formatter && self.table.extensions.edit.editors[column.definition.formatter]) { editor = self.table.extensions.edit.editors[column.definition.formatter]; } else { editor = self.table.extensions.edit.editors["input"]; } } break; } if (editor) { cellWrapper = { getValue: function getValue() { return ""; }, getField: function getField() { return column.definition.field; }, getElement: function getElement() { return filterElement; }, getRow: function getRow() { return { normalizeHeight: function normalizeHeight() {} }; } }; editorElement = editor.call(self, cellWrapper, function () {}, success, cancel, column.definition.headerFilterParams || {}); //set Placeholder Text if (field) { self.table.extensions.localize.bind("headerFilters|columns|" + column.definition.field, function (value) { editorElement.attr("placeholder", typeof value !== "undefined" && value ? value : self.table.extensions.localize.getText("headerFilters|default")); }); } else { self.table.extensions.localize.bind("headerFilters|default", function (value) { editorElement.attr("placeholdder", typeof self.column.definition.headerFilterPlaceholder !== "undefined" && self.column.definition.headerFilterPlaceholder ? self.column.definition.headerFilterPlaceholder : value); }); } //focus on element on click editorElement.on("click", function (e) { e.stopPropagation(); $(this).focus(); }); //live update filters as user types typingTimer = false; editorElement.on("keyup search", function (e) { var element = $(this); if (typingTimer) { clearTimeout(typingTimer); } typingTimer = setTimeout(function () { success(element.val()); }, 300); }); column.extensions.filter.headerElement = editorElement; //update number filtered columns on change attrType = editorElement.attr("type") ? editorElement.attr("type").toLowerCase() : ""; if (attrType == "number") { editorElement.on("change", function (e) { success($(this).val()); }); } //change text inputs to search inputs to allow for clearing of field if (attrType == "text" && this.table.browser !== "ie") { editorElement.attr("type", "search"); editorElement.off("change blur"); //prevent blur from triggering filter and preventing selection click } //prevent input and select elements from propegating click to column sorters etc tagType = editorElement.prop("tagName").toLowerCase(); if (tagType == "input" || tagType == "select" || tagType == "textarea") { editorElement.on("mousedown", function (e) { e.stopPropagation(); }); } filterElement.append(editorElement); column.contentElement.append(filterElement); self.headerFilterElements.push(editorElement); } } else { console.warn("Filter Error - Cannot add header filter, column has no field set:", column.definition.title); } }; //hide all header filter elements (used to ensure correct column widths in "fitData" layout mode) Filter.prototype.hideHeaderFilterElements = function () { this.headerFilterElements.forEach(function (element) { element.hide(); }); }; //show all header filter elements (used to ensure correct column widths in "fitData" layout mode) Filter.prototype.showHeaderFilterElements = function () { this.headerFilterElements.forEach(function (element) { element.show(); }); }; //programatically set value of header filter Filter.prototype.setHeaderFilterFocus = function (column) { if (column.extensions.filter && column.extensions.filter.headerElement) { column.extensions.filter.headerElement.focus(); } else { console.warn("Column Filter Focus Error - No header filter set on column:", column.getField()); } }; //programatically set value of header filter Filter.prototype.setHeaderFilterValue = function (column, value) { if (column) { if (column.extensions.filter && column.extensions.filter.headerElement) { column.extensions.filter.headerElement.val(value); column.extensions.filter.success(value); } else { console.warn("Column Filter Error - No header filter set on column:", column.getField()); } } }; //check if the filters has changed since last use Filter.prototype.hasChanged = function () { var changed = this.changed; this.changed = false; return changed; }; //set standard filters Filter.prototype.setFilter = function (field, type, value) { var self = this; self.filterList = []; if (!Array.isArray(field)) { field = [{ field: field, type: type, value: value }]; } self.addFilter(field); }; //add filter to array Filter.prototype.addFilter = function (field, type, value) { var self = this; if (!Array.isArray(field)) { field = [{ field: field, type: type, value: value }]; } field.forEach(function (filter) { filter = self.findFilter(filter); if (filter) { self.filterList.push(filter); self.changed = true; } }); if (this.table.options.persistentFilter && this.table.extExists("persistence", true)) { this.table.extensions.persistence.save("filter"); } }; Filter.prototype.findFilter = function (filter) { var self = this, column; if (Array.isArray(filter)) { return this.findSubFilters(filter); } var filterFunc = false; if (typeof filter.field == "function") { filterFunc = function filterFunc(data) { return filter.field(data, filter.type || {}); // pass params to custom filter function }; } else { if (self.filters[filter.type]) { column = self.table.columnManager.getColumnByField(filter.field); if (column) { filterFunc = function filterFunc(data) { return self.filters[filter.type](filter.value, column.getFieldValue(data)); }; } else { filterFunc = function filterFunc(data) { return self.filters[filter.type](filter.value, data[filter.field]); }; } } else { console.warn("Filter Error - No such filter type found, ignoring: ", filter.type); } } filter.func = filterFunc; return filter.func ? filter : false; }; Filter.prototype.findSubFilters = function (filters) { var self = this, output = []; filters.forEach(function (filter) { filter = self.findFilter(filter); if (filter) { output.push(filter); } }); return output.length ? output : false; }; //get all filters Filter.prototype.getFilters = function (all, ajax) { var self = this, output = []; if (all) { output = self.getHeaderFilters(); } self.filterList.forEach(function (filter) { output.push({ field: filter.field, type: filter.type, value: filter.value }); }); if (ajax) { output.forEach(function (item) { if (typeof item.type == "function") { item.type = "function"; } }); } return output; }; //get all filters Filter.prototype.getHeaderFilters = function () { var self = this, output = []; for (var key in this.headerFilters) { output.push({ field: key, type: this.headerFilters[key].type, value: this.headerFilters[key].value }); } return output; }; //remove filter from array Filter.prototype.removeFilter = function (field, type, value) { var self = this; if (!Array.isArray(field)) { field = [{ field: field, type: type, value: value }]; } field.forEach(function (filter) { var index = -1; if (_typeof(filter.field) == "object") { index = self.filterList.findIndex(function (element) { return filter === element; }); } else { index = self.filterList.findIndex(function (element) { return filter.field === element.field && filter.type === element.type && filter.value === element.value; }); } if (index > -1) { self.filterList.splice(index, 1); self.changed = true; } else { console.warn("Filter Error - No matching filter type found, ignoring: ", filter.type); } }); if (this.table.options.persistentFilter && this.table.extExists("persistence", true)) { this.table.extensions.persistence.save("filter"); } }; //clear filters Filter.prototype.clearFilter = function (all) { this.filterList = []; if (all) { this.clearHeaderFilter(); } this.changed = true; if (this.table.options.persistentFilter && this.table.extExists("persistence", true)) { this.table.extensions.persistence.save("filter"); } }; //clear header filters Filter.prototype.clearHeaderFilter = function () { this.headerFilters = {}; this.headerFilterElements.forEach(function (element) { element.val(""); }); this.changed = true; }; //filter row array Filter.prototype.filter = function (rowList) { var self = this, activeRows = [], activeRowComponents = []; if (self.table.options.dataFiltering) { self.table.options.dataFiltering(self.getFilters()); } if (!self.table.options.ajaxFiltering && (self.filterList.length || Object.keys(self.headerFilters).length)) { rowList.forEach(function (row) { if (self.filterRow(row)) { activeRows.push(row); } }); activeRows; } else { activeRows = rowList.slice(0); } if (self.table.options.dataFiltered) { activeRows.forEach(function (row) { activeRowComponents.push(row.getComponent()); }); self.table.options.dataFiltered(self.getFilters(), activeRowComponents); } return activeRows; }; //filter individual row Filter.prototype.filterRow = function (row) { var self = this, match = true, data = row.getData(); self.filterList.forEach(function (filter) { if (!self.filterRecurse(filter, data)) { match = false; } }); for (var field in self.headerFilters) { if (!self.headerFilters[field].func(data)) { match = false; } } return match; }; Filter.prototype.filterRecurse = function (filter, data) { var self = this, match = false; if (Array.isArray(filter)) { filter.forEach(function (subFilter) { if (self.filterRecurse(subFilter, data)) { match = true; } }); } else { match = filter.func(data); } return match; }; //list of available filters Filter.prototype.filters = { //equal to "=": function _(filterVal, rowVal) { return rowVal == filterVal ? true : false; }, //less than "<": function _(filterVal, rowVal) { return rowVal < filterVal ? true : false; }, //less than or equal to "<=": function _(filterVal, rowVal) { return rowVal <= filterVal ? true : false; }, //greater than ">": function _(filterVal, rowVal) { return rowVal > filterVal ? true : false; }, //greater than or equal to ">=": function _(filterVal, rowVal) { return rowVal >= filterVal ? true : false; }, //not equal to "!=": function _(filterVal, rowVal) { return rowVal != filterVal ? true : false; }, //contains the string "like": function like(filterVal, rowVal) { if (filterVal === null || typeof filterVal === "undefined") { return rowVal === filterVal ? true : false; } else { if (typeof rowVal !== 'undefined' && rowVal !== null) { return String(rowVal).toLowerCase().indexOf(filterVal.toLowerCase()) > -1 ? true : false; } else { return false; } } }, //in array "in": function _in(filterVal, rowVal) { if (Array.isArray(filterVal)) { return filterVal.indexOf(rowVal) > -1; } else { console.warn("Filter Error - filter value is not an array:", filterVal); return false; } } }; Tabulator.registerExtension("filter", Filter); var Format = function Format(table) { this.table = table; //hold Tabulator object }; //initialize column formatter Format.prototype.initializeColumn = function (column) { var self = this, config = { params: column.definition.formatterParams || {} }; //set column formatter switch (_typeof(column.definition.formatter)) { case "string": if (self.formatters[column.definition.formatter]) { config.formatter = self.formatters[column.definition.formatter]; if (column.definition.formatter === "email") { console.warn("The%c email%c formatter has been depricated and will be removed in version 4.0, use the %clink %cformatter with %cformatterParams:{urlPrefix:'mailto:'} %cinstead.", "font-weight:bold;", "font-weight:regular;", "font-weight:bold;", "font-weight:regular;", "font-weight:bold;", "font-weight:regular;"); } } else { console.warn("Formatter Error - No such formatter found: ", column.definition.formatter); config.formatter = self.formatters.plaintext; } break; case "function": config.formatter = column.definition.formatter; break; default: config.formatter = self.formatters.plaintext; break; } column.extensions.format = config; }; //return a formatted value for a cell Format.prototype.formatValue = function (cell) { return cell.column.extensions.format.formatter.call(this, cell.getComponent(), cell.column.extensions.format.params); }; Format.prototype.sanitizeHTML = function (value) { if (value) { var entityMap = { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''', '/': '/', '`': '`', '=': '=' }; return String(value).replace(/[&<>"'`=\/]/g, function (s) { return entityMap[s]; }); } else { return value; } }; Format.prototype.emptyToSpace = function (value) { return value === null ? " " : value; }; //get formatter for cell Format.prototype.getFormatter = function (formatter) { var formatter; switch (typeof formatter === 'undefined' ? 'undefined' : _typeof(formatter)) { case "string": if (this.formatters[formatter]) { formatter = this.formatters[formatter]; } else { console.warn("Formatter Error - No such formatter found: ", formatter); formatter = this.formatters.plaintext; } break; case "function": formatter = formatter; break; default: formatter = this.formatters.plaintext; break; } return formatter; }; //default data formatters Format.prototype.formatters = { //plain text value plaintext: function plaintext(cell, formatterParams) { return this.emptyToSpace(this.sanitizeHTML(cell.getValue())); }, //html text value html: function html(cell, formatterParams) { return cell.getValue(); }, //multiline text area textarea: function textarea(cell, formatterParams) { cell.getElement().css({ "white-space": "pre-wrap" }); return this.emptyToSpace(this.sanitizeHTML(cell.getValue())); }, //currency formatting money: function money(cell, formatterParams) { var floatVal = parseFloat(cell.getValue()), number, integer, decimal, rgx; var decimalSym = formatterParams.decimal || "."; var thousandSym = formatterParams.thousand || ","; var symbol = formatterParams.symbol || ""; var after = !!formatterParams.symbolAfter; var precision = typeof formatterParams.precision !== "undefined" ? formatterParams.precision : 2; if (isNaN(floatVal)) { return this.emptyToSpace(this.sanitizeHTML(cell.getValue())); } number = precision !== false ? floatVal.toFixed(precision) : floatVal; number = number.split("."); integer = number[0]; decimal = number.length > 1 ? decimalSym + number[1] : ""; rgx = /(\d+)(\d{3})/; while (rgx.test(integer)) { integer = integer.replace(rgx, "$1" + thousandSym + "$2"); } return after ? integer + decimal + symbol : symbol + integer + decimal; }, //clickable mailto link email: function email(cell, formatterParams) { var value = this.sanitizeHTML(cell.getValue()); return "" + this.emptyToSpace(value) + ""; }, //clickable anchor tag link: function link(cell, formatterParams) { var value = this.sanitizeHTML(cell.getValue()), urlPrefix = formatterParams.urlPrefix || "", label = this.emptyToSpace(value), data; if (formatterParams.labelField) { data = cell.getData(); label = data[formatterParams.labelField]; } if (formatterParams.label) { switch (_typeof(formatterParams.label)) { case "string": label = formatterParams.label; break; case "function": label = formatterParams.label(cell); break; } } if (formatterParams.urlField) { data = cell.getData(); value = data[formatterParams.urlField]; } if (formatterParams.url) { switch (_typeof(formatterParams.url)) { case "string": value = formatterParams.url; break; case "function": value = formatterParams.url(cell); break; } } return "" + label + ""; }, //image element image: function image(cell, formatterParams) { var value = this.sanitizeHTML(cell.getValue()); var el = $(""); el.on("load", function () { cell.getRow().normalizeHeight(); }); return el; }, //tick or empty cell tick: function tick(cell, formatterParams) { var value = cell.getValue(), element = cell.getElement(); var tick = ''; if (value === true || value === "true" || value === "True" || value === 1 || value === "1") { element.attr("aria-checked", true); return tick; } else { element.attr("aria-checked", false); return ""; } }, //tick or cross tickCross: function tickCross(cell, formatterParams) { var value = cell.getValue(), element = cell.getElement(), tick = '', cross = ''; if (value === true || value === "true" || value === "True" || value === 1 || value === "1") { element.attr("aria-checked", true); return tick; } else { element.attr("aria-checked", false); return cross; } }, //select lookup: function lookup(cell, formatterParams) { var value = cell.getValue(); if (typeof formatterParams[value] === "undefined") { console.warn('Missing display value for ' + value); return value; } return formatterParams[value]; }, //star rating star: function star(cell, formatterParams) { var value = cell.getValue(), element = cell.getElement(), maxStars = formatterParams && formatterParams.stars ? formatterParams.stars : 5, stars = $(""), starActive = $(''), starInactive = $(''); value = parseInt(value) < maxStars ? parseInt(value) : maxStars; for (var i = 1; i <= maxStars; i++) { var nextStar = i <= value ? starActive : starInactive; stars.append(nextStar.clone()); } element.css({ "white-space": "nowrap", "overflow": "hidden", "text-overflow": "ellipsis" }); element.attr("aria-label", value); return stars.html(); }, //progress bar progress: function progress(cell, formatterParams) { //progress bar var value = this.sanitizeHTML(cell.getValue()) || 0, element = cell.getElement(), max = formatterParams && formatterParams.max ? formatterParams.max : 100, min = formatterParams && formatterParams.min ? formatterParams.min : 0, legendAlign = formatterParams && formatterParams.legendAlign ? formatterParams.legendAlign : "center", percent, percentValue, color, legend, legendColor, top, left, right, bottom; //make sure value is in range percentValue = parseFloat(value) <= max ? parseFloat(value) : max; percentValue = parseFloat(percentValue) >= min ? parseFloat(percentValue) : min; //workout percentage percent = (max - min) / 100; percentValue = Math.round((percentValue - min) / percent); //set bar color switch (_typeof(formatterParams.color)) { case "string": color = formatterParams.color; break; case "function": color = formatterParams.color(value); break; case "object": if (Array.isArray(formatterParams.color)) { var unit = 100 / formatterParams.color.length; var index = Math.floor(percentValue / unit); index = Math.min(index, formatterParams.color.length - 1); index = Math.max(index, 0); color = formatterParams.color[index]; break; } default: color = "#2DC214"; } //generate legend switch (_typeof(formatterParams.legend)) { case "string": legend = formatterParams.legend; break; case "function": legend = formatterParams.legend(value); break; case "boolean": legend = value; break; default: legend = false; } //set legend color switch (_typeof(formatterParams.legendColor)) { case "string": legendColor = formatterParams.legendColor; break; case "function": legendColor = formatterParams.legendColor(value); break; case "object": if (Array.isArray(formatterParams.legendColor)) { var unit = 100 / formatterParams.legendColor.length; var index = Math.floor(percentValue / unit); index = Math.min(index, formatterParams.legendColor.length - 1); index = Math.max(index, 0); legendColor = formatterParams.legendColor[index]; break; } default: legendColor = "#000"; } element.css({ "min-width": "30px", "position": "relative" }); element.attr("aria-label", percentValue); return "
" + (legend ? "
" + legend + "
" : ""); }, //background color color: function color(cell, formatterParams) { cell.getElement().css({ "background-color": this.sanitizeHTML(cell.getValue()) }); return ""; }, //tick icon buttonTick: function buttonTick(cell, formatterParams) { return ''; }, //cross icon buttonCross: function buttonCross(cell, formatterParams) { return ''; }, //current row number rownum: function rownum(cell, formatterParams) { return this.table.rowManager.activeRows.indexOf(cell.getRow()._getSelf()) + 1; }, //row handle handle: function handle(cell, formatterParams) { cell.getElement().addClass("tabulator-row-handle"); return "
"; }, responsiveCollapse: function responsiveCollapse(cell, formatterParams) { var self = this, el = $("
+-
"); cell.getElement().addClass("tabulator-row-handle"); if (self.table.options.responsiveLayoutCollapseStartOpen) { el.addClass("open"); } el.click(function () { $(this).toggleClass("open"); $(this).closest(".tabulator-row").find(".tabulator-responsive-collapse").toggle(); }); return el; } }; Tabulator.registerExtension("format", Format); var FrozenColumns = function FrozenColumns(table) { this.table = table; //hold Tabulator object this.leftColumns = []; this.rightColumns = []; this.leftMargin = 0; this.rightMargin = 0; this.initializationMode = "left"; this.active = false; }; //reset initial state FrozenColumns.prototype.reset = function () { this.initializationMode = "left"; this.leftColumns = []; this.rightColumns = []; this.active = false; }; //initialize specific column FrozenColumns.prototype.initializeColumn = function (column) { var config = { margin: 0, edge: false }; if (column.definition.frozen) { if (!column.parent.isGroup) { if (!column.isGroup) { config.position = this.initializationMode; if (this.initializationMode == "left") { this.leftColumns.push(column); } else { this.rightColumns.unshift(column); } this.active = true; column.extensions.frozen = config; } else { console.warn("Frozen Column Error - Column Groups cannot be frozen"); } } else { console.warn("Frozen Column Error - Grouped columns cannot be frozen"); } } else { this.initializationMode = "right"; } }; //layout columns appropropriatly FrozenColumns.prototype.layout = function () { var self = this, tableHolder = this.table.rowManager.element, rightMargin = 0; if (self.active) { //calculate row padding self.leftMargin = self._calcSpace(self.leftColumns, self.leftColumns.length); self.table.columnManager.headersElement.css("margin-left", self.leftMargin); self.rightMargin = self._calcSpace(self.rightColumns, self.rightColumns.length); self.table.columnManager.element.css("padding-right", self.rightMargin); self.table.rowManager.activeRows.forEach(function (row) { self.layoutRow(row); }); if (self.table.extExists("columnCalcs")) { if (self.table.extensions.columnCalcs.topInitialized && self.table.extensions.columnCalcs.topRow) { self.layoutRow(self.table.extensions.columnCalcs.topRow); } if (self.table.extensions.columnCalcs.botInitialized && self.table.extensions.columnCalcs.botRow) { self.layoutRow(self.table.extensions.columnCalcs.botRow); } } //calculate left columns self.leftColumns.forEach(function (column, i) { column.extensions.frozen.margin = self._calcSpace(self.leftColumns, i) + self.table.columnManager.scrollLeft; if (i == self.leftColumns.length - 1) { column.extensions.frozen.edge = true; } else { column.extensions.frozen.edge = false; } self.layoutColumn(column); }); //calculate right frozen columns rightMargin = self.table.rowManager.element.innerWidth() + self.table.columnManager.scrollLeft; if (tableHolder[0].scrollHeight > tableHolder.innerHeight()) { rightMargin -= tableHolder[0].offsetWidth - tableHolder[0].clientWidth; } self.rightColumns.forEach(function (column, i) { column.extensions.frozen.margin = rightMargin - self._calcSpace(self.rightColumns, i + 1); if (i == self.rightColumns.length - 1) { column.extensions.frozen.edge = true; } else { column.extensions.frozen.edge = false; } self.layoutColumn(column); }); } }; FrozenColumns.prototype.layoutColumn = function (column) { var self = this; self.layoutElement(column.element, column); column.cells.forEach(function (cell) { self.layoutElement(cell.element, column); }); }; FrozenColumns.prototype.layoutRow = function (row) { row.getElement().css({ "padding-left": this.leftMargin, "padding-right": this.rightMargin }); }; FrozenColumns.prototype.layoutElement = function (element, column) { if (column.extensions.frozen) { var css = { position: "absolute", left: column.extensions.frozen.margin }; element.css(css); element.addClass("tabulator-frozen"); if (column.extensions.frozen.edge) { element.addClass("tabulator-frozen-" + column.extensions.frozen.position); } } }; FrozenColumns.prototype._calcSpace = function (columns, index) { var width = 0; for (var i = 0; i < index; i++) { if (columns[i].visible) { width += columns[i].getWidth(); } } return width; }; Tabulator.registerExtension("frozenColumns", FrozenColumns); var FrozenRows = function FrozenRows(table) { this.table = table; //hold Tabulator object this.topElement = $("
"); this.rows = []; this.displayIndex = 0; //index in display pipeline }; FrozenRows.prototype.initialize = function () { this.rows = []; this.table.columnManager.element.append(this.topElement); }; FrozenRows.prototype.setDisplayIndex = function (index) { this.displayIndex = index; }; FrozenRows.prototype.getDisplayIndex = function () { return this.displayIndex; }; FrozenRows.prototype.isFrozen = function () { return !!this.rows.length; }; //filter frozen rows out of display data FrozenRows.prototype.getRows = function (rows) { var self = this, frozen = [], output = rows.slice(0); this.rows.forEach(function (row) { var index = output.indexOf(row); if (index > -1) { output.splice(index, 1); } }); return output; }; FrozenRows.prototype.freezeRow = function (row) { if (!row.extensions.frozen) { row.extensions.frozen = true; this.topElement.append(row.getElement()); row.initialize(); row.normalizeHeight(); this.table.rowManager.adjustTableSize(); this.rows.push(row); this.table.rowManager.refreshActiveData("display"); this.styleRows(); } else { console.warn("Freeze Error - Row is already frozen"); } }; FrozenRows.prototype.unfreezeRow = function (row) { var index = this.rows.indexOf(row); if (row.extensions.frozen) { row.extensions.frozen = false; row.getElement().detach(); this.table.rowManager.adjustTableSize(); this.rows.splice(index, 1); this.table.rowManager.refreshActiveData("display"); if (this.rows.length) { this.styleRows(); } } else { console.warn("Freeze Error - Row is already unfrozen"); } }; FrozenRows.prototype.styleRows = function (row) { var self = this; this.rows.forEach(function (row, i) { self.table.rowManager.styleRow(row, i); }); }; Tabulator.registerExtension("frozenRows", FrozenRows); //public group object var GroupComponent = function GroupComponent(group) { this.group = group; this.type = "GroupComponent"; }; GroupComponent.prototype.getKey = function () { return this.group.key; }; GroupComponent.prototype.getElement = function () { return this.group.element; }; GroupComponent.prototype.getRows = function () { var output = []; this.group.rows.forEach(function (row) { output.push(row.getComponent()); }); return output; }; GroupComponent.prototype.getSubGroups = function () { var output = []; this.group.groupList.forEach(function (child) { output.push(child.getComponent()); }); return output; }; GroupComponent.prototype.getParentGroup = function () { return this.group.parent ? this.group.parent.getComponent() : false; }; GroupComponent.prototype.getVisibility = function () { return this.group.visible; }; GroupComponent.prototype.show = function () { this.group.show(); }; GroupComponent.prototype.hide = function () { this.group.hide(); }; GroupComponent.prototype.toggle = function () { this.group.toggleVisibility(); }; GroupComponent.prototype._getSelf = function () { return this.group; }; ////////////////////////////////////////////////// //////////////// Group Functions ///////////////// ////////////////////////////////////////////////// var Group = function Group(groupManager, parent, level, key, field, generator, oldGroup) { this.groupManager = groupManager; this.parent = parent; this.key = key; this.level = level; this.field = field; this.hasSubGroups = level < groupManager.groupIDLookups.length - 1; this.addRow = this.hasSubGroups ? this._addRowToGroup : this._addRow; this.type = "group"; //type of element this.old = oldGroup; this.rows = []; this.groups = []; this.groupList = []; this.generator = generator; this.element = $("
"); this.elementContents = $(""), this.arrowElement = $("
"); this.height = 0; this.outerHeight = 0; this.initialized = false; this.calcs = {}; this.initialized = false; this.extensions = {}; this.visible = oldGroup ? oldGroup.visible : typeof groupManager.startOpen[level] !== "undefined" ? groupManager.startOpen[level] : groupManager.startOpen[0]; this.addBindings(); }; Group.prototype.addBindings = function () { var self = this, dblTap, tapHold, tap, toggleElement; //handle group click events if (self.groupManager.table.options.groupClick) { self.element.on("click", function (e) { self.groupManager.table.options.groupClick(e, self.getComponent()); }); } if (self.groupManager.table.options.groupDblClick) { self.element.on("dblclick", function (e) { self.groupManager.table.options.groupDblClick(e, self.getComponent()); }); } if (self.groupManager.table.options.groupContext) { self.element.on("contextmenu", function (e) { self.groupManager.table.options.groupContext(e, self.getComponent()); }); } if (self.groupManager.table.options.groupTap) { tap = false; self.element.on("touchstart", function (e) { tap = true; }); self.element.on("touchend", function (e) { if (tap) { self.groupManager.table.options.groupTap(e, self.getComponent()); } tap = false; }); } if (self.groupManager.table.options.groupDblTap) { dblTap = null; self.element.on("touchend", function (e) { if (dblTap) { clearTimeout(dblTap); dblTap = null; self.groupManager.table.options.groupDblTap(e, self.getComponent()); } else { dblTap = setTimeout(function () { clearTimeout(dblTap); dblTap = null; }, 300); } }); } if (self.groupManager.table.options.groupTapHold) { tapHold = null; self.element.on("touchstart", function (e) { clearTimeout(tapHold); tapHold = setTimeout(function () { clearTimeout(tapHold); tapHold = null; tap = false; self.groupManager.table.options.groupTapHold(e, self.getComponent()); }, 1000); }); self.element.on("touchend", function (e) { clearTimeout(tapHold); tapHold = null; }); } if (self.groupManager.table.options.groupToggleElement) { toggleElement = self.groupManager.table.options.groupToggleElement == "arrow" ? self.arrowElement : self.element; toggleElement.on("click", function (e) { e.stopPropagation(); e.stopImmediatePropagation(); self.toggleVisibility(); }); } }; Group.prototype._addRowToGroup = function (row) { var level = this.level + 1; if (this.hasSubGroups) { var groupID = this.groupManager.groupIDLookups[level].func(row.getData()); if (!this.groups[groupID]) { var group = new Group(this.groupManager, this, level, groupID, this.groupManager.groupIDLookups[level].field, this.groupManager.headerGenerator[level] || this.groupManager.headerGenerator[0], this.old ? this.old.groups[groupID] : false); this.groups[groupID] = group; this.groupList.push(group); } this.groups[groupID].addRow(row); } }; Group.prototype._addRow = function (row) { this.rows.push(row); row.extensions.group = this; }; Group.prototype.insertRow = function (row, to, after) { var data = this.conformRowData({}); row.updateData(data); var toIndex = this.rows.indexOf(to); if (toIndex > -1) { if (after) { this.rows.splice(toIndex + 1, 0, row); } else { this.rows.splice(toIndex, 0, row); } } else { if (after) { this.rows.push(row); } else { this.rows.unshift(row); } } row.extensions.group = this; this.generateGroupHeaderContents(); if (this.groupManager.table.extExists("columnCalcs") && this.groupManager.table.options.columnCalcs != "table") { this.groupManager.table.extensions.columnCalcs.recalcGroup(this); } }; Group.prototype.getRowIndex = function (row) {}; //update row data to match grouping contraints Group.prototype.conformRowData = function (data) { if (this.field) { data[this.field] = this.key; } else { console.warn("Data Conforming Error - Cannot conform row data to match new group as groupBy is a function"); } if (this.parent) { data = this.parent.conformRowData(data); } return data; }; Group.prototype.removeRow = function (row) { var index = this.rows.indexOf(row); if (index > -1) { this.rows.splice(index, 1); } if (!this.rows.length) { if (this.parent) { this.parent.removeGroup(this); } else { this.groupManager.removeGroup(this); } this.groupManager.updateGroupRows(true); } else { this.generateGroupHeaderContents(); if (this.groupManager.table.extExists("columnCalcs") && this.groupManager.table.options.columnCalcs != "table") { this.groupManager.table.extensions.columnCalcs.recalcGroup(this); } } }; Group.prototype.removeGroup = function (group) { var index; if (this.groups[group.key]) { delete this.groups[group.key]; index = this.groupList.indexOf(group); if (index > -1) { this.groupList.splice(index, 1); } if (!this.groupList.length) { if (this.parent) { this.parent.removeGroup(this); } else { this.groupManager.removeGroup(this); } } } }; Group.prototype.getHeadersAndRows = function () { var output = []; output.push(this); this._visSet(); if (this.visible) { if (this.groupList.length) { this.groupList.forEach(function (group) { output = output.concat(group.getHeadersAndRows()); }); } else { if (this.groupManager.table.options.columnCalcs != "table" && this.groupManager.table.extExists("columnCalcs") && this.groupManager.table.extensions.columnCalcs.hasTopCalcs()) { this.calcs.top = this.groupManager.table.extensions.columnCalcs.generateTopRow(this.rows); output.push(this.calcs.top); } output = output.concat(this.rows); if (this.groupManager.table.options.columnCalcs != "table" && this.groupManager.table.extExists("columnCalcs") && this.groupManager.table.extensions.columnCalcs.hasBottomCalcs()) { this.calcs.bottom = this.groupManager.table.extensions.columnCalcs.generateBottomRow(this.rows); output.push(this.calcs.bottom); } } } else { if (!this.groupList.length && this.groupManager.table.options.columnCalcs != "table" && this.groupManager.table.options.groupClosedShowCalcs) { if (this.groupManager.table.extExists("columnCalcs")) { if (this.groupManager.table.extensions.columnCalcs.hasTopCalcs()) { this.calcs.top = this.groupManager.table.extensions.columnCalcs.generateTopRow(this.rows); output.push(this.calcs.top); } if (this.groupManager.table.extensions.columnCalcs.hasBottomCalcs()) { this.calcs.bottom = this.groupManager.table.extensions.columnCalcs.generateBottomRow(this.rows); output.push(this.calcs.bottom); } } } } return output; }; Group.prototype.getRows = function () { this._visSet(); return this.visible ? this.rows : []; }; Group.prototype.getRowCount = function () { var count = 0; if (this.groupList.length) { this.groupList.forEach(function (group) { count += group.getRowCount(); }); } else { count = this.rows.length; } return count; }; Group.prototype.toggleVisibility = function () { if (this.visible) { this.hide(); } else { this.show(); } }; Group.prototype.hide = function () { this.visible = false; if (this.groupManager.table.rowManager.getRenderMode() == "classic" && !this.groupManager.table.options.pagination) { this.element.removeClass("tabulator-group-visible"); if (this.groupList.length) { this.groupList.forEach(function (group) { if (group.calcs.top) { group.calcs.top.getElement().detach(); } if (group.calcs.bottom) { group.calcs.bottom.getElement().detach(); } var rows = group.getHeadersAndRows(); rows.forEach(function (row) { row.getElement().detach(); }); }); } else { this.rows.forEach(function (row) { row.getElement().detach(); }); } this.groupManager.table.rowManager.setDisplayRows(this.groupManager.updateGroupRows(), this.groupManager.getDisplayIndex()); } else { this.groupManager.updateGroupRows(true); } this.groupManager.table.options.groupVisibilityChanged(this.getComponent(), false); }; Group.prototype.show = function () { var self = this; self.visible = true; if (this.groupManager.table.rowManager.getRenderMode() == "classic" && !this.groupManager.table.options.pagination) { this.element.addClass("tabulator-group-visible"); var prev = self.getElement(); if (this.groupList.length) { this.groupList.forEach(function (group) { var rows = group.getHeadersAndRows(); rows.forEach(function (row) { prev.after(row.getElement()); row.initialize(); prev = row.getElement(); }); }); } else { self.rows.forEach(function (row) { prev.after(row.getElement()); row.initialize(); prev = row.getElement(); }); } this.groupManager.table.rowManager.setDisplayRows(this.groupManager.updateGroupRows(), this.groupManager.getDisplayIndex()); } else { this.groupManager.updateGroupRows(true); } this.groupManager.table.options.groupVisibilityChanged(this.getComponent(), true); }; Group.prototype._visSet = function () { var data = []; if (typeof this.visible == "function") { this.rows.forEach(function (row) { data.push(row.getData()); }); this.visible = this.visible(this.key, this.getRowCount(), data, this.getRowCount()); } }; Group.prototype.getRowGroup = function (row) { var match = false; if (this.groupList.length) { this.groupList.forEach(function (group) { var result = group.getRowGroup(row); if (result) { match = result; } }); } else { if (this.rows.find(function (item) { return item === row; })) { match = this; } } return match; }; Group.prototype.generateGroupHeaderContents = function () { var data = []; this.rows.forEach(function (row) { data.push(row.getData()); }); this.elementContents = this.generator(this.key, this.getRowCount(), data, this.getComponent()); this.element.empty().append(this.elementContents).prepend(this.arrowElement); }; ////////////// Standard Row Functions ////////////// Group.prototype.getElement = function () { this.addBindingsd = false; this._visSet(); if (this.visible) { this.element.addClass("tabulator-group-visible"); } else { this.element.removeClass("tabulator-group-visible"); } this.element.children().detach(); this.generateGroupHeaderContents(); // this.addBindings(); return this.element; }; //normalize the height of elements in the row Group.prototype.normalizeHeight = function () { this.setHeight(this.element.innerHeight()); }; Group.prototype.initialize = function (force) { if (!this.initialized || force) { this.normalizeHeight(); this.initialized = true; } }; Group.prototype.reinitialize = function () { this.initialized = false; this.height = 0; if (this.element.is(":visible")) { this.initialize(true); } }; Group.prototype.setHeight = function (height) { if (this.height != height) { this.height = height; this.outerHeight = this.element.outerHeight(); } }; //return rows outer height Group.prototype.getHeight = function () { return this.outerHeight; }; Group.prototype.getGroup = function () { return this; }; Group.prototype.reinitializeHeight = function () {}; Group.prototype.calcHeight = function () {}; Group.prototype.setCellHeight = function () {}; Group.prototype.clearCellHeight = function () {}; //////////////// Object Generation ///////////////// Group.prototype.getComponent = function () { return new GroupComponent(this); }; ////////////////////////////////////////////////// ////////////// Group Row Extension /////////////// ////////////////////////////////////////////////// var GroupRows = function GroupRows(table) { this.table = table; //hold Tabulator object this.groupIDLookups = false; //enable table grouping and set field to group by this.startOpen = [function () { return false; }]; //starting state of group this.headerGenerator = [function () { return ""; }]; this.groupList = []; //ordered list of groups this.groups = {}; //hold row groups this.displayIndex = 0; //index in display pipeline }; //initialize group configuration GroupRows.prototype.initialize = function () { var self = this, groupBy = self.table.options.groupBy, startOpen = self.table.options.groupStartOpen, groupHeader = self.table.options.groupHeader; self.headerGenerator = [function () { return ""; }]; this.startOpen = [function () { return false; }]; //starting state of group self.table.extensions.localize.bind("groups|item", function (langValue, lang) { self.headerGenerator[0] = function (value, count, data) { //header layout function return (typeof value === "undefined" ? "" : value) + "(" + count + " " + (count === 1 ? langValue : lang.groups.items) + ")"; }; }); this.groupIDLookups = []; if (Array.isArray(groupBy) || groupBy) { if (this.table.extExists("columnCalcs") && this.table.options.columnCalcs != "table" && this.table.options.columnCalcs != "both") { this.table.extensions.columnCalcs.removeCalcs(); } } else { if (this.table.extExists("columnCalcs") && this.table.options.columnCalcs != "group") { var cols = this.table.columnManager.getRealColumns(); cols.forEach(function (col) { if (col.definition.topCalc) { self.table.extensions.columnCalcs.initializeTopRow(); } if (col.definition.bottomCalc) { self.table.extensions.columnCalcs.initializeBottomRow(); } }); } } if (!Array.isArray(groupBy)) { groupBy = [groupBy]; } groupBy.forEach(function (group) { var lookupFunc, column; if (typeof group == "function") { lookupFunc = group; } else { column = self.table.columnManager.getColumnByField(group); if (column) { lookupFunc = function lookupFunc(data) { return column.getFieldValue(data); }; } else { lookupFunc = function lookupFunc(data) { return data[group]; }; } } self.groupIDLookups.push({ field: typeof group === "function" ? false : group, func: lookupFunc }); }); if (startOpen) { if (!Array.isArray(startOpen)) { startOpen = [startOpen]; } startOpen.forEach(function (level) { level = typeof level == "function" ? level : function () { return true; }; }); self.startOpen = startOpen; } if (groupHeader) { self.headerGenerator = Array.isArray(groupHeader) ? groupHeader : [groupHeader]; } this.initialized = true; }; GroupRows.prototype.setDisplayIndex = function (index) { this.displayIndex = index; }; GroupRows.prototype.getDisplayIndex = function () { return this.displayIndex; }; //return appropriate rows with group headers GroupRows.prototype.getRows = function (rows) { if (this.groupIDLookups.length) { this.table.options.dataGrouping(); this.generateGroups(rows); if (this.table.options.dataGrouped) { this.table.options.dataGrouped(this.getGroups()); }; return this.updateGroupRows(); } else { return rows.slice(0); } }; GroupRows.prototype.getGroups = function () { var groupComponents = []; this.groupList.forEach(function (group) { groupComponents.push(group.getComponent()); }); return groupComponents; }; GroupRows.prototype.getRowGroup = function (row) { var match = false; this.groupList.forEach(function (group) { var result = group.getRowGroup(row); if (result) { match = result; } }); return match; }; GroupRows.prototype.countGroups = function () { return this.groupList.length; }; GroupRows.prototype.generateGroups = function (rows) { var self = this, oldGroups = self.groups; self.groups = {}; self.groupList = []; rows.forEach(function (row) { self.assignRowToGroup(row, oldGroups); }); }; GroupRows.prototype.assignRowToGroup = function (row, oldGroups) { var groupID = this.groupIDLookups[0].func(row.getData()), oldGroups = oldGroups || [], newGroupNeeded = !this.groups[groupID]; if (newGroupNeeded) { var group = new Group(this, false, 0, groupID, this.groupIDLookups[0].field, this.headerGenerator[0], oldGroups[groupID]); this.groups[groupID] = group; this.groupList.push(group); } this.groups[groupID].addRow(row); return !newGroupNeeded; }; GroupRows.prototype.updateGroupRows = function (force) { var self = this, output = [], oldRowCount; self.groupList.forEach(function (group) { output = output.concat(group.getHeadersAndRows()); }); //force update of table display if (force) { var displayIndex = self.table.rowManager.setDisplayRows(output, this.getDisplayIndex()); if (displayIndex !== true) { this.setDisplayIndex(displayIndex); } self.table.rowManager.refreshActiveData("group", true, true); } return output; }; GroupRows.prototype.scrollHeaders = function (left) { this.groupList.forEach(function (group) { group.arrowElement.css("margin-left", left); }); }; GroupRows.prototype.removeGroup = function (group) { var index; if (this.groups[group.key]) { delete this.groups[group.key]; index = this.groupList.indexOf(group); if (index > -1) { this.groupList.splice(index, 1); } } }; Tabulator.registerExtension("groupRows", GroupRows); var History = function History(table) { this.table = table; //hold Tabulator object this.history = []; this.index = -1; }; History.prototype.clear = function () { this.history = []; this.index = -1; }; History.prototype.action = function (type, component, data) { this.history = this.history.slice(0, this.index + 1); this.history.push({ type: type, component: component, data: data }); this.index++; }; History.prototype.undo = function () { if (this.index > -1) { var action = this.history[this.index]; this.undoers[action.type].call(this, action); this.index--; this.table.options.historyUndo(action.type, action.component.getComponent(), action.data); return true; } else { console.warn("History Undo Error - No more history to undo"); return false; } }; History.prototype.redo = function () { if (this.history.length - 1 > this.index) { this.index++; var action = this.history[this.index]; this.redoers[action.type].call(this, action); this.table.options.historyRedo(action.type, action.component.getComponent(), action.data); return true; } else { console.warn("History Redo Error - No more history to redo"); return false; } }; History.prototype.undoers = { cellEdit: function cellEdit(action) { action.component.setValueProcessData(action.data.oldValue); }, rowAdd: function rowAdd(action) { action.component.deleteActual(); }, rowDelete: function rowDelete(action) { var newRow = this.table.rowManager.addRowActual(action.data.data, action.data.pos, action.data.index); this._rebindRow(action.component, newRow); }, rowMove: function rowMove(action) { this.table.rowManager.moveRowActual(action.component, this.table.rowManager.rows[action.data.pos], false); this.table.rowManager.redraw(); } }; History.prototype.redoers = { cellEdit: function cellEdit(action) { action.component.setValueProcessData(action.data.newValue); }, rowAdd: function rowAdd(action) { var newRow = this.table.rowManager.addRowActual(action.data.data, action.data.pos, action.data.index); this._rebindRow(action.component, newRow); }, rowDelete: function rowDelete(action) { action.component.deleteActual(); }, rowMove: function rowMove(action) { this.table.rowManager.moveRowActual(action.component, this.table.rowManager.rows[action.data.pos], false); this.table.rowManager.redraw(); } }; //rebind rows to new element after deletion History.prototype._rebindRow = function (oldRow, newRow) { this.history.forEach(function (action) { if (action.component instanceof Row) { if (action.component === oldRow) { action.component = newRow; } } else if (action.component instanceof Cell) { if (action.component.row === oldRow) { var field = action.component.column.getField(); if (field) { action.component = newRow.getCell(field); } } } }); }; Tabulator.registerExtension("history", History); var HtmlTableImport = function HtmlTableImport(table) { this.table = table; //hold Tabulator object this.hasIndex = false; }; HtmlTableImport.prototype.parseTable = function () { var self = this, element = self.table.element, options = self.table.options, columns = options.columns, headers = $("th", element), rows = $("tbody tr", element), data = []; self.hasIndex = false; self.table.options.htmlImporting(); //check for tablator inline options self._extractOptions(element, options); if (headers.length) { self._extractHeaders(element); } else { self._generateBlankHeaders(element); } //iterate through table rows and build data set rows.each(function (rowIndex) { var item = {}; //create index if the dont exist in table if (!self.hasIndex) { item[options.index] = rowIndex; } //add row data to item $("td", $(this)).each(function (colIndex) { item[$(this).data("field")] = $(this).html(); }); data.push(item); }); //create new element var newElement = $("
"); //transfer attributes to new element var attributes = element.prop("attributes"); // loop through attributes and apply them on div $.each(attributes, function () { newElement.attr(this.name, this.value); }); // replace table with div element element.replaceWith(newElement); options.data = data; self.table.options.htmlImported(); newElement.tabulator(options); }; //extract tabluator attribute options HtmlTableImport.prototype._extractOptions = function (element, options) { var self = this, attributes = element[0].attributes; for (var index in attributes) { var attrib = attributes[index]; var name; if (attrib && attrib.name && attrib.name.indexOf("tabulator-") === 0) { name = attrib.name.replace("tabulator-", ""); for (var key in options) { if (key.toLowerCase() == name) { options[key] = self._attribValue(attrib.value); } } } } }; //get value of attribute HtmlTableImport.prototype._attribValue = function (value) { if (value === "true") { return true; } if (value === "false") { return false; } return value; }; //find column if it has already been defined HtmlTableImport.prototype._findCol = function (title) { var self = this; var match = self.table.options.columns.find(function (column) { return column.title === title; }); return match || false; }; //extract column from headers HtmlTableImport.prototype._extractHeaders = function (element) { var self = this, headers = $("th", element), rows = $("tbody tr", element); headers.each(function (index) { var header = $(this), exists = false, col = self._findCol(header.text()), width, attributes; if (col) { exists = true; } else { col = { title: header.text().trim() }; } if (!col.field) { col.field = header.text().trim().toLowerCase().replace(" ", "_"); } width = header.attr("width"); if (width && !col.width) { col.width = width; } //check for tablator inline options attributes = header[0].attributes; // //check for tablator inline options self._extractOptions(header, col); for (var i in attributes) { var attrib = attributes[i], name; if (attrib && attrib.name && attrib.name.indexOf("tabulator-") === 0) { name = attrib.name.replace("tabulator-", ""); col[name] = self._attribValue(attrib.value); } } $("td:eq(" + index + ")", rows).data("field", col.field); if (col.field == self.table.options.index) { self.hasIndex = true; } if (!exists) { self.table.options.columns.push(col); } }); }; //generate blank headers HtmlTableImport.prototype._generateBlankHeaders = function (element) { var self = this, headers = $("tr:first td", element), rows = $("tbody tr", element); headers.each(function (index) { var col = { title: "", field: "col" + index }; $("td:eq(" + index + ")", rows).data("field", col.field); var width = $(this).attr("width"); if (width) { col.width = width; } self.table.options.columns.push(col); }); }; Tabulator.registerExtension("htmlTableImport", HtmlTableImport); var Keybindings = function Keybindings(table) { this.table = table; //hold Tabulator object this.watchKeys = null; this.pressedKeys = null; this.keyupBinding = false; this.keydownBinding = false; }; Keybindings.prototype.initialize = function () { var bindings = this.table.options.keybindings, mergedBindings = {}; this.watchKeys = {}; this.pressedKeys = []; if (bindings !== false) { for (var key in this.bindings) { mergedBindings[key] = this.bindings[key]; } if (Object.keys(bindings).length) { for (var _key in bindings) { mergedBindings[_key] = bindings[_key]; } } this.mapBindings(mergedBindings); this.bindEvents(); } }; Keybindings.prototype.mapBindings = function (bindings) { var _this = this; var self = this; var _loop2 = function _loop2(key) { if (_this.actions[key]) { if (bindings[key]) { if (_typeof(bindings[key]) !== "object") { bindings[key] = [bindings[key]]; } bindings[key].forEach(function (binding) { self.mapBinding(key, binding); }); } } else { console.warn("Key Binding Error - no such action:", key); } }; for (var key in bindings) { _loop2(key); } }; Keybindings.prototype.mapBinding = function (action, symbolsList) { var self = this; var binding = { action: this.actions[action], keys: [], ctrl: false, shift: false }; var symbols = symbolsList.toString().toLowerCase().split(" ").join("").split("+"); symbols.forEach(function (symbol) { switch (symbol) { case "ctrl": binding.ctrl = true; break; case "shift": binding.shift = true; break; default: symbol = parseInt(symbol); binding.keys.push(symbol); if (!self.watchKeys[symbol]) { self.watchKeys[symbol] = []; } self.watchKeys[symbol].push(binding); } }); }; Keybindings.prototype.bindEvents = function () { var self = this; this.keyupBinding = function (e) { var code = e.keyCode; var bindings = self.watchKeys[code]; if (bindings) { self.pressedKeys.push(code); bindings.forEach(function (binding) { self.checkBinding(e, binding); }); } }; this.keydownBinding = function (e) { var code = e.keyCode; var bindings = self.watchKeys[code]; if (bindings) { var index = self.pressedKeys.indexOf(code); if (index > -1) { self.pressedKeys.splice(index, 1); } } }; this.table.element.on("keydown", this.keyupBinding); this.table.element.on("keyup", this.keydownBinding); }; Keybindings.prototype.clearBindings = function () { if (this.keyupBinding) { this.table.element.off("keydown", this.keyupBinding); } if (this.keydownBinding) { this.table.element.off("keyup", this.keydownBinding); } }; Keybindings.prototype.checkBinding = function (e, binding) { var self = this, match = true; if (e.ctrlKey == binding.ctrl && e.shiftKey == binding.shift) { binding.keys.forEach(function (key) { var index = self.pressedKeys.indexOf(key); if (index == -1) { match = false; } }); if (match) { binding.action.call(self, e); } return true; } return false; }; //default bindings Keybindings.prototype.bindings = { navPrev: "shift + 9", navNext: 9, navUp: 38, navDown: 40, scrollPageUp: 33, scrollPageDown: 34, scrollToStart: 36, scrollToEnd: 35, undo: "ctrl + 90", redo: "ctrl + 89", copyToClipboard: "ctrl + 67" }; //default actions Keybindings.prototype.actions = { keyBlock: function keyBlock(e) { e.stopPropagation(); e.preventDefault(); }, scrollPageUp: function scrollPageUp(e) { var rowManager = this.table.rowManager, newPos = rowManager.scrollTop - rowManager.height, scrollMax = rowManager.element[0].scrollHeight; e.preventDefault(); if (rowManager.displayRowsCount) { if (newPos >= 0) { rowManager.element.scrollTop(newPos); } else { rowManager.scrollToRow(rowManager.getDisplayRows()[0]); } } this.table.element.focus(); }, scrollPageDown: function scrollPageDown(e) { var rowManager = this.table.rowManager, newPos = rowManager.scrollTop + rowManager.height, scrollMax = rowManager.element[0].scrollHeight; e.preventDefault(); if (rowManager.displayRowsCount) { if (newPos <= scrollMax) { rowManager.element.scrollTop(newPos); } else { rowManager.scrollToRow(rowManager.getDisplayRows()[rowManager.displayRowsCount - 1]); } } this.table.element.focus(); }, scrollToStart: function scrollToStart(e) { var rowManager = this.table.rowManager; e.preventDefault(); if (rowManager.displayRowsCount) { rowManager.scrollToRow(rowManager.getDisplayRows()[0]); } this.table.element.focus(); }, scrollToEnd: function scrollToEnd(e) { var rowManager = this.table.rowManager; e.preventDefault(); if (rowManager.displayRowsCount) { rowManager.scrollToRow(rowManager.getDisplayRows()[rowManager.displayRowsCount - 1]); } this.table.element.focus(); }, navPrev: function navPrev(e) { var cell = false; if (this.table.extExists("edit")) { cell = this.table.extensions.edit.currentCell; if (cell) { e.preventDefault(); cell.nav().prev(); } } }, navNext: function navNext(e) { var cell = false; if (this.table.extExists("edit")) { cell = this.table.extensions.edit.currentCell; if (cell) { e.preventDefault(); cell.nav().next(); } } }, navLeft: function navLeft(e) { var cell = false; if (this.table.extExists("edit")) { cell = this.table.extensions.edit.currentCell; if (cell) { e.preventDefault(); cell.nav().left(); } } }, navRight: function navRight(e) { var cell = false; if (this.table.extExists("edit")) { cell = this.table.extensions.edit.currentCell; if (cell) { e.preventDefault(); cell.nav().right(); } } }, navUp: function navUp(e) { var cell = false; if (this.table.extExists("edit")) { cell = this.table.extensions.edit.currentCell; if (cell) { e.preventDefault(); cell.nav().up(); } } }, navDown: function navDown(e) { var cell = false; if (this.table.extExists("edit")) { cell = this.table.extensions.edit.currentCell; if (cell) { e.preventDefault(); cell.nav().down(); } } }, undo: function undo(e) { var cell = false; if (this.table.options.history && this.table.extExists("history") && this.table.extExists("edit")) { cell = this.table.extensions.edit.currentCell; if (!cell) { e.preventDefault(); this.table.extensions.history.undo(); } } }, redo: function redo(e) { var cell = false; if (this.table.options.history && this.table.extExists("history") && this.table.extExists("edit")) { cell = this.table.extensions.edit.currentCell; if (!cell) { e.preventDefault(); this.table.extensions.history.redo(); } } }, copyToClipboard: function copyToClipboard(e) { if (!this.table.extensions.edit.currentCell) { if (this.table.extExists("clipboard", true)) { this.table.extensions.clipboard.copy(!this.table.options.selectable || this.table.options.selectable == "highlight" ? "active" : "selected", null, null, null, true); } } } }; Tabulator.registerExtension("keybindings", Keybindings); var MoveColumns = function MoveColumns(table) { this.table = table; //hold Tabulator object this.placeholderElement = $("
"); this.hoverElement = $(); //floating column header element this.checkTimeout = false; //click check timeout holder this.checkPeriod = 250; //period to wait on mousedown to consider this a move and not a click this.moving = false; //currently moving column this.toCol = false; //destination column this.toColAfter = false; //position of moving column relative to the desitnation column this.startX = 0; //starting position within header element this.autoScrollMargin = 40; //auto scroll on edge when within margin this.autoScrollStep = 5; //auto scroll distance in pixels this.autoScrollTimeout = false; //auto scroll timeout this.moveHover = this.moveHover.bind(this); this.endMove = this.endMove.bind(this); }; MoveColumns.prototype.initializeColumn = function (column) { var self = this, config = {}; if (!column.extensions.frozen) { config.mousemove = function (e) { if (column.parent === self.moving.parent) { if (e.pageX - column.element.offset().left + self.table.columnManager.element.scrollLeft() > column.getWidth() / 2) { if (self.toCol !== column || !self.toColAfter) { column.element.after(self.placeholderElement); self.moveColumn(column, true); } } else { if (self.toCol !== column || self.toColAfter) { column.element.before(self.placeholderElement); self.moveColumn(column, false); } } } }.bind(self); column.getElement().on("mousedown", function (e) { self.checkTimeout = setTimeout(function () { self.startMove(e, column); }, self.checkPeriod); }); column.getElement().on("mouseup", function (e) { if (self.checkTimeout) { clearTimeout(self.checkTimeout); } }); } column.extensions.moveColumn = config; }; MoveColumns.prototype.startMove = function (e, column) { var self = this, element = column.getElement(); self.moving = column; self.startX = e.pageX - element.offset().left; self.table.element.addClass("tabulator-block-select"); //create placeholder self.placeholderElement.css({ width: column.getWidth(), height: column.getHeight() }); element.before(self.placeholderElement); element.detach(); //create hover element self.hoverElement = element.clone(); self.hoverElement.addClass("tabulator-moving"); self.table.columnManager.getElement().append(self.hoverElement); self.hoverElement.css({ "left": 0, "bottom": 0 }); self._bindMouseMove(); $("body").on("mousemove", self.moveHover); $("body").on("mouseup", self.endMove); self.moveHover(e); }; MoveColumns.prototype._bindMouseMove = function () { var self = this; self.table.columnManager.columnsByIndex.forEach(function (column) { if (column.extensions.moveColumn.mousemove) { column.element.on("mousemove", column.extensions.moveColumn.mousemove); } }); }; MoveColumns.prototype._unbindMouseMove = function () { var self = this; self.table.columnManager.columnsByIndex.forEach(function (column) { if (column.extensions.moveColumn.mousemove) { column.element.off("mousemove", column.extensions.moveColumn.mousemove); } }); }; MoveColumns.prototype.moveColumn = function (column, after) { var self = this, movingCells = this.moving.getCells(); self.toCol = column; self.toColAfter = after; if (after) { column.getCells().forEach(function (cell, i) { cell.getElement().after(movingCells[i].getElement()); }); } else { column.getCells().forEach(function (cell, i) { cell.getElement().before(movingCells[i].getElement()); }); } }; MoveColumns.prototype.endMove = function (column) { var self = this; self._unbindMouseMove(); self.placeholderElement.after(self.moving.getElement()); self.placeholderElement.detach(); self.hoverElement.detach(); self.table.element.removeClass("tabulator-block-select"); if (self.toCol) { self.table.columnManager.moveColumn(self.moving, self.toCol, self.toColAfter); } self.moving = false; self.toCol = false; self.toColAfter = false; $("body").off("mousemove", self.moveHover); $("body").off("mouseup", self.endMove); }; MoveColumns.prototype.moveHover = function (e) { var self = this, columnHolder = self.table.columnManager.getElement(), scrollLeft = columnHolder.scrollLeft(), xPos = e.pageX - columnHolder.offset().left + scrollLeft, scrollPos; self.hoverElement.css({ "left": xPos - self.startX }); if (xPos - scrollLeft < self.autoScrollMargin) { if (!self.autoScrollTimeout) { self.autoScrollTimeout = setTimeout(function () { scrollPos = Math.max(0, scrollLeft - 5); self.table.rowManager.getElement().scrollLeft(scrollPos); self.autoScrollTimeout = false; }, 1); } } if (scrollLeft + columnHolder.innerWidth() - xPos < self.autoScrollMargin) { if (!self.autoScrollTimeout) { self.autoScrollTimeout = setTimeout(function () { scrollPos = Math.min(columnHolder.innerWidth(), scrollLeft + 5); self.table.rowManager.getElement().scrollLeft(scrollPos); self.autoScrollTimeout = false; }, 1); } } }; Tabulator.registerExtension("moveColumn", MoveColumns); var MoveRows = function MoveRows(table) { this.table = table; //hold Tabulator object this.placeholderElement = $("
"); this.hoverElement = $(); //floating row header element this.checkTimeout = false; //click check timeout holder this.checkPeriod = 150; //period to wait on mousedown to consider this a move and not a click this.moving = false; //currently moving row this.toRow = false; //destination row this.toRowAfter = false; //position of moving row relative to the desitnation row this.hasHandle = false; //row has handle instead of fully movable row this.startY = 0; //starting Y position within header element this.startX = 0; //starting X position within header element this.moveHover = this.moveHover.bind(this); this.endMove = this.endMove.bind(this); this.tableRowDropEvent = false; this.connection = false; this.connections = []; this.connectedTable = false; this.connectedRow = false; }; MoveRows.prototype.initialize = function (handle) { this.connection = this.table.options.movableRowsConnectedTables; }; MoveRows.prototype.setHandle = function (handle) { this.hasHandle = handle; }; MoveRows.prototype.initializeRow = function (row) { var self = this, config = {}; //inter table drag drop config.mouseup = function (e) { self.tableRowDrop(e, row); }.bind(self); //same table drag drop config.mousemove = function (e) { if (e.pageY - row.element.offset().top + self.table.rowManager.element.scrollTop() > row.getHeight() / 2) { if (self.toRow !== row || !self.toRowAfter) { row.element.after(self.placeholderElement); self.moveRow(row, true); } } else { if (self.toRow !== row || self.toRowAfter) { row.element.before(self.placeholderElement); self.moveRow(row, false); } } }.bind(self); if (!this.hasHandle) { row.getElement().on("mousedown", function (e) { self.checkTimeout = setTimeout(function () { self.startMove(e, row); }, self.checkPeriod); }); row.getElement().on("mouseup", function (e) { if (self.checkTimeout) { clearTimeout(self.checkTimeout); } }); } row.extensions.moveRow = config; }; MoveRows.prototype.initializeCell = function (cell) { var self = this; cell.getElement().on("mousedown", function (e) { self.checkTimeout = setTimeout(function () { self.startMove(e, cell.row); }, self.checkPeriod); }); cell.getElement().on("mouseup", function (e) { if (self.checkTimeout) { clearTimeout(self.checkTimeout); } }); }; MoveRows.prototype._bindMouseMove = function () { var self = this; self.table.rowManager.getDisplayRows().forEach(function (row) { if (row.type === "row" && row.extensions.moveRow.mousemove) { row.element.on("mousemove", row.extensions.moveRow.mousemove); } }); }; MoveRows.prototype._unbindMouseMove = function () { var self = this; self.table.rowManager.getDisplayRows().forEach(function (row) { if (row.type === "row" && row.extensions.moveRow.mousemove) { row.element.off("mousemove", row.extensions.moveRow.mousemove); } }); }; MoveRows.prototype.startMove = function (e, row) { var element = row.getElement(); this.setStartPosition(e, row); this.moving = row; this.table.element.addClass("tabulator-block-select"); //create placeholder this.placeholderElement.css({ width: row.getWidth(), height: row.getHeight() }); if (!this.connection) { element.before(this.placeholderElement); element.detach(); } else { this.table.element.addClass("tabulator-movingrow-sending"); this.connectToTables(row); } //create hover element this.hoverElement = element.clone(); this.hoverElement.addClass("tabulator-moving"); if (this.connection) { $("body").append(this.hoverElement); this.hoverElement.css({ "left": 0, "top": 0, "width": this.table.element.innerWidth(), "white-space": "nowrap", "overflow": "hidden", "pointer-events": "none" }); } else { this.table.rowManager.getTableElement().append(this.hoverElement); this.hoverElement.css({ "left": 0, "top": 0 }); this._bindMouseMove(); } $("body").on("mousemove", this.moveHover); $("body").on("mouseup", this.endMove); this.moveHover(e); }; MoveRows.prototype.setStartPosition = function (e, row) { var element, position; element = row.getElement(); if (this.connection) { position = element[0].getBoundingClientRect(); this.startX = position.left - e.pageX + window.scrollX; this.startY = position.top - e.pageY + window.scrollY; } else { this.startY = e.pageY - element.offset().top; } }; MoveRows.prototype.endMove = function (column) { this._unbindMouseMove(); if (!this.connection) { this.placeholderElement.after(this.moving.getElement()); this.placeholderElement.detach(); } this.hoverElement.detach(); this.table.element.removeClass("tabulator-block-select"); if (this.toRow) { this.table.rowManager.moveRow(this.moving, this.toRow, this.toRowAfter); } this.moving = false; this.toRow = false; this.toRowAfter = false; $("body").off("mousemove", this.moveHover); $("body").off("mouseup", this.endMove); if (this.connection) { this.table.element.removeClass("tabulator-movingrow-sending"); this.disconnectFromTables(); } }; MoveRows.prototype.moveRow = function (row, after) { this.toRow = row; this.toRowAfter = after; }; MoveRows.prototype.moveHover = function (e) { if (this.connection) { this.moveHoverConnections.call(this, e); } else { this.moveHoverTable.call(this, e); } }; MoveRows.prototype.moveHoverTable = function (e) { var rowHolder = this.table.rowManager.getElement(), scrollTop = rowHolder.scrollTop(), yPos = e.pageY - rowHolder.offset().top + scrollTop, scrollPos; this.hoverElement.css({ "top": yPos - this.startY }); }; MoveRows.prototype.moveHoverConnections = function (e) { this.hoverElement.css({ "left": this.startX + e.pageX, "top": this.startY + e.pageY }); }; //establish connection with other tables MoveRows.prototype.connectToTables = function (row) { var self = this, connections = this.table.extensions.comms.getConnections(this.connection); this.table.options.movableRowsSendingStart(connections); this.table.extensions.comms.send(this.connection, "moveRow", "connect", { row: row }); }; //disconnect from other tables MoveRows.prototype.disconnectFromTables = function () { var self = this, connections = this.table.extensions.comms.getConnections(this.connection); this.table.options.movableRowsSendingStop(connections); this.table.extensions.comms.send(this.connection, "moveRow", "disconnect"); }; //accept incomming connection MoveRows.prototype.connect = function (table, row) { var self = this; if (!this.connectedTable) { this.connectedTable = table; this.connectedRow = row; this.table.element.addClass("tabulator-movingrow-receiving"); self.table.rowManager.getDisplayRows().forEach(function (row) { if (row.type === "row" && row.extensions.moveRow && row.extensions.moveRow.mouseup) { row.element.on("mouseup", row.extensions.moveRow.mouseup); } }); self.tableRowDropEvent = self.tableRowDrop.bind(self); self.table.element.on("mouseup", self.tableRowDropEvent); this.table.options.movableRowsReceivingStart(row, table); return true; } else { console.warn("Move Row Error - Table cannot accept connection, already connected to table:", this.connectedTable); return false; } }; //close incomming connection MoveRows.prototype.disconnect = function (table) { var self = this; if (table === this.connectedTable) { this.connectedTable = false; this.connectedRow = false; this.table.element.removeClass("tabulator-movingrow-receiving"); self.table.rowManager.getDisplayRows().forEach(function (row) { if (row.type === "row" && row.extensions.moveRow && row.extensions.moveRow.mouseup) { row.element.off("mouseup", row.extensions.moveRow.mouseup); } }); self.table.element.off("mouseup", self.tableRowDropEvent); this.table.options.movableRowsReceivingStop(table); } else { console.warn("Move Row Error - trying to disconnect from non connected table"); } }; MoveRows.prototype.dropComplete = function (table, row, success) { var sender = false; if (success) { switch (_typeof(this.table.options.movableRowsSender)) { case "string": sender = this.senders[this.table.options.movableRowsSender]; break; case "function": sender = this.table.options.movableRowsSender; break; } if (sender) { sender.call(this, this.moving.getComponent(), row ? row.getComponent() : undefined, table); } else { if (this.table.options.movableRowsSender) { console.warn("Mover Row Error - no matching sender found:", this.table.options.movableRowsSender); } } this.table.options.movableRowsSent(this.moving.getComponent(), row ? row.getComponent() : undefined, table); } else { this.table.options.movableRowsSentFailed(this.moving.getComponent(), row ? row.getComponent() : undefined, table); } this.endMove(); }; MoveRows.prototype.tableRowDrop = function (e, row) { var receiver = false, success = false; e.stopImmediatePropagation(); switch (_typeof(this.table.options.movableRowsReceiver)) { case "string": receiver = this.receivers[this.table.options.movableRowsReceiver]; break; case "function": receiver = this.table.options.movableRowsReceiver; break; } if (receiver) { success = receiver.call(this, this.connectedRow.getComponent(), row ? row.getComponent() : undefined, this.connectedTable); } else { console.warn("Mover Row Error - no matching receiver found:", this.table.options.movableRowsReceiver); } if (success) { this.table.options.movableRowsReceived(this.connectedRow.getComponent(), row ? row.getComponent() : undefined, this.connectedTable); } else { this.table.options.movableRowsReceivedFailed(this.connectedRow.getComponent(), row ? row.getComponent() : undefined, this.connectedTable); } this.table.extensions.comms.send(this.connectedTable, "moveRow", "dropcomplete", { row: row, success: success }); }; MoveRows.prototype.receivers = { insert: function insert(fromRow, toRow, fromTable) { this.table.addRow(fromRow.getData(), undefined, toRow); return true; }, add: function add(fromRow, toRow, fromTable) { this.table.addRow(fromRow.getData()); return true; }, update: function update(fromRow, toRow, fromTable) { if (toRow) { toRow.update(fromRow.getData()); return true; } return false; }, replace: function replace(fromRow, toRow, fromTable) { if (toRow) { this.table.addRow(fromRow.getData(), undefined, toRow); toRow.delete(); return true; } return false; } }; MoveRows.prototype.senders = { delete: function _delete(fromRow, toRow, toTable) { fromRow.delete(); } }; MoveRows.prototype.commsReceived = function (table, action, data) { switch (action) { case "connect": return this.connect(table, data.row); break; case "disconnect": return this.disconnect(table); break; case "dropcomplete": return this.dropComplete(table, data.row, data.success); break; } }; Tabulator.registerExtension("moveRow", MoveRows); var Mutator = function Mutator(table) { this.table = table; //hold Tabulator object this.allowedTypes = ["", "data", "edit", "clipboard"]; //list of muatation types }; //initialize column mutator Mutator.prototype.initializeColumn = function (column) { var self = this, match = false, config = {}; this.mapDepricatedFunctionality(column); this.allowedTypes.forEach(function (type) { var key = "mutator" + (type.charAt(0).toUpperCase() + type.slice(1)), mutator; if (column.definition[key]) { mutator = self.lookupMutator(column.definition[key]); if (mutator) { match = true; config[key] = { mutator: mutator, params: column.definition[key + "Params"] || {} }; } } }); if (match) { column.extensions.mutate = config; } }; Mutator.prototype.mapDepricatedFunctionality = function (column) { var key = ""; if (column.definition.mutateType) { if (column.definition.mutateType != "all") { key = "mutator" + (type.charAt(0).toUpperCase() + type.slice(1)); column.defintion[key] = column.definition.mutator; delete column.definition.mutator; console.warn("The %cmutateType='" + column.definition.mutateType + "'' %coption has been depricated and will be removed in version 4.0, use the %c " + key + "%c option instead", "font-weight:bold;", "font-weight:regular;", "font-weight:bold;", "font-weight:regular;"); } else { console.warn("The %cmutateType='all'' %coption has been depricated and will be removed in version 4.0, it is no longer needed", "font-weight:bold;", "font-weight:regular;"); } } }; Mutator.prototype.lookupMutator = function (value) { var mutator = false; //set column mutator switch (typeof value === 'undefined' ? 'undefined' : _typeof(value)) { case "string": if (this.mutators[value]) { mutator = this.mutators[value]; } else { console.warn("Mutator Error - No such mutator found, ignoring: ", value); } break; case "function": mutator = value; break; } return mutator; }; //apply mutator to row Mutator.prototype.transformRow = function (data, type) { var self = this, key = "mutator" + (type.charAt(0).toUpperCase() + type.slice(1)); self.table.columnManager.traverse(function (column) { var mutator; if (column.extensions.mutate) { mutator = column.extensions.mutate[key] || column.extensions.mutate.mutator || false; if (mutator) { column.setFieldValue(data, mutator.mutator(column.getFieldValue(data), data, type, mutator.params, column.getComponent())); } } }); return data; }; //apply mutator to new cell value Mutator.prototype.transformCell = function (cell, value) { var mutator = cell.column.extensions.mutate.mutatorEdit || cell.column.extensions.mutate.mutator || false; if (mutator) { return mutator.mutator(value, cell.row.getData(), "edit", mutator.params, cell.getComponent()); } else { return value; } }; //default mutators Mutator.prototype.mutators = {}; Tabulator.registerExtension("mutator", Mutator); var Page = function Page(table) { this.table = table; //hold Tabulator object this.element = $(""); this.pagesElement = $(""); /*-------START------------- //changes done by Soumya---------------*/ this.displayRecCount= $("
"); this.displayRecPerPageDropDown= $(""); this.displayRecPerPage= $("
Records Per Page
"); this.hideShowColumnsElement= $("Hide/show Columns"); /*--------END------------ //changes done by Soumya---------------*/ this.firstBut = $(""); this.prevBut = $(""); this.nextBut = $(""); this.lastBut = $(""); this.mode = "local"; this.progressiveLoad = false; this.size = 0; this.page = 1; this.count = 5; this.max = 1; this.paginator = false; this.displayIndex = 0; //index in display pipeline }; //setup pageination Page.prototype.initialize = function (hidden) { var self = this; //update param names for (var key in self.table.options.paginationDataSent) { self.paginationDataSentNames[key] = self.table.options.paginationDataSent[key]; } for (var _key2 in self.table.options.paginationDataReceived) { self.paginationDataReceivedNames[_key2] = self.table.options.paginationDataReceived[_key2]; } if (self.table.options.paginator) { self.paginator = self.table.options.paginator; } //build pagination element //bind localizations self.table.extensions.localize.bind("pagination|first", function (value) { self.firstBut.html(value); }); self.table.extensions.localize.bind("pagination|first_title", function (value) { self.firstBut.attr("aria-label", value).attr("title", value); }); self.table.extensions.localize.bind("pagination|prev", function (value) { self.prevBut.html(value); }); self.table.extensions.localize.bind("pagination|prev_title", function (value) { self.prevBut.attr("aria-label", value).attr("title", value); }); self.table.extensions.localize.bind("pagination|next", function (value) { self.nextBut.html(value); }); self.table.extensions.localize.bind("pagination|next_title", function (value) { self.nextBut.attr("aria-label", value).attr("title", value); }); self.table.extensions.localize.bind("pagination|last", function (value) { self.lastBut.html(value); }); self.table.extensions.localize.bind("pagination|last_title", function (value) { self.lastBut.attr("aria-label", value).attr("title", value); }); //click bindings self.firstBut.on("click", function () { self.setPage(1); }); self.prevBut.on("click", function () { self.previousPage(); }); self.nextBut.on("click", function () { self.nextPage(); }); self.lastBut.on("click", function () { self.setPage(self.max); }); /*-------START------------- //changes done by Soumya---------------*/ self.displayRecPerPageDropDown.on("change", function(){ self.setPageSize(self.displayRecPerPageDropDown.val()); self.setPage(1); // self.trigger(); }); /*--------END------------ //changes done by Soumya---------------*/ if (self.table.options.paginationElement) { self.element = self.table.options.paginationElement; } //append to DOM /*-------START------------- //changes done by Soumya---------------*/ self.element.append(self.displayRecCount); if(self.table.options.columnVisibility){ self.element.append(self.hideShowColumnsElement); } self.displayRecPerPage.append(self.displayRecPerPageDropDown); self.element.append(self.displayRecPerPage); /*--------END------------ //changes done by Soumya---------------*/ self.element.append(self.firstBut); self.element.append(self.prevBut); self.element.append(self.pagesElement); self.element.append(self.nextBut); self.element.append(self.lastBut); if (!self.table.options.paginationElement && !hidden) { self.table.footerManager.append(self.element, self); } //set default values self.mode = self.table.options.pagination; self.size = self.table.options.paginationSize || Math.floor(self.table.rowManager.getElement().innerHeight() / 24); self.count = self.table.options.paginationButtonCount; }; 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 = 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) { if (this.mode == "local" || force) { this.page = 1; } return true; }; //set the maxmum page Page.prototype.setMaxPage = function (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) { if (page > 0 && page <= this.max) { this.page = page; this.trigger(); return true; } else { console.warn("Pagination Error - Requested page is out of range of 1 - " + this.max + ":", page); return false; } }; Page.prototype.setPageSize = function (size) { if (size > 0) { this.size = size; } }; //setup the pagination buttons Page.prototype._setPageButtons = function () { var recordsRange='No records to view'; //changes done by Soumya 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); self.pagesElement.empty(); self.displayRecCount.empty(); //changes done by Soumya if (self.page == 1) { self.firstBut.prop("disabled", true); self.prevBut.prop("disabled", true); } else { self.firstBut.prop("disabled", false); self.prevBut.prop("disabled", false); } if (self.page == self.max) { self.lastBut.prop("disabled", true); self.nextBut.prop("disabled", true); } else { self.lastBut.prop("disabled", false); self.nextBut.prop("disabled", false); } for (var i = min; i <= max; i++) { if (i > 0 && i <= self.max) { self.pagesElement.append(self._generatePageButton(i)); } } /*-------START------------- //changes done by Soumya---------------*/ // console.log(self); // console.log(self.size); // console.log(self.page); // console.log(self.total_records); // console.log(self.table.rowManager.rows.length); var currentDisplayedRec=self.table.rowManager.rows.length; var recMinCount=1; var recMaxCount=10; var type_ajaxFiltering=self.table.options.ajaxFiltering; var type_ajaxSorting=self.table.options.ajaxSorting; var type_pagination=self.table.options.pagination; // console.log(self.table.options); // console.log('ajaxFiltering--'+self.table.options.ajaxFiltering); // console.log('ajaxSorting--'+self.table.options.ajaxSorting); // console.log('pagination--'+self.table.options.pagination); // if( !(type_ajaxFiltering) || !(type_ajaxSorting) || type_pagination=='local'){ var recTotalCount=currentDisplayedRec; //console.log(self.rows.length+'=='+ self.activeRows.length); //console.log(this.rowManager.getDataCount(true)); // console.log($('#PlantResultSet').tabulator("getDataCount")); // console.log($(self.table.bindings[0]).tabulator("getDataCount")); var recTotalCount=$(self.table.bindings[0]).tabulator("getDataCount"); }else{ var recTotalCount=self.total_records; //console.log(self.total_records); } //calculate rec range (start) if(self.page<=0){ recMinCount = 1; }else{ recMinCount = parseInt(((self.page - 1) * self.size) + 1); } recMaxCount = (parseInt(recMinCount) + parseInt(self.size))-1; if(recTotalCount0){ recordsRange="View "+recMinCount+"-"+recMaxCount+" of "+recTotalCount; } self.displayRecCount.append(recordsRange); $("select#tabulator_rec_per_page").val(self.size); /*--------END------------ //changes done by Soumya---------------*/ this.footerRedraw(); }; Page.prototype._generatePageButton = function (page) { var self = this; var button = $(""); button.on("click", function (e) { self.setPage(page); }); return button; }; //previous page Page.prototype.previousPage = function () { if (this.page > 1) { this.page--; this.trigger(); return true; } else { console.warn("Pagination Error - Previous page would be less than page 1:", 0); return false; } }; //next page Page.prototype.nextPage = function () { if (this.page < this.max) { this.page++; this.trigger(); return true; } else { if (!this.progressiveLoad) { console.warn("Pagination Error - Next page would be greater than maximum page of " + this.max + ":", this.max + 1); } return false; } }; //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 = []; 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 left; switch (this.mode) { case "local": left = this.table.rowManager.scrollLeft; this.table.rowManager.refreshActiveData("page"); this.table.rowManager.scrollHorizontal(left); this.table.options.pageLoaded(this.getPage()); break; case "remote": case "progressive_load": case "progressive_scroll": this.table.extensions.ajax.blockActiveRequest(); this._getRemotePage(); break; default: console.warn("Pagination Error - no such pagination mode:", this.mode); } }; Page.prototype._getRemotePage = function () { if (this.table.extExists("ajax", true)) { if (this.paginator) { this._getRemotePagePaginator(); } else { this._getRemotePageAuto(); } } }; Page.prototype._getRemotePagePaginator = function () { var self = this, ajax = self.table.extensions.ajax, oldUrl = ajax.getUrl(); ajax.setUrl(self.paginator(ajax.getUrl(), self.page, self.size, ajax.getParams())); ajax.sendRequest(function (data) { self._parseRemoteData(data); }); ajax.setUrl(oldUrl); }; Page.prototype._getRemotePageAuto = function () { var self = this, oldParams, pageParams; //record old params and restore after request has been made oldParams = $.extend(true, {}, self.table.extensions.ajax.getParams()); pageParams = self.table.extensions.ajax.getParams(); //configure request params pageParams[this.paginationDataSentNames.page] = self.page; //set page size if defined if (this.size) { pageParams[this.paginationDataSentNames.size] = this.size; } //set sort data if defined if (this.table.extExists("sort")) { var sorters = self.table.extensions.sort.getSort(); sorters.forEach(function (item) { delete item.column; }); pageParams[this.paginationDataSentNames.sorters] = sorters; } //set filter data if defined if (this.table.extExists("filter")) { var filters = self.table.extensions.filter.getFilters(true, true); pageParams[this.paginationDataSentNames.filters] = filters; } self.table.extensions.ajax.setParams(pageParams); self.table.extensions.ajax.sendRequest(function (data) { self._parseRemoteData(data); }, this.progressiveLoad); self.table.extensions.ajax.setParams(oldParams); }; Page.prototype._parseRemoteData = function (data) { var self = this, left, data, margin; if (data[this.paginationDataReceivedNames.last_page]) { if (data[this.paginationDataReceivedNames.data]) { this.max = parseInt(data[this.paginationDataReceivedNames.last_page]); /*-------START------------- //changes done by Soumya---------------*/ this.total_records = parseInt(data[this.paginationDataReceivedNames.total_records]); // total_recordss = this.total_records; // self.element.append("
"+total_recordss+"
"); // console.log(this.total_records); /*-------END------------- //changes done by Soumya---------------*/ if (this.progressiveLoad) { switch (this.mode) { case "progressive_load": this.table.rowManager.addRows(data[this.paginationDataReceivedNames.data]); if (this.page < this.max) { setTimeout(function () { self.nextPage(); }, self.table.options.ajaxProgressiveLoadDelay); } break; case "progressive_scroll": data = this.table.rowManager.getData().concat(data[this.paginationDataReceivedNames.data]); this.table.rowManager.setData(data, true); margin = this.table.options.ajaxProgressiveLoadScrollMargin || this.table.rowManager.element[0].clientHeight * 2; if (self.table.rowManager.element[0].scrollHeight <= self.table.rowManager.element[0].clientHeight + margin) { self.nextPage(); } break; } } else { left = this.table.rowManager.scrollLeft; this.table.rowManager.setData(data[this.paginationDataReceivedNames.data]); this.table.rowManager.scrollHorizontal(left); this.table.columnManager.scrollHorizontal(left); this.table.options.pageLoaded(this.getPage()); } } else { console.warn("Remote Pagination Error - Server response missing '" + this.paginationDataReceivedNames.data + "' property"); } } else { console.warn("Remote Pagination Error - Server response missing '" + this.paginationDataReceivedNames.last_page + "' property"); } }; //handle the footer element being redrawn Page.prototype.footerRedraw = function () { var footer = this.table.footerManager.element; if (Math.ceil(footer.innerWidth()) - footer[0].scrollWidth < 0) { this.pagesElement.hide(); } else { this.pagesElement.show(); if (Math.ceil(footer.innerWidth()) - footer[0].scrollWidth < 0) { this.pagesElement.hide(); } } }; //set the paramter names for pagination requests Page.prototype.paginationDataSentNames = { "page": "page", "size": "size", "sorters": "sorters", // "sort_dir":"sort_dir", "filters": "filters" }; //set the property names for pagination responses Page.prototype.paginationDataReceivedNames = { "current_page": "current_page", "last_page": "last_page", "data": "data", /*-------START------------- //changes done by Soumya---------------*/ "total_records":"total_records" /*-------end------------- //changes done by Soumya---------------*/ }; Tabulator.registerExtension("page", Page); var Persistence = function Persistence(table) { this.table = table; //hold Tabulator object this.mode = ""; this.id = ""; this.persistProps = ["field", "width", "visible"]; }; //setup parameters Persistence.prototype.initialize = function (mode, id) { //determine persistent layout storage type this.mode = mode !== true ? mode : typeof window.localStorage !== 'undefined' ? "local" : "cookie"; //set storage tag this.id = "tabulator-" + (id || this.table.element.attr("id") || ""); }; //load saved definitions Persistence.prototype.load = function (type, current) { var data = this.retreiveData(type); if (current) { data = data ? this.mergeDefinition(current, data) : current; } return data; }; //retreive data from memory Persistence.prototype.retreiveData = function (type) { var data = "", id = this.id + (type === "columns" ? "" : "-" + type); switch (this.mode) { case "local": data = localStorage.getItem(id); break; case "cookie": //find cookie var cookie = document.cookie, cookiePos = cookie.indexOf(id + "="), end = void 0; //if cookie exists, decode and load column data into tabulator if (cookiePos > -1) { cookie = cookie.substr(cookiePos); end = cookie.indexOf(";"); if (end > -1) { cookie = cookie.substr(0, end); } data = cookie.replace(id + "=", ""); } break; default: console.warn("Persistance Load Error - invalid mode selected", this.mode); } return data ? JSON.parse(data) : false; }; //merge old and new column defintions Persistence.prototype.mergeDefinition = function (oldCols, newCols) { var self = this, output = []; // oldCols = oldCols || []; newCols = newCols || []; newCols.forEach(function (column, to) { var from = self._findColumn(oldCols, column); if (from) { from.width = column.width; from.visible = column.visible; if (from.columns) { from.columns = self.mergeDefinition(from.columns, column.columns); } output.push(from); } }); oldCols.forEach(function (column, i) { var from = self._findColumn(newCols, column); if (!from) { if (output.length > i) { output.splice(i, 0, column); } else { output.push(column); } } }); return output; }; //find matching columns Persistence.prototype._findColumn = function (columns, subject) { var type = subject.columns ? "group" : subject.field ? "field" : "object"; return columns.find(function (col) { switch (type) { case "group": return col.title === subject.title && col.columns.length === subject.columns.length; break; case "field": return col.field === subject.field; break; case "object": return col === subject; break; } }); }; //save data Persistence.prototype.save = function (type) { var data = {}; switch (type) { case "columns": data = this.parseColumns(this.table.columnManager.getColumns()); break; case "filter": data = this.table.extensions.filter.getFilters(); break; case "sort": data = this.validateSorters(this.table.extensions.sort.getSort()); break; } var id = this.id + (type === "columns" ? "" : "-" + type); this.saveData(id, data); }; //ensure sorters contain no function data Persistence.prototype.validateSorters = function (data) { data.forEach(function (item) { item.column = item.field; delete item.field; }); return data; }; //save data to chosed medium Persistence.prototype.saveData = function (id, data) { data = JSON.stringify(data); switch (this.mode) { case "local": localStorage.setItem(id, data); break; case "cookie": var expireDate = new Date(); expireDate.setDate(expireDate.getDate() + 10000); //save cookie document.cookie = id + "=" + data + "; expires=" + expireDate.toUTCString(); break; default: console.warn("Persistance Save Error - invalid mode selected", this.mode); } }; //build premission list Persistence.prototype.parseColumns = function (columns) { var self = this, definitions = []; columns.forEach(function (column) { var def = {}; if (column.isGroup) { def.title = column.getDefinition().title; def.columns = self.parseColumns(column.getColumns()); } else { def.title = column.getDefinition().title; def.field = column.getField(); def.width = column.getWidth(); def.visible = column.visible; } definitions.push(def); }); return definitions; }; Tabulator.registerExtension("persistence", Persistence); var ResizeColumns = function ResizeColumns(table) { this.table = table; //hold Tabulator object this.startColumn = false; this.startX = false; this.startWidth = false; this.handle = null; this.prevHandle = null; }; ResizeColumns.prototype.initializeColumn = function (type, column, element) { var self = this, variableHeight = false, mode = this.table.options.resizableColumns; //set column resize mode if (type === "header") { variableHeight = column.definition.formatter == "textarea" || column.definition.variableHeight; column.extensions.resize = { variableHeight: variableHeight }; } if (mode === true || mode == type) { var handle = document.createElement('div'); handle.className = "tabulator-col-resize-handle"; var prevHandle = document.createElement('div'); prevHandle.className = "tabulator-col-resize-handle prev"; handle.addEventListener("click", function (e) { e.stopPropagation(); }); handle.addEventListener("mousedown", function (e) { var nearestColumn = column.getLastColumn(); if (nearestColumn && self._checkResizability(nearestColumn)) { self.startColumn = column; self._mouseDown(e, nearestColumn); } }); //reszie column on double click handle.addEventListener("dblclick", function (e) { if (self._checkResizability(column)) { column.reinitializeWidth(true); } }); prevHandle.addEventListener("click", function (e) { e.stopPropagation(); }); prevHandle.addEventListener("mousedown", function (e) { var nearestColumn, colIndex, prevColumn; nearestColumn = column.getFirstColumn(); if (nearestColumn) { colIndex = self.table.columnManager.findColumnIndex(nearestColumn); prevColumn = colIndex > 0 ? self.table.columnManager.getColumnByIndex(colIndex - 1) : false; if (prevColumn && self._checkResizability(prevColumn)) { self.startColumn = column; self._mouseDown(e, prevColumn); } } }); //resize column on double click prevHandle.addEventListener("dblclick", function (e) { var nearestColumn, colIndex, prevColumn; nearestColumn = column.getFirstColumn(); if (nearestColumn) { colIndex = self.table.columnManager.findColumnIndex(nearestColumn); prevColumn = colIndex > 0 ? self.table.columnManager.getColumnByIndex(colIndex - 1) : false; if (prevColumn && self._checkResizability(prevColumn)) { prevColumn.reinitializeWidth(true); } } }); element.append(handle).append(prevHandle); } }; ResizeColumns.prototype._checkResizability = function (column) { return typeof column.definition.resizable != "undefined" ? column.definition.resizable : this.table.options.resizableColumns; }; ResizeColumns.prototype._mouseDown = function (e, column) { var self = this; self.table.element.addClass("tabulator-block-select"); function mouseMove(e) { column.setWidth(self.startWidth + (e.screenX - self.startX)); if (!self.table.browserSlow && column.extensions.resize && column.extensions.resize.variableHeight) { column.checkCellHeights(); } } function mouseUp(e) { //block editor from taking action while resizing is taking place if (self.startColumn.extensions.edit) { self.startColumn.extensions.edit.blocked = false; } if (self.table.browserSlow && column.extensions.resize && column.extensions.resize.variableHeight) { column.checkCellHeights(); } $("body").off("mouseup", mouseMove); $("body").off("mousemove", mouseMove); self.table.element.removeClass("tabulator-block-select"); if (self.table.options.persistentLayout && self.table.extExists("persistence", true)) { self.table.extensions.persistence.save("columns"); } self.table.options.columnResized(self.startColumn.getComponent()); } e.stopPropagation(); //prevent resize from interfereing with movable columns //block editor from taking action while resizing is taking place if (self.startColumn.extensions.edit) { self.startColumn.extensions.edit.blocked = true; } self.startX = e.screenX; self.startWidth = column.getWidth(); $("body").on("mousemove", mouseMove); $("body").on("mouseup", mouseUp); }; Tabulator.registerExtension("resizeColumns", ResizeColumns); var ResizeRows = function ResizeRows(table) { this.table = table; //hold Tabulator object this.startColumn = false; this.startY = false; this.startHeight = false; this.handle = null; this.prevHandle = null; }; ResizeRows.prototype.initializeRow = function (row) { var self = this; var handle = document.createElement('div'); handle.className = "tabulator-row-resize-handle"; var prevHandle = document.createElement('div'); prevHandle.className = "tabulator-row-resize-handle prev"; handle.addEventListener("click", function (e) { e.stopPropagation(); }); handle.addEventListener("mousedown", function (e) { self.startRow = row; self._mouseDown(e, row); }); prevHandle.addEventListener("click", function (e) { e.stopPropagation(); }); prevHandle.addEventListener("mousedown", function (e) { var prevRow = self.table.rowManager.prevDisplayRow(row); if (prevRow) { self.startRow = prevRow; self._mouseDown(e, prevRow); } }); row.getElement().append(handle).append(prevHandle); }; ResizeRows.prototype._mouseDown = function (e, row) { var self = this; self.table.element.addClass("tabulator-block-select"); function mouseMove(e) { row.setHeight(self.startHeight + (e.screenY - self.startY)); } function mouseUp(e) { // //block editor from taking action while resizing is taking place // if(self.startColumn.extensions.edit){ // self.startColumn.extensions.edit.blocked = false; // } $("body").off("mouseup", mouseMove); $("body").off("mousemove", mouseMove); self.table.element.removeClass("tabulator-block-select"); self.table.options.rowResized(row.getComponent()); } e.stopPropagation(); //prevent resize from interfereing with movable columns //block editor from taking action while resizing is taking place // if(self.startColumn.extensions.edit){ // self.startColumn.extensions.edit.blocked = true; // } self.startY = e.screenY; self.startHeight = row.getHeight(); $("body").on("mousemove", mouseMove); $("body").on("mouseup", mouseUp); }; Tabulator.registerExtension("resizeRows", ResizeRows); var ResizeTable = function ResizeTable(table) { this.table = table; //hold Tabulator object this.binding = false; this.observer = false; }; ResizeTable.prototype.initialize = function (row) { var table = this.table, observer; if (typeof ResizeObserver !== "undefined" && table.rowManager.getRenderMode() === "virtual") { this.observer = new ResizeObserver(function (entry) { table.redraw(); }); this.observer.observe(table.element[0]); } else { this.binding = function () { table.element.tabulator("redraw"); }; $(window).resize(this.binding); } }; ResizeTable.prototype.clearBindings = function (row) { if (this.binding) { $(window).off("resize", this.binding); } if (this.observer) { this.observer.unobserve(this.table.element[0]); } }; Tabulator.registerExtension("resizeTable", ResizeTable); var ResponsiveLayout = function ResponsiveLayout(table) { this.table = table; //hold Tabulator object this.columns = []; this.hiddenColumns = []; this.mode = ""; this.index = 0; this.collapseFormatter = []; this.collapseStartOpen = true; }; //generate resposive columns list ResponsiveLayout.prototype.initialize = function () { var columns = []; this.mode = this.table.options.responsiveLayout; this.collapseFormatter = this.table.options.responsiveLayoutCollapseFormatter || this.formatCollapsedData; this.collapseStartOpen = this.table.options.responsiveLayoutCollapseStartOpen; this.hiddenColumns = []; //detemine level of responsivity for each column this.table.columnManager.columnsByIndex.forEach(function (column, i) { if (column.extensions.responsive) { if (column.extensions.responsive.order && column.extensions.responsive.visible) { column.extensions.responsive.index = i; columns.push(column); if (!column.visible && this.mode === "collapse") { this.hiddenColumns.push(column); } } } }); //sort list by responsivity columns = columns.reverse(); columns = columns.sort(function (a, b) { var diff = b.extensions.responsive.order - a.extensions.responsive.order; return diff || b.extensions.responsive.index - a.extensions.responsive.index; }); this.columns = columns; if (this.mode === "collapse") { this.generateCollapsedContent(); } }; //define layout information ResponsiveLayout.prototype.initializeColumn = function (column) { var def = column.getDefinition(); column.extensions.responsive = { order: typeof def.responsive === "undefined" ? 1 : def.responsive, visible: def.visible === false ? false : true }; }; ResponsiveLayout.prototype.layoutRow = function (row) { var rowEl = row.getElement(), el = $("
"); if (!rowEl.hasClass("tabulator-calcs")) { row.extensions.responsiveLayout = { element: el }; if (!this.collapseStartOpen) { el.hide(); } row.getElement().append(el); this.generateCollapsedRowContent(row); } }; //update column visibility ResponsiveLayout.prototype.updateColumnVisibility = function (column, visible) { var index; if (column.extensions.responsive) { column.extensions.responsive.visible = visible; this.initialize(); } }; ResponsiveLayout.prototype.hideColumn = function (column) { column.hide(false, true); if (this.mode === "collapse") { this.hiddenColumns.unshift(column); this.generateCollapsedContent(); } }; ResponsiveLayout.prototype.showColumn = function (column) { var index; column.show(false, true); //set column width to prevent calculation loops on uninitialized columns column.setWidth(column.getWidth()); if (this.mode === "collapse") { index = this.hiddenColumns.indexOf(column); if (index > -1) { this.hiddenColumns.splice(index, 1); } this.generateCollapsedContent(); } }; //redraw columns to fit space ResponsiveLayout.prototype.update = function () { var self = this, working = true; while (working) { var width = self.table.extensions.layout.getMode() == "fitColumns" ? self.table.columnManager.getFlexBaseWidth() : self.table.columnManager.getWidth(); var diff = self.table.columnManager.element.innerWidth() - width; if (diff < 0) { //table is too wide var column = self.columns[self.index]; if (column) { self.hideColumn(column); self.index++; } else { working = false; } } else { //table has spare space var _column = self.columns[self.index - 1]; if (_column) { if (diff > 0) { if (diff >= _column.getWidth()) { self.showColumn(_column); self.index--; } else { working = false; } } else { working = false; } } else { working = false; } } if (!self.table.rowManager.activeRowsCount) { self.table.rowManager.renderEmptyScroll(); } } }; ResponsiveLayout.prototype.generateCollapsedContent = function () { var self = this, rows = this.table.rowManager.getDisplayRows(); rows.forEach(function (row) { self.generateCollapsedRowContent(row); }); }; ResponsiveLayout.prototype.generateCollapsedRowContent = function (row) { var el; if (row.extensions.responsiveLayout) { el = row.extensions.responsiveLayout.element; el.empty(); el.append(this.collapseFormatter(this.generateCollapsedRowData(row))); } }; ResponsiveLayout.prototype.generateCollapsedRowData = function (row) { var self = this, data = row.getData(), output = {}, mockCellComponent; this.hiddenColumns.forEach(function (column) { var value = column.getFieldValue(data); if (column.definition.title && column.field) { if (column.extensions.format && self.table.options.responsiveLayoutCollapseUseFormatters) { mockCellComponent = { value: false, data: {}, getValue: function getValue() { return value; }, getData: function getData() { return data; }, getElement: function getElement() { return $(); }, getRow: function getRow() { return row.getComponent(); }, getColumn: function getColumn() { return column.getComponent(); } }; output[column.definition.title] = column.extensions.format.formatter.call(self.table.extensions.format, mockCellComponent, column.extensions.format.params); } else { output[column.definition.title] = value; } } }); return output; }; ResponsiveLayout.prototype.formatCollapsedData = function (data) { var list = $("
"); for (var key in data) { list.append("" + key + "" + data[key] + ""); } return Object.keys(data).length ? list : ""; }; Tabulator.registerExtension("responsiveLayout", ResponsiveLayout); var SelectRow = function SelectRow(table) { this.table = table; //hold Tabulator object this.selecting = false; //flag selecting in progress this.selectPrev = []; //hold previously selected element for drag drop selection this.selectedRows = []; //hold selected rows }; SelectRow.prototype.clearSelectionData = function (silent) { this.selecting = false; this.selectPrev = []; this.selectedRows = []; if (!silent) { this._rowSelectionChanged(); } }; SelectRow.prototype.initializeRow = function (row) { var self = this, element = row.getElement(); // trigger end of row selection var endSelect = function endSelect() { setTimeout(function () { self.selecting = false; }, 50); $("body").off("mouseup", endSelect); }; row.extensions.select = { selected: false }; //set row selection class if (self.table.options.selectableCheck(row.getComponent())) { element.addClass("tabulator-selectable").removeClass("tabulator-unselectable"); if (self.table.options.selectable && self.table.options.selectable != "highlight") { element.on("click", function (e) { if (!self.selecting) { self.toggleRow(row); } }); element.on("mousedown", function (e) { if (e.shiftKey) { self.selecting = true; self.selectPrev = []; $("body").on("mouseup", endSelect); $("body").on("keyup", endSelect); self.toggleRow(row); return false; } }); element.on("mouseenter", function (e) { if (self.selecting) { self.toggleRow(row); if (self.selectPrev[1] == row) { self.toggleRow(self.selectPrev[0]); } } }); element.on("mouseout", function (e) { if (self.selecting) { self.selectPrev.unshift(row); } }); } } else { row.getElement().addClass("tabulator-unselectable").removeClass("tabulator-selectable"); } }; //toggle row selection SelectRow.prototype.toggleRow = function (row) { if (this.table.options.selectableCheck(row.getComponent())) { if (row.extensions.select.selected) { this._deselectRow(row); } else { this._selectRow(row); } } }; //select a number of rows SelectRow.prototype.selectRows = function (rows) { var self = this; switch (typeof rows === 'undefined' ? 'undefined' : _typeof(rows)) { case "undefined": self.table.rowManager.rows.forEach(function (row) { self._selectRow(row, false, true); }); self._rowSelectionChanged(); break; case "boolean": if (rows === true) { self.table.rowManager.activeRows.forEach(function (row) { self._selectRow(row, false, true); }); self._rowSelectionChanged(); } break; default: if (Array.isArray(rows)) { rows.forEach(function (row) { self._selectRow(row); }); self._rowSelectionChanged(); } else { self._selectRow(rows); } break; } }; //select an individual row SelectRow.prototype._selectRow = function (rowInfo, silent, force) { var self = this, index; //handle max row count if (!isNaN(self.table.options.selectable) && self.table.options.selectable !== true && !force) { if (self.selectedRows.length >= self.table.options.selectable) { if (self.table.options.selectableRollingSelection) { self._deselectRow(self.selectedRows[0]); } else { return false; } } } var row = self.table.rowManager.findRow(rowInfo); if (row) { if (self.selectedRows.indexOf(row) == -1) { var self = this; row.extensions.select.selected = true; row.getElement().addClass("tabulator-selected"); self.selectedRows.push(row); if (!silent) { self.table.options.rowSelected(row.getComponent()); self._rowSelectionChanged(); } } } else { if (!silent) { console.warn("Selection Error - No such row found, ignoring selection:" + rowInfo); } } }; //deselect a number of rows SelectRow.prototype.deselectRows = function (rows) { var self = this; if (typeof rows == "undefined") { var rowCount = self.selectedRows.length; for (var i = 0; i < rowCount; i++) { self._deselectRow(self.selectedRows[0], true); } self._rowSelectionChanged(); } else { if (Array.isArray(rows)) { rows.forEach(function (row) { self._deselectRow(row); }); self._rowSelectionChanged(); } else { self._deselectRow(rows); } } }; //deselect an individual row SelectRow.prototype._deselectRow = function (rowInfo, silent) { var self = this, row = self.table.rowManager.findRow(rowInfo), index; if (row) { index = self.selectedRows.findIndex(function (selectedRow) { return selectedRow == row; }); if (index > -1) { row.extensions.select.selected = false; row.getElement().removeClass("tabulator-selected"); self.selectedRows.splice(index, 1); if (!silent) { self.table.options.rowDeselected(row.getComponent()); self._rowSelectionChanged(); } } } else { if (!silent) { console.warn("Deselection Error - No such row found, ignoring selection:" + rowInfo); } } }; SelectRow.prototype.getSelectedData = function () { var data = []; this.selectedRows.forEach(function (row) { data.push(row.getData()); }); return data; }; SelectRow.prototype.getSelectedRows = function () { var rows = []; this.selectedRows.forEach(function (row) { rows.push(row.getComponent()); }); return rows; }; SelectRow.prototype._rowSelectionChanged = function () { this.table.options.rowSelectionChanged(this.getSelectedData(), this.getSelectedRows()); }; Tabulator.registerExtension("selectRow", SelectRow); var Sort = function Sort(table) { this.table = table; //hold Tabulator object this.sortList = []; //holder current sort this.changed = false; //has the sort changed since last render }; //initialize column header for sorting Sort.prototype.initializeColumn = function (column, content) { var self = this, sorter = false; switch (_typeof(column.definition.sorter)) { case "string": if (self.sorters[column.definition.sorter]) { sorter = self.sorters[column.definition.sorter]; } else { console.warn("Sort Error - No such sorter found: ", column.definition.sorter); } break; case "function": sorter = column.definition.sorter; break; } column.extensions.sort = { sorter: sorter, dir: "none", params: column.definition.sorterParams || {}, startingDir: column.definition.headerSortStartingDir || "asc" }; if (column.definition.headerSort !== false) { column.element.addClass("tabulator-sortable"); //create sorter arrow content.append($("
")); //sort on click column.element.on("click", function (e) { var dir = "", sorters = [], match = false; if (column.extensions.sort) { dir = column.extensions.sort.dir == "asc" ? "desc" : column.extensions.sort.dir == "desc" ? "asc" : column.extensions.sort.startingDir; if (e.shiftKey || e.ctrlKey) { sorters = self.getSort(); match = sorters.findIndex(function (sorter) { return sorter.field === column.getField(); }); if (match > -1) { sorters[match].dir = sorters[match].dir == "asc" ? "desc" : "asc"; if (match != sorters.length - 1) { sorters.push(sorters.splice(match, 1)[0]); } } else { sorters.push({ column: column, dir: dir }); } //add to existing sort self.setSort(sorters); } else { //sort by column only self.setSort(column, dir); } self.table.rowManager.sorterRefresh(); } }); } }; //check if the sorters have changed since last use Sort.prototype.hasChanged = function () { var changed = this.changed; this.changed = false; return changed; }; //return current sorters Sort.prototype.getSort = function () { var self = this, sorters = []; self.sortList.forEach(function (item) { if (item.column) { sorters.push({ column: item.column.getComponent(), field: item.column.getField(), dir: item.dir }); } }); return sorters; }; //change sort list and trigger sort Sort.prototype.setSort = function (sortList, dir) { var self = this, newSortList = []; if (!Array.isArray(sortList)) { sortList = [{ column: sortList, dir: dir }]; } sortList.forEach(function (item) { var column; column = self.table.columnManager.findColumn(item.column); if (column) { item.column = column; newSortList.push(item); self.changed = true; } else { console.warn("Sort Warning - Sort field does not exist and is being ignored: ", item.column); } }); self.sortList = newSortList; if (this.table.options.persistentSort && this.table.extExists("persistence", true)) { this.table.extensions.persistence.save("sort"); } }; //clear sorters Sort.prototype.clear = function () { this.setSort([]); }, //find appropriate sorter for column Sort.prototype.findSorter = function (column) { var row = this.table.rowManager.activeRows[0], sorter = "string", field, value; if (row) { row = row.getData(); field = column.getField(); if (field) { value = column.getFieldValue(row); switch (typeof value === 'undefined' ? 'undefined' : _typeof(value)) { case "undefined": sorter = "string"; break; case "boolean": sorter = "boolean"; break; default: if (!isNaN(value) && value !== "") { sorter = "number"; } else { if (value.match(/((^[0-9]+[a-z]+)|(^[a-z]+[0-9]+))+$/i)) { sorter = "alphanum"; } } break; } } } return this.sorters[sorter]; }; //work through sort list sorting data Sort.prototype.sort = function () { var self = this, lastSort; if (self.table.options.dataSorting) { self.table.options.dataSorting(self.getSort()); } self.clearColumnHeaders(); if (!self.table.options.ajaxSorting) { self.sortList.forEach(function (item, i) { if (item.column && item.column.extensions.sort) { //if no sorter has been defined, take a guess if (!item.column.extensions.sort.sorter) { item.column.extensions.sort.sorter = self.findSorter(item.column); } self._sortItem(item.column, item.dir, self.sortList, i); } self.setColumnHeader(item.column, item.dir); }); } else { self.sortList.forEach(function (item, i) { self.setColumnHeader(item.column, item.dir); }); } if (self.table.options.dataSorted) { self.table.options.dataSorted(self.getSort(), self.table.rowManager.getComponents(true)); } }; //clear sort arrows on columns Sort.prototype.clearColumnHeaders = function () { this.table.columnManager.getRealColumns().forEach(function (column) { if (column.extensions.sort) { column.extensions.sort.dir = "none"; column.element.attr("aria-sort", "none"); } }); }; //set the column header sort direction Sort.prototype.setColumnHeader = function (column, dir) { column.extensions.sort.dir = dir; column.element.attr("aria-sort", dir); }; //sort each item in sort list Sort.prototype._sortItem = function (column, dir, sortList, i) { var self = this; var activeRows = self.table.rowManager.activeRows; activeRows.sort(function (a, b) { var result = self._sortRow(a, b, column, dir); //if results match recurse through previous searchs to be sure if (result == 0 && i) { for (var j = i - 1; j >= 0; j--) { result = self._sortRow(a, b, sortList[j].column, sortList[j].dir); if (result != 0) { break; } } } return result; }); }; //process individual rows for a sort function on active data Sort.prototype._sortRow = function (a, b, column, dir) { var self = this; //switch elements depending on search direction var el1 = dir == "asc" ? a : b; var el2 = dir == "asc" ? b : a; a = column.getFieldValue(el1.getData()); b = column.getFieldValue(el2.getData()); a = typeof a !== "undefined" ? a : ""; b = typeof b !== "undefined" ? b : ""; return column.extensions.sort.sorter.call(self, a, b, el1.getComponent(), el2.getComponent(), column.getComponent(), dir, column.extensions.sort.params); }; //default data sorters Sort.prototype.sorters = { //sort numbers number: function number(a, b, aRow, bRow, column, dir, params) { var alignEmptyValues = params.alignEmptyValues; var emptyAlign = 0; var a = parseFloat(String(a).replace(",", "")); var b = parseFloat(String(b).replace(",", "")); //handle non numeric values if (isNaN(a)) { emptyAlign = isNaN(b) ? 0 : -1; } else if (isNaN(b)) { emptyAlign = 1; } else { //compare valid values return a - b; } //fix empty values in position if (alignEmptyValues === "top" && dir === "desc" || alignEmptyValues === "bottom" && dir === "asc") { emptyAlign *= -1; } return emptyAlign; }, //sort strings string: function string(a, b, aRow, bRow, column, dir, params) { var alignEmptyValues = params.alignEmptyValues; var emptyAlign = 0; var locale; //handle empty values if (!a) { emptyAlign = !b ? 0 : -1; } else if (!b) { emptyAlign = 1; } else { //compare valid values switch (_typeof(params.locale)) { case "boolean": if (params.locale) { locale = this.table.extensions.localize.getLocale(); } break; case "string": locale = params.locale; break; } return String(a).toLowerCase().localeCompare(String(b).toLowerCase(), locale); } //fix empty values in position if (alignEmptyValues === "top" && dir === "desc" || alignEmptyValues === "bottom" && dir === "asc") { emptyAlign *= -1; } return emptyAlign; }, //sort date date: function date(a, b, aRow, bRow, column, dir, params) { var self = this; var format = params.format || "DD/MM/YYYY"; var alignEmptyValues = params.alignEmptyValues; var emptyAlign = 0; if (typeof moment != "undefined") { a = moment(a, format); b = moment(b, format); if (!a.isValid()) { emptyAlign = !b.isValid() ? 0 : -1; } else if (!b.isValid()) { emptyAlign = 1; } else { //compare valid values return a - b; } //fix empty values in position if (alignEmptyValues === "top" && dir === "desc" || alignEmptyValues === "bottom" && dir === "asc") { emptyAlign *= -1; } return emptyAlign; } else { console.error("Sort Error - 'date' sorter is dependant on moment.js"); } }, //sort hh:mm formatted times time: function time(a, b, aRow, bRow, column, dir, params) { var self = this; var format = params.format || "hh:mm"; var alignEmptyValues = params.alignEmptyValues; var emptyAlign = 0; if (typeof moment != "undefined") { a = moment(a, format); b = moment(b, format); if (!a.isValid()) { emptyAlign = !b.isValid() ? 0 : -1; } else if (!b.isValid()) { emptyAlign = 1; } else { //compare valid values return a - b; } //fix empty values in position if (alignEmptyValues === "top" && dir === "desc" || alignEmptyValues === "bottom" && dir === "asc") { emptyAlign *= -1; } return emptyAlign; } else { console.error("Sort Error - 'date' sorter is dependant on moment.js"); } }, //sort datetime datetime: function datetime(a, b, aRow, bRow, column, dir, params) { var self = this; var format = params.format || "DD/MM/YYYY hh:mm:ss"; var alignEmptyValues = params.alignEmptyValues; var emptyAlign = 0; if (typeof moment != "undefined") { a = moment(a, format); b = moment(b, format); if (!a.isValid()) { emptyAlign = !b.isValid() ? 0 : -1; } else if (!b.isValid()) { emptyAlign = 1; } else { //compare valid values return a - b; } //fix empty values in position if (alignEmptyValues === "top" && dir === "desc" || alignEmptyValues === "bottom" && dir === "asc") { emptyAlign *= -1; } return emptyAlign; } else { console.error("Sort Error - 'date' sorter is dependant on moment.js"); } }, //sort booleans boolean: function boolean(a, b, aRow, bRow, column, dir, params) { var el1 = a === true || a === "true" || a === "True" || a === 1 ? 1 : 0; var el2 = b === true || b === "true" || b === "True" || b === 1 ? 1 : 0; return el1 - el2; }, //sort if element contains any data array: function array(a, b, aRow, bRow, column, dir, params) { var el1 = 0; var el2 = 0; var type = params.type || "length"; var alignEmptyValues = params.alignEmptyValues; var emptyAlign = 0; function calc(value) { switch (type) { case "length": return value.length; break; case "sum": return value.reduce(function (c, d) { return c + d; }); break; case "max": return Math.max.apply(null, value); break; case "min": return Math.min.apply(null, value); break; case "avg": return value.reduce(function (c, d) { return c + d; }) / value.length; break; } } //handle non array values if (!Array.isArray(a)) { alignEmptyValues = !Array.isArray(b) ? 0 : -1; } else if (!Array.isArray(b)) { alignEmptyValues = 1; } else { //compare valid values el1 = a ? calc(a) : 0; el2 = b ? calc(b) : 0; return el1 - el2; } //fix empty values in position if (alignEmptyValues === "top" && dir === "desc" || alignEmptyValues === "bottom" && dir === "asc") { emptyAlign *= -1; } return emptyAlign; }, //sort if element contains any data exists: function exists(a, b, aRow, bRow, column, dir, params) { var el1 = typeof a == "undefined" ? 0 : 1; var el2 = typeof b == "undefined" ? 0 : 1; return el1 - el2; }, //sort alpha numeric strings alphanum: function alphanum(as, bs, aRow, bRow, column, dir, params) { var a, b, a1, b1, i = 0, L, rx = /(\d+)|(\D+)/g, rd = /\d/; var alignEmptyValues = params.alignEmptyValues; var emptyAlign = 0; //handle empty values if (!as && as !== 0) { emptyAlign = !bs && bs !== 0 ? 0 : -1; } else if (!bs && bs !== 0) { emptyAlign = 1; } else { if (isFinite(as) && isFinite(bs)) return as - bs; a = String(as).toLowerCase(); b = String(bs).toLowerCase(); if (a === b) return 0; if (!(rd.test(a) && rd.test(b))) return a > b ? 1 : -1; a = a.match(rx); b = b.match(rx); L = a.length > b.length ? b.length : a.length; while (i < L) { a1 = a[i]; b1 = b[i++]; if (a1 !== b1) { if (isFinite(a1) && isFinite(b1)) { if (a1.charAt(0) === "0") a1 = "." + a1; if (b1.charAt(0) === "0") b1 = "." + b1; return a1 - b1; } else return a1 > b1 ? 1 : -1; } } return a.length > b.length; } //fix empty values in position if (alignEmptyValues === "top" && dir === "desc" || alignEmptyValues === "bottom" && dir === "asc") { emptyAlign *= -1; } return emptyAlign; } }; Tabulator.registerExtension("sort", Sort); var Validate = function Validate(table) { this.table = table; }; //validate Validate.prototype.initializeColumn = function (column) { var self = this, config = [], validator; if (column.definition.validator) { if (Array.isArray(column.definition.validator)) { column.definition.validator.forEach(function (item) { validator = self._extractValidator(item); if (validator) { config.push(validator); } }); } else { validator = this._extractValidator(column.definition.validator); if (validator) { config.push(validator); } } column.extensions.validate = config.length ? config : false; } }; Validate.prototype._extractValidator = function (value) { switch (typeof value === 'undefined' ? 'undefined' : _typeof(value)) { case "string": var parts = value.split(":"); var _type = parts.shift(); var params = parts.join(); return this._buildValidator(_type, params); break; case "function": return this._buildValidator(value); break; case "object": return this._buildValidator(value.type, value.parameters); break; } }; Validate.prototype._buildValidator = function (type, params) { var func = typeof type == "function" ? type : this.validators[type]; if (!func) { console.warn("Validator Setup Error - No matching validator found:", type); return false; } else { return { type: typeof type == "function" ? "function" : type, func: func, params: params }; } }; Validate.prototype.validate = function (validators, cell, value) { var self = this, valid = []; if (validators) { validators.forEach(function (item) { if (!item.func.call(self, cell, value, item.params)) { valid.push({ type: item.type, parameters: item.params }); } }); } return valid.length ? valid : true; }; Validate.prototype.validators = { //is integer integer: function integer(cell, value, parameters) { if (value === "" || value === null || typeof value === "undefined") { return true; } value = Number(value); return typeof value === 'number' && isFinite(value) && Math.floor(value) === value; }, //is float float: function float(cell, value, parameters) { if (value === "" || value === null || typeof value === "undefined") { return true; } value = Number(value); return typeof value === 'number' && isFinite(value) && value % 1 !== 0;; }, //must be a number numeric: function numeric(cell, value, parameters) { if (value === "" || value === null || typeof value === "undefined") { return true; } return !isNaN(value); }, //must be a string string: function string(cell, value, parameters) { if (value === "" || value === null || typeof value === "undefined") { return true; } return isNaN(value); }, //maximum value max: function max(cell, value, parameters) { if (value === "" || value === null || typeof value === "undefined") { return true; } return parseFloat(value) <= parameters; }, //minimum value min: function min(cell, value, parameters) { if (value === "" || value === null || typeof value === "undefined") { return true; } return parseFloat(value) >= parameters; }, //minimum string length minLength: function minLength(cell, value, parameters) { if (value === "" || value === null || typeof value === "undefined") { return true; } return String(value).length >= parameters; }, //maximum string length maxLength: function maxLength(cell, value, parameters) { if (value === "" || value === null || typeof value === "undefined") { return true; } return String(value).length <= parameters; }, //in provided value list in: function _in(cell, value, parameters) { if (value === "" || value === null || typeof value === "undefined") { return true; } if (typeof parameters == "string") { parameters = parameters.split("|"); } return value === "" || parameters.indexOf(value) > -1; }, //must match provided regex regex: function regex(cell, value, parameters) { if (value === "" || value === null || typeof value === "undefined") { return true; } var reg = new RegExp(parameters); return reg.test(value); }, //value must be unique in this column unique: function unique(cell, value, parameters) { if (value === "" || value === null || typeof value === "undefined") { return true; } var unique = true; var cellData = cell.getData(); var column = cell.getColumn()._getSelf(); this.table.rowManager.rows.forEach(function (row) { var data = row.getData(); if (data !== cellData) { if (value == column.getFieldValue(data)) { unique = false; } } }); return unique; }, //must have a value required: function required(cell, value, parameters) { return value !== "" & value !== null && typeof value !== "undefined"; } }; Tabulator.registerExtension("validate", Validate); })(); $.widget("ui.tabulator", Tabulator); }); /*-------START------------- //changes done by Soumya---------------*/ function toggleContent(thisObj){ //toggle the icons class $(thisObj).toggleClass('collapse-tab-grid-collapse-in'); $(thisObj).toggleClass('collapse-tab-grid-collapse-out'); //get defined styles of the tabulator div var definedStyles = $(thisObj).parent().parent().attr("style"); //if it is defined if(typeof(definedStyles)!='undefined'){ var definedStyles = definedStyles.toLowerCase(); /*if height is defined in tabulator div, get the index/check for height property * if greater or equla to 0 -> height is defined * else not defined */ var definedHeightIndex = definedStyles.indexOf('height'); if(definedHeightIndex >= 0){ return false; //dont hide/show(collapse) the table } } $(thisObj).parent().parent().find('div.tabulator-header').slideToggle('slow'); $(thisObj).parent().parent().find('div.tabulator-footer').slideToggle('slow'); $(thisObj).parent().parent().find('div.tabulator-tableHolder').slideToggle('slow'); } function toggleRowCheckbox(gridId,rowId){ var isSelected = $('#'+gridId+' div[tabulator-field="id"][title="'+rowId+'"]').parent().find('.selectRow').prop('checked'); $('#'+gridId+' div[tabulator-field="id"][title="'+rowId+'"]').parent().find('.selectRow').prop('checked',(!isSelected)); } function getTabulatorSelectedRowIds(gridId,isArray=false){ var rowIds = []; var selectedData = $("#"+gridId).tabulator("getSelectedRows"); selectedData.forEach(function(row){ rowIds.push(row.getCell('id').getValue()); }); if(!isArray) rowIds = rowIds.join(","); return rowIds; } function tabulator_select_all_grid_rows(thisObj){ var isSelectAllChecked=$(thisObj).is(":checked"); var tabulatorGridId=$(thisObj).parents("div.customGridWrapper.tabulator").attr('id'); if(isSelectAllChecked){ $("#"+tabulatorGridId).tabulator("selectRow"); }else{ $("#"+tabulatorGridId).tabulator("deselectRow"); } $('#'+tabulatorGridId).find('.selectRow').prop('checked',(isSelectAllChecked)) } var tabulatorColumnVisibility = new Array(); function tabulatorDispalyColumns(thisObj){ var tab_grid_d =$(thisObj).parents("div.customGridWrapper.tabulator").attr('id'); var htmlContent=''; htmlContent+='
'; $("#bs-modal .modal-title").text('Select columns'); $("#bs-modal .modal-body").html(htmlContent); $('#bs-modal').modal('show'); } function tabulatorHideShowColumns(gridId){ var selectedCols = []; var arrColumns = []; //get all columns $.each($("select#"+gridId+" option"), function(){ arrColumns.push($(this).val()); }); //get selected columns $.each($("select#"+gridId+" option:selected"), function(){ selectedCols.push($(this).val()); }); arrColumns.forEach(function(col) { var isColSelected=isInArray(col,selectedCols) if(isColSelected){ $("#"+gridId).tabulator("showColumn",col) //hide the "name" column }else{ $("#"+gridId).tabulator("hideColumn",col) //hide the "name" column } }); $('#bs-modal').modal('hide'); } function isInArray(value, array) { return array.indexOf(value) > -1; } /*-------END------------- //changes done by Soumya---------------*/