added messages list, new client form, logic for client Apps plus others
This commit is contained in:
16
public/libs/tabulator-master/src/js/builds/esm.js
Normal file
16
public/libs/tabulator-master/src/js/builds/esm.js
Normal file
@@ -0,0 +1,16 @@
|
||||
export * from '../core/modules/optional.js';
|
||||
export {default as Tabulator} from '../core/Tabulator.js';
|
||||
export {default as TabulatorFull} from '../core/TabulatorFull.js';
|
||||
|
||||
export {default as CellComponent} from '../core/cell/CellComponent.js';
|
||||
export {default as ColumnComponent} from '../core/column/ColumnComponent.js';
|
||||
export {default as RowComponent} from '../core/row/RowComponent.js';
|
||||
export {default as GroupComponent} from '../modules/GroupRows/GroupComponent.js';
|
||||
export {default as CalcComponent} from '../modules/ColumnCalcs/CalcComponent.js';
|
||||
export {default as RangeComponent} from '../modules/SelectRange/RangeComponent.js';
|
||||
export {default as SheetComponent} from '../modules/Spreadsheet/SheetComponent.js';
|
||||
|
||||
export {default as PseudoRow} from '../core/row/PseudoRow.js';
|
||||
|
||||
export {default as Module} from '../core/Module.js';
|
||||
export {default as Renderer} from '../core/rendering/Renderer.js';
|
||||
63
public/libs/tabulator-master/src/js/builds/jquery_wrapper.js
vendored
Normal file
63
public/libs/tabulator-master/src/js/builds/jquery_wrapper.js
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* This file is part of the Tabulator package.
|
||||
*
|
||||
* (c) Oliver Folkerd <oliver.folkerd@gmail.com>
|
||||
*
|
||||
* 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 (root, factory) {
|
||||
"use strict";
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
define(['jquery', 'tabulator', 'jquery-ui'], factory);
|
||||
}
|
||||
else if(typeof module !== 'undefined' && module.exports) {
|
||||
module.exports = factory(
|
||||
require('jquery'),
|
||||
require('tabulator'),
|
||||
require('jquery-ui')
|
||||
);
|
||||
}
|
||||
else {
|
||||
factory(root.jQuery, root.Tabulator);
|
||||
}
|
||||
}(this, function ($, Tabulator) {
|
||||
|
||||
$.widget("ui.tabulator", {
|
||||
_create:function(){
|
||||
var options = Object.assign({}, this.options);
|
||||
var props = [];
|
||||
|
||||
delete options.create;
|
||||
delete options.disabled;
|
||||
|
||||
this.table = new Tabulator(this.element[0], options);
|
||||
window.table = this.table;
|
||||
|
||||
//retrieve properties on prototype
|
||||
props = Object.getOwnPropertyNames(Object.getPrototypeOf(Object.getPrototypeOf(this.table)));
|
||||
|
||||
//retrieve properties added by modules
|
||||
props = props.concat(Object.getOwnPropertyNames(this.table));
|
||||
|
||||
//map tabulator functions to jquery wrapper
|
||||
for(let key of props){
|
||||
if(typeof this.table[key] === "function" && key.charAt(0) !== "_"){
|
||||
this[key] = this.table[key].bind(this.table);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_setOption: function(option, value){
|
||||
console.error("Tabulator jQuery wrapper does not support setting options after the table has been instantiated");
|
||||
},
|
||||
|
||||
_destroy: function(option, value){
|
||||
this.table.destroy();
|
||||
},
|
||||
});
|
||||
}));
|
||||
1
public/libs/tabulator-master/src/js/builds/usd.js
Normal file
1
public/libs/tabulator-master/src/js/builds/usd.js
Normal file
@@ -0,0 +1 @@
|
||||
export { default } from '../core/TabulatorFull.js';
|
||||
789
public/libs/tabulator-master/src/js/core/ColumnManager.js
Normal file
789
public/libs/tabulator-master/src/js/core/ColumnManager.js
Normal file
@@ -0,0 +1,789 @@
|
||||
import CoreFeature from './CoreFeature.js';
|
||||
import Column from './column/Column.js';
|
||||
import ColumnComponent from './column/ColumnComponent.js';
|
||||
import Helpers from './tools/Helpers.js';
|
||||
import OptionsList from './tools/OptionsList.js';
|
||||
|
||||
import RendererBasicHorizontal from './rendering/renderers/BasicHorizontal.js';
|
||||
import RendererVirtualDomHorizontal from './rendering/renderers/VirtualDomHorizontal.js';
|
||||
|
||||
import defaultColumnOptions from './column/defaults/options.js';
|
||||
|
||||
export default class ColumnManager extends CoreFeature {
|
||||
|
||||
constructor (table){
|
||||
super(table);
|
||||
|
||||
this.blockHozScrollEvent = false;
|
||||
this.headersElement = null;
|
||||
this.contentsElement = null;
|
||||
this.rowHeader = null;
|
||||
this.element = null ; //containing element
|
||||
this.columns = []; // column definition object
|
||||
this.columnsByIndex = []; //columns by index
|
||||
this.columnsByField = {}; //columns by field
|
||||
this.scrollLeft = 0;
|
||||
this.optionsList = new OptionsList(this.table, "column definition", defaultColumnOptions);
|
||||
|
||||
this.redrawBlock = false; //prevent redraws to allow multiple data manipulations before continuing
|
||||
this.redrawBlockUpdate = null; //store latest redraw update only status
|
||||
|
||||
this.renderer = null;
|
||||
}
|
||||
|
||||
////////////// Setup Functions /////////////////
|
||||
|
||||
initialize(){
|
||||
this.initializeRenderer();
|
||||
|
||||
this.headersElement = this.createHeadersElement();
|
||||
this.contentsElement = this.createHeaderContentsElement();
|
||||
this.element = this.createHeaderElement();
|
||||
|
||||
this.contentsElement.insertBefore(this.headersElement, this.contentsElement.firstChild);
|
||||
this.element.insertBefore(this.contentsElement, this.element.firstChild);
|
||||
|
||||
this.initializeScrollWheelWatcher();
|
||||
|
||||
this.subscribe("scroll-horizontal", this.scrollHorizontal.bind(this));
|
||||
this.subscribe("scrollbar-vertical", this.padVerticalScrollbar.bind(this));
|
||||
}
|
||||
|
||||
padVerticalScrollbar(width){
|
||||
if(this.table.rtl){
|
||||
this.headersElement.style.marginLeft = width + "px";
|
||||
}else{
|
||||
this.headersElement.style.marginRight = width + "px";
|
||||
}
|
||||
}
|
||||
|
||||
initializeRenderer(){
|
||||
var renderClass;
|
||||
|
||||
var renderers = {
|
||||
"virtual": RendererVirtualDomHorizontal,
|
||||
"basic": RendererBasicHorizontal,
|
||||
};
|
||||
|
||||
if(typeof this.table.options.renderHorizontal === "string"){
|
||||
renderClass = renderers[this.table.options.renderHorizontal];
|
||||
}else{
|
||||
renderClass = this.table.options.renderHorizontal;
|
||||
}
|
||||
|
||||
if(renderClass){
|
||||
this.renderer = new renderClass(this.table, this.element, this.tableElement);
|
||||
this.renderer.initialize();
|
||||
}else{
|
||||
console.error("Unable to find matching renderer:", this.table.options.renderHorizontal);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
createHeadersElement (){
|
||||
var el = document.createElement("div");
|
||||
|
||||
el.classList.add("tabulator-headers");
|
||||
el.setAttribute("role", "row");
|
||||
|
||||
return el;
|
||||
}
|
||||
|
||||
createHeaderContentsElement (){
|
||||
var el = document.createElement("div");
|
||||
|
||||
el.classList.add("tabulator-header-contents");
|
||||
|
||||
return el;
|
||||
}
|
||||
|
||||
createHeaderElement (){
|
||||
var el = document.createElement("div");
|
||||
|
||||
el.classList.add("tabulator-header");
|
||||
el.setAttribute("role", "rowgroup");
|
||||
|
||||
if(!this.table.options.headerVisible){
|
||||
el.classList.add("tabulator-header-hidden");
|
||||
}
|
||||
|
||||
return el;
|
||||
}
|
||||
|
||||
//return containing element
|
||||
getElement(){
|
||||
return this.element;
|
||||
}
|
||||
|
||||
//return containing contents element
|
||||
getContentsElement(){
|
||||
return this.contentsElement;
|
||||
}
|
||||
|
||||
|
||||
//return header containing element
|
||||
getHeadersElement(){
|
||||
return this.headersElement;
|
||||
}
|
||||
|
||||
//scroll horizontally to match table body
|
||||
scrollHorizontal(left){
|
||||
this.contentsElement.scrollLeft = left;
|
||||
|
||||
this.scrollLeft = left;
|
||||
|
||||
this.renderer.scrollColumns(left);
|
||||
}
|
||||
|
||||
initializeScrollWheelWatcher(){
|
||||
this.contentsElement.addEventListener("wheel", (e) => {
|
||||
var left;
|
||||
|
||||
if(e.deltaX){
|
||||
left = this.contentsElement.scrollLeft + e.deltaX;
|
||||
|
||||
this.table.rowManager.scrollHorizontal(left);
|
||||
this.table.columnManager.scrollHorizontal(left);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
///////////// Column Setup Functions /////////////
|
||||
generateColumnsFromRowData(data){
|
||||
var cols = [],
|
||||
collProgress = {},
|
||||
rowSample = this.table.options.autoColumns === "full" ? data : [data[0]],
|
||||
definitions = this.table.options.autoColumnsDefinitions;
|
||||
|
||||
if(data && data.length){
|
||||
|
||||
rowSample.forEach((row) => {
|
||||
|
||||
Object.keys(row).forEach((key, index) => {
|
||||
let value = row[key],
|
||||
col;
|
||||
|
||||
if(!collProgress[key]){
|
||||
col = {
|
||||
field:key,
|
||||
title:key,
|
||||
sorter:this.calculateSorterFromValue(value),
|
||||
};
|
||||
|
||||
cols.splice(index, 0, col);
|
||||
collProgress[key] = typeof value === "undefined" ? col : true;
|
||||
}else if(collProgress[key] !== true){
|
||||
if(typeof value !== "undefined"){
|
||||
collProgress[key].sorter = this.calculateSorterFromValue(value);
|
||||
collProgress[key] = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
if(definitions){
|
||||
|
||||
switch(typeof definitions){
|
||||
case "function":
|
||||
this.table.options.columns = definitions.call(this.table, cols);
|
||||
break;
|
||||
|
||||
case "object":
|
||||
if(Array.isArray(definitions)){
|
||||
cols.forEach((col) => {
|
||||
var match = definitions.find((def) => {
|
||||
return def.field === col.field;
|
||||
});
|
||||
|
||||
if(match){
|
||||
Object.assign(col, match);
|
||||
}
|
||||
});
|
||||
|
||||
}else{
|
||||
cols.forEach((col) => {
|
||||
if(definitions[col.field]){
|
||||
Object.assign(col, definitions[col.field]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
this.table.options.columns = cols;
|
||||
break;
|
||||
}
|
||||
}else{
|
||||
this.table.options.columns = cols;
|
||||
}
|
||||
|
||||
this.setColumns(this.table.options.columns);
|
||||
}
|
||||
}
|
||||
|
||||
calculateSorterFromValue(value){
|
||||
var sorter;
|
||||
|
||||
switch(typeof value){
|
||||
case "undefined":
|
||||
sorter = "string";
|
||||
break;
|
||||
|
||||
case "boolean":
|
||||
sorter = "boolean";
|
||||
break;
|
||||
|
||||
case "number":
|
||||
sorter = "number";
|
||||
break;
|
||||
|
||||
case "object":
|
||||
if(Array.isArray(value)){
|
||||
sorter = "array";
|
||||
}else{
|
||||
sorter = "string";
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if(!isNaN(value) && value !== ""){
|
||||
sorter = "number";
|
||||
}else{
|
||||
if(value.match(/((^[0-9]+[a-z]+)|(^[a-z]+[0-9]+))+$/i)){
|
||||
sorter = "alphanum";
|
||||
}else{
|
||||
sorter = "string";
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return sorter;
|
||||
}
|
||||
|
||||
setColumns(cols, row){
|
||||
while(this.headersElement.firstChild) this.headersElement.removeChild(this.headersElement.firstChild);
|
||||
|
||||
this.columns = [];
|
||||
this.columnsByIndex = [];
|
||||
this.columnsByField = {};
|
||||
|
||||
this.dispatch("columns-loading");
|
||||
this.dispatchExternal("columnsLoading");
|
||||
|
||||
if(this.table.options.rowHeader){
|
||||
this.rowHeader = new Column(this.table.options.rowHeader === true ? {} : this.table.options.rowHeader, this, true);
|
||||
this.columns.push(this.rowHeader);
|
||||
this.headersElement.appendChild(this.rowHeader.getElement());
|
||||
this.rowHeader.columnRendered();
|
||||
}
|
||||
|
||||
cols.forEach((def, i) => {
|
||||
this._addColumn(def);
|
||||
});
|
||||
|
||||
this._reIndexColumns();
|
||||
|
||||
this.dispatch("columns-loaded");
|
||||
|
||||
if(this.subscribedExternal("columnsLoaded")){
|
||||
this.dispatchExternal("columnsLoaded", this.getComponents());
|
||||
}
|
||||
|
||||
this.rerenderColumns(false, true);
|
||||
|
||||
this.redraw(true);
|
||||
}
|
||||
|
||||
_addColumn(definition, before, nextToColumn){
|
||||
var column = new Column(definition, this),
|
||||
colEl = column.getElement(),
|
||||
index = nextToColumn ? this.findColumnIndex(nextToColumn) : nextToColumn;
|
||||
|
||||
//prevent adding of rows in front of row header
|
||||
if(before && this.rowHeader && (!nextToColumn || nextToColumn === this.rowHeader)){
|
||||
before = false;
|
||||
nextToColumn = this.rowHeader;
|
||||
index = 0;
|
||||
}
|
||||
|
||||
if(nextToColumn && index > -1){
|
||||
var topColumn = nextToColumn.getTopColumn();
|
||||
var parentIndex = this.columns.indexOf(topColumn);
|
||||
var nextEl = topColumn.getElement();
|
||||
|
||||
if(before){
|
||||
this.columns.splice(parentIndex, 0, column);
|
||||
nextEl.parentNode.insertBefore(colEl, nextEl);
|
||||
}else{
|
||||
this.columns.splice(parentIndex + 1, 0, column);
|
||||
nextEl.parentNode.insertBefore(colEl, nextEl.nextSibling);
|
||||
}
|
||||
}else{
|
||||
if(before){
|
||||
this.columns.unshift(column);
|
||||
this.headersElement.insertBefore(column.getElement(), this.headersElement.firstChild);
|
||||
}else{
|
||||
this.columns.push(column);
|
||||
this.headersElement.appendChild(column.getElement());
|
||||
}
|
||||
}
|
||||
|
||||
column.columnRendered();
|
||||
|
||||
return column;
|
||||
}
|
||||
|
||||
registerColumnField(col){
|
||||
if(col.definition.field){
|
||||
this.columnsByField[col.definition.field] = col;
|
||||
}
|
||||
}
|
||||
|
||||
registerColumnPosition(col){
|
||||
this.columnsByIndex.push(col);
|
||||
}
|
||||
|
||||
_reIndexColumns(){
|
||||
this.columnsByIndex = [];
|
||||
|
||||
this.columns.forEach(function(column){
|
||||
column.reRegisterPosition();
|
||||
});
|
||||
}
|
||||
|
||||
//ensure column headers take up the correct amount of space in column groups
|
||||
verticalAlignHeaders(){
|
||||
var minHeight = 0;
|
||||
|
||||
if(!this.redrawBlock){
|
||||
|
||||
this.headersElement.style.height="";
|
||||
|
||||
this.columns.forEach((column) => {
|
||||
column.clearVerticalAlign();
|
||||
});
|
||||
|
||||
this.columns.forEach((column) => {
|
||||
var height = column.getHeight();
|
||||
|
||||
if(height > minHeight){
|
||||
minHeight = height;
|
||||
}
|
||||
});
|
||||
|
||||
this.headersElement.style.height = minHeight + "px";
|
||||
|
||||
this.columns.forEach((column) => {
|
||||
column.verticalAlign(this.table.options.columnHeaderVertAlign, minHeight);
|
||||
});
|
||||
|
||||
this.table.rowManager.adjustTableSize();
|
||||
}
|
||||
}
|
||||
|
||||
//////////////// Column Details /////////////////
|
||||
findColumn(subject){
|
||||
var columns;
|
||||
|
||||
if(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(typeof HTMLElement !== "undefined" && subject instanceof HTMLElement){
|
||||
|
||||
columns = [];
|
||||
|
||||
this.columns.forEach((column) => {
|
||||
columns.push(column);
|
||||
columns = columns.concat(column.getColumns(true));
|
||||
});
|
||||
|
||||
//subject is a HTML element of the column header
|
||||
let match = columns.find((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;
|
||||
}
|
||||
|
||||
getColumnByField(field){
|
||||
return this.columnsByField[field];
|
||||
}
|
||||
|
||||
getColumnsByFieldRoot(root){
|
||||
var matches = [];
|
||||
|
||||
Object.keys(this.columnsByField).forEach((field) => {
|
||||
var fieldRoot = this.table.options.nestedFieldSeparator ? field.split(this.table.options.nestedFieldSeparator)[0] : field;
|
||||
if(fieldRoot === root){
|
||||
matches.push(this.columnsByField[field]);
|
||||
}
|
||||
});
|
||||
|
||||
return matches;
|
||||
}
|
||||
|
||||
getColumnByIndex(index){
|
||||
return this.columnsByIndex[index];
|
||||
}
|
||||
|
||||
getFirstVisibleColumn(){
|
||||
var index = this.columnsByIndex.findIndex((col) => {
|
||||
return col.visible;
|
||||
});
|
||||
|
||||
return index > -1 ? this.columnsByIndex[index] : false;
|
||||
}
|
||||
|
||||
getVisibleColumnsByIndex() {
|
||||
return this.columnsByIndex.filter((col) => col.visible);
|
||||
}
|
||||
|
||||
getColumns(){
|
||||
return this.columns;
|
||||
}
|
||||
|
||||
findColumnIndex(column){
|
||||
return this.columnsByIndex.findIndex((col) => {
|
||||
return column === col;
|
||||
});
|
||||
}
|
||||
|
||||
//return all columns that are not groups
|
||||
getRealColumns(){
|
||||
return this.columnsByIndex;
|
||||
}
|
||||
|
||||
//traverse across columns and call action
|
||||
traverse(callback){
|
||||
this.columnsByIndex.forEach((column,i) =>{
|
||||
callback(column, i);
|
||||
});
|
||||
}
|
||||
|
||||
//get definitions of actual columns
|
||||
getDefinitions(active){
|
||||
var output = [];
|
||||
|
||||
this.columnsByIndex.forEach((column) => {
|
||||
if(!active || (active && column.visible)){
|
||||
output.push(column.getDefinition());
|
||||
}
|
||||
});
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
//get full nested definition tree
|
||||
getDefinitionTree(){
|
||||
var output = [];
|
||||
|
||||
this.columns.forEach((column) => {
|
||||
output.push(column.getDefinition(true));
|
||||
});
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
getComponents(structured){
|
||||
var output = [],
|
||||
columns = structured ? this.columns : this.columnsByIndex;
|
||||
|
||||
columns.forEach((column) => {
|
||||
output.push(column.getComponent());
|
||||
});
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
getWidth(){
|
||||
var width = 0;
|
||||
|
||||
this.columnsByIndex.forEach((column) => {
|
||||
if(column.visible){
|
||||
width += column.getWidth();
|
||||
}
|
||||
});
|
||||
|
||||
return width;
|
||||
}
|
||||
|
||||
moveColumn(from, to, after){
|
||||
to.element.parentNode.insertBefore(from.element, to.element);
|
||||
|
||||
if(after){
|
||||
to.element.parentNode.insertBefore(to.element, from.element);
|
||||
}
|
||||
|
||||
this.moveColumnActual(from, to, after);
|
||||
|
||||
this.verticalAlignHeaders();
|
||||
|
||||
this.table.rowManager.reinitialize();
|
||||
}
|
||||
|
||||
moveColumnActual(from, to, after){
|
||||
if(from.parent.isGroup){
|
||||
this._moveColumnInArray(from.parent.columns, from, to, after);
|
||||
}else{
|
||||
this._moveColumnInArray(this.columns, from, to, after);
|
||||
}
|
||||
|
||||
this._moveColumnInArray(this.columnsByIndex, from, to, after, true);
|
||||
|
||||
this.rerenderColumns(true);
|
||||
|
||||
this.dispatch("column-moved", from, to, after);
|
||||
|
||||
if(this.subscribedExternal("columnMoved")){
|
||||
this.dispatchExternal("columnMoved", from.getComponent(), this.table.columnManager.getComponents());
|
||||
}
|
||||
}
|
||||
|
||||
_moveColumnInArray(columns, from, to, after, updateRows){
|
||||
var fromIndex = columns.indexOf(from),
|
||||
toIndex, rows = [];
|
||||
|
||||
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){
|
||||
|
||||
rows = this.chain("column-moving-rows", [from, to, after], null, []) || [];
|
||||
|
||||
rows = rows.concat(this.table.rowManager.rows);
|
||||
|
||||
rows.forEach(function(row){
|
||||
if(row.cells.length){
|
||||
var cell = row.cells.splice(fromIndex, 1)[0];
|
||||
row.cells.splice(toIndex, 0, cell);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
scrollToColumn(column, position, ifVisible){
|
||||
var left = 0,
|
||||
offset = column.getLeftOffset(),
|
||||
adjust = 0,
|
||||
colEl = column.getElement();
|
||||
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
|
||||
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.clientWidth / 2;
|
||||
break;
|
||||
|
||||
case "right":
|
||||
adjust = colEl.clientWidth - this.headersElement.clientWidth;
|
||||
break;
|
||||
}
|
||||
|
||||
//check column visibility
|
||||
if(!ifVisible){
|
||||
if(offset > 0 && offset + colEl.offsetWidth < this.element.clientWidth){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//calculate scroll position
|
||||
left = offset + adjust;
|
||||
|
||||
left = Math.max(Math.min(left, this.table.rowManager.element.scrollWidth - this.table.rowManager.element.clientWidth),0);
|
||||
|
||||
this.table.rowManager.scrollHorizontal(left);
|
||||
this.scrollHorizontal(left);
|
||||
|
||||
resolve();
|
||||
}else{
|
||||
console.warn("Scroll Error - Column not visible");
|
||||
reject("Scroll Error - Column not visible");
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
//////////////// Cell Management /////////////////
|
||||
generateCells(row){
|
||||
var cells = [];
|
||||
|
||||
this.columnsByIndex.forEach((column) => {
|
||||
cells.push(column.generateCell(row));
|
||||
});
|
||||
|
||||
return cells;
|
||||
}
|
||||
|
||||
//////////////// Column Management /////////////////
|
||||
getFlexBaseWidth(){
|
||||
var totalWidth = this.table.element.clientWidth, //table element width
|
||||
fixedWidth = 0;
|
||||
|
||||
//adjust for vertical scrollbar if present
|
||||
if(this.table.rowManager.element.scrollHeight > this.table.rowManager.element.clientHeight){
|
||||
totalWidth -= this.table.rowManager.element.offsetWidth - this.table.rowManager.element.clientWidth;
|
||||
}
|
||||
|
||||
this.columnsByIndex.forEach(function(column){
|
||||
var width, minWidth, colWidth;
|
||||
|
||||
if(column.visible){
|
||||
|
||||
width = column.definition.width || 0;
|
||||
|
||||
minWidth = 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;
|
||||
}
|
||||
|
||||
addColumn(definition, before, nextToColumn){
|
||||
return new Promise((resolve, reject) => {
|
||||
var column = this._addColumn(definition, before, nextToColumn);
|
||||
|
||||
this._reIndexColumns();
|
||||
|
||||
this.dispatch("column-add", definition, before, nextToColumn);
|
||||
|
||||
if(this.layoutMode() != "fitColumns"){
|
||||
column.reinitializeWidth();
|
||||
}
|
||||
|
||||
this.redraw(true);
|
||||
|
||||
this.table.rowManager.reinitialize();
|
||||
|
||||
this.rerenderColumns();
|
||||
|
||||
resolve(column);
|
||||
});
|
||||
}
|
||||
|
||||
//remove column from system
|
||||
deregisterColumn(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);
|
||||
}
|
||||
|
||||
this.verticalAlignHeaders();
|
||||
|
||||
this.redraw();
|
||||
}
|
||||
|
||||
rerenderColumns(update, silent){
|
||||
if(!this.redrawBlock){
|
||||
this.renderer.rerenderColumns(update, silent);
|
||||
}else{
|
||||
if(update === false || (update === true && this.redrawBlockUpdate === null)){
|
||||
this.redrawBlockUpdate = update;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
blockRedraw(){
|
||||
this.redrawBlock = true;
|
||||
this.redrawBlockUpdate = null;
|
||||
}
|
||||
|
||||
restoreRedraw(){
|
||||
this.redrawBlock = false;
|
||||
this.verticalAlignHeaders();
|
||||
this.renderer.rerenderColumns(this.redrawBlockUpdate);
|
||||
|
||||
}
|
||||
|
||||
//redraw columns
|
||||
redraw(force){
|
||||
if(Helpers.elVisible(this.element)){
|
||||
this.verticalAlignHeaders();
|
||||
}
|
||||
|
||||
if(force){
|
||||
this.table.rowManager.resetScroll();
|
||||
this.table.rowManager.reinitialize();
|
||||
}
|
||||
|
||||
if(!this.confirm("table-redrawing", force)){
|
||||
this.layoutRefresh(force);
|
||||
}
|
||||
|
||||
this.dispatch("table-redraw", force);
|
||||
|
||||
this.table.footerManager.redraw();
|
||||
}
|
||||
}
|
||||
139
public/libs/tabulator-master/src/js/core/CoreFeature.js
Normal file
139
public/libs/tabulator-master/src/js/core/CoreFeature.js
Normal file
@@ -0,0 +1,139 @@
|
||||
export default class CoreFeature{
|
||||
|
||||
constructor(table){
|
||||
this.table = table;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////
|
||||
/////////////// DataLoad /////////////////
|
||||
//////////////////////////////////////////
|
||||
|
||||
reloadData(data, silent, columnsChanged){
|
||||
return this.table.dataLoader.load(data, undefined, undefined, undefined, silent, columnsChanged);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////
|
||||
///////////// Localization ///////////////
|
||||
//////////////////////////////////////////
|
||||
|
||||
langText(){
|
||||
return this.table.modules.localize.getText(...arguments);
|
||||
}
|
||||
|
||||
langBind(){
|
||||
return this.table.modules.localize.bind(...arguments);
|
||||
}
|
||||
|
||||
langLocale(){
|
||||
return this.table.modules.localize.getLocale(...arguments);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////
|
||||
////////// Inter Table Comms /////////////
|
||||
//////////////////////////////////////////
|
||||
|
||||
commsConnections(){
|
||||
return this.table.modules.comms.getConnections(...arguments);
|
||||
}
|
||||
|
||||
commsSend(){
|
||||
return this.table.modules.comms.send(...arguments);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////
|
||||
//////////////// Layout /////////////////
|
||||
//////////////////////////////////////////
|
||||
|
||||
layoutMode(){
|
||||
return this.table.modules.layout.getMode();
|
||||
}
|
||||
|
||||
layoutRefresh(force){
|
||||
return this.table.modules.layout.layout(force);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////
|
||||
/////////////// Event Bus ////////////////
|
||||
//////////////////////////////////////////
|
||||
|
||||
subscribe(){
|
||||
return this.table.eventBus.subscribe(...arguments);
|
||||
}
|
||||
|
||||
unsubscribe(){
|
||||
return this.table.eventBus.unsubscribe(...arguments);
|
||||
}
|
||||
|
||||
subscribed(key){
|
||||
return this.table.eventBus.subscribed(key);
|
||||
}
|
||||
|
||||
subscriptionChange(){
|
||||
return this.table.eventBus.subscriptionChange(...arguments);
|
||||
}
|
||||
|
||||
dispatch(){
|
||||
return this.table.eventBus.dispatch(...arguments);
|
||||
}
|
||||
|
||||
chain(){
|
||||
return this.table.eventBus.chain(...arguments);
|
||||
}
|
||||
|
||||
confirm(){
|
||||
return this.table.eventBus.confirm(...arguments);
|
||||
}
|
||||
|
||||
dispatchExternal(){
|
||||
return this.table.externalEvents.dispatch(...arguments);
|
||||
}
|
||||
|
||||
subscribedExternal(key){
|
||||
return this.table.externalEvents.subscribed(key);
|
||||
}
|
||||
|
||||
subscriptionChangeExternal(){
|
||||
return this.table.externalEvents.subscriptionChange(...arguments);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////
|
||||
//////////////// Options /////////////////
|
||||
//////////////////////////////////////////
|
||||
|
||||
options(key){
|
||||
return this.table.options[key];
|
||||
}
|
||||
|
||||
setOption(key, value){
|
||||
if(typeof value !== "undefined"){
|
||||
this.table.options[key] = value;
|
||||
}
|
||||
|
||||
return this.table.options[key];
|
||||
}
|
||||
|
||||
//////////////////////////////////////////
|
||||
/////////// Deprecation Checks ///////////
|
||||
//////////////////////////////////////////
|
||||
|
||||
deprecationCheck(oldOption, newOption, convert){
|
||||
return this.table.deprecationAdvisor.check(oldOption, newOption, convert);
|
||||
}
|
||||
|
||||
deprecationCheckMsg(oldOption, msg){
|
||||
return this.table.deprecationAdvisor.checkMsg(oldOption, msg);
|
||||
}
|
||||
|
||||
deprecationMsg(msg){
|
||||
return this.table.deprecationAdvisor.msg(msg);
|
||||
}
|
||||
//////////////////////////////////////////
|
||||
//////////////// Modules /////////////////
|
||||
//////////////////////////////////////////
|
||||
|
||||
module(key){
|
||||
return this.table.module(key);
|
||||
}
|
||||
}
|
||||
102
public/libs/tabulator-master/src/js/core/FooterManager.js
Normal file
102
public/libs/tabulator-master/src/js/core/FooterManager.js
Normal file
@@ -0,0 +1,102 @@
|
||||
import CoreFeature from './CoreFeature.js';
|
||||
|
||||
export default class FooterManager extends CoreFeature{
|
||||
|
||||
constructor(table){
|
||||
super(table);
|
||||
|
||||
this.active = false;
|
||||
this.element = this.createElement(); //containing element
|
||||
this.containerElement = this.createContainerElement(); //containing element
|
||||
this.external = false;
|
||||
}
|
||||
|
||||
initialize(){
|
||||
this.initializeElement();
|
||||
}
|
||||
|
||||
createElement(){
|
||||
var el = document.createElement("div");
|
||||
|
||||
el.classList.add("tabulator-footer");
|
||||
|
||||
return el;
|
||||
}
|
||||
|
||||
|
||||
createContainerElement(){
|
||||
var el = document.createElement("div");
|
||||
|
||||
el.classList.add("tabulator-footer-contents");
|
||||
|
||||
this.element.appendChild(el);
|
||||
|
||||
return el;
|
||||
}
|
||||
|
||||
initializeElement(){
|
||||
if(this.table.options.footerElement){
|
||||
|
||||
switch(typeof this.table.options.footerElement){
|
||||
case "string":
|
||||
if(this.table.options.footerElement[0] === "<"){
|
||||
this.containerElement.innerHTML = this.table.options.footerElement;
|
||||
}else{
|
||||
this.external = true;
|
||||
this.containerElement = document.querySelector(this.table.options.footerElement);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
this.element = this.table.options.footerElement;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getElement(){
|
||||
return this.element;
|
||||
}
|
||||
|
||||
append(element){
|
||||
this.activate();
|
||||
|
||||
this.containerElement.appendChild(element);
|
||||
this.table.rowManager.adjustTableSize();
|
||||
}
|
||||
|
||||
prepend(element){
|
||||
this.activate();
|
||||
|
||||
this.element.insertBefore(element, this.element.firstChild);
|
||||
this.table.rowManager.adjustTableSize();
|
||||
}
|
||||
|
||||
remove(element){
|
||||
element.parentNode.removeChild(element);
|
||||
this.deactivate();
|
||||
}
|
||||
|
||||
deactivate(force){
|
||||
if(!this.element.firstChild || force){
|
||||
if(!this.external){
|
||||
this.element.parentNode.removeChild(this.element);
|
||||
}
|
||||
this.active = false;
|
||||
}
|
||||
}
|
||||
|
||||
activate(){
|
||||
if(!this.active){
|
||||
this.active = true;
|
||||
if(!this.external){
|
||||
this.table.element.appendChild(this.getElement());
|
||||
this.table.element.style.display = '';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
redraw(){
|
||||
this.dispatch("footer-redraw");
|
||||
}
|
||||
}
|
||||
140
public/libs/tabulator-master/src/js/core/Module.js
Normal file
140
public/libs/tabulator-master/src/js/core/Module.js
Normal file
@@ -0,0 +1,140 @@
|
||||
import CoreFeature from './CoreFeature.js';
|
||||
import Popup from './tools/Popup.js';
|
||||
|
||||
export default class Module extends CoreFeature{
|
||||
|
||||
constructor(table, name){
|
||||
super(table);
|
||||
|
||||
this._handler = null;
|
||||
}
|
||||
|
||||
initialize(){
|
||||
// setup module when table is initialized, to be overridden in module
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////
|
||||
////// Options Registration ///////
|
||||
///////////////////////////////////
|
||||
|
||||
registerTableOption(key, value){
|
||||
this.table.optionsList.register(key, value);
|
||||
}
|
||||
|
||||
registerColumnOption(key, value){
|
||||
this.table.columnManager.optionsList.register(key, value);
|
||||
}
|
||||
|
||||
///////////////////////////////////
|
||||
/// Public Function Registration ///
|
||||
///////////////////////////////////
|
||||
|
||||
registerTableFunction(name, func){
|
||||
if(typeof this.table[name] === "undefined"){
|
||||
this.table[name] = (...args) => {
|
||||
this.table.initGuard(name);
|
||||
|
||||
return func(...args);
|
||||
};
|
||||
}else{
|
||||
console.warn("Unable to bind table function, name already in use", name);
|
||||
}
|
||||
}
|
||||
|
||||
registerComponentFunction(component, func, handler){
|
||||
return this.table.componentFunctionBinder.bind(component, func, handler);
|
||||
}
|
||||
|
||||
///////////////////////////////////
|
||||
////////// Data Pipeline //////////
|
||||
///////////////////////////////////
|
||||
|
||||
registerDataHandler(handler, priority){
|
||||
this.table.rowManager.registerDataPipelineHandler(handler, priority);
|
||||
this._handler = handler;
|
||||
}
|
||||
|
||||
registerDisplayHandler(handler, priority){
|
||||
this.table.rowManager.registerDisplayPipelineHandler(handler, priority);
|
||||
this._handler = handler;
|
||||
}
|
||||
|
||||
displayRows(adjust){
|
||||
var index = this.table.rowManager.displayRows.length - 1,
|
||||
lookupIndex;
|
||||
|
||||
if(this._handler){
|
||||
lookupIndex = this.table.rowManager.displayPipeline.findIndex((item) => {
|
||||
return item.handler === this._handler;
|
||||
});
|
||||
|
||||
if(lookupIndex > -1){
|
||||
index = lookupIndex;
|
||||
}
|
||||
}
|
||||
|
||||
if(adjust){
|
||||
index = index + adjust;
|
||||
}
|
||||
|
||||
if(this._handler){
|
||||
if(index > -1){
|
||||
return this.table.rowManager.getDisplayRows(index);
|
||||
}else{
|
||||
return this.activeRows();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
activeRows(){
|
||||
return this.table.rowManager.activeRows;
|
||||
}
|
||||
|
||||
refreshData(renderInPosition, handler){
|
||||
if(!handler){
|
||||
handler = this._handler;
|
||||
}
|
||||
|
||||
if(handler){
|
||||
this.table.rowManager.refreshActiveData(handler, false, renderInPosition);
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////
|
||||
//////// Footer Management ////////
|
||||
///////////////////////////////////
|
||||
|
||||
footerAppend(element){
|
||||
return this.table.footerManager.append(element);
|
||||
}
|
||||
|
||||
footerPrepend(element){
|
||||
return this.table.footerManager.prepend(element);
|
||||
}
|
||||
|
||||
footerRemove(element){
|
||||
return this.table.footerManager.remove(element);
|
||||
}
|
||||
|
||||
///////////////////////////////////
|
||||
//////// Popups Management ////////
|
||||
///////////////////////////////////
|
||||
|
||||
popup(menuEl, menuContainer){
|
||||
return new Popup(this.table, menuEl, menuContainer);
|
||||
}
|
||||
|
||||
///////////////////////////////////
|
||||
//////// Alert Management ////////
|
||||
///////////////////////////////////
|
||||
|
||||
alert(content, type){
|
||||
return this.table.alertManager.alert(content, type);
|
||||
}
|
||||
|
||||
clearAlert(){
|
||||
return this.table.alertManager.clear();
|
||||
}
|
||||
|
||||
}
|
||||
1140
public/libs/tabulator-master/src/js/core/RowManager.js
Normal file
1140
public/libs/tabulator-master/src/js/core/RowManager.js
Normal file
File diff suppressed because it is too large
Load Diff
928
public/libs/tabulator-master/src/js/core/Tabulator.js
Normal file
928
public/libs/tabulator-master/src/js/core/Tabulator.js
Normal file
@@ -0,0 +1,928 @@
|
||||
'use strict';
|
||||
|
||||
import defaultOptions from './defaults/options.js';
|
||||
|
||||
import ColumnManager from './ColumnManager.js';
|
||||
import RowManager from './RowManager.js';
|
||||
import FooterManager from './FooterManager.js';
|
||||
|
||||
import InteractionMonitor from './tools/InteractionMonitor.js';
|
||||
import ComponentFunctionBinder from './tools/ComponentFunctionBinder.js';
|
||||
import DataLoader from './tools/DataLoader.js';
|
||||
|
||||
import ExternalEventBus from './tools/ExternalEventBus.js';
|
||||
import InternalEventBus from './tools/InternalEventBus.js';
|
||||
|
||||
import DeprecationAdvisor from './tools/DeprecationAdvisor.js';
|
||||
import DependencyRegistry from './tools/DependencyRegistry.js';
|
||||
|
||||
import ModuleBinder from './tools/ModuleBinder.js';
|
||||
|
||||
import OptionsList from './tools/OptionsList.js';
|
||||
|
||||
import Alert from './tools/Alert.js';
|
||||
|
||||
class Tabulator extends ModuleBinder{
|
||||
|
||||
//default setup options
|
||||
static defaultOptions = defaultOptions;
|
||||
|
||||
static extendModule(){
|
||||
Tabulator.initializeModuleBinder();
|
||||
Tabulator._extendModule(...arguments);
|
||||
}
|
||||
|
||||
static registerModule(){
|
||||
Tabulator.initializeModuleBinder();
|
||||
Tabulator._registerModule(...arguments);
|
||||
}
|
||||
|
||||
constructor(element, options, modules){
|
||||
super();
|
||||
|
||||
Tabulator.initializeModuleBinder(modules);
|
||||
|
||||
this.options = {};
|
||||
|
||||
this.columnManager = null; // hold Column Manager
|
||||
this.rowManager = null; //hold Row Manager
|
||||
this.footerManager = null; //holder Footer Manager
|
||||
this.alertManager = null; //hold Alert Manager
|
||||
this.vdomHoz = null; //holder horizontal virtual dom
|
||||
this.externalEvents = null; //handle external event messaging
|
||||
this.eventBus = null; //handle internal event messaging
|
||||
this.interactionMonitor = false; //track user interaction
|
||||
this.browser = ""; //hold current browser type
|
||||
this.browserSlow = false; //handle reduced functionality for slower browsers
|
||||
this.browserMobile = false; //check if running on mobile, prevent resize cancelling edit on keyboard appearance
|
||||
this.rtl = false; //check if the table is in RTL mode
|
||||
this.originalElement = null; //hold original table element if it has been replaced
|
||||
|
||||
this.componentFunctionBinder = new ComponentFunctionBinder(this); //bind component functions
|
||||
this.dataLoader = false; //bind component functions
|
||||
|
||||
this.modules = {}; //hold all modules bound to this table
|
||||
this.modulesCore = []; //hold core modules bound to this table (for initialization purposes)
|
||||
this.modulesRegular = []; //hold regular modules bound to this table (for initialization purposes)
|
||||
|
||||
this.deprecationAdvisor = new DeprecationAdvisor(this);
|
||||
this.optionsList = new OptionsList(this, "table constructor");
|
||||
|
||||
this.dependencyRegistry = new DependencyRegistry(this);
|
||||
|
||||
this.initialized = false;
|
||||
this.destroyed = false;
|
||||
|
||||
if(this.initializeElement(element)){
|
||||
|
||||
this.initializeCoreSystems(options);
|
||||
|
||||
//delay table creation to allow event bindings immediately after the constructor
|
||||
setTimeout(() => {
|
||||
this._create();
|
||||
});
|
||||
}
|
||||
|
||||
this.constructor.registry.register(this); //register table for inter-device communication
|
||||
}
|
||||
|
||||
initializeElement(element){
|
||||
if(typeof HTMLElement !== "undefined" && element instanceof HTMLElement){
|
||||
this.element = element;
|
||||
return true;
|
||||
}else if(typeof element === "string"){
|
||||
this.element = document.querySelector(element);
|
||||
|
||||
if(this.element){
|
||||
return true;
|
||||
}else{
|
||||
console.error("Tabulator Creation Error - no element found matching selector: ", element);
|
||||
return false;
|
||||
}
|
||||
}else{
|
||||
console.error("Tabulator Creation Error - Invalid element provided:", element);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
initializeCoreSystems(options){
|
||||
this.columnManager = new ColumnManager(this);
|
||||
this.rowManager = new RowManager(this);
|
||||
this.footerManager = new FooterManager(this);
|
||||
this.dataLoader = new DataLoader(this);
|
||||
this.alertManager = new Alert(this);
|
||||
|
||||
this._bindModules();
|
||||
|
||||
this.options = this.optionsList.generate(Tabulator.defaultOptions, options);
|
||||
|
||||
this._clearObjectPointers();
|
||||
|
||||
this._mapDeprecatedFunctionality();
|
||||
|
||||
this.externalEvents = new ExternalEventBus(this, this.options, this.options.debugEventsExternal);
|
||||
this.eventBus = new InternalEventBus(this.options.debugEventsInternal);
|
||||
|
||||
this.interactionMonitor = new InteractionMonitor(this);
|
||||
|
||||
this.dataLoader.initialize();
|
||||
this.footerManager.initialize();
|
||||
|
||||
this.dependencyRegistry.initialize();
|
||||
}
|
||||
|
||||
//convert deprecated functionality to new functions
|
||||
_mapDeprecatedFunctionality(){
|
||||
//all previously deprecated functionality removed in the 6.0 release
|
||||
}
|
||||
|
||||
_clearSelection(){
|
||||
|
||||
this.element.classList.add("tabulator-block-select");
|
||||
|
||||
if (window.getSelection) {
|
||||
if (window.getSelection().empty) { // Chrome
|
||||
window.getSelection().empty();
|
||||
} else if (window.getSelection().removeAllRanges) { // Firefox
|
||||
window.getSelection().removeAllRanges();
|
||||
}
|
||||
} else if (document.selection) { // IE?
|
||||
document.selection.empty();
|
||||
}
|
||||
|
||||
this.element.classList.remove("tabulator-block-select");
|
||||
}
|
||||
|
||||
//create table
|
||||
_create(){
|
||||
this.externalEvents.dispatch("tableBuilding");
|
||||
this.eventBus.dispatch("table-building");
|
||||
|
||||
this._rtlCheck();
|
||||
|
||||
this._buildElement();
|
||||
|
||||
this._initializeTable();
|
||||
|
||||
this.initialized = true;
|
||||
|
||||
this._loadInitialData()
|
||||
.finally(() => {
|
||||
this.eventBus.dispatch("table-initialized");
|
||||
this.externalEvents.dispatch("tableBuilt");
|
||||
});
|
||||
}
|
||||
|
||||
_rtlCheck(){
|
||||
var style = window.getComputedStyle(this.element);
|
||||
|
||||
switch(this.options.textDirection){
|
||||
case"auto":
|
||||
if(style.direction !== "rtl"){
|
||||
break;
|
||||
}
|
||||
|
||||
case "rtl":
|
||||
this.element.classList.add("tabulator-rtl");
|
||||
this.rtl = true;
|
||||
break;
|
||||
|
||||
case "ltr":
|
||||
this.element.classList.add("tabulator-ltr");
|
||||
|
||||
default:
|
||||
this.rtl = false;
|
||||
}
|
||||
}
|
||||
|
||||
//clear pointers to objects in default config object
|
||||
_clearObjectPointers(){
|
||||
this.options.columns = this.options.columns.slice(0);
|
||||
|
||||
if(Array.isArray(this.options.data) && !this.options.reactiveData){
|
||||
this.options.data = this.options.data.slice(0);
|
||||
}
|
||||
}
|
||||
|
||||
//build tabulator element
|
||||
_buildElement(){
|
||||
var element = this.element,
|
||||
options = this.options,
|
||||
newElement;
|
||||
|
||||
if(element.tagName === "TABLE"){
|
||||
this.originalElement = this.element;
|
||||
newElement = document.createElement("div");
|
||||
|
||||
//transfer attributes to new element
|
||||
var attributes = element.attributes;
|
||||
|
||||
// loop through attributes and apply them on div
|
||||
for(var i in attributes){
|
||||
if(typeof attributes[i] == "object"){
|
||||
newElement.setAttribute(attributes[i].name, attributes[i].value);
|
||||
}
|
||||
}
|
||||
|
||||
// replace table with div element
|
||||
element.parentNode.replaceChild(newElement, element);
|
||||
|
||||
this.element = element = newElement;
|
||||
}
|
||||
|
||||
element.classList.add("tabulator");
|
||||
element.setAttribute("role", "grid");
|
||||
element.setAttribute("aria-owns", "tabulator-table-body");
|
||||
|
||||
//empty element
|
||||
while(element.firstChild) element.removeChild(element.firstChild);
|
||||
|
||||
//set table height
|
||||
if(options.height){
|
||||
options.height = isNaN(options.height) ? options.height : options.height + "px";
|
||||
element.style.height = options.height;
|
||||
}
|
||||
|
||||
//set table min height
|
||||
if(options.minHeight !== false){
|
||||
options.minHeight = isNaN(options.minHeight) ? options.minHeight : options.minHeight + "px";
|
||||
element.style.minHeight = options.minHeight;
|
||||
}
|
||||
|
||||
//set table maxHeight
|
||||
if(options.maxHeight !== false){
|
||||
options.maxHeight = isNaN(options.maxHeight) ? options.maxHeight : options.maxHeight + "px";
|
||||
element.style.maxHeight = options.maxHeight;
|
||||
}
|
||||
}
|
||||
|
||||
//initialize core systems and modules
|
||||
_initializeTable(){
|
||||
var element = this.element,
|
||||
options = this.options;
|
||||
|
||||
this.interactionMonitor.initialize();
|
||||
|
||||
this.columnManager.initialize();
|
||||
this.rowManager.initialize();
|
||||
|
||||
this._detectBrowser();
|
||||
|
||||
//initialize core modules
|
||||
this.modulesCore.forEach((mod) => {
|
||||
mod.initialize();
|
||||
});
|
||||
|
||||
//build table elements
|
||||
element.appendChild(this.columnManager.getElement());
|
||||
element.appendChild(this.rowManager.getElement());
|
||||
|
||||
if(options.footerElement){
|
||||
this.footerManager.activate();
|
||||
}
|
||||
|
||||
if(options.autoColumns && options.data){
|
||||
|
||||
this.columnManager.generateColumnsFromRowData(this.options.data);
|
||||
}
|
||||
|
||||
//initialize regular modules
|
||||
this.modulesRegular.forEach((mod) => {
|
||||
mod.initialize();
|
||||
});
|
||||
|
||||
this.columnManager.setColumns(options.columns);
|
||||
|
||||
this.eventBus.dispatch("table-built");
|
||||
}
|
||||
|
||||
_loadInitialData(){
|
||||
return this.dataLoader.load(this.options.data)
|
||||
.finally(() => {
|
||||
this.columnManager.verticalAlignHeaders();
|
||||
});
|
||||
}
|
||||
|
||||
//deconstructor
|
||||
destroy(){
|
||||
var element = this.element;
|
||||
|
||||
this.destroyed = true;
|
||||
|
||||
this.constructor.registry.deregister(this); //deregister table from inter-device communication
|
||||
|
||||
this.eventBus.dispatch("table-destroy");
|
||||
|
||||
//clear row data
|
||||
this.rowManager.destroy();
|
||||
|
||||
//clear DOM
|
||||
while(element.firstChild) element.removeChild(element.firstChild);
|
||||
element.classList.remove("tabulator");
|
||||
element.removeAttribute("tabulator-layout");
|
||||
|
||||
this.externalEvents.dispatch("tableDestroyed");
|
||||
}
|
||||
|
||||
_detectBrowser(){
|
||||
var ua = navigator.userAgent||navigator.vendor||window.opera;
|
||||
|
||||
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 if(ua.indexOf("Mac OS") > -1){
|
||||
this.browser = "safari";
|
||||
this.browserSlow = false;
|
||||
}else{
|
||||
this.browser = "other";
|
||||
this.browserSlow = false;
|
||||
}
|
||||
|
||||
this.browserMobile = /(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino|android|ipad|playbook|silk/i.test(ua)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw-(n|u)|c55\/|capi|ccwa|cdm-|cell|chtm|cldc|cmd-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc-s|devi|dica|dmob|do(c|p)o|ds(12|-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(-|_)|g1 u|g560|gene|gf-5|g-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd-(m|p|t)|hei-|hi(pt|ta)|hp( i|ip)|hs-c|ht(c(-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i-(20|go|ma)|i230|iac( |-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|-[a-w])|libw|lynx|m1-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|-([1-8]|c))|phil|pire|pl(ay|uc)|pn-2|po(ck|rt|se)|prox|psio|pt-g|qa-a|qc(07|12|21|32|60|-[2-7]|i-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h-|oo|p-)|sdk\/|se(c(-|0|1)|47|mc|nd|ri)|sgh-|shar|sie(-|m)|sk-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h-|v-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl-|tdg-|tel(i|m)|tim-|t-mo|to(pl|sh)|ts(70|m-|m3|m5)|tx-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas-|your|zeto|zte-/i.test(ua.slice(0,4));
|
||||
}
|
||||
|
||||
initGuard(func, msg){
|
||||
var stack, line;
|
||||
|
||||
if(this.options.debugInitialization && !this.initialized){
|
||||
if(!func){
|
||||
stack = new Error().stack.split("\n");
|
||||
|
||||
line = stack[0] == "Error" ? stack[2] : stack[1];
|
||||
|
||||
if(line[0] == " "){
|
||||
func = line.trim().split(" ")[1].split(".")[1];
|
||||
}else{
|
||||
func = line.trim().split("@")[0];
|
||||
}
|
||||
}
|
||||
|
||||
console.warn("Table Not Initialized - Calling the " + func + " function before the table is initialized may result in inconsistent behavior, Please wait for the `tableBuilt` event before calling this function." + (msg ? " " + msg : ""));
|
||||
}
|
||||
|
||||
return this.initialized;
|
||||
}
|
||||
|
||||
////////////////// Data Handling //////////////////
|
||||
//block table redrawing
|
||||
blockRedraw(){
|
||||
this.initGuard();
|
||||
|
||||
this.eventBus.dispatch("redraw-blocking");
|
||||
|
||||
this.rowManager.blockRedraw();
|
||||
this.columnManager.blockRedraw();
|
||||
|
||||
this.eventBus.dispatch("redraw-blocked");
|
||||
}
|
||||
|
||||
//restore table redrawing
|
||||
restoreRedraw(){
|
||||
this.initGuard();
|
||||
|
||||
this.eventBus.dispatch("redraw-restoring");
|
||||
|
||||
this.rowManager.restoreRedraw();
|
||||
this.columnManager.restoreRedraw();
|
||||
|
||||
this.eventBus.dispatch("redraw-restored");
|
||||
}
|
||||
|
||||
//load data
|
||||
setData(data, params, config){
|
||||
this.initGuard(false, "To set initial data please use the 'data' property in the table constructor.");
|
||||
|
||||
return this.dataLoader.load(data, params, config, false);
|
||||
}
|
||||
|
||||
//clear data
|
||||
clearData(){
|
||||
this.initGuard();
|
||||
|
||||
this.dataLoader.blockActiveLoad();
|
||||
this.rowManager.clearData();
|
||||
}
|
||||
|
||||
//get table data array
|
||||
getData(active){
|
||||
return this.rowManager.getData(active);
|
||||
}
|
||||
|
||||
//get table data array count
|
||||
getDataCount(active){
|
||||
return this.rowManager.getDataCount(active);
|
||||
}
|
||||
|
||||
//replace data, keeping table in position with same sort
|
||||
replaceData(data, params, config){
|
||||
this.initGuard();
|
||||
|
||||
return this.dataLoader.load(data, params, config, true, true);
|
||||
}
|
||||
|
||||
//update table data
|
||||
updateData(data){
|
||||
var responses = 0;
|
||||
|
||||
this.initGuard();
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
this.dataLoader.blockActiveLoad();
|
||||
|
||||
if(typeof data === "string"){
|
||||
data = JSON.parse(data);
|
||||
}
|
||||
|
||||
if(data && data.length > 0){
|
||||
data.forEach((item) => {
|
||||
var row = this.rowManager.findRow(item[this.options.index]);
|
||||
|
||||
if(row){
|
||||
responses++;
|
||||
|
||||
row.updateData(item)
|
||||
.then(()=>{
|
||||
responses--;
|
||||
|
||||
if(!responses){
|
||||
resolve();
|
||||
}
|
||||
})
|
||||
.catch((e) => {
|
||||
reject("Update Error - Unable to update row", item, e);
|
||||
});
|
||||
}else{
|
||||
reject("Update Error - Unable to find row", item);
|
||||
}
|
||||
});
|
||||
}else{
|
||||
console.warn("Update Error - No data provided");
|
||||
reject("Update Error - No data provided");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
addData(data, pos, index){
|
||||
this.initGuard();
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
this.dataLoader.blockActiveLoad();
|
||||
|
||||
if(typeof data === "string"){
|
||||
data = JSON.parse(data);
|
||||
}
|
||||
|
||||
if(data){
|
||||
this.rowManager.addRows(data, pos, index)
|
||||
.then((rows) => {
|
||||
var output = [];
|
||||
|
||||
rows.forEach(function(row){
|
||||
output.push(row.getComponent());
|
||||
});
|
||||
|
||||
resolve(output);
|
||||
});
|
||||
}else{
|
||||
console.warn("Update Error - No data provided");
|
||||
reject("Update Error - No data provided");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//update table data
|
||||
updateOrAddData(data){
|
||||
var rows = [],
|
||||
responses = 0;
|
||||
|
||||
this.initGuard();
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
this.dataLoader.blockActiveLoad();
|
||||
|
||||
if(typeof data === "string"){
|
||||
data = JSON.parse(data);
|
||||
}
|
||||
|
||||
if(data && data.length > 0){
|
||||
data.forEach((item) => {
|
||||
var row = this.rowManager.findRow(item[this.options.index]);
|
||||
|
||||
responses++;
|
||||
|
||||
if(row){
|
||||
row.updateData(item)
|
||||
.then(()=>{
|
||||
responses--;
|
||||
rows.push(row.getComponent());
|
||||
|
||||
if(!responses){
|
||||
resolve(rows);
|
||||
}
|
||||
});
|
||||
}else{
|
||||
this.rowManager.addRows(item)
|
||||
.then((newRows)=>{
|
||||
responses--;
|
||||
rows.push(newRows[0].getComponent());
|
||||
|
||||
if(!responses){
|
||||
resolve(rows);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}else{
|
||||
console.warn("Update Error - No data provided");
|
||||
reject("Update Error - No data provided");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//get row object
|
||||
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(position){
|
||||
var row = this.rowManager.getRowFromPosition(position);
|
||||
|
||||
if(row){
|
||||
return row.getComponent();
|
||||
}else{
|
||||
console.warn("Find Error - No matching row found:", position);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//delete row from table
|
||||
deleteRow(index){
|
||||
var foundRows = [];
|
||||
|
||||
this.initGuard();
|
||||
|
||||
if(!Array.isArray(index)){
|
||||
index = [index];
|
||||
}
|
||||
|
||||
//find matching rows
|
||||
for(let item of index){
|
||||
let row = this.rowManager.findRow(item, true);
|
||||
|
||||
if(row){
|
||||
foundRows.push(row);
|
||||
}else{
|
||||
console.error("Delete Error - No matching row found:", item);
|
||||
return Promise.reject("Delete Error - No matching row found");
|
||||
}
|
||||
}
|
||||
|
||||
//sort rows into correct order to ensure smooth delete from table
|
||||
foundRows.sort((a, b) => {
|
||||
return this.rowManager.rows.indexOf(a) > this.rowManager.rows.indexOf(b) ? 1 : -1;
|
||||
});
|
||||
|
||||
//delete rows
|
||||
foundRows.forEach((row) =>{
|
||||
row.delete();
|
||||
});
|
||||
|
||||
this.rowManager.reRenderInPosition();
|
||||
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
//add row to table
|
||||
addRow(data, pos, index){
|
||||
this.initGuard();
|
||||
|
||||
if(typeof data === "string"){
|
||||
data = JSON.parse(data);
|
||||
}
|
||||
|
||||
return this.rowManager.addRows(data, pos, index, true)
|
||||
.then((rows)=>{
|
||||
return rows[0].getComponent();
|
||||
});
|
||||
}
|
||||
|
||||
//update a row if it exists otherwise create it
|
||||
updateOrAddRow(index, data){
|
||||
var row = this.rowManager.findRow(index);
|
||||
|
||||
this.initGuard();
|
||||
|
||||
if(typeof data === "string"){
|
||||
data = JSON.parse(data);
|
||||
}
|
||||
|
||||
if(row){
|
||||
return row.updateData(data)
|
||||
.then(()=>{
|
||||
return row.getComponent();
|
||||
});
|
||||
}else{
|
||||
return this.rowManager.addRows(data)
|
||||
.then((rows)=>{
|
||||
return rows[0].getComponent();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
//update row data
|
||||
updateRow(index, data){
|
||||
var row = this.rowManager.findRow(index);
|
||||
|
||||
this.initGuard();
|
||||
|
||||
if(typeof data === "string"){
|
||||
data = JSON.parse(data);
|
||||
}
|
||||
|
||||
if(row){
|
||||
return row.updateData(data)
|
||||
.then(()=>{
|
||||
return Promise.resolve(row.getComponent());
|
||||
});
|
||||
}else{
|
||||
console.warn("Update Error - No matching row found:", index);
|
||||
return Promise.reject("Update Error - No matching row found");
|
||||
}
|
||||
}
|
||||
|
||||
//scroll to row in DOM
|
||||
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 Promise.reject("Scroll Error - No matching row found");
|
||||
}
|
||||
}
|
||||
|
||||
moveRow(from, to, after){
|
||||
var fromRow = this.rowManager.findRow(from);
|
||||
|
||||
this.initGuard();
|
||||
|
||||
if(fromRow){
|
||||
fromRow.moveToRow(to, after);
|
||||
}else{
|
||||
console.warn("Move Error - No matching row found:", from);
|
||||
}
|
||||
}
|
||||
|
||||
getRows(active){
|
||||
return this.rowManager.getComponents(active);
|
||||
}
|
||||
|
||||
//get position of row in table
|
||||
getRowPosition(index){
|
||||
var row = this.rowManager.findRow(index);
|
||||
|
||||
if(row){
|
||||
return row.getPosition();
|
||||
}else{
|
||||
console.warn("Position Error - No matching row found:", index);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/////////////// Column Functions ///////////////
|
||||
setColumns(definition){
|
||||
this.initGuard(false, "To set initial columns please use the 'columns' property in the table constructor");
|
||||
|
||||
this.columnManager.setColumns(definition);
|
||||
}
|
||||
|
||||
getColumns(structured){
|
||||
return this.columnManager.getComponents(structured);
|
||||
}
|
||||
|
||||
getColumn(field){
|
||||
var column = this.columnManager.findColumn(field);
|
||||
|
||||
if(column){
|
||||
return column.getComponent();
|
||||
}else{
|
||||
console.warn("Find Error - No matching column found:", field);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
getColumnDefinitions(){
|
||||
return this.columnManager.getDefinitionTree();
|
||||
}
|
||||
|
||||
showColumn(field){
|
||||
var column = this.columnManager.findColumn(field);
|
||||
|
||||
this.initGuard();
|
||||
|
||||
if(column){
|
||||
column.show();
|
||||
}else{
|
||||
console.warn("Column Show Error - No matching column found:", field);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
hideColumn(field){
|
||||
var column = this.columnManager.findColumn(field);
|
||||
|
||||
this.initGuard();
|
||||
|
||||
if(column){
|
||||
column.hide();
|
||||
}else{
|
||||
console.warn("Column Hide Error - No matching column found:", field);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
toggleColumn(field){
|
||||
var column = this.columnManager.findColumn(field);
|
||||
|
||||
this.initGuard();
|
||||
|
||||
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(definition, before, field){
|
||||
var column = this.columnManager.findColumn(field);
|
||||
|
||||
this.initGuard();
|
||||
|
||||
return this.columnManager.addColumn(definition, before, column)
|
||||
.then((column) => {
|
||||
return column.getComponent();
|
||||
});
|
||||
}
|
||||
|
||||
deleteColumn(field){
|
||||
var column = this.columnManager.findColumn(field);
|
||||
|
||||
this.initGuard();
|
||||
|
||||
if(column){
|
||||
return column.delete();
|
||||
}else{
|
||||
console.warn("Column Delete Error - No matching column found:", field);
|
||||
return Promise.reject();
|
||||
}
|
||||
}
|
||||
|
||||
updateColumnDefinition(field, definition){
|
||||
var column = this.columnManager.findColumn(field);
|
||||
|
||||
this.initGuard();
|
||||
|
||||
if(column){
|
||||
return column.updateDefinition(definition);
|
||||
}else{
|
||||
console.warn("Column Update Error - No matching column found:", field);
|
||||
return Promise.reject();
|
||||
}
|
||||
}
|
||||
|
||||
moveColumn(from, to, after){
|
||||
var fromColumn = this.columnManager.findColumn(from),
|
||||
toColumn = this.columnManager.findColumn(to);
|
||||
|
||||
this.initGuard();
|
||||
|
||||
if(fromColumn){
|
||||
if(toColumn){
|
||||
this.columnManager.moveColumn(fromColumn, toColumn, after);
|
||||
}else{
|
||||
console.warn("Move Error - No matching column found:", toColumn);
|
||||
}
|
||||
}else{
|
||||
console.warn("Move Error - No matching column found:", from);
|
||||
}
|
||||
}
|
||||
|
||||
//scroll to column in DOM
|
||||
scrollToColumn(field, position, ifVisible){
|
||||
return new Promise((resolve, reject) => {
|
||||
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 Promise.reject("Scroll Error - No matching column found");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//////////// General Public Functions ////////////
|
||||
//redraw list without updating data
|
||||
redraw(force){
|
||||
this.initGuard();
|
||||
|
||||
this.columnManager.redraw(force);
|
||||
this.rowManager.redraw(force);
|
||||
}
|
||||
|
||||
setHeight(height){
|
||||
this.options.height = isNaN(height) ? height : height + "px";
|
||||
this.element.style.height = this.options.height;
|
||||
this.rowManager.initializeRenderer();
|
||||
this.rowManager.redraw(true);
|
||||
}
|
||||
|
||||
setMaxHeight(maxHeight){
|
||||
this.options.maxHeight = isNaN(maxHeight) ? maxHeight : maxHeight + "px";
|
||||
this.element.style.maxHeight = this.options.maxHeight;
|
||||
this.rowManager.initializeRenderer();
|
||||
this.rowManager.redraw(true);
|
||||
}
|
||||
|
||||
setMinHeight(minHeight){
|
||||
this.options.minHeight = isNaN(minHeight) ? minHeight : minHeight + "px";
|
||||
this.element.style.minHeight = this.options.minHeight;
|
||||
this.rowManager.initializeRenderer();
|
||||
this.rowManager.redraw(true);
|
||||
}
|
||||
|
||||
//////////////////// Event Bus ///////////////////
|
||||
|
||||
on(key, callback){
|
||||
this.externalEvents.subscribe(key, callback);
|
||||
}
|
||||
|
||||
off(key, callback){
|
||||
this.externalEvents.unsubscribe(key, callback);
|
||||
}
|
||||
|
||||
dispatchEvent(){
|
||||
var args = Array.from(arguments);
|
||||
args.shift();
|
||||
|
||||
this.externalEvents.dispatch(...arguments);
|
||||
}
|
||||
|
||||
//////////////////// Alerts ///////////////////
|
||||
|
||||
alert(contents, type){
|
||||
this.initGuard();
|
||||
|
||||
this.alertManager.alert(contents, type);
|
||||
}
|
||||
|
||||
clearAlert(){
|
||||
this.initGuard();
|
||||
|
||||
this.alertManager.clear();
|
||||
}
|
||||
|
||||
////////////// Extension Management //////////////
|
||||
modExists(plugin, required){
|
||||
if(this.modules[plugin]){
|
||||
return true;
|
||||
}else{
|
||||
if(required){
|
||||
console.error("Tabulator Module Not Installed: " + plugin);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
module(key){
|
||||
var mod = this.modules[key];
|
||||
|
||||
if(!mod){
|
||||
console.error("Tabulator module not installed: " + key);
|
||||
}
|
||||
|
||||
return mod;
|
||||
}
|
||||
}
|
||||
|
||||
export default Tabulator;
|
||||
21
public/libs/tabulator-master/src/js/core/TabulatorFull.js
Normal file
21
public/libs/tabulator-master/src/js/core/TabulatorFull.js
Normal file
@@ -0,0 +1,21 @@
|
||||
//tabulator with all modules installed
|
||||
import {default as Tabulator} from './Tabulator.js';
|
||||
import * as allModules from '../core/modules/optional.js';
|
||||
|
||||
class TabulatorFull extends Tabulator {
|
||||
static extendModule(){
|
||||
Tabulator.initializeModuleBinder(allModules);
|
||||
Tabulator._extendModule(...arguments);
|
||||
}
|
||||
|
||||
static registerModule(){
|
||||
Tabulator.initializeModuleBinder(allModules);
|
||||
Tabulator._registerModule(...arguments);
|
||||
}
|
||||
|
||||
constructor(element, options, modules){
|
||||
super(element, options, allModules);
|
||||
}
|
||||
}
|
||||
|
||||
export default TabulatorFull;
|
||||
299
public/libs/tabulator-master/src/js/core/cell/Cell.js
Normal file
299
public/libs/tabulator-master/src/js/core/cell/Cell.js
Normal file
@@ -0,0 +1,299 @@
|
||||
import CoreFeature from '../CoreFeature.js';
|
||||
import CellComponent from './CellComponent.js';
|
||||
|
||||
export default class Cell extends CoreFeature{
|
||||
constructor(column, row){
|
||||
super(column.table);
|
||||
|
||||
this.table = column.table;
|
||||
this.column = column;
|
||||
this.row = row;
|
||||
this.element = null;
|
||||
this.value = null;
|
||||
this.initialValue;
|
||||
this.oldValue = null;
|
||||
this.modules = {};
|
||||
|
||||
this.height = null;
|
||||
this.width = null;
|
||||
this.minWidth = null;
|
||||
|
||||
this.component = null;
|
||||
|
||||
this.loaded = false; //track if the cell has been added to the DOM yet
|
||||
|
||||
this.build();
|
||||
}
|
||||
|
||||
//////////////// Setup Functions /////////////////
|
||||
//generate element
|
||||
build(){
|
||||
this.generateElement();
|
||||
|
||||
this.setWidth();
|
||||
|
||||
this._configureCell();
|
||||
|
||||
this.setValueActual(this.column.getFieldValue(this.row.data));
|
||||
|
||||
this.initialValue = this.value;
|
||||
}
|
||||
|
||||
generateElement(){
|
||||
this.element = document.createElement('div');
|
||||
this.element.className = "tabulator-cell";
|
||||
this.element.setAttribute("role", "gridcell");
|
||||
|
||||
if(this.column.isRowHeader){
|
||||
this.element.classList.add("tabulator-row-header");
|
||||
}
|
||||
}
|
||||
|
||||
_configureCell(){
|
||||
var element = this.element,
|
||||
field = this.column.getField(),
|
||||
vertAligns = {
|
||||
top:"flex-start",
|
||||
bottom:"flex-end",
|
||||
middle:"center",
|
||||
},
|
||||
hozAligns = {
|
||||
left:"flex-start",
|
||||
right:"flex-end",
|
||||
center:"center",
|
||||
};
|
||||
|
||||
//set text alignment
|
||||
element.style.textAlign = this.column.hozAlign;
|
||||
|
||||
if(this.column.vertAlign){
|
||||
element.style.display = "inline-flex";
|
||||
|
||||
element.style.alignItems = vertAligns[this.column.vertAlign] || "";
|
||||
|
||||
if(this.column.hozAlign){
|
||||
element.style.justifyContent = hozAligns[this.column.hozAlign] || "";
|
||||
}
|
||||
}
|
||||
|
||||
if(field){
|
||||
element.setAttribute("tabulator-field", field);
|
||||
}
|
||||
|
||||
//add class to cell if needed
|
||||
if(this.column.definition.cssClass){
|
||||
var classNames = this.column.definition.cssClass.split(" ");
|
||||
classNames.forEach((className) => {
|
||||
element.classList.add(className);
|
||||
});
|
||||
}
|
||||
|
||||
this.dispatch("cell-init", this);
|
||||
|
||||
//hide cell if not visible
|
||||
if(!this.column.visible){
|
||||
this.hide();
|
||||
}
|
||||
}
|
||||
|
||||
//generate cell contents
|
||||
_generateContents(){
|
||||
var val;
|
||||
|
||||
val = this.chain("cell-format", this, null, () => {
|
||||
return this.element.innerHTML = this.value;
|
||||
});
|
||||
|
||||
switch(typeof val){
|
||||
case "object":
|
||||
if(val instanceof Node){
|
||||
|
||||
//clear previous cell contents
|
||||
while(this.element.firstChild) this.element.removeChild(this.element.firstChild);
|
||||
|
||||
this.element.appendChild(val);
|
||||
}else{
|
||||
this.element.innerHTML = "";
|
||||
|
||||
if(val != null){
|
||||
console.warn("Format Error - Formatter has returned a type of object, the only valid formatter object return is an instance of Node, the formatter returned:", val);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "undefined":
|
||||
this.element.innerHTML = "";
|
||||
break;
|
||||
default:
|
||||
this.element.innerHTML = val;
|
||||
}
|
||||
}
|
||||
|
||||
cellRendered(){
|
||||
this.dispatch("cell-rendered", this);
|
||||
}
|
||||
|
||||
//////////////////// Getters ////////////////////
|
||||
getElement(containerOnly){
|
||||
if(!this.loaded){
|
||||
this.loaded = true;
|
||||
if(!containerOnly){
|
||||
this.layoutElement();
|
||||
}
|
||||
}
|
||||
|
||||
return this.element;
|
||||
}
|
||||
|
||||
getValue(){
|
||||
return this.value;
|
||||
}
|
||||
|
||||
getOldValue(){
|
||||
return this.oldValue;
|
||||
}
|
||||
|
||||
//////////////////// Actions ////////////////////
|
||||
setValue(value, mutate, force){
|
||||
var changed = this.setValueProcessData(value, mutate, force);
|
||||
|
||||
if(changed){
|
||||
this.dispatch("cell-value-updated", this);
|
||||
|
||||
this.cellRendered();
|
||||
|
||||
if(this.column.definition.cellEdited){
|
||||
this.column.definition.cellEdited.call(this.table, this.getComponent());
|
||||
}
|
||||
|
||||
this.dispatchExternal("cellEdited", this.getComponent());
|
||||
|
||||
if(this.subscribedExternal("dataChanged")){
|
||||
this.dispatchExternal("dataChanged", this.table.rowManager.getData());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setValueProcessData(value, mutate, force){
|
||||
var changed = false;
|
||||
|
||||
if(this.value !== value || force){
|
||||
|
||||
changed = true;
|
||||
|
||||
if(mutate){
|
||||
value = this.chain("cell-value-changing", [this, value], null, value);
|
||||
}
|
||||
}
|
||||
|
||||
this.setValueActual(value);
|
||||
|
||||
if(changed){
|
||||
this.dispatch("cell-value-changed", this);
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
setValueActual(value){
|
||||
this.oldValue = this.value;
|
||||
|
||||
this.value = value;
|
||||
|
||||
this.dispatch("cell-value-save-before", this);
|
||||
|
||||
this.column.setFieldValue(this.row.data, value);
|
||||
|
||||
this.dispatch("cell-value-save-after", this);
|
||||
|
||||
if(this.loaded){
|
||||
this.layoutElement();
|
||||
}
|
||||
}
|
||||
|
||||
layoutElement(){
|
||||
this._generateContents();
|
||||
|
||||
this.dispatch("cell-layout", this);
|
||||
}
|
||||
|
||||
setWidth(){
|
||||
this.width = this.column.width;
|
||||
this.element.style.width = this.column.widthStyled;
|
||||
}
|
||||
|
||||
clearWidth(){
|
||||
this.width = "";
|
||||
this.element.style.width = "";
|
||||
}
|
||||
|
||||
getWidth(){
|
||||
return this.width || this.element.offsetWidth;
|
||||
}
|
||||
|
||||
setMinWidth(){
|
||||
this.minWidth = this.column.minWidth;
|
||||
this.element.style.minWidth = this.column.minWidthStyled;
|
||||
}
|
||||
|
||||
setMaxWidth(){
|
||||
this.maxWidth = this.column.maxWidth;
|
||||
this.element.style.maxWidth = this.column.maxWidthStyled;
|
||||
}
|
||||
|
||||
checkHeight(){
|
||||
// var height = this.element.css("height");
|
||||
this.row.reinitializeHeight();
|
||||
}
|
||||
|
||||
clearHeight(){
|
||||
this.element.style.height = "";
|
||||
this.height = null;
|
||||
|
||||
this.dispatch("cell-height", this, "");
|
||||
}
|
||||
|
||||
setHeight(){
|
||||
this.height = this.row.height;
|
||||
this.element.style.height = this.row.heightStyled;
|
||||
|
||||
this.dispatch("cell-height", this, this.row.heightStyled);
|
||||
}
|
||||
|
||||
getHeight(){
|
||||
return this.height || this.element.offsetHeight;
|
||||
}
|
||||
|
||||
show(){
|
||||
this.element.style.display = this.column.vertAlign ? "inline-flex" : "";
|
||||
}
|
||||
|
||||
hide(){
|
||||
this.element.style.display = "none";
|
||||
}
|
||||
|
||||
delete(){
|
||||
this.dispatch("cell-delete", this);
|
||||
|
||||
if(!this.table.rowManager.redrawBlock && this.element.parentNode){
|
||||
this.element.parentNode.removeChild(this.element);
|
||||
}
|
||||
|
||||
this.element = false;
|
||||
this.column.deleteCell(this);
|
||||
this.row.deleteCell(this);
|
||||
this.calcs = {};
|
||||
}
|
||||
|
||||
getIndex(){
|
||||
return this.row.getCellIndex(this);
|
||||
}
|
||||
|
||||
//////////////// Object Generation /////////////////
|
||||
getComponent(){
|
||||
if(!this.component){
|
||||
this.component = new CellComponent(this);
|
||||
}
|
||||
|
||||
return this.component;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
//public cell object
|
||||
export default class CellComponent {
|
||||
|
||||
constructor (cell){
|
||||
this._cell = cell;
|
||||
|
||||
return new Proxy(this, {
|
||||
get: function(target, name, receiver) {
|
||||
if (typeof target[name] !== "undefined") {
|
||||
return target[name];
|
||||
}else{
|
||||
return target._cell.table.componentFunctionBinder.handle("cell", target._cell, name);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
getValue(){
|
||||
return this._cell.getValue();
|
||||
}
|
||||
|
||||
getOldValue(){
|
||||
return this._cell.getOldValue();
|
||||
}
|
||||
|
||||
getInitialValue(){
|
||||
return this._cell.initialValue;
|
||||
}
|
||||
|
||||
getElement(){
|
||||
return this._cell.getElement();
|
||||
}
|
||||
|
||||
getRow(){
|
||||
return this._cell.row.getComponent();
|
||||
}
|
||||
|
||||
getData(transform){
|
||||
return this._cell.row.getData(transform);
|
||||
}
|
||||
getType(){
|
||||
return "cell";
|
||||
}
|
||||
getField(){
|
||||
return this._cell.column.getField();
|
||||
}
|
||||
|
||||
getColumn(){
|
||||
return this._cell.column.getComponent();
|
||||
}
|
||||
|
||||
setValue(value, mutate){
|
||||
if(typeof mutate == "undefined"){
|
||||
mutate = true;
|
||||
}
|
||||
|
||||
this._cell.setValue(value, mutate);
|
||||
}
|
||||
|
||||
restoreOldValue(){
|
||||
this._cell.setValueActual(this._cell.getOldValue());
|
||||
}
|
||||
|
||||
restoreInitialValue(){
|
||||
this._cell.setValueActual(this._cell.initialValue);
|
||||
}
|
||||
|
||||
checkHeight(){
|
||||
this._cell.checkHeight();
|
||||
}
|
||||
|
||||
getTable(){
|
||||
return this._cell.table;
|
||||
}
|
||||
|
||||
_getSelf(){
|
||||
return this._cell;
|
||||
}
|
||||
}
|
||||
978
public/libs/tabulator-master/src/js/core/column/Column.js
Normal file
978
public/libs/tabulator-master/src/js/core/column/Column.js
Normal file
@@ -0,0 +1,978 @@
|
||||
import CoreFeature from '../CoreFeature.js';
|
||||
import ColumnComponent from './ColumnComponent.js';
|
||||
import defaultOptions from './defaults/options.js';
|
||||
|
||||
import Cell from '../cell/Cell.js';
|
||||
|
||||
export default class Column extends CoreFeature{
|
||||
|
||||
static defaultOptionList = defaultOptions;
|
||||
|
||||
constructor(def, parent, rowHeader){
|
||||
super(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.isGroup = false;
|
||||
this.isRowHeader = rowHeader;
|
||||
this.element = this.createElement(); //column header element
|
||||
this.contentElement = false;
|
||||
this.titleHolderElement = false;
|
||||
this.titleElement = false;
|
||||
this.groupElement = this.createGroupElement(); //column group holder element
|
||||
this.hozAlign = ""; //horizontal text alignment
|
||||
this.vertAlign = ""; //vert text alignment
|
||||
|
||||
//multi dimensional filed handling
|
||||
this.field ="";
|
||||
this.fieldStructure = "";
|
||||
this.getFieldValue = "";
|
||||
this.setFieldValue = "";
|
||||
|
||||
this.titleDownload = null;
|
||||
this.titleFormatterRendered = false;
|
||||
|
||||
this.mapDefinitions();
|
||||
|
||||
this.setField(this.definition.field);
|
||||
|
||||
this.modules = {}; //hold module variables;
|
||||
|
||||
this.width = null; //column width
|
||||
this.widthStyled = ""; //column width pre-styled to improve render efficiency
|
||||
this.maxWidth = null; //column maximum width
|
||||
this.maxWidthStyled = ""; //column maximum pre-styled to improve render efficiency
|
||||
this.maxInitialWidth = null;
|
||||
this.minWidth = null; //column minimum width
|
||||
this.minWidthStyled = ""; //column minimum pre-styled to improve render efficiency
|
||||
this.widthFixed = false; //user has specified a width for this column
|
||||
|
||||
this.visible = true; //default visible state
|
||||
|
||||
this.component = null;
|
||||
|
||||
//initialize column
|
||||
if(this.definition.columns){
|
||||
|
||||
this.isGroup = true;
|
||||
|
||||
this.definition.columns.forEach((def, i) => {
|
||||
var newCol = new Column(def, this);
|
||||
this.attachColumn(newCol);
|
||||
});
|
||||
|
||||
this.checkColumnVisibility();
|
||||
}else{
|
||||
parent.registerColumnField(this);
|
||||
}
|
||||
|
||||
this._initialize();
|
||||
}
|
||||
|
||||
createElement (){
|
||||
var el = document.createElement("div");
|
||||
|
||||
el.classList.add("tabulator-col");
|
||||
el.setAttribute("role", "columnheader");
|
||||
el.setAttribute("aria-sort", "none");
|
||||
|
||||
if(this.isRowHeader){
|
||||
el.classList.add("tabulator-row-header");
|
||||
}
|
||||
|
||||
switch(this.table.options.columnHeaderVertAlign){
|
||||
case "middle":
|
||||
el.style.justifyContent = "center";
|
||||
break;
|
||||
case "bottom":
|
||||
el.style.justifyContent = "flex-end";
|
||||
break;
|
||||
}
|
||||
|
||||
return el;
|
||||
}
|
||||
|
||||
createGroupElement (){
|
||||
var el = document.createElement("div");
|
||||
|
||||
el.classList.add("tabulator-col-group-cols");
|
||||
|
||||
return el;
|
||||
}
|
||||
|
||||
mapDefinitions(){
|
||||
var defaults = this.table.options.columnDefaults;
|
||||
|
||||
//map columnDefaults onto column definitions
|
||||
if(defaults){
|
||||
for(let key in defaults){
|
||||
if(typeof this.definition[key] === "undefined"){
|
||||
this.definition[key] = defaults[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.definition = this.table.columnManager.optionsList.generate(Column.defaultOptionList, this.definition);
|
||||
}
|
||||
|
||||
checkDefinition(){
|
||||
Object.keys(this.definition).forEach((key) => {
|
||||
if(Column.defaultOptionList.indexOf(key) === -1){
|
||||
console.warn("Invalid column definition option in '" + (this.field || this.definition.title) + "' column:", key);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
setField(field){
|
||||
this.field = field;
|
||||
this.fieldStructure = field ? (this.table.options.nestedFieldSeparator ? field.split(this.table.options.nestedFieldSeparator) : [field]) : [];
|
||||
this.getFieldValue = this.fieldStructure.length > 1 ? this._getNestedData : this._getFlatData;
|
||||
this.setFieldValue = this.fieldStructure.length > 1 ? this._setNestedData : this._setFlatData;
|
||||
}
|
||||
|
||||
//register column position with column manager
|
||||
registerColumnPosition(column){
|
||||
this.parent.registerColumnPosition(column);
|
||||
}
|
||||
|
||||
//register column position with column manager
|
||||
registerColumnField(column){
|
||||
this.parent.registerColumnField(column);
|
||||
}
|
||||
|
||||
//trigger position registration
|
||||
reRegisterPosition(){
|
||||
if(this.isGroup){
|
||||
this.columns.forEach(function(column){
|
||||
column.reRegisterPosition();
|
||||
});
|
||||
}else{
|
||||
this.registerColumnPosition(this);
|
||||
}
|
||||
}
|
||||
|
||||
//build header element
|
||||
_initialize(){
|
||||
var def = this.definition;
|
||||
|
||||
while(this.element.firstChild) this.element.removeChild(this.element.firstChild);
|
||||
|
||||
if(def.headerVertical){
|
||||
this.element.classList.add("tabulator-col-vertical");
|
||||
|
||||
if(def.headerVertical === "flip"){
|
||||
this.element.classList.add("tabulator-col-vertical-flip");
|
||||
}
|
||||
}
|
||||
|
||||
this.contentElement = this._buildColumnHeaderContent();
|
||||
|
||||
this.element.appendChild(this.contentElement);
|
||||
|
||||
if(this.isGroup){
|
||||
this._buildGroupHeader();
|
||||
}else{
|
||||
this._buildColumnHeader();
|
||||
}
|
||||
|
||||
this.dispatch("column-init", this);
|
||||
}
|
||||
|
||||
//build header element for header
|
||||
_buildColumnHeader(){
|
||||
var def = this.definition;
|
||||
|
||||
this.dispatch("column-layout", this);
|
||||
|
||||
//set column visibility
|
||||
if(typeof def.visible != "undefined"){
|
||||
if(def.visible){
|
||||
this.show(true);
|
||||
}else{
|
||||
this.hide(true);
|
||||
}
|
||||
}
|
||||
|
||||
//assign additional css classes to column header
|
||||
if(def.cssClass){
|
||||
var classNames = def.cssClass.split(" ");
|
||||
classNames.forEach((className) => {
|
||||
this.element.classList.add(className);
|
||||
});
|
||||
}
|
||||
|
||||
if(def.field){
|
||||
this.element.setAttribute("tabulator-field", def.field);
|
||||
}
|
||||
|
||||
//set min width if present
|
||||
this.setMinWidth(parseInt(def.minWidth));
|
||||
|
||||
if (def.maxInitialWidth) {
|
||||
this.maxInitialWidth = parseInt(def.maxInitialWidth);
|
||||
}
|
||||
|
||||
if(def.maxWidth){
|
||||
this.setMaxWidth(parseInt(def.maxWidth));
|
||||
}
|
||||
|
||||
this.reinitializeWidth();
|
||||
|
||||
//set horizontal text alignment
|
||||
this.hozAlign = this.definition.hozAlign;
|
||||
this.vertAlign = this.definition.vertAlign;
|
||||
|
||||
this.titleElement.style.textAlign = this.definition.headerHozAlign;
|
||||
}
|
||||
|
||||
_buildColumnHeaderContent(){
|
||||
var contentElement = document.createElement("div");
|
||||
contentElement.classList.add("tabulator-col-content");
|
||||
|
||||
this.titleHolderElement = document.createElement("div");
|
||||
this.titleHolderElement.classList.add("tabulator-col-title-holder");
|
||||
|
||||
contentElement.appendChild(this.titleHolderElement);
|
||||
|
||||
this.titleElement = this._buildColumnHeaderTitle();
|
||||
|
||||
this.titleHolderElement.appendChild(this.titleElement);
|
||||
|
||||
return contentElement;
|
||||
}
|
||||
|
||||
//build title element of column
|
||||
_buildColumnHeaderTitle(){
|
||||
var def = this.definition;
|
||||
|
||||
var titleHolderElement = document.createElement("div");
|
||||
titleHolderElement.classList.add("tabulator-col-title");
|
||||
|
||||
if(def.headerWordWrap){
|
||||
titleHolderElement.classList.add("tabulator-col-title-wrap");
|
||||
}
|
||||
|
||||
if(def.editableTitle){
|
||||
var titleElement = document.createElement("input");
|
||||
titleElement.classList.add("tabulator-title-editor");
|
||||
|
||||
titleElement.addEventListener("click", (e) => {
|
||||
e.stopPropagation();
|
||||
titleElement.focus();
|
||||
});
|
||||
|
||||
titleElement.addEventListener("mousedown", (e) => {
|
||||
e.stopPropagation();
|
||||
});
|
||||
|
||||
titleElement.addEventListener("change", () => {
|
||||
def.title = titleElement.value;
|
||||
this.dispatchExternal("columnTitleChanged", this.getComponent());
|
||||
});
|
||||
|
||||
titleHolderElement.appendChild(titleElement);
|
||||
|
||||
if(def.field){
|
||||
this.langBind("columns|" + def.field, (text) => {
|
||||
titleElement.value = text || (def.title || " ");
|
||||
});
|
||||
}else{
|
||||
titleElement.value = def.title || " ";
|
||||
}
|
||||
|
||||
}else{
|
||||
if(def.field){
|
||||
this.langBind("columns|" + def.field, (text) => {
|
||||
this._formatColumnHeaderTitle(titleHolderElement, text || (def.title || " "));
|
||||
});
|
||||
}else{
|
||||
this._formatColumnHeaderTitle(titleHolderElement, def.title || " ");
|
||||
}
|
||||
}
|
||||
|
||||
return titleHolderElement;
|
||||
}
|
||||
|
||||
_formatColumnHeaderTitle(el, title){
|
||||
var contents = this.chain("column-format", [this, title, el], null, () => {
|
||||
return title;
|
||||
});
|
||||
|
||||
switch(typeof contents){
|
||||
case "object":
|
||||
if(contents instanceof Node){
|
||||
el.appendChild(contents);
|
||||
}else{
|
||||
el.innerHTML = "";
|
||||
console.warn("Format Error - Title formatter has returned a type of object, the only valid formatter object return is an instance of Node, the formatter returned:", contents);
|
||||
}
|
||||
break;
|
||||
case "undefined":
|
||||
el.innerHTML = "";
|
||||
break;
|
||||
default:
|
||||
el.innerHTML = contents;
|
||||
}
|
||||
}
|
||||
|
||||
//build header element for column group
|
||||
_buildGroupHeader(){
|
||||
this.element.classList.add("tabulator-col-group");
|
||||
this.element.setAttribute("role", "columngroup");
|
||||
this.element.setAttribute("aria-title", this.definition.title);
|
||||
|
||||
//asign additional css classes to column header
|
||||
if(this.definition.cssClass){
|
||||
var classNames = this.definition.cssClass.split(" ");
|
||||
classNames.forEach((className) => {
|
||||
this.element.classList.add(className);
|
||||
});
|
||||
}
|
||||
|
||||
this.titleElement.style.textAlign = this.definition.headerHozAlign;
|
||||
|
||||
this.element.appendChild(this.groupElement);
|
||||
}
|
||||
|
||||
//flat field lookup
|
||||
_getFlatData(data){
|
||||
return data[this.field];
|
||||
}
|
||||
|
||||
//nested field lookup
|
||||
_getNestedData(data){
|
||||
var dataObj = data,
|
||||
structure = this.fieldStructure,
|
||||
length = structure.length,
|
||||
output;
|
||||
|
||||
for(let i = 0; i < length; i++){
|
||||
|
||||
dataObj = dataObj[structure[i]];
|
||||
|
||||
output = dataObj;
|
||||
|
||||
if(!dataObj){
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
//flat field set
|
||||
_setFlatData(data, value){
|
||||
if(this.field){
|
||||
data[this.field] = value;
|
||||
}
|
||||
}
|
||||
|
||||
//nested field set
|
||||
_setNestedData(data, value){
|
||||
var dataObj = data,
|
||||
structure = this.fieldStructure,
|
||||
length = structure.length;
|
||||
|
||||
for(let i = 0; i < length; i++){
|
||||
|
||||
if(i == length -1){
|
||||
dataObj[structure[i]] = value;
|
||||
}else{
|
||||
if(!dataObj[structure[i]]){
|
||||
if(typeof value !== "undefined"){
|
||||
dataObj[structure[i]] = {};
|
||||
}else{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
dataObj = dataObj[structure[i]];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//attach column to this group
|
||||
attachColumn(column){
|
||||
if(this.groupElement){
|
||||
this.columns.push(column);
|
||||
this.groupElement.appendChild(column.getElement());
|
||||
|
||||
column.columnRendered();
|
||||
}else{
|
||||
console.warn("Column Warning - Column being attached to another column instead of column group");
|
||||
}
|
||||
}
|
||||
|
||||
//vertically align header in column
|
||||
verticalAlign(alignment, height){
|
||||
|
||||
//calculate height of column header and group holder element
|
||||
var parentHeight = this.parent.isGroup ? this.parent.getGroupElement().clientHeight : (height || this.parent.getHeadersElement().clientHeight);
|
||||
// var parentHeight = this.parent.isGroup ? this.parent.getGroupElement().clientHeight : this.parent.getHeadersElement().clientHeight;
|
||||
|
||||
this.element.style.height = parentHeight + "px";
|
||||
|
||||
this.dispatch("column-height", this, this.element.style.height);
|
||||
|
||||
if(this.isGroup){
|
||||
this.groupElement.style.minHeight = (parentHeight - this.contentElement.offsetHeight) + "px";
|
||||
}
|
||||
|
||||
//vertically align cell contents
|
||||
// if(!this.isGroup && alignment !== "top"){
|
||||
// if(alignment === "bottom"){
|
||||
// this.element.style.paddingTop = (this.element.clientHeight - this.contentElement.offsetHeight) + "px";
|
||||
// }else{
|
||||
// this.element.style.paddingTop = ((this.element.clientHeight - this.contentElement.offsetHeight) / 2) + "px";
|
||||
// }
|
||||
// }
|
||||
|
||||
this.columns.forEach(function(column){
|
||||
column.verticalAlign(alignment);
|
||||
});
|
||||
}
|
||||
|
||||
//clear vertical alignment
|
||||
clearVerticalAlign(){
|
||||
this.element.style.paddingTop = "";
|
||||
this.element.style.height = "";
|
||||
this.element.style.minHeight = "";
|
||||
this.groupElement.style.minHeight = "";
|
||||
|
||||
this.columns.forEach(function(column){
|
||||
column.clearVerticalAlign();
|
||||
});
|
||||
|
||||
this.dispatch("column-height", this, "");
|
||||
}
|
||||
|
||||
//// Retrieve Column Information ////
|
||||
//return column header element
|
||||
getElement(){
|
||||
return this.element;
|
||||
}
|
||||
|
||||
//return column group element
|
||||
getGroupElement(){
|
||||
return this.groupElement;
|
||||
}
|
||||
|
||||
//return field name
|
||||
getField(){
|
||||
return this.field;
|
||||
}
|
||||
|
||||
getTitleDownload() {
|
||||
return this.titleDownload;
|
||||
}
|
||||
|
||||
//return the first column in a group
|
||||
getFirstColumn(){
|
||||
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
|
||||
getLastColumn(){
|
||||
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
|
||||
getColumns(traverse){
|
||||
var columns = [];
|
||||
|
||||
if(traverse){
|
||||
this.columns.forEach((column) => {
|
||||
columns.push(column);
|
||||
|
||||
columns = columns.concat(column.getColumns(true));
|
||||
});
|
||||
}else{
|
||||
columns = this.columns;
|
||||
}
|
||||
|
||||
return columns;
|
||||
}
|
||||
|
||||
//return all columns in a group
|
||||
getCells(){
|
||||
return this.cells;
|
||||
}
|
||||
|
||||
//retrieve the top column in a group of columns
|
||||
getTopColumn(){
|
||||
if(this.parent.isGroup){
|
||||
return this.parent.getTopColumn();
|
||||
}else{
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
//return column definition object
|
||||
getDefinition(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 ////////////////////
|
||||
checkColumnVisibility(){
|
||||
var visible = false;
|
||||
|
||||
this.columns.forEach(function(column){
|
||||
if(column.visible){
|
||||
visible = true;
|
||||
}
|
||||
});
|
||||
|
||||
if(visible){
|
||||
this.show();
|
||||
this.dispatchExternal("columnVisibilityChanged", this.getComponent(), false);
|
||||
}else{
|
||||
this.hide();
|
||||
}
|
||||
}
|
||||
|
||||
//show column
|
||||
show(silent, responsiveToggle){
|
||||
if(!this.visible){
|
||||
this.visible = true;
|
||||
|
||||
this.element.style.display = "";
|
||||
|
||||
if(this.parent.isGroup){
|
||||
this.parent.checkColumnVisibility();
|
||||
}
|
||||
|
||||
this.cells.forEach(function(cell){
|
||||
cell.show();
|
||||
});
|
||||
|
||||
if(!this.isGroup && this.width === null){
|
||||
this.reinitializeWidth();
|
||||
}
|
||||
|
||||
this.table.columnManager.verticalAlignHeaders();
|
||||
|
||||
this.dispatch("column-show", this, responsiveToggle);
|
||||
|
||||
if(!silent){
|
||||
this.dispatchExternal("columnVisibilityChanged", this.getComponent(), true);
|
||||
}
|
||||
|
||||
if(this.parent.isGroup){
|
||||
this.parent.matchChildWidths();
|
||||
}
|
||||
|
||||
if(!this.silent){
|
||||
this.table.columnManager.rerenderColumns();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//hide column
|
||||
hide(silent, responsiveToggle){
|
||||
if(this.visible){
|
||||
this.visible = false;
|
||||
|
||||
this.element.style.display = "none";
|
||||
|
||||
this.table.columnManager.verticalAlignHeaders();
|
||||
|
||||
if(this.parent.isGroup){
|
||||
this.parent.checkColumnVisibility();
|
||||
}
|
||||
|
||||
this.cells.forEach(function(cell){
|
||||
cell.hide();
|
||||
});
|
||||
|
||||
this.dispatch("column-hide", this, responsiveToggle);
|
||||
|
||||
if(!silent){
|
||||
this.dispatchExternal("columnVisibilityChanged", this.getComponent(), false);
|
||||
}
|
||||
|
||||
if(this.parent.isGroup){
|
||||
this.parent.matchChildWidths();
|
||||
}
|
||||
|
||||
if(!this.silent){
|
||||
this.table.columnManager.rerenderColumns();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
matchChildWidths(){
|
||||
var childWidth = 0;
|
||||
|
||||
if(this.contentElement && this.columns.length){
|
||||
this.columns.forEach(function(column){
|
||||
if(column.visible){
|
||||
childWidth += column.getWidth();
|
||||
}
|
||||
});
|
||||
|
||||
this.contentElement.style.maxWidth = (childWidth - 1) + "px";
|
||||
if (this.table.initialized) {
|
||||
this.element.style.width = childWidth + "px";
|
||||
}
|
||||
|
||||
if(this.parent.isGroup){
|
||||
this.parent.matchChildWidths();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
removeChild(child){
|
||||
var index = this.columns.indexOf(child);
|
||||
|
||||
if(index > -1){
|
||||
this.columns.splice(index, 1);
|
||||
}
|
||||
|
||||
if(!this.columns.length){
|
||||
this.delete();
|
||||
}
|
||||
}
|
||||
|
||||
setWidth(width){
|
||||
this.widthFixed = true;
|
||||
this.setWidthActual(width);
|
||||
}
|
||||
|
||||
setWidthActual(width){
|
||||
if(isNaN(width)){
|
||||
width = Math.floor((this.table.element.clientWidth/100) * parseInt(width));
|
||||
}
|
||||
|
||||
width = Math.max(this.minWidth, width);
|
||||
|
||||
if(this.maxWidth){
|
||||
width = Math.min(this.maxWidth, width);
|
||||
}
|
||||
|
||||
this.width = width;
|
||||
this.widthStyled = width ? width + "px" : "";
|
||||
|
||||
this.element.style.width = this.widthStyled;
|
||||
|
||||
if(!this.isGroup){
|
||||
this.cells.forEach(function(cell){
|
||||
cell.setWidth();
|
||||
});
|
||||
}
|
||||
|
||||
if(this.parent.isGroup){
|
||||
this.parent.matchChildWidths();
|
||||
}
|
||||
|
||||
this.dispatch("column-width", this);
|
||||
|
||||
if(this.subscribedExternal("columnWidth")){
|
||||
this.dispatchExternal("columnWidth", this.getComponent());
|
||||
}
|
||||
}
|
||||
|
||||
checkCellHeights(){
|
||||
var rows = [];
|
||||
|
||||
this.cells.forEach(function(cell){
|
||||
if(cell.row.heightInitialized){
|
||||
if(cell.row.getElement().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();
|
||||
});
|
||||
}
|
||||
|
||||
getWidth(){
|
||||
var width = 0;
|
||||
|
||||
if(this.isGroup){
|
||||
this.columns.forEach(function(column){
|
||||
if(column.visible){
|
||||
width += column.getWidth();
|
||||
}
|
||||
});
|
||||
}else{
|
||||
width = this.width;
|
||||
}
|
||||
|
||||
return width;
|
||||
}
|
||||
|
||||
getLeftOffset(){
|
||||
var offset = this.element.offsetLeft;
|
||||
|
||||
if(this.parent.isGroup){
|
||||
offset += this.parent.getLeftOffset();
|
||||
}
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
getHeight(){
|
||||
return Math.ceil(this.element.getBoundingClientRect().height);
|
||||
}
|
||||
|
||||
setMinWidth(minWidth){
|
||||
if(this.maxWidth && minWidth > this.maxWidth){
|
||||
minWidth = this.maxWidth;
|
||||
|
||||
console.warn("the minWidth ("+ minWidth + "px) for column '" + this.field + "' cannot be bigger that its maxWidth ("+ this.maxWidthStyled + ")");
|
||||
}
|
||||
|
||||
this.minWidth = minWidth;
|
||||
this.minWidthStyled = minWidth ? minWidth + "px" : "";
|
||||
|
||||
this.element.style.minWidth = this.minWidthStyled;
|
||||
|
||||
this.cells.forEach(function(cell){
|
||||
cell.setMinWidth();
|
||||
});
|
||||
}
|
||||
|
||||
setMaxWidth(maxWidth){
|
||||
if(this.minWidth && maxWidth < this.minWidth){
|
||||
maxWidth = this.minWidth;
|
||||
|
||||
console.warn("the maxWidth ("+ maxWidth + "px) for column '" + this.field + "' cannot be smaller that its minWidth ("+ this.minWidthStyled + ")");
|
||||
}
|
||||
|
||||
this.maxWidth = maxWidth;
|
||||
this.maxWidthStyled = maxWidth ? maxWidth + "px" : "";
|
||||
|
||||
this.element.style.maxWidth = this.maxWidthStyled;
|
||||
|
||||
this.cells.forEach(function(cell){
|
||||
cell.setMaxWidth();
|
||||
});
|
||||
}
|
||||
|
||||
delete(){
|
||||
return new Promise((resolve, reject) => {
|
||||
if(this.isGroup){
|
||||
this.columns.forEach(function(column){
|
||||
column.delete();
|
||||
});
|
||||
}
|
||||
|
||||
this.dispatch("column-delete", this);
|
||||
|
||||
var cellCount = this.cells.length;
|
||||
|
||||
for(let i = 0; i < cellCount; i++){
|
||||
this.cells[0].delete();
|
||||
}
|
||||
|
||||
if(this.element.parentNode){
|
||||
this.element.parentNode.removeChild(this.element);
|
||||
}
|
||||
|
||||
this.element = false;
|
||||
this.contentElement = false;
|
||||
this.titleElement = false;
|
||||
this.groupElement = false;
|
||||
|
||||
if(this.parent.isGroup){
|
||||
this.parent.removeChild(this);
|
||||
}
|
||||
|
||||
this.table.columnManager.deregisterColumn(this);
|
||||
|
||||
this.table.columnManager.rerenderColumns(true);
|
||||
|
||||
this.dispatch("column-deleted", this);
|
||||
|
||||
resolve();
|
||||
});
|
||||
}
|
||||
|
||||
columnRendered(){
|
||||
if(this.titleFormatterRendered){
|
||||
this.titleFormatterRendered();
|
||||
}
|
||||
|
||||
this.dispatch("column-rendered", this);
|
||||
}
|
||||
|
||||
//////////////// Cell Management /////////////////
|
||||
//generate cell for this column
|
||||
generateCell(row){
|
||||
var cell = new Cell(this, row);
|
||||
|
||||
this.cells.push(cell);
|
||||
|
||||
return cell;
|
||||
}
|
||||
|
||||
nextColumn(){
|
||||
var index = this.table.columnManager.findColumnIndex(this);
|
||||
return index > -1 ? this._nextVisibleColumn(index + 1) : false;
|
||||
}
|
||||
|
||||
_nextVisibleColumn(index){
|
||||
var column = this.table.columnManager.getColumnByIndex(index);
|
||||
return !column || column.visible ? column : this._nextVisibleColumn(index + 1);
|
||||
}
|
||||
|
||||
prevColumn(){
|
||||
var index = this.table.columnManager.findColumnIndex(this);
|
||||
return index > -1 ? this._prevVisibleColumn(index - 1) : false;
|
||||
}
|
||||
|
||||
_prevVisibleColumn(index){
|
||||
var column = this.table.columnManager.getColumnByIndex(index);
|
||||
return !column || column.visible ? column : this._prevVisibleColumn(index - 1);
|
||||
}
|
||||
|
||||
reinitializeWidth(force){
|
||||
this.widthFixed = false;
|
||||
|
||||
//set width if present
|
||||
if(typeof this.definition.width !== "undefined" && !force){
|
||||
// maxInitialWidth ignored here as width specified
|
||||
this.setWidth(this.definition.width);
|
||||
}
|
||||
|
||||
this.dispatch("column-width-fit-before", this);
|
||||
|
||||
this.fitToData(force);
|
||||
|
||||
this.dispatch("column-width-fit-after", this);
|
||||
}
|
||||
|
||||
//set column width to maximum cell width for non group columns
|
||||
fitToData(force){
|
||||
if(this.isGroup){
|
||||
return;
|
||||
}
|
||||
|
||||
if(!this.widthFixed){
|
||||
this.element.style.width = "";
|
||||
|
||||
this.cells.forEach((cell) => {
|
||||
cell.clearWidth();
|
||||
});
|
||||
}
|
||||
|
||||
var maxWidth = this.element.offsetWidth;
|
||||
|
||||
if(!this.width || !this.widthFixed){
|
||||
this.cells.forEach((cell) => {
|
||||
var width = cell.getWidth();
|
||||
|
||||
if(width > maxWidth){
|
||||
maxWidth = width;
|
||||
}
|
||||
});
|
||||
|
||||
if(maxWidth){
|
||||
var setTo = maxWidth + 1;
|
||||
|
||||
if(force){
|
||||
this.setWidth(setTo);
|
||||
}else{
|
||||
if (this.maxInitialWidth && !force) {
|
||||
setTo = Math.min(setTo, this.maxInitialWidth);
|
||||
}
|
||||
this.setWidthActual(setTo);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
updateDefinition(updates){
|
||||
var definition;
|
||||
|
||||
if(!this.isGroup){
|
||||
if(!this.parent.isGroup){
|
||||
definition = Object.assign({}, this.getDefinition());
|
||||
definition = Object.assign(definition, updates);
|
||||
|
||||
return this.table.columnManager.addColumn(definition, false, this)
|
||||
.then((column) => {
|
||||
|
||||
if(definition.field == this.field){
|
||||
this.field = false; //clear field name to prevent deletion of duplicate column from arrays
|
||||
}
|
||||
|
||||
return this.delete()
|
||||
.then(() => {
|
||||
return column.getComponent();
|
||||
});
|
||||
|
||||
});
|
||||
}else{
|
||||
console.error("Column Update Error - The updateDefinition function is only available on ungrouped columns");
|
||||
return Promise.reject("Column Update Error - The updateDefinition function is only available on columns, not column groups");
|
||||
}
|
||||
}else{
|
||||
console.error("Column Update Error - The updateDefinition function is only available on ungrouped columns");
|
||||
return Promise.reject("Column Update Error - The updateDefinition function is only available on columns, not column groups");
|
||||
}
|
||||
}
|
||||
|
||||
deleteCell(cell){
|
||||
var index = this.cells.indexOf(cell);
|
||||
|
||||
if(index > -1){
|
||||
this.cells.splice(index, 1);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////// Object Generation /////////////////
|
||||
getComponent(){
|
||||
if(!this.component){
|
||||
this.component = new ColumnComponent(this);
|
||||
}
|
||||
|
||||
return this.component;
|
||||
}
|
||||
|
||||
getPosition(){
|
||||
return this.table.columnManager.getVisibleColumnsByIndex().indexOf(this) + 1;
|
||||
}
|
||||
|
||||
getParentComponent(){
|
||||
return this.parent instanceof Column ? this.parent.getComponent() : false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,151 @@
|
||||
//public column object
|
||||
export default class ColumnComponent {
|
||||
constructor (column){
|
||||
this._column = column;
|
||||
this.type = "ColumnComponent";
|
||||
|
||||
return new Proxy(this, {
|
||||
get: function(target, name, receiver) {
|
||||
if (typeof target[name] !== "undefined") {
|
||||
return target[name];
|
||||
}else{
|
||||
return target._column.table.componentFunctionBinder.handle("column", target._column, name);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
getElement(){
|
||||
return this._column.getElement();
|
||||
}
|
||||
|
||||
getDefinition(){
|
||||
return this._column.getDefinition();
|
||||
}
|
||||
|
||||
getField(){
|
||||
return this._column.getField();
|
||||
}
|
||||
|
||||
getTitleDownload() {
|
||||
return this._column.getTitleDownload();
|
||||
}
|
||||
|
||||
getCells(){
|
||||
var cells = [];
|
||||
|
||||
this._column.cells.forEach(function(cell){
|
||||
cells.push(cell.getComponent());
|
||||
});
|
||||
|
||||
return cells;
|
||||
}
|
||||
|
||||
isVisible(){
|
||||
return this._column.visible;
|
||||
}
|
||||
|
||||
show(){
|
||||
if(this._column.isGroup){
|
||||
this._column.columns.forEach(function(column){
|
||||
column.show();
|
||||
});
|
||||
}else{
|
||||
this._column.show();
|
||||
}
|
||||
}
|
||||
|
||||
hide(){
|
||||
if(this._column.isGroup){
|
||||
this._column.columns.forEach(function(column){
|
||||
column.hide();
|
||||
});
|
||||
}else{
|
||||
this._column.hide();
|
||||
}
|
||||
}
|
||||
|
||||
toggle(){
|
||||
if(this._column.visible){
|
||||
this.hide();
|
||||
}else{
|
||||
this.show();
|
||||
}
|
||||
}
|
||||
|
||||
delete(){
|
||||
return this._column.delete();
|
||||
}
|
||||
|
||||
getSubColumns(){
|
||||
var output = [];
|
||||
|
||||
if(this._column.columns.length){
|
||||
this._column.columns.forEach(function(column){
|
||||
output.push(column.getComponent());
|
||||
});
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
getParentColumn(){
|
||||
return this._column.getParentComponent();
|
||||
}
|
||||
|
||||
_getSelf(){
|
||||
return this._column;
|
||||
}
|
||||
|
||||
scrollTo(position, ifVisible){
|
||||
return this._column.table.columnManager.scrollToColumn(this._column, position, ifVisible);
|
||||
}
|
||||
|
||||
getTable(){
|
||||
return this._column.table;
|
||||
}
|
||||
|
||||
move(to, after){
|
||||
var toColumn = this._column.table.columnManager.findColumn(to);
|
||||
|
||||
if(toColumn){
|
||||
this._column.table.columnManager.moveColumn(this._column, toColumn, after);
|
||||
}else{
|
||||
console.warn("Move Error - No matching column found:", toColumn);
|
||||
}
|
||||
}
|
||||
|
||||
getNextColumn(){
|
||||
var nextCol = this._column.nextColumn();
|
||||
|
||||
return nextCol ? nextCol.getComponent() : false;
|
||||
}
|
||||
|
||||
getPrevColumn(){
|
||||
var prevCol = this._column.prevColumn();
|
||||
|
||||
return prevCol ? prevCol.getComponent() : false;
|
||||
}
|
||||
|
||||
updateDefinition(updates){
|
||||
return this._column.updateDefinition(updates);
|
||||
}
|
||||
|
||||
getWidth(){
|
||||
return this._column.getWidth();
|
||||
}
|
||||
|
||||
setWidth(width){
|
||||
var result;
|
||||
|
||||
if(width === true){
|
||||
result = this._column.reinitializeWidth(true);
|
||||
}else{
|
||||
result = this._column.setWidth(width);
|
||||
}
|
||||
|
||||
this._column.table.columnManager.rerenderColumns(true);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
export default {
|
||||
"title": undefined,
|
||||
"field": undefined,
|
||||
"columns": undefined,
|
||||
"visible": undefined,
|
||||
"hozAlign": undefined,
|
||||
"vertAlign": undefined,
|
||||
"width": undefined,
|
||||
"minWidth": 40,
|
||||
"maxWidth": undefined,
|
||||
"maxInitialWidth": undefined,
|
||||
"cssClass": undefined,
|
||||
"variableHeight": undefined,
|
||||
"headerVertical": undefined,
|
||||
"headerHozAlign": undefined,
|
||||
"headerWordWrap": false,
|
||||
"editableTitle": undefined,
|
||||
};
|
||||
66
public/libs/tabulator-master/src/js/core/defaults/options.js
Normal file
66
public/libs/tabulator-master/src/js/core/defaults/options.js
Normal file
@@ -0,0 +1,66 @@
|
||||
export default {
|
||||
|
||||
debugEventsExternal:false, //flag to console log events
|
||||
debugEventsInternal:false, //flag to console log events
|
||||
debugInvalidOptions:true, //allow toggling of invalid option warnings
|
||||
debugInvalidComponentFuncs:true, //allow toggling of invalid component warnings
|
||||
debugInitialization:true, //allow toggling of pre initialization function call warnings
|
||||
debugDeprecation:true, //allow toggling of deprecation warnings
|
||||
|
||||
height:false, //height of tabulator
|
||||
minHeight:false, //minimum height of tabulator
|
||||
maxHeight:false, //maximum height of tabulator
|
||||
|
||||
columnHeaderVertAlign:"top", //vertical alignment of column headers
|
||||
|
||||
popupContainer:false,
|
||||
|
||||
columns:[],//store for colum header info
|
||||
columnDefaults:{}, //store column default props
|
||||
rowHeader:false,
|
||||
|
||||
data:false, //default starting data
|
||||
|
||||
autoColumns:false, //build columns from data row structure
|
||||
autoColumnsDefinitions:false,
|
||||
|
||||
nestedFieldSeparator:".", //separator for nested data
|
||||
|
||||
footerElement:false, //hold footer element
|
||||
|
||||
index:"id", //filed for row index
|
||||
|
||||
textDirection:"auto",
|
||||
|
||||
addRowPos:"bottom", //position to insert blank rows, top|bottom
|
||||
|
||||
headerVisible:true, //hide header
|
||||
|
||||
renderVertical:"virtual",
|
||||
renderHorizontal:"basic",
|
||||
renderVerticalBuffer:0, // set virtual DOM buffer size
|
||||
|
||||
scrollToRowPosition:"top",
|
||||
scrollToRowIfVisible:true,
|
||||
|
||||
scrollToColumnPosition:"left",
|
||||
scrollToColumnIfVisible:true,
|
||||
|
||||
rowFormatter:false,
|
||||
rowFormatterPrint:null,
|
||||
rowFormatterClipboard:null,
|
||||
rowFormatterHtmlOutput:null,
|
||||
|
||||
rowHeight:null,
|
||||
|
||||
placeholder:false,
|
||||
|
||||
dataLoader:true,
|
||||
dataLoaderLoading:false,
|
||||
dataLoaderError:false,
|
||||
dataLoaderErrorTimeout:3000,
|
||||
dataSendParams:{},
|
||||
dataReceiveParams:{},
|
||||
|
||||
dependencies:{},
|
||||
};
|
||||
3
public/libs/tabulator-master/src/js/core/modules/core.js
Normal file
3
public/libs/tabulator-master/src/js/core/modules/core.js
Normal file
@@ -0,0 +1,3 @@
|
||||
export {default as LayoutModule} from '../../modules/Layout/Layout.js';
|
||||
export {default as LocalizeModule} from '../../modules/Localize/Localize.js';
|
||||
export {default as CommsModule} from '../../modules/Comms/Comms.js';
|
||||
37
public/libs/tabulator-master/src/js/core/modules/optional.js
Normal file
37
public/libs/tabulator-master/src/js/core/modules/optional.js
Normal file
@@ -0,0 +1,37 @@
|
||||
export {default as AccessorModule} from '../../modules/Accessor/Accessor.js';
|
||||
export {default as AjaxModule} from '../../modules/Ajax/Ajax.js';
|
||||
export {default as ClipboardModule} from '../../modules/Clipboard/Clipboard.js';
|
||||
export {default as ColumnCalcsModule} from '../../modules/ColumnCalcs/ColumnCalcs.js';
|
||||
export {default as DataTreeModule} from '../../modules/DataTree/DataTree.js';
|
||||
export {default as DownloadModule} from '../../modules/Download/Download.js';
|
||||
export {default as EditModule} from '../../modules/Edit/Edit.js';
|
||||
export {default as ExportModule} from '../../modules/Export/Export.js';
|
||||
export {default as FilterModule} from '../../modules/Filter/Filter.js';
|
||||
export {default as FormatModule} from '../../modules/Format/Format.js';
|
||||
export {default as FrozenColumnsModule} from '../../modules/FrozenColumns/FrozenColumns.js';
|
||||
export {default as FrozenRowsModule} from '../../modules/FrozenRows/FrozenRows.js';
|
||||
export {default as GroupRowsModule} from '../../modules/GroupRows/GroupRows.js';
|
||||
export {default as HistoryModule} from '../../modules/History/History.js';
|
||||
export {default as HtmlTableImportModule} from '../../modules/HtmlTableImport/HtmlTableImport.js';
|
||||
export {default as ImportModule} from '../../modules/Import/Import.js';
|
||||
export {default as InteractionModule} from '../../modules/Interaction/Interaction.js';
|
||||
export {default as KeybindingsModule} from '../../modules/Keybindings/Keybindings.js';
|
||||
export {default as MenuModule} from '../../modules/Menu/Menu.js';
|
||||
export {default as MoveColumnsModule} from '../../modules/MoveColumns/MoveColumns.js';
|
||||
export {default as MoveRowsModule} from '../../modules/MoveRows/MoveRows.js';
|
||||
export {default as MutatorModule} from '../../modules/Mutator/Mutator.js';
|
||||
export {default as PageModule} from '../../modules/Page/Page.js';
|
||||
export {default as PersistenceModule} from '../../modules/Persistence/Persistence.js';
|
||||
export {default as PopupModule} from '../../modules/Popup/Popup.js';
|
||||
export {default as PrintModule} from '../../modules/Print/Print.js';
|
||||
export {default as ReactiveDataModule} from '../../modules/ReactiveData/ReactiveData.js';
|
||||
export {default as ResizeColumnsModule} from '../../modules/ResizeColumns/ResizeColumns.js';
|
||||
export {default as ResizeRowsModule} from '../../modules/ResizeRows/ResizeRows.js';
|
||||
export {default as ResizeTableModule} from '../../modules/ResizeTable/ResizeTable.js';
|
||||
export {default as ResponsiveLayoutModule} from '../../modules/ResponsiveLayout/ResponsiveLayout.js';
|
||||
export {default as SelectRowModule} from '../../modules/SelectRow/SelectRow.js';
|
||||
export {default as SelectRangeModule} from '../../modules/SelectRange/SelectRange.js';
|
||||
export {default as SortModule} from '../../modules/Sort/Sort.js';
|
||||
export {default as SpreadsheetModule} from '../../modules/Spreadsheet/Spreadsheet.js';
|
||||
export {default as TooltipModule} from '../../modules/Tooltip/Tooltip.js';
|
||||
export {default as ValidateModule} from '../../modules/Validate/Validate.js';
|
||||
204
public/libs/tabulator-master/src/js/core/rendering/Renderer.js
Normal file
204
public/libs/tabulator-master/src/js/core/rendering/Renderer.js
Normal file
@@ -0,0 +1,204 @@
|
||||
import CoreFeature from '../CoreFeature.js';
|
||||
import Helpers from '../tools/Helpers.js';
|
||||
|
||||
export default class Renderer extends CoreFeature{
|
||||
constructor(table){
|
||||
super(table);
|
||||
|
||||
this.elementVertical = table.rowManager.element;
|
||||
this.elementHorizontal = table.columnManager.element;
|
||||
this.tableElement = table.rowManager.tableElement;
|
||||
|
||||
this.verticalFillMode = "fit"; // used by row manager to determine how to size the render area ("fit" - fits container to the contents, "fill" - fills the container without resizing it)
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////
|
||||
/////// Internal Bindings /////////
|
||||
///////////////////////////////////
|
||||
|
||||
initialize(){
|
||||
//initialize core functionality
|
||||
}
|
||||
|
||||
clearRows(){
|
||||
//clear down existing rows layout
|
||||
}
|
||||
|
||||
clearColumns(){
|
||||
//clear down existing columns layout
|
||||
}
|
||||
|
||||
|
||||
reinitializeColumnWidths(columns){
|
||||
//resize columns to fit data
|
||||
}
|
||||
|
||||
|
||||
renderRows(){
|
||||
//render rows from a clean slate
|
||||
}
|
||||
|
||||
renderColumns(){
|
||||
//render columns from a clean slate
|
||||
}
|
||||
|
||||
rerenderRows(callback){
|
||||
// rerender rows and keep position
|
||||
if(callback){
|
||||
callback();
|
||||
}
|
||||
}
|
||||
|
||||
rerenderColumns(update, blockRedraw){
|
||||
//rerender columns
|
||||
}
|
||||
|
||||
renderRowCells(row){
|
||||
//render the cells in a row
|
||||
}
|
||||
|
||||
rerenderRowCells(row, force){
|
||||
//rerender the cells in a row
|
||||
}
|
||||
|
||||
scrollColumns(left, dir){
|
||||
//handle horizontal scrolling
|
||||
}
|
||||
|
||||
scrollRows(top, dir){
|
||||
//handle vertical scrolling
|
||||
}
|
||||
|
||||
resize(){
|
||||
//container has resized, carry out any needed recalculations (DO NOT RERENDER IN THIS FUNCTION)
|
||||
}
|
||||
|
||||
scrollToRow(row){
|
||||
//scroll to a specific row
|
||||
}
|
||||
|
||||
scrollToRowNearestTop(row){
|
||||
//determine weather the row is nearest the top or bottom of the table, return true for top or false for bottom
|
||||
}
|
||||
|
||||
visibleRows(includingBuffer){
|
||||
//return the visible rows
|
||||
return [];
|
||||
}
|
||||
|
||||
///////////////////////////////////
|
||||
//////// Helper Functions /////////
|
||||
///////////////////////////////////
|
||||
|
||||
rows(){
|
||||
return this.table.rowManager.getDisplayRows();
|
||||
}
|
||||
|
||||
styleRow(row, index){
|
||||
var rowEl = row.getElement();
|
||||
|
||||
if(index % 2){
|
||||
rowEl.classList.add("tabulator-row-even");
|
||||
rowEl.classList.remove("tabulator-row-odd");
|
||||
}else{
|
||||
rowEl.classList.add("tabulator-row-odd");
|
||||
rowEl.classList.remove("tabulator-row-even");
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////
|
||||
/////// External Triggers /////////
|
||||
/////// (DO NOT OVERRIDE) /////////
|
||||
///////////////////////////////////
|
||||
|
||||
clear(){
|
||||
//clear down existing layout
|
||||
this.clearRows();
|
||||
this.clearColumns();
|
||||
}
|
||||
|
||||
render(){
|
||||
//render from a clean slate
|
||||
this.renderRows();
|
||||
this.renderColumns();
|
||||
}
|
||||
|
||||
rerender(callback){
|
||||
// rerender and keep position
|
||||
this.rerenderRows();
|
||||
this.rerenderColumns();
|
||||
}
|
||||
|
||||
scrollToRowPosition(row, position, ifVisible){
|
||||
var rowIndex = this.rows().indexOf(row),
|
||||
rowEl = row.getElement(),
|
||||
offset = 0;
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
if(rowIndex > -1){
|
||||
|
||||
if(typeof ifVisible === "undefined"){
|
||||
ifVisible = this.table.options.scrollToRowIfVisible;
|
||||
}
|
||||
|
||||
//check row visibility
|
||||
if(!ifVisible){
|
||||
if(Helpers.elVisible(rowEl)){
|
||||
offset = Helpers.elOffset(rowEl).top - Helpers.elOffset(this.elementVertical).top;
|
||||
|
||||
if(offset > 0 && offset < this.elementVertical.clientHeight - rowEl.offsetHeight){
|
||||
resolve();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(typeof position === "undefined"){
|
||||
position = this.table.options.scrollToRowPosition;
|
||||
}
|
||||
|
||||
if(position === "nearest"){
|
||||
position = this.scrollToRowNearestTop(row) ? "top" : "bottom";
|
||||
}
|
||||
|
||||
//scroll to row
|
||||
this.scrollToRow(row);
|
||||
|
||||
//align to correct position
|
||||
switch(position){
|
||||
case "middle":
|
||||
case "center":
|
||||
|
||||
if(this.elementVertical.scrollHeight - this.elementVertical.scrollTop == this.elementVertical.clientHeight){
|
||||
this.elementVertical.scrollTop = this.elementVertical.scrollTop + (rowEl.offsetTop - this.elementVertical.scrollTop) - ((this.elementVertical.scrollHeight - rowEl.offsetTop) / 2);
|
||||
}else{
|
||||
this.elementVertical.scrollTop = this.elementVertical.scrollTop - (this.elementVertical.clientHeight / 2);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case "bottom":
|
||||
|
||||
if(this.elementVertical.scrollHeight - this.elementVertical.scrollTop == this.elementVertical.clientHeight){
|
||||
this.elementVertical.scrollTop = this.elementVertical.scrollTop - (this.elementVertical.scrollHeight - rowEl.offsetTop) + rowEl.offsetHeight;
|
||||
}else{
|
||||
this.elementVertical.scrollTop = this.elementVertical.scrollTop - this.elementVertical.clientHeight + rowEl.offsetHeight;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case "top":
|
||||
this.elementVertical.scrollTop = rowEl.offsetTop;
|
||||
break;
|
||||
}
|
||||
|
||||
resolve();
|
||||
|
||||
}else{
|
||||
console.warn("Scroll Error - Row not visible");
|
||||
reject("Scroll Error - Row not visible");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
import Renderer from '../Renderer.js';
|
||||
|
||||
export default class BasicHorizontal extends Renderer{
|
||||
constructor(table){
|
||||
super(table);
|
||||
}
|
||||
|
||||
renderRowCells(row, inFragment) {
|
||||
const rowFrag = document.createDocumentFragment();
|
||||
row.cells.forEach((cell) => {
|
||||
rowFrag.appendChild(cell.getElement());
|
||||
});
|
||||
row.element.appendChild(rowFrag);
|
||||
|
||||
if(!inFragment){
|
||||
row.cells.forEach((cell) => {
|
||||
cell.cellRendered();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
reinitializeColumnWidths(columns){
|
||||
columns.forEach(function(column){
|
||||
column.reinitializeWidth();
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
import Renderer from '../Renderer.js';
|
||||
import Helpers from '../../tools/Helpers.js';
|
||||
|
||||
export default class BasicVertical extends Renderer{
|
||||
constructor(table){
|
||||
super(table);
|
||||
|
||||
this.verticalFillMode = "fill";
|
||||
|
||||
this.scrollTop = 0;
|
||||
this.scrollLeft = 0;
|
||||
|
||||
this.scrollTop = 0;
|
||||
this.scrollLeft = 0;
|
||||
}
|
||||
|
||||
clearRows(){
|
||||
var element = this.tableElement;
|
||||
|
||||
// element.children.detach();
|
||||
while(element.firstChild) element.removeChild(element.firstChild);
|
||||
|
||||
element.scrollTop = 0;
|
||||
element.scrollLeft = 0;
|
||||
|
||||
element.style.minWidth = "";
|
||||
element.style.minHeight = "";
|
||||
element.style.display = "";
|
||||
element.style.visibility = "";
|
||||
}
|
||||
|
||||
renderRows() {
|
||||
var element = this.tableElement,
|
||||
onlyGroupHeaders = true,
|
||||
tableFrag = document.createDocumentFragment(),
|
||||
rows = this.rows();
|
||||
|
||||
rows.forEach((row, index) => {
|
||||
this.styleRow(row, index);
|
||||
row.initialize(false, true);
|
||||
|
||||
if (row.type !== "group") {
|
||||
onlyGroupHeaders = false;
|
||||
}
|
||||
|
||||
tableFrag.appendChild(row.getElement());
|
||||
});
|
||||
|
||||
element.appendChild(tableFrag);
|
||||
|
||||
rows.forEach((row) => {
|
||||
row.rendered();
|
||||
|
||||
if(!row.heightInitialized) {
|
||||
row.calcHeight(true);
|
||||
}
|
||||
});
|
||||
|
||||
rows.forEach((row) => {
|
||||
if(!row.heightInitialized) {
|
||||
row.setCellHeight();
|
||||
}
|
||||
});
|
||||
|
||||
if(onlyGroupHeaders){
|
||||
element.style.minWidth = this.table.columnManager.getWidth() + "px";
|
||||
}else{
|
||||
element.style.minWidth = "";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
rerenderRows(callback){
|
||||
this.clearRows();
|
||||
|
||||
if(callback){
|
||||
callback();
|
||||
}
|
||||
|
||||
this.renderRows();
|
||||
|
||||
if(!this.rows().length){
|
||||
this.table.rowManager.tableEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
scrollToRowNearestTop(row){
|
||||
var rowTop = Helpers.elOffset(row.getElement()).top;
|
||||
|
||||
return !(Math.abs(this.elementVertical.scrollTop - rowTop) > Math.abs(this.elementVertical.scrollTop + this.elementVertical.clientHeight - rowTop));
|
||||
}
|
||||
|
||||
scrollToRow(row){
|
||||
var rowEl = row.getElement();
|
||||
|
||||
this.elementVertical.scrollTop = Helpers.elOffset(rowEl).top - Helpers.elOffset(this.elementVertical).top + this.elementVertical.scrollTop;
|
||||
}
|
||||
|
||||
visibleRows(includingBuffer){
|
||||
return this.rows();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,587 @@
|
||||
import Renderer from '../Renderer.js';
|
||||
|
||||
export default class VirtualDomHorizontal extends Renderer{
|
||||
constructor(table){
|
||||
super(table);
|
||||
|
||||
this.leftCol = 0;
|
||||
this.rightCol = 0;
|
||||
this.scrollLeft = 0;
|
||||
|
||||
this.vDomScrollPosLeft = 0;
|
||||
this.vDomScrollPosRight = 0;
|
||||
|
||||
this.vDomPadLeft = 0;
|
||||
this.vDomPadRight = 0;
|
||||
|
||||
this.fitDataColAvg = 0;
|
||||
|
||||
this.windowBuffer = 200; //pixel margin to make column visible before it is shown on screen
|
||||
|
||||
this.visibleRows = null;
|
||||
|
||||
this.initialized = false;
|
||||
this.isFitData = false;
|
||||
|
||||
this.columns = [];
|
||||
}
|
||||
|
||||
initialize(){
|
||||
this.compatibilityCheck();
|
||||
this.layoutCheck();
|
||||
this.vertScrollListen();
|
||||
}
|
||||
|
||||
compatibilityCheck(){
|
||||
if(this.options("layout") == "fitDataTable"){
|
||||
console.warn("Horizontal Virtual DOM is not compatible with fitDataTable layout mode");
|
||||
}
|
||||
|
||||
if(this.options("responsiveLayout")){
|
||||
console.warn("Horizontal Virtual DOM is not compatible with responsive columns");
|
||||
}
|
||||
|
||||
if(this.options("rtl")){
|
||||
console.warn("Horizontal Virtual DOM is not currently compatible with RTL text direction");
|
||||
}
|
||||
}
|
||||
|
||||
layoutCheck(){
|
||||
this.isFitData = this.options("layout").startsWith('fitData');
|
||||
}
|
||||
|
||||
vertScrollListen(){
|
||||
this.subscribe("scroll-vertical", this.clearVisRowCache.bind(this));
|
||||
this.subscribe("data-refreshed", this.clearVisRowCache.bind(this));
|
||||
}
|
||||
|
||||
clearVisRowCache(){
|
||||
this.visibleRows = null;
|
||||
}
|
||||
|
||||
//////////////////////////////////////
|
||||
///////// Public Functions ///////////
|
||||
//////////////////////////////////////
|
||||
|
||||
renderColumns(row, force){
|
||||
this.dataChange();
|
||||
}
|
||||
|
||||
|
||||
scrollColumns(left, dir){
|
||||
if(this.scrollLeft != left){
|
||||
this.scrollLeft = left;
|
||||
|
||||
this.scroll(left - (this.vDomScrollPosLeft + this.windowBuffer));
|
||||
}
|
||||
}
|
||||
|
||||
calcWindowBuffer(){
|
||||
var buffer = this.elementVertical.clientWidth;
|
||||
|
||||
this.table.columnManager.columnsByIndex.forEach((column) => {
|
||||
if(column.visible){
|
||||
var width = column.getWidth();
|
||||
|
||||
if(width > buffer){
|
||||
buffer = width;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
this.windowBuffer = buffer * 2;
|
||||
}
|
||||
|
||||
rerenderColumns(update, blockRedraw){
|
||||
var old = {
|
||||
cols:this.columns,
|
||||
leftCol:this.leftCol,
|
||||
rightCol:this.rightCol,
|
||||
},
|
||||
colPos = 0;
|
||||
|
||||
if(update && !this.initialized){
|
||||
return;
|
||||
}
|
||||
|
||||
this.clear();
|
||||
|
||||
this.calcWindowBuffer();
|
||||
|
||||
this.scrollLeft = this.elementVertical.scrollLeft;
|
||||
|
||||
this.vDomScrollPosLeft = this.scrollLeft - this.windowBuffer;
|
||||
this.vDomScrollPosRight = this.scrollLeft + this.elementVertical.clientWidth + this.windowBuffer;
|
||||
|
||||
this.table.columnManager.columnsByIndex.forEach((column) => {
|
||||
var config = {},
|
||||
width;
|
||||
|
||||
if(column.visible){
|
||||
if(!column.modules.frozen){
|
||||
width = column.getWidth();
|
||||
|
||||
config.leftPos = colPos;
|
||||
config.rightPos = colPos + width;
|
||||
|
||||
config.width = width;
|
||||
|
||||
if (this.isFitData) {
|
||||
config.fitDataCheck = column.modules.vdomHoz ? column.modules.vdomHoz.fitDataCheck : true;
|
||||
}
|
||||
|
||||
if((colPos + width > this.vDomScrollPosLeft) && (colPos < this.vDomScrollPosRight)){
|
||||
//column is visible
|
||||
|
||||
if(this.leftCol == -1){
|
||||
this.leftCol = this.columns.length;
|
||||
this.vDomPadLeft = colPos;
|
||||
}
|
||||
|
||||
this.rightCol = this.columns.length;
|
||||
}else{
|
||||
// column is hidden
|
||||
if(this.leftCol !== -1){
|
||||
this.vDomPadRight += width;
|
||||
}
|
||||
}
|
||||
|
||||
this.columns.push(column);
|
||||
|
||||
column.modules.vdomHoz = config;
|
||||
|
||||
colPos += width;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
this.tableElement.style.paddingLeft = this.vDomPadLeft + "px";
|
||||
this.tableElement.style.paddingRight = this.vDomPadRight + "px";
|
||||
|
||||
this.initialized = true;
|
||||
|
||||
if(!blockRedraw){
|
||||
if(!update || this.reinitChanged(old)){
|
||||
this.reinitializeRows();
|
||||
}
|
||||
}
|
||||
|
||||
this.elementVertical.scrollLeft = this.scrollLeft;
|
||||
}
|
||||
|
||||
renderRowCells(row){
|
||||
if(this.initialized){
|
||||
this.initializeRow(row);
|
||||
}else{
|
||||
const rowFrag = document.createDocumentFragment();
|
||||
row.cells.forEach((cell) => {
|
||||
rowFrag.appendChild(cell.getElement());
|
||||
});
|
||||
row.element.appendChild(rowFrag);
|
||||
|
||||
row.cells.forEach((cell) => {
|
||||
cell.cellRendered();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
rerenderRowCells(row, force){
|
||||
this.reinitializeRow(row, force);
|
||||
}
|
||||
|
||||
reinitializeColumnWidths(columns){
|
||||
for(let i = this.leftCol; i <= this.rightCol; i++){
|
||||
let col = this.columns[i];
|
||||
|
||||
if(col){
|
||||
col.reinitializeWidth();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////
|
||||
//////// Internal Rendering //////////
|
||||
//////////////////////////////////////
|
||||
|
||||
deinitialize(){
|
||||
this.initialized = false;
|
||||
}
|
||||
|
||||
clear(){
|
||||
this.columns = [];
|
||||
|
||||
this.leftCol = -1;
|
||||
this.rightCol = 0;
|
||||
|
||||
this.vDomScrollPosLeft = 0;
|
||||
this.vDomScrollPosRight = 0;
|
||||
this.vDomPadLeft = 0;
|
||||
this.vDomPadRight = 0;
|
||||
}
|
||||
|
||||
dataChange(){
|
||||
var change = false,
|
||||
row, rowEl;
|
||||
|
||||
if(this.isFitData){
|
||||
this.table.columnManager.columnsByIndex.forEach((column) => {
|
||||
if(!column.definition.width && column.visible){
|
||||
change = true;
|
||||
}
|
||||
});
|
||||
|
||||
if(change && this.table.rowManager.getDisplayRows().length){
|
||||
this.vDomScrollPosRight = this.scrollLeft + this.elementVertical.clientWidth + this.windowBuffer;
|
||||
|
||||
row = this.chain("rows-sample", [1], [], () => {
|
||||
return this.table.rowManager.getDisplayRows();
|
||||
})[0];
|
||||
|
||||
if(row){
|
||||
rowEl = row.getElement();
|
||||
|
||||
row.generateCells();
|
||||
|
||||
this.tableElement.appendChild(rowEl);
|
||||
|
||||
for(let colEnd = 0; colEnd < row.cells.length; colEnd++){
|
||||
let cell = row.cells[colEnd];
|
||||
rowEl.appendChild(cell.getElement());
|
||||
|
||||
cell.column.reinitializeWidth();
|
||||
}
|
||||
|
||||
rowEl.parentNode.removeChild(rowEl);
|
||||
|
||||
this.rerenderColumns(false, true);
|
||||
}
|
||||
}
|
||||
}else{
|
||||
if(this.options("layout") === "fitColumns"){
|
||||
this.layoutRefresh();
|
||||
this.rerenderColumns(false, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
reinitChanged(old){
|
||||
var match = true;
|
||||
|
||||
if(old.cols.length !== this.columns.length || old.leftCol !== this.leftCol || old.rightCol !== this.rightCol){
|
||||
return true;
|
||||
}
|
||||
|
||||
old.cols.forEach((col, i) => {
|
||||
if(col !== this.columns[i]){
|
||||
match = false;
|
||||
}
|
||||
});
|
||||
|
||||
return !match;
|
||||
}
|
||||
|
||||
reinitializeRows(){
|
||||
var visibleRows = this.getVisibleRows(),
|
||||
otherRows = this.table.rowManager.getRows().filter(row => !visibleRows.includes(row));
|
||||
|
||||
visibleRows.forEach((row) => {
|
||||
this.reinitializeRow(row, true);
|
||||
});
|
||||
|
||||
otherRows.forEach((row) =>{
|
||||
row.deinitialize();
|
||||
});
|
||||
}
|
||||
|
||||
getVisibleRows(){
|
||||
if (!this.visibleRows){
|
||||
this.visibleRows = this.table.rowManager.getVisibleRows();
|
||||
}
|
||||
|
||||
return this.visibleRows;
|
||||
}
|
||||
|
||||
scroll(diff){
|
||||
this.vDomScrollPosLeft += diff;
|
||||
this.vDomScrollPosRight += diff;
|
||||
|
||||
if(Math.abs(diff) > (this.windowBuffer / 2)){
|
||||
this.rerenderColumns();
|
||||
}else{
|
||||
if(diff > 0){
|
||||
//scroll right
|
||||
this.addColRight();
|
||||
this.removeColLeft();
|
||||
}else{
|
||||
//scroll left
|
||||
this.addColLeft();
|
||||
this.removeColRight();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
colPositionAdjust (start, end, diff){
|
||||
for(let i = start; i < end; i++){
|
||||
let column = this.columns[i];
|
||||
|
||||
column.modules.vdomHoz.leftPos += diff;
|
||||
column.modules.vdomHoz.rightPos += diff;
|
||||
}
|
||||
}
|
||||
|
||||
addColRight(){
|
||||
var changes = false,
|
||||
working = true;
|
||||
|
||||
while(working){
|
||||
|
||||
let column = this.columns[this.rightCol + 1];
|
||||
|
||||
if(column){
|
||||
if(column.modules.vdomHoz.leftPos <= this.vDomScrollPosRight){
|
||||
changes = true;
|
||||
|
||||
this.getVisibleRows().forEach((row) => {
|
||||
if(row.type !== "group"){
|
||||
var cell = row.getCell(column);
|
||||
row.getElement().insertBefore(cell.getElement(), row.getCell(this.columns[this.rightCol]).getElement().nextSibling);
|
||||
cell.cellRendered();
|
||||
}
|
||||
});
|
||||
|
||||
this.fitDataColActualWidthCheck(column);
|
||||
|
||||
this.rightCol++; // Don't move this below the >= check below
|
||||
|
||||
this.getVisibleRows().forEach((row) => {
|
||||
if(row.type !== "group"){
|
||||
row.modules.vdomHoz.rightCol = this.rightCol;
|
||||
}
|
||||
});
|
||||
|
||||
if(this.rightCol >= (this.columns.length - 1)){
|
||||
this.vDomPadRight = 0;
|
||||
}else{
|
||||
this.vDomPadRight -= column.getWidth();
|
||||
}
|
||||
}else{
|
||||
working = false;
|
||||
}
|
||||
}else{
|
||||
working = false;
|
||||
}
|
||||
}
|
||||
|
||||
if(changes){
|
||||
this.tableElement.style.paddingRight = this.vDomPadRight + "px";
|
||||
}
|
||||
}
|
||||
|
||||
addColLeft(){
|
||||
var changes = false,
|
||||
working = true;
|
||||
|
||||
while(working){
|
||||
let column = this.columns[this.leftCol - 1];
|
||||
|
||||
if(column){
|
||||
if(column.modules.vdomHoz.rightPos >= this.vDomScrollPosLeft){
|
||||
changes = true;
|
||||
|
||||
this.getVisibleRows().forEach((row) => {
|
||||
if(row.type !== "group"){
|
||||
var cell = row.getCell(column);
|
||||
row.getElement().insertBefore(cell.getElement(), row.getCell(this.columns[this.leftCol]).getElement());
|
||||
cell.cellRendered();
|
||||
}
|
||||
});
|
||||
|
||||
this.leftCol--; // don't move this below the <= check below
|
||||
|
||||
this.getVisibleRows().forEach((row) => {
|
||||
if(row.type !== "group"){
|
||||
row.modules.vdomHoz.leftCol = this.leftCol;
|
||||
}
|
||||
});
|
||||
|
||||
if(this.leftCol <= 0){ // replicating logic in addColRight
|
||||
this.vDomPadLeft = 0;
|
||||
}else{
|
||||
this.vDomPadLeft -= column.getWidth();
|
||||
}
|
||||
|
||||
let diff = this.fitDataColActualWidthCheck(column);
|
||||
|
||||
if(diff){
|
||||
this.scrollLeft = this.elementVertical.scrollLeft = this.elementVertical.scrollLeft + diff;
|
||||
this.vDomPadRight -= diff;
|
||||
}
|
||||
|
||||
}else{
|
||||
working = false;
|
||||
}
|
||||
}else{
|
||||
working = false;
|
||||
}
|
||||
}
|
||||
|
||||
if(changes){
|
||||
this.tableElement.style.paddingLeft = this.vDomPadLeft + "px";
|
||||
}
|
||||
}
|
||||
|
||||
removeColRight(){
|
||||
var changes = false,
|
||||
working = true;
|
||||
|
||||
while(working){
|
||||
let column = this.columns[this.rightCol];
|
||||
|
||||
if(column){
|
||||
if(column.modules.vdomHoz.leftPos > this.vDomScrollPosRight){
|
||||
changes = true;
|
||||
|
||||
this.getVisibleRows().forEach((row) => {
|
||||
if(row.type !== "group"){
|
||||
var cell = row.getCell(column);
|
||||
|
||||
try {
|
||||
row.getElement().removeChild(cell.getElement());
|
||||
} catch (ex) {
|
||||
console.warn("Could not removeColRight", ex.message);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
this.vDomPadRight += column.getWidth();
|
||||
this.rightCol --;
|
||||
|
||||
this.getVisibleRows().forEach((row) => {
|
||||
if(row.type !== "group"){
|
||||
row.modules.vdomHoz.rightCol = this.rightCol;
|
||||
}
|
||||
});
|
||||
}else{
|
||||
working = false;
|
||||
}
|
||||
}else{
|
||||
working = false;
|
||||
}
|
||||
}
|
||||
|
||||
if(changes){
|
||||
this.tableElement.style.paddingRight = this.vDomPadRight + "px";
|
||||
}
|
||||
}
|
||||
|
||||
removeColLeft(){
|
||||
var changes = false,
|
||||
working = true;
|
||||
|
||||
while(working){
|
||||
let column = this.columns[this.leftCol];
|
||||
|
||||
if(column){
|
||||
if(column.modules.vdomHoz.rightPos < this.vDomScrollPosLeft){
|
||||
changes = true;
|
||||
|
||||
this.getVisibleRows().forEach((row) => {
|
||||
if(row.type !== "group"){
|
||||
var cell = row.getCell(column);
|
||||
|
||||
try {
|
||||
row.getElement().removeChild(cell.getElement());
|
||||
} catch (ex) {
|
||||
console.warn("Could not removeColLeft", ex.message);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
this.vDomPadLeft += column.getWidth();
|
||||
this.leftCol ++;
|
||||
|
||||
this.getVisibleRows().forEach((row) => {
|
||||
if(row.type !== "group"){
|
||||
row.modules.vdomHoz.leftCol = this.leftCol;
|
||||
}
|
||||
});
|
||||
}else{
|
||||
working = false;
|
||||
}
|
||||
}else{
|
||||
working = false;
|
||||
}
|
||||
}
|
||||
|
||||
if(changes){
|
||||
this.tableElement.style.paddingLeft = this.vDomPadLeft + "px";
|
||||
}
|
||||
}
|
||||
|
||||
fitDataColActualWidthCheck(column){
|
||||
var newWidth, widthDiff;
|
||||
|
||||
if(column.modules.vdomHoz.fitDataCheck){
|
||||
column.reinitializeWidth();
|
||||
|
||||
newWidth = column.getWidth();
|
||||
widthDiff = newWidth - column.modules.vdomHoz.width;
|
||||
|
||||
if(widthDiff){
|
||||
column.modules.vdomHoz.rightPos += widthDiff;
|
||||
column.modules.vdomHoz.width = newWidth;
|
||||
this.colPositionAdjust(this.columns.indexOf(column) + 1, this.columns.length, widthDiff);
|
||||
}
|
||||
|
||||
column.modules.vdomHoz.fitDataCheck = false;
|
||||
}
|
||||
|
||||
return widthDiff;
|
||||
}
|
||||
|
||||
initializeRow(row){
|
||||
if(row.type !== "group"){
|
||||
row.modules.vdomHoz = {
|
||||
leftCol:this.leftCol,
|
||||
rightCol:this.rightCol,
|
||||
};
|
||||
|
||||
if(this.table.modules.frozenColumns){
|
||||
this.table.modules.frozenColumns.leftColumns.forEach((column) => {
|
||||
this.appendCell(row, column);
|
||||
});
|
||||
}
|
||||
|
||||
for(let i = this.leftCol; i <= this.rightCol; i++){
|
||||
this.appendCell(row, this.columns[i]);
|
||||
}
|
||||
|
||||
if(this.table.modules.frozenColumns){
|
||||
this.table.modules.frozenColumns.rightColumns.forEach((column) => {
|
||||
this.appendCell(row, column);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
appendCell(row, column){
|
||||
if(column && column.visible){
|
||||
let cell = row.getCell(column);
|
||||
|
||||
row.getElement().appendChild(cell.getElement());
|
||||
cell.cellRendered();
|
||||
}
|
||||
}
|
||||
|
||||
reinitializeRow(row, force){
|
||||
if(row.type !== "group"){
|
||||
if(force || !row.modules.vdomHoz || row.modules.vdomHoz.leftCol !== this.leftCol || row.modules.vdomHoz.rightCol !== this.rightCol){
|
||||
|
||||
var rowEl = row.getElement();
|
||||
while(rowEl.firstChild) rowEl.removeChild(rowEl.firstChild);
|
||||
|
||||
this.initializeRow(row);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,639 @@
|
||||
import Renderer from '../Renderer.js';
|
||||
import Helpers from '../../tools/Helpers.js';
|
||||
|
||||
export default class VirtualDomVertical extends Renderer{
|
||||
constructor(table){
|
||||
super(table);
|
||||
|
||||
this.verticalFillMode = "fill";
|
||||
|
||||
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 position for last rendered row in the virtual DOM
|
||||
|
||||
this.vDomScrollPosTop = 0; //last scroll position of the vDom top;
|
||||
this.vDomScrollPosBottom = 0; //last scroll position of the vDom bottom;
|
||||
|
||||
this.vDomTopPad = 0; //hold value of padding for top of virtual DOM
|
||||
this.vDomBottomPad = 0; //hold value of padding for bottom of virtual DOM
|
||||
|
||||
this.vDomMaxRenderChain = 90; //the maximum number of dom elements that can be rendered in 1 go
|
||||
|
||||
this.vDomWindowBuffer = 0; //window row buffer before removing elements, to smooth scrolling
|
||||
|
||||
this.vDomWindowMinTotalRows = 20; //minimum number of rows to be generated in virtual dom (prevent buffering issues on tables with tall rows)
|
||||
this.vDomWindowMinMarginRows = 5; //minimum number of rows to be generated in virtual dom margin
|
||||
|
||||
this.vDomTopNewRows = []; //rows to normalize after appending to optimize render speed
|
||||
this.vDomBottomNewRows = []; //rows to normalize after appending to optimize render speed
|
||||
}
|
||||
|
||||
//////////////////////////////////////
|
||||
///////// Public Functions ///////////
|
||||
//////////////////////////////////////
|
||||
|
||||
clearRows(){
|
||||
var element = this.tableElement;
|
||||
|
||||
// element.children.detach();
|
||||
while(element.firstChild) element.removeChild(element.firstChild);
|
||||
|
||||
element.style.paddingTop = "";
|
||||
element.style.paddingBottom = "";
|
||||
element.style.minHeight = "";
|
||||
element.style.display = "";
|
||||
element.style.visibility = "";
|
||||
|
||||
this.elementVertical.scrollTop = 0;
|
||||
this.elementVertical.scrollLeft = 0;
|
||||
|
||||
this.scrollTop = 0;
|
||||
this.scrollLeft = 0;
|
||||
|
||||
this.vDomTop = 0;
|
||||
this.vDomBottom = 0;
|
||||
this.vDomTopPad = 0;
|
||||
this.vDomBottomPad = 0;
|
||||
this.vDomScrollPosTop = 0;
|
||||
this.vDomScrollPosBottom = 0;
|
||||
}
|
||||
|
||||
renderRows(){
|
||||
this._virtualRenderFill();
|
||||
}
|
||||
|
||||
rerenderRows(callback){
|
||||
var scrollTop = this.elementVertical.scrollTop;
|
||||
var topRow = false;
|
||||
var topOffset = false;
|
||||
|
||||
var left = this.table.rowManager.scrollLeft;
|
||||
|
||||
var rows = this.rows();
|
||||
|
||||
for(var i = this.vDomTop; i <= this.vDomBottom; i++){
|
||||
|
||||
if(rows[i]){
|
||||
var diff = scrollTop - rows[i].getElement().offsetTop;
|
||||
|
||||
if(topOffset === false || Math.abs(diff) < topOffset){
|
||||
topOffset = diff;
|
||||
topRow = i;
|
||||
}else{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rows.forEach((row) => {
|
||||
row.deinitializeHeight();
|
||||
});
|
||||
|
||||
if(callback){
|
||||
callback();
|
||||
}
|
||||
|
||||
if(this.rows().length){
|
||||
this._virtualRenderFill((topRow === false ? this.rows.length - 1 : topRow), true, topOffset || 0);
|
||||
}else{
|
||||
this.clear();
|
||||
this.table.rowManager.tableEmpty();
|
||||
}
|
||||
|
||||
this.scrollColumns(left);
|
||||
}
|
||||
|
||||
scrollColumns(left){
|
||||
this.table.rowManager.scrollHorizontal(left);
|
||||
}
|
||||
|
||||
scrollRows(top, dir){
|
||||
var topDiff = top - this.vDomScrollPosTop;
|
||||
var bottomDiff = top - this.vDomScrollPosBottom;
|
||||
var margin = this.vDomWindowBuffer * 2;
|
||||
var rows = this.rows();
|
||||
|
||||
this.scrollTop = top;
|
||||
|
||||
if(-topDiff > margin || bottomDiff > margin){
|
||||
//if big scroll redraw table;
|
||||
var left = this.table.rowManager.scrollLeft;
|
||||
this._virtualRenderFill(Math.floor((this.elementVertical.scrollTop / this.elementVertical.scrollHeight) * rows.length));
|
||||
this.scrollColumns(left);
|
||||
}else{
|
||||
|
||||
if(dir){
|
||||
//scrolling up
|
||||
if(topDiff < 0){
|
||||
this._addTopRow(rows, -topDiff);
|
||||
}
|
||||
|
||||
if(bottomDiff < 0){
|
||||
//hide bottom row if needed
|
||||
if(this.vDomScrollHeight - this.scrollTop > this.vDomWindowBuffer){
|
||||
this._removeBottomRow(rows, -bottomDiff);
|
||||
}else{
|
||||
this.vDomScrollPosBottom = this.scrollTop;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
|
||||
if(bottomDiff >= 0){
|
||||
this._addBottomRow(rows, bottomDiff);
|
||||
}
|
||||
|
||||
//scrolling down
|
||||
if(topDiff >= 0){
|
||||
//hide top row if needed
|
||||
if(this.scrollTop > this.vDomWindowBuffer){
|
||||
this._removeTopRow(rows, topDiff);
|
||||
}else{
|
||||
this.vDomScrollPosTop = this.scrollTop;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resize(){
|
||||
this.vDomWindowBuffer = this.table.options.renderVerticalBuffer || this.elementVertical.clientHeight;
|
||||
}
|
||||
|
||||
scrollToRowNearestTop(row){
|
||||
var rowIndex = this.rows().indexOf(row);
|
||||
|
||||
return !(Math.abs(this.vDomTop - rowIndex) > Math.abs(this.vDomBottom - rowIndex));
|
||||
}
|
||||
|
||||
scrollToRow(row){
|
||||
var index = this.rows().indexOf(row);
|
||||
|
||||
if(index > -1){
|
||||
this._virtualRenderFill(index, true);
|
||||
}
|
||||
}
|
||||
|
||||
visibleRows(includingBuffer){
|
||||
var topEdge = this.elementVertical.scrollTop,
|
||||
bottomEdge = this.elementVertical.clientHeight + topEdge,
|
||||
topFound = false,
|
||||
topRow = 0,
|
||||
bottomRow = 0,
|
||||
rows = this.rows();
|
||||
|
||||
if(includingBuffer){
|
||||
topRow = this.vDomTop;
|
||||
bottomRow = this.vDomBottom;
|
||||
}else{
|
||||
for(var i = this.vDomTop; i <= this.vDomBottom; i++){
|
||||
if(rows[i]){
|
||||
if(!topFound){
|
||||
if((topEdge - rows[i].getElement().offsetTop) >= 0){
|
||||
topRow = i;
|
||||
}else{
|
||||
topFound = true;
|
||||
|
||||
if(bottomEdge - rows[i].getElement().offsetTop >= 0){
|
||||
bottomRow = i;
|
||||
}else{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
if(bottomEdge - rows[i].getElement().offsetTop >= 0){
|
||||
bottomRow = i;
|
||||
}else{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return rows.slice(topRow, bottomRow + 1);
|
||||
}
|
||||
|
||||
//////////////////////////////////////
|
||||
//////// Internal Rendering //////////
|
||||
//////////////////////////////////////
|
||||
|
||||
//full virtual render
|
||||
_virtualRenderFill(position, forceMove, offset) {
|
||||
var element = this.tableElement,
|
||||
holder = this.elementVertical,
|
||||
topPad = 0,
|
||||
rowsHeight = 0,
|
||||
rowHeight = 0,
|
||||
heightOccupied = 0,
|
||||
topPadHeight = 0,
|
||||
i = 0,
|
||||
rows = this.rows(),
|
||||
rowsCount = rows.length,
|
||||
index = 0,
|
||||
row,
|
||||
rowFragment,
|
||||
renderedRows = [],
|
||||
totalRowsRendered = 0,
|
||||
rowsToRender = 0,
|
||||
fixedHeight = this.table.rowManager.fixedHeight,
|
||||
containerHeight = this.elementVertical.clientHeight,
|
||||
avgRowHeight = this.table.options.rowHeight,
|
||||
resized = true;
|
||||
|
||||
position = position || 0;
|
||||
|
||||
offset = offset || 0;
|
||||
|
||||
if(!position){
|
||||
this.clear();
|
||||
}else {
|
||||
while(element.firstChild) element.removeChild(element.firstChild);
|
||||
|
||||
//check if position is too close to bottom of table
|
||||
heightOccupied = (rowsCount - position + 1) * this.vDomRowHeight;
|
||||
|
||||
if(heightOccupied < containerHeight){
|
||||
position -= Math.ceil((containerHeight - heightOccupied) / this.vDomRowHeight);
|
||||
if(position < 0){
|
||||
position = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//calculate initial pad
|
||||
topPad = Math.min(Math.max(Math.floor(this.vDomWindowBuffer / this.vDomRowHeight), this.vDomWindowMinMarginRows), position);
|
||||
position -= topPad;
|
||||
}
|
||||
|
||||
if(rowsCount && Helpers.elVisible(this.elementVertical)){
|
||||
this.vDomTop = position;
|
||||
this.vDomBottom = position -1;
|
||||
|
||||
if(fixedHeight || this.table.options.maxHeight) {
|
||||
if(avgRowHeight) {
|
||||
rowsToRender = (containerHeight / avgRowHeight) + (this.vDomWindowBuffer / avgRowHeight);
|
||||
}
|
||||
rowsToRender = Math.max(this.vDomWindowMinTotalRows, Math.ceil(rowsToRender));
|
||||
}
|
||||
else {
|
||||
rowsToRender = rowsCount;
|
||||
}
|
||||
|
||||
while(((rowsToRender == rowsCount || rowsHeight <= containerHeight + this.vDomWindowBuffer) || totalRowsRendered < this.vDomWindowMinTotalRows) && this.vDomBottom < rowsCount -1) {
|
||||
renderedRows = [];
|
||||
rowFragment = document.createDocumentFragment();
|
||||
|
||||
i = 0;
|
||||
|
||||
while ((i < rowsToRender) && this.vDomBottom < rowsCount -1) {
|
||||
index = this.vDomBottom + 1,
|
||||
row = rows[index];
|
||||
|
||||
this.styleRow(row, index);
|
||||
|
||||
row.initialize(false, true);
|
||||
if(!row.heightInitialized && !this.table.options.rowHeight){
|
||||
row.clearCellHeight();
|
||||
}
|
||||
|
||||
rowFragment.appendChild(row.getElement());
|
||||
renderedRows.push(row);
|
||||
this.vDomBottom ++;
|
||||
i++;
|
||||
}
|
||||
|
||||
if(!renderedRows.length){
|
||||
break;
|
||||
}
|
||||
|
||||
element.appendChild(rowFragment);
|
||||
|
||||
// NOTE: The next 4 loops are separate on purpose
|
||||
// This is to batch up the dom writes and reads which drastically improves performance
|
||||
|
||||
renderedRows.forEach((row) => {
|
||||
row.rendered();
|
||||
});
|
||||
|
||||
const rowsNeedingHeightInit = [];
|
||||
renderedRows.forEach((row) => {
|
||||
if(!row.heightInitialized) {
|
||||
row.calcHeight(true);
|
||||
rowsNeedingHeightInit.push(row);
|
||||
}
|
||||
});
|
||||
|
||||
rowsNeedingHeightInit.forEach((row) => {
|
||||
row.setCellHeight();
|
||||
});
|
||||
|
||||
renderedRows.forEach((row) => {
|
||||
rowHeight = row.getHeight();
|
||||
|
||||
if(totalRowsRendered < topPad){
|
||||
topPadHeight += rowHeight;
|
||||
}else {
|
||||
rowsHeight += rowHeight;
|
||||
}
|
||||
|
||||
if(rowHeight > this.vDomWindowBuffer){
|
||||
this.vDomWindowBuffer = rowHeight * 2;
|
||||
}
|
||||
totalRowsRendered++;
|
||||
});
|
||||
|
||||
resized = this.table.rowManager.adjustTableSize();
|
||||
containerHeight = this.elementVertical.clientHeight;
|
||||
if(resized && (fixedHeight || this.table.options.maxHeight))
|
||||
{
|
||||
avgRowHeight = rowsHeight / totalRowsRendered;
|
||||
rowsToRender = Math.max(this.vDomWindowMinTotalRows, Math.ceil((containerHeight / avgRowHeight) + (this.vDomWindowBuffer / avgRowHeight)));
|
||||
}
|
||||
}
|
||||
|
||||
if(!position){
|
||||
this.vDomTopPad = 0;
|
||||
//adjust row height to match average of rendered elements
|
||||
this.vDomRowHeight = Math.floor((rowsHeight + topPadHeight) / totalRowsRendered);
|
||||
this.vDomBottomPad = this.vDomRowHeight * (rowsCount - this.vDomBottom -1);
|
||||
|
||||
this.vDomScrollHeight = topPadHeight + rowsHeight + this.vDomBottomPad - containerHeight;
|
||||
}else {
|
||||
this.vDomTopPad = !forceMove ? this.scrollTop - topPadHeight : (this.vDomRowHeight * this.vDomTop) + offset;
|
||||
this.vDomBottomPad = this.vDomBottom == rowsCount-1 ? 0 : Math.max(this.vDomScrollHeight - this.vDomTopPad - rowsHeight - topPadHeight, 0);
|
||||
}
|
||||
|
||||
element.style.paddingTop = this.vDomTopPad+"px";
|
||||
element.style.paddingBottom = this.vDomBottomPad+"px";
|
||||
|
||||
if(forceMove){
|
||||
this.scrollTop = this.vDomTopPad + (topPadHeight) + offset - (this.elementVertical.scrollWidth > this.elementVertical.clientWidth ? this.elementVertical.offsetHeight - containerHeight : 0);
|
||||
}
|
||||
|
||||
this.scrollTop = Math.min(this.scrollTop, this.elementVertical.scrollHeight - containerHeight);
|
||||
|
||||
//adjust for horizontal scrollbar if present (and not at top of table)
|
||||
if(this.elementVertical.scrollWidth > this.elementVertical.clientWidth && forceMove){
|
||||
this.scrollTop += this.elementVertical.offsetHeight - containerHeight;
|
||||
}
|
||||
|
||||
this.vDomScrollPosTop = this.scrollTop;
|
||||
this.vDomScrollPosBottom = this.scrollTop;
|
||||
|
||||
holder.scrollTop = this.scrollTop;
|
||||
|
||||
this.dispatch("render-virtual-fill");
|
||||
}
|
||||
}
|
||||
|
||||
_addTopRow(rows, fillableSpace){
|
||||
var table = this.tableElement,
|
||||
addedRows = [],
|
||||
paddingAdjust = 0,
|
||||
index = this.vDomTop -1,
|
||||
i = 0,
|
||||
working = true;
|
||||
|
||||
while(working){
|
||||
if(this.vDomTop){
|
||||
let row = rows[index],
|
||||
rowHeight, initialized;
|
||||
|
||||
if(row && i < this.vDomMaxRenderChain){
|
||||
rowHeight = row.getHeight() || this.vDomRowHeight;
|
||||
initialized = row.initialized;
|
||||
|
||||
if(fillableSpace >= rowHeight){
|
||||
|
||||
this.styleRow(row, index);
|
||||
table.insertBefore(row.getElement(), table.firstChild);
|
||||
|
||||
if(!row.initialized || !row.heightInitialized){
|
||||
addedRows.push(row);
|
||||
}
|
||||
|
||||
row.initialize();
|
||||
|
||||
if(!initialized){
|
||||
rowHeight = row.getElement().offsetHeight;
|
||||
|
||||
if(rowHeight > this.vDomWindowBuffer){
|
||||
this.vDomWindowBuffer = rowHeight * 2;
|
||||
}
|
||||
}
|
||||
|
||||
fillableSpace -= rowHeight;
|
||||
paddingAdjust += rowHeight;
|
||||
|
||||
this.vDomTop--;
|
||||
index--;
|
||||
i++;
|
||||
|
||||
}else{
|
||||
working = false;
|
||||
}
|
||||
|
||||
}else{
|
||||
working = false;
|
||||
}
|
||||
|
||||
}else{
|
||||
working = false;
|
||||
}
|
||||
}
|
||||
|
||||
for (let row of addedRows){
|
||||
row.clearCellHeight();
|
||||
}
|
||||
|
||||
this._quickNormalizeRowHeight(addedRows);
|
||||
|
||||
if(paddingAdjust){
|
||||
this.vDomTopPad -= paddingAdjust;
|
||||
|
||||
if(this.vDomTopPad < 0){
|
||||
this.vDomTopPad = index * this.vDomRowHeight;
|
||||
}
|
||||
|
||||
if(index < 1){
|
||||
this.vDomTopPad = 0;
|
||||
}
|
||||
|
||||
table.style.paddingTop = this.vDomTopPad + "px";
|
||||
this.vDomScrollPosTop -= paddingAdjust;
|
||||
}
|
||||
}
|
||||
|
||||
_removeTopRow(rows, fillableSpace){
|
||||
var removableRows = [],
|
||||
paddingAdjust = 0,
|
||||
i = 0,
|
||||
working = true;
|
||||
|
||||
while(working){
|
||||
let row = rows[this.vDomTop],
|
||||
rowHeight;
|
||||
|
||||
if(row && i < this.vDomMaxRenderChain){
|
||||
rowHeight = row.getHeight() || this.vDomRowHeight;
|
||||
|
||||
if(fillableSpace >= rowHeight){
|
||||
this.vDomTop++;
|
||||
|
||||
fillableSpace -= rowHeight;
|
||||
paddingAdjust += rowHeight;
|
||||
|
||||
removableRows.push(row);
|
||||
i++;
|
||||
}else{
|
||||
working = false;
|
||||
}
|
||||
}else{
|
||||
working = false;
|
||||
}
|
||||
}
|
||||
|
||||
for (let row of removableRows){
|
||||
let rowEl = row.getElement();
|
||||
|
||||
if(rowEl.parentNode){
|
||||
rowEl.parentNode.removeChild(rowEl);
|
||||
}
|
||||
}
|
||||
|
||||
if(paddingAdjust){
|
||||
this.vDomTopPad += paddingAdjust;
|
||||
this.tableElement.style.paddingTop = this.vDomTopPad + "px";
|
||||
this.vDomScrollPosTop += this.vDomTop ? paddingAdjust : paddingAdjust + this.vDomWindowBuffer;
|
||||
}
|
||||
}
|
||||
|
||||
_addBottomRow(rows, fillableSpace){
|
||||
var table = this.tableElement,
|
||||
addedRows = [],
|
||||
paddingAdjust = 0,
|
||||
index = this.vDomBottom + 1,
|
||||
i = 0,
|
||||
working = true;
|
||||
|
||||
while(working){
|
||||
let row = rows[index],
|
||||
rowHeight, initialized;
|
||||
|
||||
if(row && i < this.vDomMaxRenderChain){
|
||||
rowHeight = row.getHeight() || this.vDomRowHeight;
|
||||
initialized = row.initialized;
|
||||
|
||||
if(fillableSpace >= rowHeight){
|
||||
|
||||
this.styleRow(row, index);
|
||||
table.appendChild(row.getElement());
|
||||
|
||||
if(!row.initialized || !row.heightInitialized){
|
||||
addedRows.push(row);
|
||||
}
|
||||
|
||||
row.initialize();
|
||||
|
||||
if(!initialized){
|
||||
rowHeight = row.getElement().offsetHeight;
|
||||
|
||||
if(rowHeight > this.vDomWindowBuffer){
|
||||
this.vDomWindowBuffer = rowHeight * 2;
|
||||
}
|
||||
}
|
||||
|
||||
fillableSpace -= rowHeight;
|
||||
paddingAdjust += rowHeight;
|
||||
|
||||
this.vDomBottom++;
|
||||
index++;
|
||||
i++;
|
||||
}else{
|
||||
working = false;
|
||||
}
|
||||
}else{
|
||||
working = false;
|
||||
}
|
||||
}
|
||||
|
||||
for (let row of addedRows){
|
||||
row.clearCellHeight();
|
||||
}
|
||||
|
||||
this._quickNormalizeRowHeight(addedRows);
|
||||
|
||||
if(paddingAdjust){
|
||||
this.vDomBottomPad -= paddingAdjust;
|
||||
|
||||
if(this.vDomBottomPad < 0 || index == rows.length -1){
|
||||
this.vDomBottomPad = 0;
|
||||
}
|
||||
|
||||
table.style.paddingBottom = this.vDomBottomPad + "px";
|
||||
this.vDomScrollPosBottom += paddingAdjust;
|
||||
}
|
||||
}
|
||||
|
||||
_removeBottomRow(rows, fillableSpace){
|
||||
var removableRows = [],
|
||||
paddingAdjust = 0,
|
||||
i = 0,
|
||||
working = true;
|
||||
|
||||
while(working){
|
||||
let row = rows[this.vDomBottom],
|
||||
rowHeight;
|
||||
|
||||
if(row && i < this.vDomMaxRenderChain){
|
||||
rowHeight = row.getHeight() || this.vDomRowHeight;
|
||||
|
||||
if(fillableSpace >= rowHeight){
|
||||
this.vDomBottom --;
|
||||
|
||||
fillableSpace -= rowHeight;
|
||||
paddingAdjust += rowHeight;
|
||||
|
||||
removableRows.push(row);
|
||||
i++;
|
||||
}else{
|
||||
working = false;
|
||||
}
|
||||
}else{
|
||||
working = false;
|
||||
}
|
||||
}
|
||||
|
||||
for (let row of removableRows){
|
||||
let rowEl = row.getElement();
|
||||
|
||||
if(rowEl.parentNode){
|
||||
rowEl.parentNode.removeChild(rowEl);
|
||||
}
|
||||
}
|
||||
|
||||
if(paddingAdjust){
|
||||
this.vDomBottomPad += paddingAdjust;
|
||||
|
||||
if(this.vDomBottomPad < 0){
|
||||
this.vDomBottomPad = 0;
|
||||
}
|
||||
|
||||
this.tableElement.style.paddingBottom = this.vDomBottomPad + "px";
|
||||
this.vDomScrollPosBottom -= paddingAdjust;
|
||||
}
|
||||
}
|
||||
|
||||
_quickNormalizeRowHeight(rows){
|
||||
for(let row of rows){
|
||||
row.calcHeight();
|
||||
}
|
||||
|
||||
for(let row of rows){
|
||||
row.setCellHeight();
|
||||
}
|
||||
}
|
||||
}
|
||||
47
public/libs/tabulator-master/src/js/core/row/PseudoRow.js
Normal file
47
public/libs/tabulator-master/src/js/core/row/PseudoRow.js
Normal file
@@ -0,0 +1,47 @@
|
||||
export default class PseudoRow {
|
||||
|
||||
constructor (type){
|
||||
this.type = type;
|
||||
this.element = this._createElement();
|
||||
}
|
||||
|
||||
_createElement(){
|
||||
var el = document.createElement("div");
|
||||
el.classList.add("tabulator-row");
|
||||
return el;
|
||||
}
|
||||
|
||||
getElement(){
|
||||
return this.element;
|
||||
}
|
||||
|
||||
getComponent(){
|
||||
return false;
|
||||
}
|
||||
|
||||
getData(){
|
||||
return {};
|
||||
}
|
||||
|
||||
getHeight(){
|
||||
return this.element.outerHeight;
|
||||
}
|
||||
|
||||
initialize(){}
|
||||
|
||||
reinitialize(){}
|
||||
|
||||
normalizeHeight(){}
|
||||
|
||||
generateCells(){}
|
||||
|
||||
reinitializeHeight(){}
|
||||
|
||||
calcHeight(){}
|
||||
|
||||
setCellHeight(){}
|
||||
|
||||
clearCellHeight(){}
|
||||
|
||||
rendered(){}
|
||||
}
|
||||
487
public/libs/tabulator-master/src/js/core/row/Row.js
Normal file
487
public/libs/tabulator-master/src/js/core/row/Row.js
Normal file
@@ -0,0 +1,487 @@
|
||||
import CoreFeature from '../CoreFeature.js';
|
||||
import RowComponent from './RowComponent.js';
|
||||
import Helpers from '../tools/Helpers.js';
|
||||
|
||||
export default class Row extends CoreFeature{
|
||||
constructor (data, parent, type = "row"){
|
||||
super(parent.table);
|
||||
|
||||
this.parent = parent;
|
||||
this.data = {};
|
||||
this.type = type; //type of element
|
||||
this.element = false;
|
||||
this.modules = {}; //hold module variables;
|
||||
this.cells = [];
|
||||
this.height = 0; //hold element height
|
||||
this.heightStyled = ""; //hold element height pre-styled to improve render efficiency
|
||||
this.manualHeight = false; //user has manually set row height
|
||||
this.outerHeight = 0; //hold elements outer height
|
||||
this.initialized = false; //element has been rendered
|
||||
this.heightInitialized = false; //element has resized cells to fit
|
||||
this.position = 0; //store position of element in row list
|
||||
this.positionWatchers = [];
|
||||
|
||||
this.component = null;
|
||||
|
||||
this.created = false;
|
||||
|
||||
this.setData(data);
|
||||
}
|
||||
|
||||
create(){
|
||||
if(!this.created){
|
||||
this.created = true;
|
||||
this.generateElement();
|
||||
}
|
||||
}
|
||||
|
||||
createElement (){
|
||||
var el = document.createElement("div");
|
||||
|
||||
el.classList.add("tabulator-row");
|
||||
el.setAttribute("role", "row");
|
||||
|
||||
this.element = el;
|
||||
}
|
||||
|
||||
getElement(){
|
||||
this.create();
|
||||
return this.element;
|
||||
}
|
||||
|
||||
detachElement(){
|
||||
if (this.element && this.element.parentNode){
|
||||
this.element.parentNode.removeChild(this.element);
|
||||
}
|
||||
}
|
||||
|
||||
generateElement(){
|
||||
this.createElement();
|
||||
this.dispatch("row-init", this);
|
||||
}
|
||||
|
||||
generateCells(){
|
||||
this.cells = this.table.columnManager.generateCells(this);
|
||||
}
|
||||
|
||||
//functions to setup on first render
|
||||
initialize(force, inFragment){
|
||||
this.create();
|
||||
|
||||
if(!this.initialized || force){
|
||||
|
||||
this.deleteCells();
|
||||
|
||||
while(this.element.firstChild) this.element.removeChild(this.element.firstChild);
|
||||
|
||||
this.dispatch("row-layout-before", this);
|
||||
|
||||
this.generateCells();
|
||||
|
||||
this.initialized = true;
|
||||
|
||||
this.table.columnManager.renderer.renderRowCells(this, inFragment);
|
||||
|
||||
if(force){
|
||||
this.normalizeHeight();
|
||||
}
|
||||
|
||||
this.dispatch("row-layout", this);
|
||||
|
||||
if(this.table.options.rowFormatter){
|
||||
this.table.options.rowFormatter(this.getComponent());
|
||||
}
|
||||
|
||||
this.dispatch("row-layout-after", this);
|
||||
}else{
|
||||
this.table.columnManager.renderer.rerenderRowCells(this, inFragment);
|
||||
}
|
||||
}
|
||||
|
||||
rendered(){
|
||||
this.cells.forEach((cell) => {
|
||||
cell.cellRendered();
|
||||
});
|
||||
}
|
||||
|
||||
reinitializeHeight(){
|
||||
this.heightInitialized = false;
|
||||
|
||||
if(this.element && this.element.offsetParent !== null){
|
||||
this.normalizeHeight(true);
|
||||
}
|
||||
}
|
||||
|
||||
deinitialize(){
|
||||
this.initialized = false;
|
||||
}
|
||||
|
||||
deinitializeHeight(){
|
||||
this.heightInitialized = false;
|
||||
}
|
||||
|
||||
reinitialize(children){
|
||||
this.initialized = false;
|
||||
this.heightInitialized = false;
|
||||
|
||||
if(!this.manualHeight){
|
||||
this.height = 0;
|
||||
this.heightStyled = "";
|
||||
}
|
||||
|
||||
if(this.element && this.element.offsetParent !== null){
|
||||
this.initialize(true);
|
||||
}
|
||||
|
||||
this.dispatch("row-relayout", this);
|
||||
}
|
||||
|
||||
//get heights when doing bulk row style calcs in virtual DOM
|
||||
calcHeight(force){
|
||||
var maxHeight = 0, minHeight = 0;
|
||||
|
||||
if(this.table.options.rowHeight){
|
||||
this.height = this.table.options.rowHeight;
|
||||
}else{
|
||||
minHeight = this.calcMinHeight();
|
||||
maxHeight = this.calcMaxHeight();
|
||||
|
||||
if(force){
|
||||
this.height = Math.max(maxHeight, minHeight);
|
||||
}else{
|
||||
this.height = this.manualHeight ? this.height : Math.max(maxHeight, minHeight);
|
||||
}
|
||||
}
|
||||
|
||||
this.heightStyled = this.height ? this.height + "px" : "";
|
||||
this.outerHeight = this.element.offsetHeight;
|
||||
}
|
||||
|
||||
calcMinHeight(){
|
||||
return this.table.options.resizableRows ? this.element.clientHeight : 0;
|
||||
}
|
||||
|
||||
calcMaxHeight(){
|
||||
var maxHeight = 0;
|
||||
|
||||
this.cells.forEach(function(cell){
|
||||
var height = cell.getHeight();
|
||||
|
||||
if(height > maxHeight){
|
||||
maxHeight = height;
|
||||
}
|
||||
});
|
||||
|
||||
return maxHeight;
|
||||
}
|
||||
|
||||
//set of cells
|
||||
setCellHeight(){
|
||||
this.cells.forEach(function(cell){
|
||||
cell.setHeight();
|
||||
});
|
||||
|
||||
this.heightInitialized = true;
|
||||
}
|
||||
|
||||
clearCellHeight(){
|
||||
this.cells.forEach(function(cell){
|
||||
cell.clearHeight();
|
||||
});
|
||||
}
|
||||
|
||||
//normalize the height of elements in the row
|
||||
normalizeHeight(force){
|
||||
if(force && !this.table.options.rowHeight){
|
||||
this.clearCellHeight();
|
||||
}
|
||||
|
||||
this.calcHeight(force);
|
||||
|
||||
this.setCellHeight();
|
||||
}
|
||||
|
||||
//set height of rows
|
||||
setHeight(height, force){
|
||||
if(this.height != height || force){
|
||||
|
||||
this.manualHeight = true;
|
||||
|
||||
this.height = height;
|
||||
this.heightStyled = height ? height + "px" : "";
|
||||
|
||||
this.setCellHeight();
|
||||
|
||||
// this.outerHeight = this.element.outerHeight();
|
||||
this.outerHeight = this.element.offsetHeight;
|
||||
|
||||
if(this.subscribedExternal("rowHeight")){
|
||||
this.dispatchExternal("rowHeight", this.getComponent());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//return rows outer height
|
||||
getHeight(){
|
||||
return this.outerHeight;
|
||||
}
|
||||
|
||||
//return rows outer Width
|
||||
getWidth(){
|
||||
return this.element.offsetWidth;
|
||||
}
|
||||
|
||||
//////////////// Cell Management /////////////////
|
||||
deleteCell(cell){
|
||||
var index = this.cells.indexOf(cell);
|
||||
|
||||
if(index > -1){
|
||||
this.cells.splice(index, 1);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////// Data Management /////////////////
|
||||
setData(data){
|
||||
this.data = this.chain("row-data-init-before", [this, data], undefined, data);
|
||||
|
||||
this.dispatch("row-data-init-after", this);
|
||||
}
|
||||
|
||||
//update the rows data
|
||||
updateData(updatedData){
|
||||
var visible = this.element && Helpers.elVisible(this.element),
|
||||
tempData = {},
|
||||
newRowData;
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
|
||||
if(typeof updatedData === "string"){
|
||||
updatedData = JSON.parse(updatedData);
|
||||
}
|
||||
|
||||
this.dispatch("row-data-save-before", this);
|
||||
|
||||
if(this.subscribed("row-data-changing")){
|
||||
tempData = Object.assign(tempData, this.data);
|
||||
tempData = Object.assign(tempData, updatedData);
|
||||
}
|
||||
|
||||
newRowData = this.chain("row-data-changing", [this, tempData, updatedData], null, updatedData);
|
||||
|
||||
// compute cells to update
|
||||
// This must be done prior to updating the row data otherwise uninitialized cells get
|
||||
// generated directly with the updated data, which prevents the run of callbacks
|
||||
// registered on cells updates (e.g. mutators)
|
||||
const cellsToUpdate = [];
|
||||
for (let attrname in updatedData) {
|
||||
|
||||
let columns = this.table.columnManager.getColumnsByFieldRoot(attrname);
|
||||
|
||||
columns.forEach((column) => {
|
||||
let cell = this.getCell(column.getField());
|
||||
|
||||
if(cell){
|
||||
let value = column.getFieldValue(newRowData);
|
||||
if(cell.getValue() !== value){
|
||||
cellsToUpdate.push([cell, value]);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//set data
|
||||
for (let attrname in newRowData) {
|
||||
this.data[attrname] = newRowData[attrname];
|
||||
}
|
||||
|
||||
this.dispatch("row-data-save-after", this);
|
||||
|
||||
//update affected cells only
|
||||
cellsToUpdate.forEach(([cell, value]) => {
|
||||
cell.setValueProcessData(value);
|
||||
|
||||
if(visible){
|
||||
cell.cellRendered();
|
||||
}
|
||||
});
|
||||
|
||||
//Partial reinitialization if visible
|
||||
if(visible){
|
||||
this.normalizeHeight(true);
|
||||
|
||||
if(this.table.options.rowFormatter){
|
||||
this.table.options.rowFormatter(this.getComponent());
|
||||
}
|
||||
}else{
|
||||
this.initialized = false;
|
||||
this.height = 0;
|
||||
this.heightStyled = "";
|
||||
}
|
||||
|
||||
this.dispatch("row-data-changed", this, visible, updatedData);
|
||||
|
||||
//this.reinitialize();
|
||||
|
||||
this.dispatchExternal("rowUpdated", this.getComponent());
|
||||
|
||||
if(this.subscribedExternal("dataChanged")){
|
||||
this.dispatchExternal("dataChanged", this.table.rowManager.getData());
|
||||
}
|
||||
|
||||
resolve();
|
||||
});
|
||||
}
|
||||
|
||||
getData(transform){
|
||||
if(transform){
|
||||
return this.chain("row-data-retrieve", [this, transform], null, this.data);
|
||||
}
|
||||
|
||||
return this.data;
|
||||
}
|
||||
|
||||
getCell(column){
|
||||
var match = false;
|
||||
|
||||
column = this.table.columnManager.findColumn(column);
|
||||
|
||||
if(!this.initialized && this.cells.length === 0){
|
||||
this.generateCells();
|
||||
}
|
||||
|
||||
match = this.cells.find(function(cell){
|
||||
return cell.column === column;
|
||||
});
|
||||
|
||||
return match;
|
||||
}
|
||||
|
||||
getCellIndex(findCell){
|
||||
return this.cells.findIndex(function(cell){
|
||||
return cell === findCell;
|
||||
});
|
||||
}
|
||||
|
||||
findCell(subject){
|
||||
return this.cells.find((cell) => {
|
||||
return cell.element === subject;
|
||||
});
|
||||
}
|
||||
|
||||
getCells(){
|
||||
if(!this.initialized && this.cells.length === 0){
|
||||
this.generateCells();
|
||||
}
|
||||
|
||||
return this.cells;
|
||||
}
|
||||
|
||||
nextRow(){
|
||||
var row = this.table.rowManager.nextDisplayRow(this, true);
|
||||
return row || false;
|
||||
}
|
||||
|
||||
prevRow(){
|
||||
var row = this.table.rowManager.prevDisplayRow(this, true);
|
||||
return row || false;
|
||||
}
|
||||
|
||||
moveToRow(to, before){
|
||||
var toRow = this.table.rowManager.findRow(to);
|
||||
|
||||
if(toRow){
|
||||
this.table.rowManager.moveRowActual(this, toRow, !before);
|
||||
this.table.rowManager.refreshActiveData("display", false, true);
|
||||
}else{
|
||||
console.warn("Move Error - No matching row found:", to);
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////// Actions /////////////////////
|
||||
delete(){
|
||||
this.dispatch("row-delete", this);
|
||||
|
||||
this.deleteActual();
|
||||
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
deleteActual(blockRedraw){
|
||||
this.detachModules();
|
||||
|
||||
this.table.rowManager.deleteRow(this, blockRedraw);
|
||||
|
||||
this.deleteCells();
|
||||
|
||||
this.initialized = false;
|
||||
this.heightInitialized = false;
|
||||
this.element = false;
|
||||
|
||||
this.dispatch("row-deleted", this);
|
||||
}
|
||||
|
||||
detachModules(){
|
||||
this.dispatch("row-deleting", this);
|
||||
}
|
||||
|
||||
deleteCells(){
|
||||
var cellCount = this.cells.length;
|
||||
|
||||
for(let i = 0; i < cellCount; i++){
|
||||
this.cells[0].delete();
|
||||
}
|
||||
}
|
||||
|
||||
wipe(){
|
||||
this.detachModules();
|
||||
this.deleteCells();
|
||||
|
||||
if(this.element){
|
||||
while(this.element.firstChild) this.element.removeChild(this.element.firstChild);
|
||||
|
||||
if(this.element.parentNode){
|
||||
this.element.parentNode.removeChild(this.element);
|
||||
}
|
||||
}
|
||||
|
||||
this.element = false;
|
||||
this.modules = {};
|
||||
}
|
||||
|
||||
isDisplayed(){
|
||||
return this.table.rowManager.getDisplayRows().includes(this);
|
||||
}
|
||||
|
||||
getPosition(){
|
||||
return this.isDisplayed() ? this.position : false;
|
||||
}
|
||||
|
||||
setPosition(position){
|
||||
if(position != this.position){
|
||||
this.position = position;
|
||||
|
||||
this.positionWatchers.forEach((callback) => {
|
||||
callback(this.position);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
watchPosition(callback){
|
||||
this.positionWatchers.push(callback);
|
||||
|
||||
callback(this.position);
|
||||
}
|
||||
|
||||
getGroup(){
|
||||
return this.modules.group || false;
|
||||
}
|
||||
|
||||
//////////////// Object Generation /////////////////
|
||||
getComponent(){
|
||||
if(!this.component){
|
||||
this.component = new RowComponent(this);
|
||||
}
|
||||
|
||||
return this.component;
|
||||
}
|
||||
}
|
||||
94
public/libs/tabulator-master/src/js/core/row/RowComponent.js
Normal file
94
public/libs/tabulator-master/src/js/core/row/RowComponent.js
Normal file
@@ -0,0 +1,94 @@
|
||||
//public row object
|
||||
export default class RowComponent {
|
||||
|
||||
constructor (row){
|
||||
this._row = row;
|
||||
|
||||
return new Proxy(this, {
|
||||
get: function(target, name, receiver) {
|
||||
if (typeof target[name] !== "undefined") {
|
||||
return target[name];
|
||||
}else{
|
||||
return target._row.table.componentFunctionBinder.handle("row", target._row, name);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
getData(transform){
|
||||
return this._row.getData(transform);
|
||||
}
|
||||
|
||||
getElement(){
|
||||
return this._row.getElement();
|
||||
}
|
||||
|
||||
getCells(){
|
||||
var cells = [];
|
||||
|
||||
this._row.getCells().forEach(function(cell){
|
||||
cells.push(cell.getComponent());
|
||||
});
|
||||
|
||||
return cells;
|
||||
}
|
||||
|
||||
getCell(column){
|
||||
var cell = this._row.getCell(column);
|
||||
return cell ? cell.getComponent() : false;
|
||||
}
|
||||
|
||||
getIndex(){
|
||||
return this._row.getData("data")[this._row.table.options.index];
|
||||
}
|
||||
|
||||
getPosition(){
|
||||
return this._row.getPosition();
|
||||
}
|
||||
|
||||
watchPosition(callback){
|
||||
return this._row.watchPosition(callback);
|
||||
}
|
||||
|
||||
delete(){
|
||||
return this._row.delete();
|
||||
}
|
||||
|
||||
scrollTo(position, ifVisible){
|
||||
return this._row.table.rowManager.scrollToRow(this._row, position, ifVisible);
|
||||
}
|
||||
|
||||
move(to, after){
|
||||
this._row.moveToRow(to, after);
|
||||
}
|
||||
|
||||
update(data){
|
||||
return this._row.updateData(data);
|
||||
}
|
||||
|
||||
normalizeHeight(){
|
||||
this._row.normalizeHeight(true);
|
||||
}
|
||||
|
||||
_getSelf(){
|
||||
return this._row;
|
||||
}
|
||||
|
||||
reformat(){
|
||||
return this._row.reinitialize();
|
||||
}
|
||||
|
||||
getTable(){
|
||||
return this._row.table;
|
||||
}
|
||||
|
||||
getNextRow(){
|
||||
var row = this._row.nextRow();
|
||||
return row ? row.getComponent() : row;
|
||||
}
|
||||
|
||||
getPrevRow(){
|
||||
var row = this._row.prevRow();
|
||||
return row ? row.getComponent() : row;
|
||||
}
|
||||
}
|
||||
66
public/libs/tabulator-master/src/js/core/tools/Alert.js
Normal file
66
public/libs/tabulator-master/src/js/core/tools/Alert.js
Normal file
@@ -0,0 +1,66 @@
|
||||
import CoreFeature from '../CoreFeature.js';
|
||||
|
||||
export default class Alert extends CoreFeature{
|
||||
constructor(table){
|
||||
super(table);
|
||||
|
||||
this.element = this._createAlertElement();
|
||||
this.msgElement = this._createMsgElement();
|
||||
this.type = null;
|
||||
|
||||
this.element.appendChild(this.msgElement);
|
||||
}
|
||||
|
||||
_createAlertElement(){
|
||||
var el = document.createElement("div");
|
||||
el.classList.add("tabulator-alert");
|
||||
return el;
|
||||
}
|
||||
|
||||
_createMsgElement(){
|
||||
var el = document.createElement("div");
|
||||
el.classList.add("tabulator-alert-msg");
|
||||
el.setAttribute("role", "alert");
|
||||
return el;
|
||||
}
|
||||
|
||||
_typeClass(){
|
||||
return "tabulator-alert-state-" + this.type;
|
||||
}
|
||||
|
||||
alert(content, type = "msg"){
|
||||
if(content){
|
||||
this.clear();
|
||||
|
||||
this.dispatch("alert-show", type);
|
||||
|
||||
this.type = type;
|
||||
|
||||
while(this.msgElement.firstChild) this.msgElement.removeChild(this.msgElement.firstChild);
|
||||
|
||||
this.msgElement.classList.add(this._typeClass());
|
||||
|
||||
if(typeof content === "function"){
|
||||
content = content();
|
||||
}
|
||||
|
||||
if(content instanceof HTMLElement){
|
||||
this.msgElement.appendChild(content);
|
||||
}else{
|
||||
this.msgElement.innerHTML = content;
|
||||
}
|
||||
|
||||
this.table.element.appendChild(this.element);
|
||||
}
|
||||
}
|
||||
|
||||
clear(){
|
||||
this.dispatch("alert-hide", this.type);
|
||||
|
||||
if(this.element.parentNode){
|
||||
this.element.parentNode.removeChild(this.element);
|
||||
}
|
||||
|
||||
this.msgElement.classList.remove(this._typeClass());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
export default class ComponentFunctionBinder{
|
||||
|
||||
constructor(table){
|
||||
this.table = table;
|
||||
|
||||
this.bindings = {};
|
||||
}
|
||||
|
||||
bind(type, funcName, handler){
|
||||
if(!this.bindings[type]){
|
||||
this.bindings[type] = {};
|
||||
}
|
||||
|
||||
if(this.bindings[type][funcName]){
|
||||
console.warn("Unable to bind component handler, a matching function name is already bound", type, funcName, handler);
|
||||
}else{
|
||||
this.bindings[type][funcName] = handler;
|
||||
}
|
||||
}
|
||||
|
||||
handle(type, component, name){
|
||||
if(this.bindings[type] && this.bindings[type][name] && typeof this.bindings[type][name].bind === 'function'){
|
||||
return this.bindings[type][name].bind(null, component);
|
||||
}else{
|
||||
if(name !== "then" && typeof name === "string" && !name.startsWith("_")){
|
||||
if(this.table.options.debugInvalidComponentFuncs){
|
||||
console.error("The " + type + " component does not have a " + name + " function, have you checked that you have the correct Tabulator module installed?");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
128
public/libs/tabulator-master/src/js/core/tools/DataLoader.js
Normal file
128
public/libs/tabulator-master/src/js/core/tools/DataLoader.js
Normal file
@@ -0,0 +1,128 @@
|
||||
import CoreFeature from '../CoreFeature.js';
|
||||
|
||||
export default class DataLoader extends CoreFeature{
|
||||
constructor(table){
|
||||
super(table);
|
||||
|
||||
this.requestOrder = 0; //prevent requests coming out of sequence if overridden by another load request
|
||||
this.loading = false;
|
||||
}
|
||||
|
||||
initialize(){}
|
||||
|
||||
load(data, params, config, replace, silent, columnsChanged){
|
||||
var requestNo = ++this.requestOrder;
|
||||
|
||||
if(this.table.destroyed){
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
this.dispatchExternal("dataLoading", data);
|
||||
|
||||
//parse json data to array
|
||||
if (data && (data.indexOf("{") == 0 || data.indexOf("[") == 0)){
|
||||
data = JSON.parse(data);
|
||||
}
|
||||
|
||||
if(this.confirm("data-loading", [data, params, config, silent])){
|
||||
this.loading = true;
|
||||
|
||||
if(!silent){
|
||||
this.alertLoader();
|
||||
}
|
||||
|
||||
//get params for request
|
||||
params = this.chain("data-params", [data, config, silent], params || {}, params || {});
|
||||
|
||||
params = this.mapParams(params, this.table.options.dataSendParams);
|
||||
|
||||
var result = this.chain("data-load", [data, params, config, silent], false, Promise.resolve([]));
|
||||
|
||||
return result.then((response) => {
|
||||
if(!this.table.destroyed){
|
||||
if(!Array.isArray(response) && typeof response == "object"){
|
||||
response = this.mapParams(response, this.objectInvert(this.table.options.dataReceiveParams));
|
||||
}
|
||||
|
||||
var rowData = this.chain("data-loaded", [response], null, response);
|
||||
|
||||
if(requestNo == this.requestOrder){
|
||||
this.clearAlert();
|
||||
|
||||
if(rowData !== false){
|
||||
this.dispatchExternal("dataLoaded", rowData);
|
||||
this.table.rowManager.setData(rowData, replace, typeof columnsChanged === "undefined" ? !replace : columnsChanged);
|
||||
}
|
||||
}else{
|
||||
console.warn("Data Load Response Blocked - An active data load request was blocked by an attempt to change table data while the request was being made");
|
||||
}
|
||||
}else{
|
||||
console.warn("Data Load Response Blocked - Table has been destroyed");
|
||||
}
|
||||
}).catch((error) => {
|
||||
console.error("Data Load Error: ", error);
|
||||
this.dispatchExternal("dataLoadError", error);
|
||||
|
||||
if(!silent){
|
||||
this.alertError();
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
this.clearAlert();
|
||||
}, this.table.options.dataLoaderErrorTimeout);
|
||||
})
|
||||
.finally(() => {
|
||||
this.loading = false;
|
||||
});
|
||||
}else{
|
||||
this.dispatchExternal("dataLoaded", data);
|
||||
|
||||
if(!data){
|
||||
data = [];
|
||||
}
|
||||
|
||||
this.table.rowManager.setData(data, replace, typeof columnsChanged === "undefined" ? !replace : columnsChanged);
|
||||
return Promise.resolve();
|
||||
}
|
||||
}
|
||||
|
||||
mapParams(params, map){
|
||||
var output = {};
|
||||
|
||||
for(let key in params){
|
||||
output[map.hasOwnProperty(key) ? map[key] : key] = params[key];
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
objectInvert(obj){
|
||||
var output = {};
|
||||
|
||||
for(let key in obj){
|
||||
output[obj[key]] = key;
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
blockActiveLoad(){
|
||||
this.requestOrder++;
|
||||
}
|
||||
|
||||
alertLoader(){
|
||||
var shouldLoad = typeof this.table.options.dataLoader === "function" ? this.table.options.dataLoader() : this.table.options.dataLoader;
|
||||
|
||||
if(shouldLoad){
|
||||
this.table.alertManager.alert(this.table.options.dataLoaderLoading || this.langText("data|loading"));
|
||||
}
|
||||
}
|
||||
|
||||
alertError(){
|
||||
this.table.alertManager.alert(this.table.options.dataLoaderError || this.langText("data|error"), "error");
|
||||
}
|
||||
|
||||
clearAlert(){
|
||||
this.table.alertManager.clear();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
import CoreFeature from '../CoreFeature.js';
|
||||
|
||||
export default class DependencyRegistry extends CoreFeature{
|
||||
|
||||
constructor(table){
|
||||
super(table);
|
||||
|
||||
this.deps = {};
|
||||
|
||||
this.props = {
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
initialize(){
|
||||
this.deps = Object.assign({}, this.options("dependencies"));
|
||||
}
|
||||
|
||||
lookup(key, prop, silent){
|
||||
if(Array.isArray(key)){
|
||||
for (const item of key) {
|
||||
var match = this.lookup(item, prop, true);
|
||||
|
||||
if(match){
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(match){
|
||||
return match;
|
||||
}else{
|
||||
this.error(key);
|
||||
}
|
||||
}else{
|
||||
if(prop){
|
||||
return this.lookupProp(key, prop, silent);
|
||||
}else{
|
||||
return this.lookupKey(key, silent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lookupProp(key, prop, silent){
|
||||
var dependency;
|
||||
|
||||
if(this.props[key] && this.props[key][prop]){
|
||||
return this.props[key][prop];
|
||||
}else{
|
||||
dependency = this.lookupKey(key, silent);
|
||||
|
||||
if(dependency){
|
||||
if(!this.props[key]){
|
||||
this.props[key] = {};
|
||||
}
|
||||
|
||||
this.props[key][prop] = dependency[prop] || dependency;
|
||||
return this.props[key][prop];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lookupKey(key, silent){
|
||||
var dependency;
|
||||
|
||||
if(this.deps[key]){
|
||||
dependency = this.deps[key];
|
||||
}else if(window[key]){
|
||||
this.deps[key] = window[key];
|
||||
dependency = this.deps[key];
|
||||
}else{
|
||||
if(!silent){
|
||||
this.error(key);
|
||||
}
|
||||
}
|
||||
|
||||
return dependency;
|
||||
}
|
||||
|
||||
error(key){
|
||||
console.error("Unable to find dependency", key, "Please check documentation and ensure you have imported the required library into your project");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
import CoreFeature from '../CoreFeature.js';
|
||||
|
||||
export default class DeprecationAdvisor extends CoreFeature{
|
||||
|
||||
constructor(table){
|
||||
super(table);
|
||||
}
|
||||
|
||||
_warnUser(){
|
||||
if(this.options("debugDeprecation")){
|
||||
console.warn(...arguments);
|
||||
}
|
||||
}
|
||||
|
||||
check(oldOption, newOption, convert){
|
||||
var msg = "";
|
||||
|
||||
if(typeof this.options(oldOption) !== "undefined"){
|
||||
msg = "Deprecated Setup Option - Use of the %c" + oldOption + "%c option is now deprecated";
|
||||
|
||||
if(newOption){
|
||||
msg = msg + ", Please use the %c" + newOption + "%c option instead";
|
||||
this._warnUser(msg, 'font-weight: bold;', 'font-weight: normal;', 'font-weight: bold;', 'font-weight: normal;');
|
||||
|
||||
if(convert){
|
||||
this.table.options[newOption] = this.table.options[oldOption];
|
||||
}
|
||||
}else{
|
||||
this._warnUser(msg, 'font-weight: bold;', 'font-weight: normal;');
|
||||
}
|
||||
|
||||
return false;
|
||||
}else{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
checkMsg(oldOption, msg){
|
||||
if(typeof this.options(oldOption) !== "undefined"){
|
||||
this._warnUser("%cDeprecated Setup Option - Use of the %c" + oldOption + " %c option is now deprecated, " + msg, 'font-weight: normal;', 'font-weight: bold;', 'font-weight: normal;');
|
||||
|
||||
return false;
|
||||
}else{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
msg(msg){
|
||||
this._warnUser(msg);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
export default class ExternalEventBus {
|
||||
|
||||
constructor(table, optionsList, debug){
|
||||
this.table = table;
|
||||
this.events = {};
|
||||
this.optionsList = optionsList || {};
|
||||
this.subscriptionNotifiers = {};
|
||||
|
||||
this.dispatch = debug ? this._debugDispatch.bind(this) : this._dispatch.bind(this);
|
||||
this.debug = debug;
|
||||
}
|
||||
|
||||
subscriptionChange(key, callback){
|
||||
if(!this.subscriptionNotifiers[key]){
|
||||
this.subscriptionNotifiers[key] = [];
|
||||
}
|
||||
|
||||
this.subscriptionNotifiers[key].push(callback);
|
||||
|
||||
if(this.subscribed(key)){
|
||||
this._notifySubscriptionChange(key, true);
|
||||
}
|
||||
}
|
||||
|
||||
subscribe(key, callback){
|
||||
if(!this.events[key]){
|
||||
this.events[key] = [];
|
||||
}
|
||||
|
||||
this.events[key].push(callback);
|
||||
|
||||
this._notifySubscriptionChange(key, true);
|
||||
}
|
||||
|
||||
unsubscribe(key, callback){
|
||||
var index;
|
||||
|
||||
if(this.events[key]){
|
||||
if(callback){
|
||||
index = this.events[key].findIndex((item) => {
|
||||
return item === callback;
|
||||
});
|
||||
|
||||
if(index > -1){
|
||||
this.events[key].splice(index, 1);
|
||||
}else{
|
||||
console.warn("Cannot remove event, no matching event found:", key, callback);
|
||||
return;
|
||||
}
|
||||
}else{
|
||||
delete this.events[key];
|
||||
}
|
||||
}else{
|
||||
console.warn("Cannot remove event, no events set on:", key);
|
||||
return;
|
||||
}
|
||||
|
||||
this._notifySubscriptionChange(key, false);
|
||||
}
|
||||
|
||||
subscribed(key){
|
||||
return this.events[key] && this.events[key].length;
|
||||
}
|
||||
|
||||
_notifySubscriptionChange(key, subscribed){
|
||||
var notifiers = this.subscriptionNotifiers[key];
|
||||
|
||||
if(notifiers){
|
||||
notifiers.forEach((callback)=>{
|
||||
callback(subscribed);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
_dispatch(){
|
||||
var args = Array.from(arguments),
|
||||
key = args.shift(),
|
||||
result;
|
||||
|
||||
if(this.events[key]){
|
||||
this.events[key].forEach((callback, i) => {
|
||||
let callResult = callback.apply(this.table, args);
|
||||
|
||||
if(!i){
|
||||
result = callResult;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
_debugDispatch(){
|
||||
var args = Array.from(arguments),
|
||||
key = args[0];
|
||||
|
||||
args[0] = "ExternalEvent:" + args[0];
|
||||
|
||||
if(this.debug === true || this.debug.includes(key)){
|
||||
console.log(...args);
|
||||
}
|
||||
|
||||
return this._dispatch(...arguments);
|
||||
}
|
||||
}
|
||||
66
public/libs/tabulator-master/src/js/core/tools/Helpers.js
Normal file
66
public/libs/tabulator-master/src/js/core/tools/Helpers.js
Normal file
@@ -0,0 +1,66 @@
|
||||
export default class Helpers{
|
||||
|
||||
static elVisible(el){
|
||||
return !(el.offsetWidth <= 0 && el.offsetHeight <= 0);
|
||||
}
|
||||
|
||||
static elOffset(el){
|
||||
var box = el.getBoundingClientRect();
|
||||
|
||||
return {
|
||||
top: box.top + window.pageYOffset - document.documentElement.clientTop,
|
||||
left: box.left + window.pageXOffset - document.documentElement.clientLeft
|
||||
};
|
||||
}
|
||||
|
||||
static retrieveNestedData(separator, field, data){
|
||||
var structure = separator ? field.split(separator) : [field],
|
||||
length = structure.length,
|
||||
output;
|
||||
|
||||
for(let i = 0; i < length; i++){
|
||||
|
||||
data = data[structure[i]];
|
||||
|
||||
output = data;
|
||||
|
||||
if(!data){
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
static deepClone(obj, clone, list = []){
|
||||
var objectProto = {}.__proto__,
|
||||
arrayProto = [].__proto__;
|
||||
|
||||
if (!clone){
|
||||
clone = Object.assign(Array.isArray(obj) ? [] : {}, obj);
|
||||
}
|
||||
|
||||
for(var i in obj) {
|
||||
let subject = obj[i],
|
||||
match, copy;
|
||||
|
||||
if(subject != null && typeof subject === "object" && (subject.__proto__ === objectProto || subject.__proto__ === arrayProto)){
|
||||
match = list.findIndex((item) => {
|
||||
return item.subject === subject;
|
||||
});
|
||||
|
||||
if(match > -1){
|
||||
clone[i] = list[match].copy;
|
||||
}else{
|
||||
copy = Object.assign(Array.isArray(subject) ? [] : {}, subject);
|
||||
|
||||
list.unshift({subject, copy});
|
||||
|
||||
clone[i] = this.deepClone(subject, copy, list);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return clone;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,329 @@
|
||||
import CoreFeature from '../CoreFeature.js';
|
||||
import Row from '../row/Row.js';
|
||||
|
||||
export default class InteractionManager extends CoreFeature {
|
||||
|
||||
constructor (table){
|
||||
super(table);
|
||||
|
||||
this.el = null;
|
||||
|
||||
this.abortClasses = ["tabulator-headers", "tabulator-table"];
|
||||
|
||||
this.previousTargets = {};
|
||||
|
||||
this.listeners = [
|
||||
"click",
|
||||
"dblclick",
|
||||
"contextmenu",
|
||||
"mouseenter",
|
||||
"mouseleave",
|
||||
"mouseover",
|
||||
"mouseout",
|
||||
"mousemove",
|
||||
"mouseup",
|
||||
"mousedown",
|
||||
"touchstart",
|
||||
"touchend",
|
||||
];
|
||||
|
||||
this.componentMap = {
|
||||
"tabulator-cell":"cell",
|
||||
"tabulator-row":"row",
|
||||
"tabulator-group":"group",
|
||||
"tabulator-col":"column",
|
||||
};
|
||||
|
||||
this.pseudoTrackers = {
|
||||
"row":{
|
||||
subscriber:null,
|
||||
target:null,
|
||||
},
|
||||
"cell":{
|
||||
subscriber:null,
|
||||
target:null,
|
||||
},
|
||||
"group":{
|
||||
subscriber:null,
|
||||
target:null,
|
||||
},
|
||||
"column":{
|
||||
subscriber:null,
|
||||
target:null,
|
||||
},
|
||||
};
|
||||
|
||||
this.pseudoTracking = false;
|
||||
}
|
||||
|
||||
initialize(){
|
||||
this.el = this.table.element;
|
||||
|
||||
this.buildListenerMap();
|
||||
this.bindSubscriptionWatchers();
|
||||
}
|
||||
|
||||
buildListenerMap(){
|
||||
var listenerMap = {};
|
||||
|
||||
this.listeners.forEach((listener) => {
|
||||
listenerMap[listener] = {
|
||||
handler:null,
|
||||
components:[],
|
||||
};
|
||||
});
|
||||
|
||||
this.listeners = listenerMap;
|
||||
}
|
||||
|
||||
bindPseudoEvents(){
|
||||
Object.keys(this.pseudoTrackers).forEach((key) => {
|
||||
this.pseudoTrackers[key].subscriber = this.pseudoMouseEnter.bind(this, key);
|
||||
this.subscribe(key + "-mouseover", this.pseudoTrackers[key].subscriber);
|
||||
});
|
||||
|
||||
this.pseudoTracking = true;
|
||||
}
|
||||
|
||||
pseudoMouseEnter(key, e, target){
|
||||
if(this.pseudoTrackers[key].target !== target){
|
||||
|
||||
if(this.pseudoTrackers[key].target){
|
||||
this.dispatch(key + "-mouseleave", e, this.pseudoTrackers[key].target);
|
||||
}
|
||||
|
||||
this.pseudoMouseLeave(key, e);
|
||||
|
||||
this.pseudoTrackers[key].target = target;
|
||||
|
||||
this.dispatch(key + "-mouseenter", e, target);
|
||||
}
|
||||
}
|
||||
|
||||
pseudoMouseLeave(key, e){
|
||||
var leaveList = Object.keys(this.pseudoTrackers),
|
||||
linkedKeys = {
|
||||
"row":["cell"],
|
||||
"cell":["row"],
|
||||
};
|
||||
|
||||
leaveList = leaveList.filter((item) => {
|
||||
var links = linkedKeys[key];
|
||||
return item !== key && (!links || (links && !links.includes(item)));
|
||||
});
|
||||
|
||||
|
||||
leaveList.forEach((key) => {
|
||||
var target = this.pseudoTrackers[key].target;
|
||||
|
||||
if(this.pseudoTrackers[key].target){
|
||||
this.dispatch(key + "-mouseleave", e, target);
|
||||
|
||||
this.pseudoTrackers[key].target = null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
bindSubscriptionWatchers(){
|
||||
var listeners = Object.keys(this.listeners),
|
||||
components = Object.values(this.componentMap);
|
||||
|
||||
for(let comp of components){
|
||||
for(let listener of listeners){
|
||||
let key = comp + "-" + listener;
|
||||
|
||||
this.subscriptionChange(key, this.subscriptionChanged.bind(this, comp, listener));
|
||||
}
|
||||
}
|
||||
|
||||
this.subscribe("table-destroy", this.clearWatchers.bind(this));
|
||||
}
|
||||
|
||||
subscriptionChanged(component, key, added){
|
||||
var listener = this.listeners[key].components,
|
||||
index = listener.indexOf(component),
|
||||
changed = false;
|
||||
|
||||
if(added){
|
||||
if(index === -1){
|
||||
listener.push(component);
|
||||
changed = true;
|
||||
}
|
||||
}else{
|
||||
if(!this.subscribed(component + "-" + key)){
|
||||
if(index > -1){
|
||||
listener.splice(index, 1);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if((key === "mouseenter" || key === "mouseleave") && !this.pseudoTracking){
|
||||
this.bindPseudoEvents();
|
||||
}
|
||||
|
||||
if(changed){
|
||||
this.updateEventListeners();
|
||||
}
|
||||
}
|
||||
|
||||
updateEventListeners(){
|
||||
for(let key in this.listeners){
|
||||
let listener = this.listeners[key];
|
||||
|
||||
if(listener.components.length){
|
||||
if(!listener.handler){
|
||||
listener.handler = this.track.bind(this, key);
|
||||
this.el.addEventListener(key, listener.handler);
|
||||
// this.el.addEventListener(key, listener.handler, {passive: true})
|
||||
}
|
||||
}else{
|
||||
if(listener.handler){
|
||||
this.el.removeEventListener(key, listener.handler);
|
||||
listener.handler = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
track(type, e){
|
||||
var path = (e.composedPath && e.composedPath()) || e.path;
|
||||
|
||||
var targets = this.findTargets(path);
|
||||
targets = this.bindComponents(type, targets);
|
||||
|
||||
this.triggerEvents(type, e, targets);
|
||||
|
||||
if(this.pseudoTracking && (type == "mouseover" || type == "mouseleave") && !Object.keys(targets).length){
|
||||
this.pseudoMouseLeave("none", e);
|
||||
}
|
||||
}
|
||||
|
||||
findTargets(path){
|
||||
var targets = {};
|
||||
|
||||
let componentMap = Object.keys(this.componentMap);
|
||||
|
||||
for (let el of path) {
|
||||
let classList = el.classList ? [...el.classList] : [];
|
||||
|
||||
let abort = classList.filter((item) => {
|
||||
return this.abortClasses.includes(item);
|
||||
});
|
||||
|
||||
if(abort.length){
|
||||
break;
|
||||
}
|
||||
|
||||
let elTargets = classList.filter((item) => {
|
||||
return componentMap.includes(item);
|
||||
});
|
||||
|
||||
for (let target of elTargets) {
|
||||
if(!targets[this.componentMap[target]]){
|
||||
targets[this.componentMap[target]] = el;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(targets.group && targets.group === targets.row){
|
||||
delete targets.row;
|
||||
}
|
||||
|
||||
return targets;
|
||||
}
|
||||
|
||||
bindComponents(type, targets){
|
||||
//ensure row component is looked up before cell
|
||||
var keys = Object.keys(targets).reverse(),
|
||||
listener = this.listeners[type],
|
||||
matches = {},
|
||||
output = {},
|
||||
targetMatches = {};
|
||||
|
||||
for(let key of keys){
|
||||
let component,
|
||||
target = targets[key],
|
||||
previousTarget = this.previousTargets[key];
|
||||
|
||||
if(previousTarget && previousTarget.target === target){
|
||||
component = previousTarget.component;
|
||||
}else{
|
||||
switch(key){
|
||||
case "row":
|
||||
case "group":
|
||||
if(listener.components.includes("row") || listener.components.includes("cell") || listener.components.includes("group")){
|
||||
let rows = this.table.rowManager.getVisibleRows(true);
|
||||
|
||||
component = rows.find((row) => {
|
||||
return row.getElement() === target;
|
||||
});
|
||||
|
||||
if(targets["row"] && targets["row"].parentNode && targets["row"].parentNode.closest(".tabulator-row")){
|
||||
targets[key] = false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case "column":
|
||||
if(listener.components.includes("column")){
|
||||
component = this.table.columnManager.findColumn(target);
|
||||
}
|
||||
break;
|
||||
|
||||
case "cell":
|
||||
if(listener.components.includes("cell")){
|
||||
if(matches["row"] instanceof Row){
|
||||
component = matches["row"].findCell(target);
|
||||
}else{
|
||||
if(targets["row"]){
|
||||
console.warn("Event Target Lookup Error - The row this cell is attached to cannot be found, has the table been reinitialized without being destroyed first?");
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(component){
|
||||
matches[key] = component;
|
||||
targetMatches[key] = {
|
||||
target:target,
|
||||
component:component,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
this.previousTargets = targetMatches;
|
||||
|
||||
//reverse order keys are set in so events trigger in correct sequence
|
||||
Object.keys(targets).forEach((key) => {
|
||||
let value = matches[key];
|
||||
output[key] = value;
|
||||
});
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
triggerEvents(type, e, targets){
|
||||
var listener = this.listeners[type];
|
||||
|
||||
for(let key in targets){
|
||||
if(targets[key] && listener.components.includes(key)){
|
||||
this.dispatch(key + "-" + type, e, targets[key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
clearWatchers(){
|
||||
for(let key in this.listeners){
|
||||
let listener = this.listeners[key];
|
||||
|
||||
if(listener.handler){
|
||||
this.el.removeEventListener(key, listener.handler);
|
||||
listener.handler = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
export default class InternalEventBus {
|
||||
|
||||
constructor(debug){
|
||||
this.events = {};
|
||||
this.subscriptionNotifiers = {};
|
||||
|
||||
this.dispatch = debug ? this._debugDispatch.bind(this) : this._dispatch.bind(this);
|
||||
this.chain = debug ? this._debugChain.bind(this) : this._chain.bind(this);
|
||||
this.confirm = debug ? this._debugConfirm.bind(this) : this._confirm.bind(this);
|
||||
this.debug = debug;
|
||||
}
|
||||
|
||||
subscriptionChange(key, callback){
|
||||
if(!this.subscriptionNotifiers[key]){
|
||||
this.subscriptionNotifiers[key] = [];
|
||||
}
|
||||
|
||||
this.subscriptionNotifiers[key].push(callback);
|
||||
|
||||
if(this.subscribed(key)){
|
||||
this._notifySubscriptionChange(key, true);
|
||||
}
|
||||
}
|
||||
|
||||
subscribe(key, callback, priority = 10000){
|
||||
if(!this.events[key]){
|
||||
this.events[key] = [];
|
||||
}
|
||||
|
||||
this.events[key].push({callback, priority});
|
||||
|
||||
this.events[key].sort((a, b) => {
|
||||
return a.priority - b.priority;
|
||||
});
|
||||
|
||||
this._notifySubscriptionChange(key, true);
|
||||
}
|
||||
|
||||
unsubscribe(key, callback){
|
||||
var index;
|
||||
|
||||
if(this.events[key]){
|
||||
if(callback){
|
||||
index = this.events[key].findIndex((item) => {
|
||||
return item.callback === callback;
|
||||
});
|
||||
|
||||
if(index > -1){
|
||||
this.events[key].splice(index, 1);
|
||||
}else{
|
||||
console.warn("Cannot remove event, no matching event found:", key, callback);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
console.warn("Cannot remove event, no events set on:", key);
|
||||
return;
|
||||
}
|
||||
|
||||
this._notifySubscriptionChange(key, false);
|
||||
}
|
||||
|
||||
subscribed(key){
|
||||
return this.events[key] && this.events[key].length;
|
||||
}
|
||||
|
||||
_chain(key, args, initialValue, fallback){
|
||||
var value = initialValue;
|
||||
|
||||
if(!Array.isArray(args)){
|
||||
args = [args];
|
||||
}
|
||||
|
||||
if(this.subscribed(key)){
|
||||
this.events[key].forEach((subscriber, i) => {
|
||||
value = subscriber.callback.apply(this, args.concat([value]));
|
||||
});
|
||||
|
||||
return value;
|
||||
}else{
|
||||
return typeof fallback === "function" ? fallback() : fallback;
|
||||
}
|
||||
}
|
||||
|
||||
_confirm(key, args){
|
||||
var confirmed = false;
|
||||
|
||||
if(!Array.isArray(args)){
|
||||
args = [args];
|
||||
}
|
||||
|
||||
if(this.subscribed(key)){
|
||||
this.events[key].forEach((subscriber, i) => {
|
||||
if(subscriber.callback.apply(this, args)){
|
||||
confirmed = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return confirmed;
|
||||
}
|
||||
|
||||
_notifySubscriptionChange(key, subscribed){
|
||||
var notifiers = this.subscriptionNotifiers[key];
|
||||
|
||||
if(notifiers){
|
||||
notifiers.forEach((callback)=>{
|
||||
callback(subscribed);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
_dispatch(){
|
||||
var args = Array.from(arguments),
|
||||
key = args.shift();
|
||||
|
||||
if(this.events[key]){
|
||||
this.events[key].forEach((subscriber) => {
|
||||
subscriber.callback.apply(this, args);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
_debugDispatch(){
|
||||
var args = Array.from(arguments),
|
||||
key = args[0];
|
||||
|
||||
args[0] = "InternalEvent:" + key;
|
||||
|
||||
if(this.debug === true || this.debug.includes(key)){
|
||||
console.log(...args);
|
||||
}
|
||||
|
||||
return this._dispatch(...arguments);
|
||||
}
|
||||
|
||||
_debugChain(){
|
||||
var args = Array.from(arguments),
|
||||
key = args[0];
|
||||
|
||||
args[0] = "InternalEvent:" + key;
|
||||
|
||||
if(this.debug === true || this.debug.includes(key)){
|
||||
console.log(...args);
|
||||
}
|
||||
|
||||
return this._chain(...arguments);
|
||||
}
|
||||
|
||||
_debugConfirm(){
|
||||
var args = Array.from(arguments),
|
||||
key = args[0];
|
||||
|
||||
args[0] = "InternalEvent:" + key;
|
||||
|
||||
if(this.debug === true || this.debug.includes(key)){
|
||||
console.log(...args);
|
||||
}
|
||||
|
||||
return this._confirm(...arguments);
|
||||
}
|
||||
}
|
||||
153
public/libs/tabulator-master/src/js/core/tools/ModuleBinder.js
Normal file
153
public/libs/tabulator-master/src/js/core/tools/ModuleBinder.js
Normal file
@@ -0,0 +1,153 @@
|
||||
import * as coreModules from '../modules/core.js';
|
||||
import TableRegistry from './TableRegistry.js';
|
||||
|
||||
export default class ModuleBinder extends TableRegistry {
|
||||
|
||||
static moduleBindings = {};
|
||||
static moduleExtensions = {};
|
||||
static modulesRegistered = false;
|
||||
|
||||
static defaultModules = false;
|
||||
|
||||
constructor(){
|
||||
super();
|
||||
}
|
||||
|
||||
static initializeModuleBinder(defaultModules){
|
||||
if(!ModuleBinder.modulesRegistered){
|
||||
ModuleBinder.modulesRegistered = true;
|
||||
ModuleBinder._registerModules(coreModules, true);
|
||||
|
||||
if(defaultModules){
|
||||
ModuleBinder._registerModules(defaultModules);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static _extendModule(name, property, values){
|
||||
if(ModuleBinder.moduleBindings[name]){
|
||||
var source = ModuleBinder.moduleBindings[name][property];
|
||||
|
||||
if(source){
|
||||
if(typeof values == "object"){
|
||||
for(let key in values){
|
||||
source[key] = values[key];
|
||||
}
|
||||
}else{
|
||||
console.warn("Module Error - Invalid value type, it must be an object");
|
||||
}
|
||||
}else{
|
||||
console.warn("Module Error - property does not exist:", property);
|
||||
}
|
||||
}else{
|
||||
console.warn("Module Error - module does not exist:", name);
|
||||
}
|
||||
}
|
||||
|
||||
static _registerModules(modules, core){
|
||||
var mods = Object.values(modules);
|
||||
|
||||
if(core){
|
||||
mods.forEach((mod) => {
|
||||
mod.prototype.moduleCore = true;
|
||||
});
|
||||
}
|
||||
|
||||
ModuleBinder._registerModule(mods);
|
||||
}
|
||||
|
||||
static _registerModule(modules){
|
||||
if(!Array.isArray(modules)){
|
||||
modules = [modules];
|
||||
}
|
||||
|
||||
modules.forEach((mod) => {
|
||||
ModuleBinder._registerModuleBinding(mod);
|
||||
ModuleBinder._registerModuleExtensions(mod);
|
||||
});
|
||||
}
|
||||
|
||||
static _registerModuleBinding(mod){
|
||||
if(mod.moduleName){
|
||||
ModuleBinder.moduleBindings[mod.moduleName] = mod;
|
||||
}else{
|
||||
console.error("Unable to bind module, no moduleName defined", mod.moduleName);
|
||||
}
|
||||
}
|
||||
|
||||
static _registerModuleExtensions(mod){
|
||||
var extensions = mod.moduleExtensions;
|
||||
|
||||
if(mod.moduleExtensions){
|
||||
for (let modKey in extensions) {
|
||||
let ext = extensions[modKey];
|
||||
|
||||
if(ModuleBinder.moduleBindings[modKey]){
|
||||
for (let propKey in ext) {
|
||||
ModuleBinder._extendModule(modKey, propKey, ext[propKey]);
|
||||
}
|
||||
}else{
|
||||
if(!ModuleBinder.moduleExtensions[modKey]){
|
||||
ModuleBinder.moduleExtensions[modKey] = {};
|
||||
}
|
||||
|
||||
for (let propKey in ext) {
|
||||
if(!ModuleBinder.moduleExtensions[modKey][propKey]){
|
||||
ModuleBinder.moduleExtensions[modKey][propKey] = {};
|
||||
}
|
||||
|
||||
Object.assign(ModuleBinder.moduleExtensions[modKey][propKey], ext[propKey]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ModuleBinder._extendModuleFromQueue(mod);
|
||||
}
|
||||
|
||||
static _extendModuleFromQueue(mod){
|
||||
var extensions = ModuleBinder.moduleExtensions[mod.moduleName];
|
||||
|
||||
if(extensions){
|
||||
for (let propKey in extensions) {
|
||||
ModuleBinder._extendModule(mod.moduleName, propKey, extensions[propKey]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//ensure that module are bound to instantiated function
|
||||
_bindModules(){
|
||||
var orderedStartMods = [],
|
||||
orderedEndMods = [],
|
||||
unOrderedMods = [];
|
||||
|
||||
this.modules = {};
|
||||
|
||||
for(var name in ModuleBinder.moduleBindings){
|
||||
let mod = ModuleBinder.moduleBindings[name];
|
||||
let module = new mod(this);
|
||||
|
||||
this.modules[name] = module;
|
||||
|
||||
if(mod.prototype.moduleCore){
|
||||
this.modulesCore.push(module);
|
||||
}else{
|
||||
if(mod.moduleInitOrder){
|
||||
if(mod.moduleInitOrder < 0){
|
||||
orderedStartMods.push(module);
|
||||
}else{
|
||||
orderedEndMods.push(module);
|
||||
}
|
||||
|
||||
}else{
|
||||
unOrderedMods.push(module);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
orderedStartMods.sort((a, b) => a.moduleInitOrder > b.moduleInitOrder ? 1 : -1);
|
||||
orderedEndMods.sort((a, b) => a.moduleInitOrder > b.moduleInitOrder ? 1 : -1);
|
||||
|
||||
this.modulesRegular = orderedStartMods.concat(unOrderedMods.concat(orderedEndMods));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
export default class OptionsList {
|
||||
constructor(table, msgType, defaults = {}){
|
||||
this.table = table;
|
||||
this.msgType = msgType;
|
||||
this.registeredDefaults = Object.assign({}, defaults);
|
||||
}
|
||||
|
||||
register(option, value){
|
||||
this.registeredDefaults[option] = value;
|
||||
}
|
||||
|
||||
generate(defaultOptions, userOptions = {}){
|
||||
var output = Object.assign({}, this.registeredDefaults),
|
||||
warn = this.table.options.debugInvalidOptions || userOptions.debugInvalidOptions === true;
|
||||
|
||||
Object.assign(output, defaultOptions);
|
||||
|
||||
for (let key in userOptions){
|
||||
if(!output.hasOwnProperty(key)){
|
||||
if(warn){
|
||||
console.warn("Invalid " + this.msgType + " option:", key);
|
||||
}
|
||||
|
||||
output[key] = userOptions.key;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (let key in output){
|
||||
if(key in userOptions){
|
||||
output[key] = userOptions[key];
|
||||
}else{
|
||||
if(Array.isArray(output[key])){
|
||||
output[key] = Object.assign([], output[key]);
|
||||
}else if(typeof output[key] === "object" && output[key] !== null){
|
||||
output[key] = Object.assign({}, output[key]);
|
||||
}else if (typeof output[key] === "undefined"){
|
||||
delete output[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
}
|
||||
307
public/libs/tabulator-master/src/js/core/tools/Popup.js
Normal file
307
public/libs/tabulator-master/src/js/core/tools/Popup.js
Normal file
@@ -0,0 +1,307 @@
|
||||
import CoreFeature from '../CoreFeature.js';
|
||||
import Helpers from './Helpers.js';
|
||||
|
||||
export default class Popup extends CoreFeature{
|
||||
constructor(table, element, parent){
|
||||
super(table);
|
||||
|
||||
this.element = element;
|
||||
this.container = this._lookupContainer();
|
||||
|
||||
this.parent = parent;
|
||||
|
||||
this.reversedX = false;
|
||||
this.childPopup = null;
|
||||
this.blurable = false;
|
||||
this.blurCallback = null;
|
||||
this.blurEventsBound = false;
|
||||
this.renderedCallback = null;
|
||||
|
||||
this.visible = false;
|
||||
this.hideable = true;
|
||||
|
||||
this.element.classList.add("tabulator-popup-container");
|
||||
|
||||
this.blurEvent = this.hide.bind(this, false);
|
||||
this.escEvent = this._escapeCheck.bind(this);
|
||||
|
||||
this.destroyBinding = this.tableDestroyed.bind(this);
|
||||
this.destroyed = false;
|
||||
}
|
||||
|
||||
tableDestroyed(){
|
||||
this.destroyed = true;
|
||||
this.hide(true);
|
||||
}
|
||||
|
||||
_lookupContainer(){
|
||||
var container = this.table.options.popupContainer;
|
||||
|
||||
if(typeof container === "string"){
|
||||
container = document.querySelector(container);
|
||||
|
||||
if(!container){
|
||||
console.warn("Menu Error - no container element found matching selector:", this.table.options.popupContainer , "(defaulting to document body)");
|
||||
}
|
||||
}else if (container === true){
|
||||
container = this.table.element;
|
||||
}
|
||||
|
||||
if(container && !this._checkContainerIsParent(container)){
|
||||
container = false;
|
||||
console.warn("Menu Error - container element does not contain this table:", this.table.options.popupContainer , "(defaulting to document body)");
|
||||
}
|
||||
|
||||
if(!container){
|
||||
container = document.body;
|
||||
}
|
||||
|
||||
return container;
|
||||
}
|
||||
|
||||
_checkContainerIsParent(container, element = this.table.element){
|
||||
if(container === element){
|
||||
return true;
|
||||
}else{
|
||||
return element.parentNode ? this._checkContainerIsParent(container, element.parentNode) : false;
|
||||
}
|
||||
}
|
||||
|
||||
renderCallback(callback){
|
||||
this.renderedCallback = callback;
|
||||
}
|
||||
|
||||
containerEventCoords(e){
|
||||
var touch = !(e instanceof MouseEvent);
|
||||
|
||||
var x = touch ? e.touches[0].pageX : e.pageX;
|
||||
var y = touch ? e.touches[0].pageY : e.pageY;
|
||||
|
||||
if(this.container !== document.body){
|
||||
let parentOffset = Helpers.elOffset(this.container);
|
||||
|
||||
x -= parentOffset.left;
|
||||
y -= parentOffset.top;
|
||||
}
|
||||
|
||||
return {x, y};
|
||||
}
|
||||
|
||||
elementPositionCoords(element, position = "right"){
|
||||
var offset = Helpers.elOffset(element),
|
||||
containerOffset, x, y;
|
||||
|
||||
if(this.container !== document.body){
|
||||
containerOffset = Helpers.elOffset(this.container);
|
||||
|
||||
offset.left -= containerOffset.left;
|
||||
offset.top -= containerOffset.top;
|
||||
}
|
||||
|
||||
switch(position){
|
||||
case "right":
|
||||
x = offset.left + element.offsetWidth;
|
||||
y = offset.top - 1;
|
||||
break;
|
||||
|
||||
case "bottom":
|
||||
x = offset.left;
|
||||
y = offset.top + element.offsetHeight;
|
||||
break;
|
||||
|
||||
case "left":
|
||||
x = offset.left;
|
||||
y = offset.top - 1;
|
||||
break;
|
||||
|
||||
case "top":
|
||||
x = offset.left;
|
||||
y = offset.top;
|
||||
break;
|
||||
|
||||
case "center":
|
||||
x = offset.left + (element.offsetWidth / 2);
|
||||
y = offset.top + (element.offsetHeight / 2);
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
return {x, y, offset};
|
||||
}
|
||||
|
||||
show(origin, position){
|
||||
var x, y, parentEl, parentOffset, coords;
|
||||
|
||||
if(this.destroyed || this.table.destroyed){
|
||||
return this;
|
||||
}
|
||||
|
||||
if(origin instanceof HTMLElement){
|
||||
parentEl = origin;
|
||||
coords = this.elementPositionCoords(origin, position);
|
||||
|
||||
parentOffset = coords.offset;
|
||||
x = coords.x;
|
||||
y = coords.y;
|
||||
|
||||
}else if(typeof origin === "number"){
|
||||
parentOffset = {top:0, left:0};
|
||||
x = origin;
|
||||
y = position;
|
||||
}else{
|
||||
coords = this.containerEventCoords(origin);
|
||||
|
||||
x = coords.x;
|
||||
y = coords.y;
|
||||
|
||||
this.reversedX = false;
|
||||
}
|
||||
|
||||
this.element.style.top = y + "px";
|
||||
this.element.style.left = x + "px";
|
||||
|
||||
this.container.appendChild(this.element);
|
||||
|
||||
if(typeof this.renderedCallback === "function"){
|
||||
this.renderedCallback();
|
||||
}
|
||||
|
||||
this._fitToScreen(x, y, parentEl, parentOffset, position);
|
||||
|
||||
this.visible = true;
|
||||
|
||||
this.subscribe("table-destroy", this.destroyBinding);
|
||||
|
||||
this.element.addEventListener("mousedown", (e) => {
|
||||
e.stopPropagation();
|
||||
});
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
_fitToScreen(x, y, parentEl, parentOffset, position){
|
||||
var scrollTop = this.container === document.body ? document.documentElement.scrollTop : this.container.scrollTop;
|
||||
|
||||
//move menu to start on right edge if it is too close to the edge of the screen
|
||||
if((x + this.element.offsetWidth) >= this.container.offsetWidth || this.reversedX){
|
||||
this.element.style.left = "";
|
||||
|
||||
if(parentEl){
|
||||
this.element.style.right = (this.container.offsetWidth - parentOffset.left) + "px";
|
||||
}else{
|
||||
this.element.style.right = (this.container.offsetWidth - x) + "px";
|
||||
}
|
||||
|
||||
this.reversedX = true;
|
||||
}
|
||||
|
||||
//move menu to start on bottom edge if it is too close to the edge of the screen
|
||||
let offsetHeight = Math.max(this.container.offsetHeight, scrollTop ? this.container.scrollHeight : 0);
|
||||
if((y + this.element.offsetHeight) > offsetHeight) {
|
||||
if(parentEl){
|
||||
switch(position){
|
||||
case "bottom":
|
||||
this.element.style.top = (parseInt(this.element.style.top) - this.element.offsetHeight - parentEl.offsetHeight - 1) + "px";
|
||||
break;
|
||||
|
||||
default:
|
||||
this.element.style.top = (parseInt(this.element.style.top) - this.element.offsetHeight + parentEl.offsetHeight + 1) + "px";
|
||||
}
|
||||
|
||||
}else{
|
||||
this.element.style.height = offsetHeight + "px";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
isVisible(){
|
||||
return this.visible;
|
||||
}
|
||||
|
||||
hideOnBlur(callback){
|
||||
this.blurable = true;
|
||||
|
||||
if(this.visible){
|
||||
setTimeout(() => {
|
||||
if(this.visible){
|
||||
this.table.rowManager.element.addEventListener("scroll", this.blurEvent);
|
||||
this.subscribe("cell-editing", this.blurEvent);
|
||||
document.body.addEventListener("click", this.blurEvent);
|
||||
document.body.addEventListener("contextmenu", this.blurEvent);
|
||||
document.body.addEventListener("mousedown", this.blurEvent);
|
||||
window.addEventListener("resize", this.blurEvent);
|
||||
document.body.addEventListener("keydown", this.escEvent);
|
||||
|
||||
this.blurEventsBound = true;
|
||||
}
|
||||
}, 100);
|
||||
|
||||
this.blurCallback = callback;
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/** @param {KeyboardEvent} e */
|
||||
_escapeCheck(e){
|
||||
if(e.key == 27){
|
||||
this.hide();
|
||||
}
|
||||
}
|
||||
|
||||
blockHide(){
|
||||
this.hideable = false;
|
||||
}
|
||||
|
||||
restoreHide(){
|
||||
this.hideable = true;
|
||||
}
|
||||
|
||||
hide(silent = false){
|
||||
if(this.visible && this.hideable){
|
||||
if(this.blurable && this.blurEventsBound){
|
||||
document.body.removeEventListener("keydown", this.escEvent);
|
||||
document.body.removeEventListener("click", this.blurEvent);
|
||||
document.body.removeEventListener("contextmenu", this.blurEvent);
|
||||
document.body.removeEventListener("mousedown", this.blurEvent);
|
||||
window.removeEventListener("resize", this.blurEvent);
|
||||
this.table.rowManager.element.removeEventListener("scroll", this.blurEvent);
|
||||
this.unsubscribe("cell-editing", this.blurEvent);
|
||||
|
||||
this.blurEventsBound = false;
|
||||
}
|
||||
|
||||
if(this.childPopup){
|
||||
this.childPopup.hide();
|
||||
}
|
||||
|
||||
if(this.parent){
|
||||
this.parent.childPopup = null;
|
||||
}
|
||||
|
||||
if(this.element.parentNode){
|
||||
this.element.parentNode.removeChild(this.element);
|
||||
}
|
||||
|
||||
this.visible = false;
|
||||
|
||||
if(this.blurCallback && !silent){
|
||||
this.blurCallback();
|
||||
}
|
||||
|
||||
this.unsubscribe("table-destroy", this.destroyBinding);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
child(element){
|
||||
if(this.childPopup){
|
||||
this.childPopup.hide();
|
||||
}
|
||||
|
||||
this.childPopup = new Popup(this.table, element, this);
|
||||
|
||||
return this.childPopup;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
export default class TableRegistry {
|
||||
static registry = {
|
||||
tables:[],
|
||||
|
||||
register(table){
|
||||
TableRegistry.registry.tables.push(table);
|
||||
},
|
||||
|
||||
deregister(table){
|
||||
var index = TableRegistry.registry.tables.indexOf(table);
|
||||
|
||||
if(index > -1){
|
||||
TableRegistry.registry.tables.splice(index, 1);
|
||||
}
|
||||
},
|
||||
|
||||
lookupTable(query, silent){
|
||||
var results = [],
|
||||
matches, match;
|
||||
|
||||
if(typeof query === "string"){
|
||||
matches = document.querySelectorAll(query);
|
||||
|
||||
if(matches.length){
|
||||
for(var i = 0; i < matches.length; i++){
|
||||
match = TableRegistry.registry.matchElement(matches[i]);
|
||||
|
||||
if(match){
|
||||
results.push(match);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}else if((typeof HTMLElement !== "undefined" && query instanceof HTMLElement) || query instanceof TableRegistry){
|
||||
match = TableRegistry.registry.matchElement(query);
|
||||
|
||||
if(match){
|
||||
results.push(match);
|
||||
}
|
||||
}else if(Array.isArray(query)){
|
||||
query.forEach(function(item){
|
||||
results = results.concat(TableRegistry.registry.lookupTable(item));
|
||||
});
|
||||
}else{
|
||||
if(!silent){
|
||||
console.warn("Table Connection Error - Invalid Selector", query);
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
},
|
||||
|
||||
matchElement(element){
|
||||
return TableRegistry.registry.tables.find(function(table){
|
||||
return element instanceof TableRegistry ? table === element : table.element === element;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
static findTable(query){
|
||||
var results = TableRegistry.registry.lookupTable(query, true);
|
||||
return Array.isArray(results) && !results.length ? false : results;
|
||||
}
|
||||
}
|
||||
115
public/libs/tabulator-master/src/js/modules/Accessor/Accessor.js
Normal file
115
public/libs/tabulator-master/src/js/modules/Accessor/Accessor.js
Normal file
@@ -0,0 +1,115 @@
|
||||
import Module from '../../core/Module.js';
|
||||
import Helpers from '../../core/tools/Helpers.js';
|
||||
|
||||
import defaultAccessors from './defaults/accessors.js';
|
||||
|
||||
export default class Accessor extends Module{
|
||||
|
||||
static moduleName = "accessor";
|
||||
|
||||
//load defaults
|
||||
static accessors = defaultAccessors;
|
||||
|
||||
constructor(table){
|
||||
super(table);
|
||||
|
||||
this.allowedTypes = ["", "data", "download", "clipboard", "print", "htmlOutput"]; //list of accessor types
|
||||
|
||||
this.registerColumnOption("accessor");
|
||||
this.registerColumnOption("accessorParams");
|
||||
this.registerColumnOption("accessorData");
|
||||
this.registerColumnOption("accessorDataParams");
|
||||
this.registerColumnOption("accessorDownload");
|
||||
this.registerColumnOption("accessorDownloadParams");
|
||||
this.registerColumnOption("accessorClipboard");
|
||||
this.registerColumnOption("accessorClipboardParams");
|
||||
this.registerColumnOption("accessorPrint");
|
||||
this.registerColumnOption("accessorPrintParams");
|
||||
this.registerColumnOption("accessorHtmlOutput");
|
||||
this.registerColumnOption("accessorHtmlOutputParams");
|
||||
}
|
||||
|
||||
initialize(){
|
||||
this.subscribe("column-layout", this.initializeColumn.bind(this));
|
||||
this.subscribe("row-data-retrieve", this.transformRow.bind(this));
|
||||
}
|
||||
|
||||
//initialize column accessor
|
||||
initializeColumn(column){
|
||||
var match = false,
|
||||
config = {};
|
||||
|
||||
this.allowedTypes.forEach((type) => {
|
||||
var key = "accessor" + (type.charAt(0).toUpperCase() + type.slice(1)),
|
||||
accessor;
|
||||
|
||||
if(column.definition[key]){
|
||||
accessor = this.lookupAccessor(column.definition[key]);
|
||||
|
||||
if(accessor){
|
||||
match = true;
|
||||
|
||||
config[key] = {
|
||||
accessor:accessor,
|
||||
params: column.definition[key + "Params"] || {},
|
||||
};
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if(match){
|
||||
column.modules.accessor = config;
|
||||
}
|
||||
}
|
||||
|
||||
lookupAccessor(value){
|
||||
var accessor = false;
|
||||
|
||||
//set column accessor
|
||||
switch(typeof value){
|
||||
case "string":
|
||||
if(Accessor.accessors[value]){
|
||||
accessor = Accessor.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
|
||||
transformRow(row, type){
|
||||
var key = "accessor" + (type.charAt(0).toUpperCase() + type.slice(1)),
|
||||
rowComponent = row.getComponent();
|
||||
|
||||
//clone data object with deep copy to isolate internal data from returned result
|
||||
var data = Helpers.deepClone(row.data || {});
|
||||
|
||||
this.table.columnManager.traverse(function(column){
|
||||
var value, accessor, params, colComponent;
|
||||
|
||||
if(column.modules.accessor){
|
||||
|
||||
accessor = column.modules.accessor[key] || column.modules.accessor.accessor || false;
|
||||
|
||||
if(accessor){
|
||||
value = column.getFieldValue(data);
|
||||
|
||||
if(value != "undefined"){
|
||||
colComponent = column.getComponent();
|
||||
params = typeof accessor.params === "function" ? accessor.params(value, data, type, colComponent, rowComponent) : accessor.params;
|
||||
column.setFieldValue(data, accessor.accessor(value, data, type, params, colComponent, rowComponent));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return data;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
export default {
|
||||
rownum:function(value, data, type, params, column, row){
|
||||
return row.getPosition();
|
||||
}
|
||||
};
|
||||
142
public/libs/tabulator-master/src/js/modules/Ajax/Ajax.js
Normal file
142
public/libs/tabulator-master/src/js/modules/Ajax/Ajax.js
Normal file
@@ -0,0 +1,142 @@
|
||||
import Module from '../../core/Module.js';
|
||||
|
||||
import defaultConfig from './defaults/config.js';
|
||||
import defaultURLGenerator from './defaults/urlGenerator.js';
|
||||
import defaultLoaderPromise from './defaults/loaderPromise.js';
|
||||
import defaultContentTypeFormatters from './defaults/contentTypeFormatters.js';
|
||||
|
||||
export default class Ajax extends Module{
|
||||
|
||||
static moduleName = "ajax";
|
||||
|
||||
//load defaults
|
||||
static defaultConfig = defaultConfig;
|
||||
static defaultURLGenerator = defaultURLGenerator;
|
||||
static defaultLoaderPromise = defaultLoaderPromise;
|
||||
static contentTypeFormatters = defaultContentTypeFormatters;
|
||||
|
||||
constructor(table){
|
||||
super(table);
|
||||
|
||||
this.config = {}; //hold config object for ajax request
|
||||
this.url = ""; //request URL
|
||||
this.urlGenerator = false;
|
||||
this.params = false; //request parameters
|
||||
|
||||
this.loaderPromise = false;
|
||||
|
||||
this.registerTableOption("ajaxURL", false); //url for ajax loading
|
||||
this.registerTableOption("ajaxURLGenerator", false);
|
||||
this.registerTableOption("ajaxParams", {}); //params for ajax loading
|
||||
this.registerTableOption("ajaxConfig", "get"); //ajax request type
|
||||
this.registerTableOption("ajaxContentType", "form"); //ajax request type
|
||||
this.registerTableOption("ajaxRequestFunc", false); //promise function
|
||||
|
||||
this.registerTableOption("ajaxRequesting", function(){});
|
||||
this.registerTableOption("ajaxResponse", false);
|
||||
|
||||
this.contentTypeFormatters = Ajax.contentTypeFormatters;
|
||||
}
|
||||
|
||||
//initialize setup options
|
||||
initialize(){
|
||||
this.loaderPromise = this.table.options.ajaxRequestFunc || Ajax.defaultLoaderPromise;
|
||||
this.urlGenerator = this.table.options.ajaxURLGenerator || Ajax.defaultURLGenerator;
|
||||
|
||||
if(this.table.options.ajaxURL){
|
||||
this.setUrl(this.table.options.ajaxURL);
|
||||
}
|
||||
|
||||
|
||||
this.setDefaultConfig(this.table.options.ajaxConfig);
|
||||
|
||||
this.registerTableFunction("getAjaxUrl", this.getUrl.bind(this));
|
||||
|
||||
this.subscribe("data-loading", this.requestDataCheck.bind(this));
|
||||
this.subscribe("data-params", this.requestParams.bind(this));
|
||||
this.subscribe("data-load", this.requestData.bind(this));
|
||||
}
|
||||
|
||||
requestParams(data, config, silent, params){
|
||||
var ajaxParams = this.table.options.ajaxParams;
|
||||
|
||||
if(ajaxParams){
|
||||
if(typeof ajaxParams === "function"){
|
||||
ajaxParams = ajaxParams.call(this.table);
|
||||
}
|
||||
|
||||
params = Object.assign(Object.assign({}, ajaxParams), params);
|
||||
}
|
||||
|
||||
return params;
|
||||
}
|
||||
|
||||
requestDataCheck(data, params, config, silent){
|
||||
return !!((!data && this.url) || typeof data === "string");
|
||||
}
|
||||
|
||||
requestData(url, params, config, silent, previousData){
|
||||
var ajaxConfig;
|
||||
|
||||
if(!previousData && this.requestDataCheck(url)){
|
||||
if(url){
|
||||
this.setUrl(url);
|
||||
}
|
||||
|
||||
ajaxConfig = this.generateConfig(config);
|
||||
|
||||
return this.sendRequest(this.url, params, ajaxConfig);
|
||||
}else{
|
||||
return previousData;
|
||||
}
|
||||
}
|
||||
|
||||
setDefaultConfig(config = {}){
|
||||
this.config = Object.assign({}, Ajax.defaultConfig);
|
||||
|
||||
if(typeof config == "string"){
|
||||
this.config.method = config;
|
||||
}else{
|
||||
Object.assign(this.config, config);
|
||||
}
|
||||
}
|
||||
|
||||
//load config object
|
||||
generateConfig(config = {}){
|
||||
var ajaxConfig = Object.assign({}, this.config);
|
||||
|
||||
if(typeof config == "string"){
|
||||
ajaxConfig.method = config;
|
||||
}else{
|
||||
Object.assign(ajaxConfig, config);
|
||||
}
|
||||
|
||||
return ajaxConfig;
|
||||
}
|
||||
|
||||
//set request url
|
||||
setUrl(url){
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
//get request url
|
||||
getUrl(){
|
||||
return this.url;
|
||||
}
|
||||
|
||||
//send ajax request
|
||||
sendRequest(url, params, config){
|
||||
if(this.table.options.ajaxRequesting.call(this.table, url, params) !== false){
|
||||
return this.loaderPromise(url, config, params)
|
||||
.then((data)=>{
|
||||
if(this.table.options.ajaxResponse){
|
||||
data = this.table.options.ajaxResponse.call(this.table, url, params, data);
|
||||
}
|
||||
|
||||
return data;
|
||||
});
|
||||
}else{
|
||||
return Promise.reject();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
export default {
|
||||
method: "GET",
|
||||
};
|
||||
@@ -0,0 +1,45 @@
|
||||
function generateParamsList(data, prefix){
|
||||
var output = [];
|
||||
|
||||
prefix = prefix || "";
|
||||
|
||||
if(Array.isArray(data)){
|
||||
data.forEach((item, i) => {
|
||||
output = output.concat(generateParamsList(item, prefix ? prefix + "[" + i + "]" : i));
|
||||
});
|
||||
}else if (typeof data === "object"){
|
||||
for (var key in data){
|
||||
output = output.concat(generateParamsList(data[key], prefix ? prefix + "[" + key + "]" : key));
|
||||
}
|
||||
}else{
|
||||
output.push({key:prefix, value:data});
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
export default {
|
||||
"json":{
|
||||
headers:{
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body:function(url, config, params){
|
||||
return JSON.stringify(params);
|
||||
},
|
||||
},
|
||||
"form":{
|
||||
headers:{
|
||||
},
|
||||
body:function(url, config, params){
|
||||
|
||||
var output = generateParamsList(params),
|
||||
form = new FormData();
|
||||
|
||||
output.forEach(function(item){
|
||||
form.append(item.key, item.value);
|
||||
});
|
||||
|
||||
return form;
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,87 @@
|
||||
export default function(url, config, params){
|
||||
var contentType;
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
//set url
|
||||
url = this.urlGenerator.call(this.table, url, config, params);
|
||||
|
||||
//set body content if not GET request
|
||||
if(config.method.toUpperCase() != "GET"){
|
||||
contentType = typeof this.table.options.ajaxContentType === "object" ? this.table.options.ajaxContentType : this.contentTypeFormatters[this.table.options.ajaxContentType];
|
||||
if(contentType){
|
||||
|
||||
for(var key in contentType.headers){
|
||||
if(!config.headers){
|
||||
config.headers = {};
|
||||
}
|
||||
|
||||
if(typeof config.headers[key] === "undefined"){
|
||||
config.headers[key] = contentType.headers[key];
|
||||
}
|
||||
}
|
||||
|
||||
config.body = contentType.body.call(this, url, config, params);
|
||||
|
||||
}else{
|
||||
console.warn("Ajax Error - Invalid ajaxContentType value:", this.table.options.ajaxContentType);
|
||||
}
|
||||
}
|
||||
|
||||
if(url){
|
||||
//configure headers
|
||||
if(typeof config.headers === "undefined"){
|
||||
config.headers = {};
|
||||
}
|
||||
|
||||
if(typeof config.headers.Accept === "undefined"){
|
||||
config.headers.Accept = "application/json";
|
||||
}
|
||||
|
||||
if(typeof config.headers["X-Requested-With"] === "undefined"){
|
||||
config.headers["X-Requested-With"] = "XMLHttpRequest";
|
||||
}
|
||||
|
||||
if(typeof config.mode === "undefined"){
|
||||
config.mode = "cors";
|
||||
}
|
||||
|
||||
if(config.mode == "cors"){
|
||||
if(typeof config.headers["Origin"] === "undefined"){
|
||||
config.headers["Origin"] = window.location.origin;
|
||||
}
|
||||
|
||||
if(typeof config.credentials === "undefined"){
|
||||
config.credentials = 'same-origin';
|
||||
}
|
||||
}else{
|
||||
if(typeof config.credentials === "undefined"){
|
||||
config.credentials = 'include';
|
||||
}
|
||||
}
|
||||
|
||||
//send request
|
||||
fetch(url, config)
|
||||
.then((response)=>{
|
||||
if(response.ok) {
|
||||
response.json()
|
||||
.then((data)=>{
|
||||
resolve(data);
|
||||
}).catch((error)=>{
|
||||
reject(error);
|
||||
console.warn("Ajax Load Error - Invalid JSON returned", error);
|
||||
});
|
||||
}else{
|
||||
console.error("Ajax Load Error - Connection Error: " + response.status, response.statusText);
|
||||
reject(response);
|
||||
}
|
||||
})
|
||||
.catch((error)=>{
|
||||
console.error("Ajax Load Error - Connection Error: ", error);
|
||||
reject(error);
|
||||
});
|
||||
}else{
|
||||
console.warn("Ajax Load Error - No URL Set");
|
||||
resolve([]);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
function generateParamsList(data, prefix){
|
||||
var output = [];
|
||||
|
||||
prefix = prefix || "";
|
||||
|
||||
if(Array.isArray(data)){
|
||||
data.forEach((item, i) => {
|
||||
output = output.concat(generateParamsList(item, prefix ? prefix + "[" + i + "]" : i));
|
||||
});
|
||||
}else if (typeof data === "object"){
|
||||
for (var key in data){
|
||||
output = output.concat(generateParamsList(data[key], prefix ? prefix + "[" + key + "]" : key));
|
||||
}
|
||||
}else{
|
||||
output.push({key:prefix, value:data});
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
function serializeParams(params){
|
||||
var output = generateParamsList(params),
|
||||
encoded = [];
|
||||
|
||||
output.forEach(function(item){
|
||||
encoded.push(encodeURIComponent(item.key) + "=" + encodeURIComponent(item.value));
|
||||
});
|
||||
|
||||
return encoded.join("&");
|
||||
}
|
||||
|
||||
export default function(url, config, params){
|
||||
if(url){
|
||||
if(params && Object.keys(params).length){
|
||||
if(!config.method || config.method.toLowerCase() == "get"){
|
||||
config.method = "get";
|
||||
|
||||
url += (url.includes("?") ? "&" : "?") + serializeParams(params);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return url;
|
||||
}
|
||||
@@ -0,0 +1,282 @@
|
||||
import Module from '../../core/Module.js';
|
||||
|
||||
import defaultPasteActions from './defaults/pasteActions.js';
|
||||
import defaultPasteParsers from './defaults/pasteParsers.js';
|
||||
import extensions from './extensions/extensions.js';
|
||||
|
||||
export default class Clipboard extends Module{
|
||||
|
||||
static moduleName = "clipboard";
|
||||
static moduleExtensions = extensions;
|
||||
|
||||
//load defaults
|
||||
static pasteActions = defaultPasteActions;
|
||||
static pasteParsers = defaultPasteParsers;
|
||||
|
||||
constructor(table){
|
||||
super(table);
|
||||
|
||||
this.mode = true;
|
||||
this.pasteParser = function(){};
|
||||
this.pasteAction = function(){};
|
||||
this.customSelection = false;
|
||||
this.rowRange = false;
|
||||
this.blocked = true; //block copy actions not originating from this command
|
||||
|
||||
this.registerTableOption("clipboard", false); //enable clipboard
|
||||
this.registerTableOption("clipboardCopyStyled", true); //formatted table data
|
||||
this.registerTableOption("clipboardCopyConfig", false); //clipboard config
|
||||
this.registerTableOption("clipboardCopyFormatter", false); //DEPRECATED - REMOVE in 5.0
|
||||
this.registerTableOption("clipboardCopyRowRange", "active"); //restrict clipboard to visible rows only
|
||||
this.registerTableOption("clipboardPasteParser", "table"); //convert pasted clipboard data to rows
|
||||
this.registerTableOption("clipboardPasteAction", "insert"); //how to insert pasted data into the table
|
||||
|
||||
this.registerColumnOption("clipboard");
|
||||
this.registerColumnOption("titleClipboard");
|
||||
}
|
||||
|
||||
initialize(){
|
||||
this.mode = this.table.options.clipboard;
|
||||
|
||||
this.rowRange = this.table.options.clipboardCopyRowRange;
|
||||
|
||||
if(this.mode === true || this.mode === "copy"){
|
||||
this.table.element.addEventListener("copy", (e) => {
|
||||
var plain, html, list;
|
||||
|
||||
if(!this.blocked){
|
||||
e.preventDefault();
|
||||
|
||||
if(this.customSelection){
|
||||
plain = this.customSelection;
|
||||
|
||||
if(this.table.options.clipboardCopyFormatter){
|
||||
plain = this.table.options.clipboardCopyFormatter("plain", plain);
|
||||
}
|
||||
}else{
|
||||
|
||||
list = this.table.modules.export.generateExportList(this.table.options.clipboardCopyConfig, this.table.options.clipboardCopyStyled, this.rowRange, "clipboard");
|
||||
|
||||
html = this.table.modules.export.generateHTMLTable(list);
|
||||
plain = html ? this.generatePlainContent(list) : "";
|
||||
|
||||
if(this.table.options.clipboardCopyFormatter){
|
||||
plain = this.table.options.clipboardCopyFormatter("plain", plain);
|
||||
html = this.table.options.clipboardCopyFormatter("html", html);
|
||||
}
|
||||
}
|
||||
|
||||
if (window.clipboardData && window.clipboardData.setData) {
|
||||
window.clipboardData.setData('Text', plain);
|
||||
} else if (e.clipboardData && e.clipboardData.setData) {
|
||||
e.clipboardData.setData('text/plain', plain);
|
||||
if(html){
|
||||
e.clipboardData.setData('text/html', html);
|
||||
}
|
||||
} else if (e.originalEvent && e.originalEvent.clipboardData.setData) {
|
||||
e.originalEvent.clipboardData.setData('text/plain', plain);
|
||||
if(html){
|
||||
e.originalEvent.clipboardData.setData('text/html', html);
|
||||
}
|
||||
}
|
||||
|
||||
this.dispatchExternal("clipboardCopied", plain, html);
|
||||
|
||||
this.reset();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if(this.mode === true || this.mode === "paste"){
|
||||
this.table.element.addEventListener("paste", (e) => {
|
||||
this.paste(e);
|
||||
});
|
||||
}
|
||||
|
||||
this.setPasteParser(this.table.options.clipboardPasteParser);
|
||||
this.setPasteAction(this.table.options.clipboardPasteAction);
|
||||
|
||||
this.registerTableFunction("copyToClipboard", this.copy.bind(this));
|
||||
}
|
||||
|
||||
reset(){
|
||||
this.blocked = true;
|
||||
this.customSelection = false;
|
||||
}
|
||||
|
||||
generatePlainContent (list) {
|
||||
var output = [];
|
||||
|
||||
list.forEach((row) => {
|
||||
var rowData = [];
|
||||
|
||||
row.columns.forEach((col) => {
|
||||
var value = "";
|
||||
|
||||
if(col){
|
||||
|
||||
if(row.type === "group"){
|
||||
col.value = col.component.getKey();
|
||||
}
|
||||
|
||||
if(col.value === null){
|
||||
value = "";
|
||||
}else{
|
||||
switch(typeof col.value){
|
||||
case "object":
|
||||
value = JSON.stringify(col.value);
|
||||
break;
|
||||
|
||||
case "undefined":
|
||||
value = "";
|
||||
break;
|
||||
|
||||
default:
|
||||
value = col.value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rowData.push(value);
|
||||
});
|
||||
|
||||
output.push(rowData.join("\t"));
|
||||
});
|
||||
|
||||
return output.join("\n");
|
||||
}
|
||||
|
||||
copy (range, internal) {
|
||||
var sel, textRange;
|
||||
this.blocked = false;
|
||||
this.customSelection = false;
|
||||
|
||||
|
||||
if (this.mode === true || this.mode === "copy") {
|
||||
|
||||
this.rowRange = range || this.table.options.clipboardCopyRowRange;
|
||||
|
||||
if (typeof window.getSelection != "undefined" && typeof document.createRange != "undefined") {
|
||||
range = document.createRange();
|
||||
range.selectNodeContents(this.table.element);
|
||||
sel = window.getSelection();
|
||||
|
||||
if (sel.toString() && internal) {
|
||||
this.customSelection = 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);
|
||||
textRange.select();
|
||||
}
|
||||
|
||||
document.execCommand('copy');
|
||||
|
||||
if (sel) {
|
||||
sel.removeAllRanges();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//PASTE EVENT HANDLING
|
||||
setPasteAction(action){
|
||||
|
||||
switch(typeof action){
|
||||
case "string":
|
||||
this.pasteAction = Clipboard.pasteActions[action];
|
||||
|
||||
if(!this.pasteAction){
|
||||
console.warn("Clipboard Error - No such paste action found:", action);
|
||||
}
|
||||
break;
|
||||
|
||||
case "function":
|
||||
this.pasteAction = action;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
setPasteParser(parser){
|
||||
switch(typeof parser){
|
||||
case "string":
|
||||
this.pasteParser = Clipboard.pasteParsers[parser];
|
||||
|
||||
if(!this.pasteParser){
|
||||
console.warn("Clipboard Error - No such paste parser found:", parser);
|
||||
}
|
||||
break;
|
||||
|
||||
case "function":
|
||||
this.pasteParser = parser;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
paste(e){
|
||||
var data, rowData, rows;
|
||||
|
||||
if(this.checkPasteOrigin(e)){
|
||||
|
||||
data = this.getPasteData(e);
|
||||
|
||||
rowData = this.pasteParser.call(this, data);
|
||||
|
||||
if(rowData){
|
||||
e.preventDefault();
|
||||
|
||||
if(this.table.modExists("mutator")){
|
||||
rowData = this.mutateData(rowData);
|
||||
}
|
||||
|
||||
rows = this.pasteAction.call(this, rowData);
|
||||
|
||||
this.dispatchExternal("clipboardPasted", data, rowData, rows);
|
||||
}else{
|
||||
this.dispatchExternal("clipboardPasteError", data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mutateData(data){
|
||||
var output = [];
|
||||
|
||||
if(Array.isArray(data)){
|
||||
data.forEach((row) => {
|
||||
output.push(this.table.modules.mutator.transformRow(row, "clipboard"));
|
||||
});
|
||||
}else{
|
||||
output = data;
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
checkPasteOrigin(e){
|
||||
var valid = true;
|
||||
var blocked = this.confirm("clipboard-paste", [e]);
|
||||
|
||||
if(blocked || !["DIV", "SPAN"].includes(e.target.tagName)){
|
||||
valid = false;
|
||||
}
|
||||
|
||||
return valid;
|
||||
}
|
||||
|
||||
getPasteData(e){
|
||||
var data;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
export default {
|
||||
replace:function(data){
|
||||
return this.table.setData(data);
|
||||
},
|
||||
update:function(data){
|
||||
return this.table.updateOrAddData(data);
|
||||
},
|
||||
insert:function(data){
|
||||
return this.table.addData(data);
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,75 @@
|
||||
export default {
|
||||
table:function(clipboard){
|
||||
var data = [],
|
||||
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)){
|
||||
|
||||
//check if headers are present by title
|
||||
data[0].forEach(function(value){
|
||||
var column = columns.find(function(column){
|
||||
return value && column.definition.title && 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 && column.field && 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;
|
||||
}
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,9 @@
|
||||
import bindings from './keybindings/bindings.js';
|
||||
import actions from './keybindings/actions.js';
|
||||
|
||||
export default {
|
||||
keybindings:{
|
||||
bindings:bindings,
|
||||
actions:actions
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,9 @@
|
||||
export default {
|
||||
copyToClipboard:function(e){
|
||||
if(!this.table.modules.edit.currentCell){
|
||||
if(this.table.modExists("clipboard", true)){
|
||||
this.table.modules.clipboard.copy(false, true);
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,3 @@
|
||||
export default {
|
||||
copyToClipboard:["ctrl + 67", "meta + 67"],
|
||||
};
|
||||
@@ -0,0 +1,46 @@
|
||||
export default class CalcComponent{
|
||||
constructor (row){
|
||||
this._row = row;
|
||||
|
||||
return new Proxy(this, {
|
||||
get: function(target, name, receiver) {
|
||||
if (typeof target[name] !== "undefined") {
|
||||
return target[name];
|
||||
}else{
|
||||
return target._row.table.componentFunctionBinder.handle("row", target._row, name);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
getData(transform){
|
||||
return this._row.getData(transform);
|
||||
}
|
||||
|
||||
getElement(){
|
||||
return this._row.getElement();
|
||||
}
|
||||
|
||||
getTable(){
|
||||
return this._row.table;
|
||||
}
|
||||
|
||||
getCells(){
|
||||
var cells = [];
|
||||
|
||||
this._row.getCells().forEach(function(cell){
|
||||
cells.push(cell.getComponent());
|
||||
});
|
||||
|
||||
return cells;
|
||||
}
|
||||
|
||||
getCell(column){
|
||||
var cell = this._row.getCell(column);
|
||||
return cell ? cell.getComponent() : false;
|
||||
}
|
||||
|
||||
_getSelf(){
|
||||
return this._row;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,586 @@
|
||||
import Module from '../../core/Module.js';
|
||||
|
||||
import CalcComponent from './CalcComponent.js';
|
||||
|
||||
import Cell from '../../core/cell/Cell.js';
|
||||
import Column from '../../core/column/Column.js';
|
||||
import Row from '../../core/row/Row.js';
|
||||
|
||||
import defaultCalculations from './defaults/calculations.js';
|
||||
|
||||
export default class ColumnCalcs extends Module{
|
||||
|
||||
static moduleName = "columnCalcs";
|
||||
|
||||
//load defaults
|
||||
static calculations = defaultCalculations;
|
||||
|
||||
constructor(table){
|
||||
super(table);
|
||||
|
||||
this.topCalcs = [];
|
||||
this.botCalcs = [];
|
||||
this.genColumn = false;
|
||||
this.topElement = this.createElement();
|
||||
this.botElement = this.createElement();
|
||||
this.topRow = false;
|
||||
this.botRow = false;
|
||||
this.topInitialized = false;
|
||||
this.botInitialized = false;
|
||||
|
||||
this.blocked = false;
|
||||
this.recalcAfterBlock = false;
|
||||
|
||||
this.registerTableOption("columnCalcs", true);
|
||||
|
||||
this.registerColumnOption("topCalc");
|
||||
this.registerColumnOption("topCalcParams");
|
||||
this.registerColumnOption("topCalcFormatter");
|
||||
this.registerColumnOption("topCalcFormatterParams");
|
||||
this.registerColumnOption("bottomCalc");
|
||||
this.registerColumnOption("bottomCalcParams");
|
||||
this.registerColumnOption("bottomCalcFormatter");
|
||||
this.registerColumnOption("bottomCalcFormatterParams");
|
||||
}
|
||||
|
||||
createElement (){
|
||||
var el = document.createElement("div");
|
||||
el.classList.add("tabulator-calcs-holder");
|
||||
return el;
|
||||
}
|
||||
|
||||
initialize(){
|
||||
this.genColumn = new Column({field:"value"}, this);
|
||||
|
||||
this.subscribe("cell-value-changed", this.cellValueChanged.bind(this));
|
||||
this.subscribe("column-init", this.initializeColumnCheck.bind(this));
|
||||
this.subscribe("row-deleted", this.rowsUpdated.bind(this));
|
||||
this.subscribe("scroll-horizontal", this.scrollHorizontal.bind(this));
|
||||
this.subscribe("row-added", this.rowsUpdated.bind(this));
|
||||
this.subscribe("column-moved", this.recalcActiveRows.bind(this));
|
||||
this.subscribe("column-add", this.recalcActiveRows.bind(this));
|
||||
this.subscribe("data-refreshed", this.recalcActiveRowsRefresh.bind(this));
|
||||
this.subscribe("table-redraw", this.tableRedraw.bind(this));
|
||||
this.subscribe("rows-visible", this.visibleRows.bind(this));
|
||||
this.subscribe("scrollbar-vertical", this.adjustForScrollbar.bind(this));
|
||||
|
||||
this.subscribe("redraw-blocked", this.blockRedraw.bind(this));
|
||||
this.subscribe("redraw-restored", this.restoreRedraw.bind(this));
|
||||
|
||||
this.subscribe("table-redrawing", this.resizeHolderWidth.bind(this));
|
||||
this.subscribe("column-resized", this.resizeHolderWidth.bind(this));
|
||||
this.subscribe("column-show", this.resizeHolderWidth.bind(this));
|
||||
this.subscribe("column-hide", this.resizeHolderWidth.bind(this));
|
||||
|
||||
this.registerTableFunction("getCalcResults", this.getResults.bind(this));
|
||||
this.registerTableFunction("recalc", this.userRecalc.bind(this));
|
||||
|
||||
|
||||
this.resizeHolderWidth();
|
||||
}
|
||||
|
||||
resizeHolderWidth(){
|
||||
this.topElement.style.minWidth = this.table.columnManager.headersElement.offsetWidth + "px";
|
||||
}
|
||||
|
||||
|
||||
tableRedraw(force){
|
||||
this.recalc(this.table.rowManager.activeRows);
|
||||
|
||||
if(force){
|
||||
this.redraw();
|
||||
}
|
||||
}
|
||||
|
||||
blockRedraw(){
|
||||
this.blocked = true;
|
||||
this.recalcAfterBlock = false;
|
||||
}
|
||||
|
||||
|
||||
restoreRedraw(){
|
||||
this.blocked = false;
|
||||
|
||||
if(this.recalcAfterBlock){
|
||||
this.recalcAfterBlock = false;
|
||||
this.recalcActiveRowsRefresh();
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////
|
||||
///////// Table Functions /////////
|
||||
///////////////////////////////////
|
||||
userRecalc(){
|
||||
this.recalc(this.table.rowManager.activeRows);
|
||||
}
|
||||
|
||||
///////////////////////////////////
|
||||
///////// Internal Logic //////////
|
||||
///////////////////////////////////
|
||||
|
||||
blockCheck(){
|
||||
if(this.blocked){
|
||||
this.recalcAfterBlock = true;
|
||||
}
|
||||
|
||||
return this.blocked;
|
||||
}
|
||||
|
||||
visibleRows(viewable, rows){
|
||||
if(this.topRow){
|
||||
rows.unshift(this.topRow);
|
||||
}
|
||||
|
||||
if(this.botRow){
|
||||
rows.push(this.botRow);
|
||||
}
|
||||
|
||||
return rows;
|
||||
}
|
||||
|
||||
rowsUpdated(row){
|
||||
if(this.table.options.groupBy){
|
||||
this.recalcRowGroup(row);
|
||||
}else{
|
||||
this.recalcActiveRows();
|
||||
}
|
||||
}
|
||||
|
||||
recalcActiveRowsRefresh(){
|
||||
if(this.table.options.groupBy && this.table.options.dataTreeStartExpanded && this.table.options.dataTree){
|
||||
this.recalcAll();
|
||||
}else{
|
||||
this.recalcActiveRows();
|
||||
}
|
||||
}
|
||||
|
||||
recalcActiveRows(){
|
||||
this.recalc(this.table.rowManager.activeRows);
|
||||
}
|
||||
|
||||
cellValueChanged(cell){
|
||||
if(cell.column.definition.topCalc || cell.column.definition.bottomCalc){
|
||||
if(this.table.options.groupBy){
|
||||
if(this.table.options.columnCalcs == "table" || this.table.options.columnCalcs == "both"){
|
||||
this.recalcActiveRows();
|
||||
}
|
||||
|
||||
if(this.table.options.columnCalcs != "table"){
|
||||
this.recalcRowGroup(cell.row);
|
||||
}
|
||||
}else{
|
||||
this.recalcActiveRows();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
initializeColumnCheck(column){
|
||||
if(column.definition.topCalc || column.definition.bottomCalc){
|
||||
this.initializeColumn(column);
|
||||
}
|
||||
}
|
||||
|
||||
//initialize column calcs
|
||||
initializeColumn(column){
|
||||
var def = column.definition;
|
||||
|
||||
var config = {
|
||||
topCalcParams:def.topCalcParams || {},
|
||||
botCalcParams:def.bottomCalcParams || {},
|
||||
};
|
||||
|
||||
if(def.topCalc){
|
||||
|
||||
switch(typeof def.topCalc){
|
||||
case "string":
|
||||
if(ColumnCalcs.calculations[def.topCalc]){
|
||||
config.topCalc = ColumnCalcs.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.modules.columnCalcs = config;
|
||||
this.topCalcs.push(column);
|
||||
|
||||
if(this.table.options.columnCalcs != "group"){
|
||||
this.initializeTopRow();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(def.bottomCalc){
|
||||
switch(typeof def.bottomCalc){
|
||||
case "string":
|
||||
if(ColumnCalcs.calculations[def.bottomCalc]){
|
||||
config.botCalc = ColumnCalcs.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.modules.columnCalcs = config;
|
||||
this.botCalcs.push(column);
|
||||
|
||||
if(this.table.options.columnCalcs != "group"){
|
||||
this.initializeBottomRow();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//dummy functions to handle being mock column manager
|
||||
registerColumnField(){}
|
||||
|
||||
removeCalcs(){
|
||||
var changed = false;
|
||||
|
||||
if(this.topInitialized){
|
||||
this.topInitialized = false;
|
||||
this.topElement.parentNode.removeChild(this.topElement);
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if(this.botInitialized){
|
||||
this.botInitialized = false;
|
||||
this.footerRemove(this.botElement);
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if(changed){
|
||||
this.table.rowManager.adjustTableSize();
|
||||
}
|
||||
}
|
||||
|
||||
reinitializeCalcs(){
|
||||
if(this.topCalcs.length){
|
||||
this.initializeTopRow();
|
||||
}
|
||||
|
||||
if(this.botCalcs.length){
|
||||
this.initializeBottomRow();
|
||||
}
|
||||
}
|
||||
|
||||
initializeTopRow(){
|
||||
var fragment = document.createDocumentFragment();
|
||||
|
||||
if(!this.topInitialized){
|
||||
|
||||
fragment.appendChild(document.createElement("br"));
|
||||
fragment.appendChild(this.topElement);
|
||||
|
||||
this.table.columnManager.getContentsElement().insertBefore(fragment, this.table.columnManager.headersElement.nextSibling);
|
||||
this.topInitialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
initializeBottomRow(){
|
||||
if(!this.botInitialized){
|
||||
this.footerPrepend(this.botElement);
|
||||
this.botInitialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
scrollHorizontal(left){
|
||||
if(this.botInitialized && this.botRow){
|
||||
this.botElement.scrollLeft = left;
|
||||
}
|
||||
}
|
||||
|
||||
recalc(rows){
|
||||
var data, row;
|
||||
|
||||
if(!this.blockCheck()){
|
||||
if(this.topInitialized || this.botInitialized){
|
||||
data = this.rowsToData(rows);
|
||||
|
||||
if(this.topInitialized){
|
||||
if(this.topRow){
|
||||
this.topRow.deleteCells();
|
||||
}
|
||||
|
||||
row = this.generateRow("top", data);
|
||||
this.topRow = row;
|
||||
while(this.topElement.firstChild) this.topElement.removeChild(this.topElement.firstChild);
|
||||
this.topElement.appendChild(row.getElement());
|
||||
row.initialize(true);
|
||||
}
|
||||
|
||||
if(this.botInitialized){
|
||||
if(this.botRow){
|
||||
this.botRow.deleteCells();
|
||||
}
|
||||
|
||||
row = this.generateRow("bottom", data);
|
||||
this.botRow = row;
|
||||
while(this.botElement.firstChild) this.botElement.removeChild(this.botElement.firstChild);
|
||||
this.botElement.appendChild(row.getElement());
|
||||
row.initialize(true);
|
||||
}
|
||||
|
||||
this.table.rowManager.adjustTableSize();
|
||||
|
||||
//set resizable handles
|
||||
if(this.table.modExists("frozenColumns")){
|
||||
this.table.modules.frozenColumns.layout();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
recalcRowGroup(row){
|
||||
this.recalcGroup(this.table.modules.groupRows.getRowGroup(row));
|
||||
}
|
||||
|
||||
recalcAll(){
|
||||
if(this.topCalcs.length || this.botCalcs.length){
|
||||
if(this.table.options.columnCalcs !== "group"){
|
||||
this.recalcActiveRows();
|
||||
}
|
||||
|
||||
if(this.table.options.groupBy && this.table.options.columnCalcs !== "table"){
|
||||
|
||||
var groups = this.table.modules.groupRows.getChildGroups();
|
||||
|
||||
groups.forEach((group) => {
|
||||
this.recalcGroup(group);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
recalcGroup(group){
|
||||
var data, rowData;
|
||||
|
||||
if(!this.blockCheck()){
|
||||
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
|
||||
generateTopRow(rows){
|
||||
return this.generateRow("top", this.rowsToData(rows));
|
||||
}
|
||||
//generate bottom stats row
|
||||
generateBottomRow(rows){
|
||||
return this.generateRow("bottom", this.rowsToData(rows));
|
||||
}
|
||||
|
||||
rowsToData(rows){
|
||||
var data = [],
|
||||
hasDataTreeColumnCalcs = this.table.options.dataTree && this.table.options.dataTreeChildColumnCalcs,
|
||||
dataTree = this.table.modules.dataTree;
|
||||
|
||||
rows.forEach((row) => {
|
||||
data.push(row.getData());
|
||||
|
||||
if(hasDataTreeColumnCalcs && row.modules.dataTree?.open){
|
||||
this.rowsToData(dataTree.getFilteredTreeChildren(row)).forEach(dataRow =>{
|
||||
data.push(row);
|
||||
});
|
||||
}
|
||||
});
|
||||
return data;
|
||||
}
|
||||
|
||||
//generate stats row
|
||||
generateRow(pos, data){
|
||||
var rowData = this.generateRowData(pos, data),
|
||||
row;
|
||||
|
||||
if(this.table.modExists("mutator")){
|
||||
this.table.modules.mutator.disable();
|
||||
}
|
||||
|
||||
row = new Row(rowData, this, "calc");
|
||||
|
||||
if(this.table.modExists("mutator")){
|
||||
this.table.modules.mutator.enable();
|
||||
}
|
||||
|
||||
row.getElement().classList.add("tabulator-calcs", "tabulator-calcs-" + pos);
|
||||
|
||||
row.component = false;
|
||||
|
||||
row.getComponent = () => {
|
||||
if(!row.component){
|
||||
row.component = new CalcComponent(row);
|
||||
}
|
||||
|
||||
return row.component;
|
||||
};
|
||||
|
||||
row.generateCells = () => {
|
||||
|
||||
var cells = [];
|
||||
|
||||
this.table.columnManager.columnsByIndex.forEach((column) => {
|
||||
|
||||
//set field name of mock column
|
||||
this.genColumn.setField(column.getField());
|
||||
this.genColumn.hozAlign = column.hozAlign;
|
||||
|
||||
if(column.definition[pos + "CalcFormatter"] && this.table.modExists("format")){
|
||||
this.genColumn.modules.format = {
|
||||
formatter: this.table.modules.format.lookupFormatter(column.definition[pos + "CalcFormatter"]),
|
||||
params: column.definition[pos + "CalcFormatterParams"] || {},
|
||||
};
|
||||
}else{
|
||||
this.genColumn.modules.format = {
|
||||
formatter: this.table.modules.format.lookupFormatter("plaintext"),
|
||||
params:{}
|
||||
};
|
||||
}
|
||||
|
||||
//ensure css class definition is replicated to calculation cell
|
||||
this.genColumn.definition.cssClass = column.definition.cssClass;
|
||||
|
||||
//generate cell and assign to correct column
|
||||
var cell = new Cell(this.genColumn, row);
|
||||
cell.getElement();
|
||||
cell.column = column;
|
||||
cell.setWidth();
|
||||
|
||||
column.cells.push(cell);
|
||||
cells.push(cell);
|
||||
|
||||
if(!column.visible){
|
||||
cell.hide();
|
||||
}
|
||||
});
|
||||
|
||||
row.cells = cells;
|
||||
};
|
||||
|
||||
return row;
|
||||
}
|
||||
|
||||
//generate stats row
|
||||
generateRowData(pos, data){
|
||||
var rowData = {},
|
||||
calcs = pos == "top" ? this.topCalcs : this.botCalcs,
|
||||
type = pos == "top" ? "topCalc" : "botCalc",
|
||||
params, paramKey;
|
||||
|
||||
calcs.forEach(function(column){
|
||||
var values = [];
|
||||
|
||||
if(column.modules.columnCalcs && column.modules.columnCalcs[type]){
|
||||
data.forEach(function(item){
|
||||
values.push(column.getFieldValue(item));
|
||||
});
|
||||
|
||||
paramKey = type + "Params";
|
||||
params = typeof column.modules.columnCalcs[paramKey] === "function" ? column.modules.columnCalcs[paramKey](values, data) : column.modules.columnCalcs[paramKey];
|
||||
|
||||
column.setFieldValue(rowData, column.modules.columnCalcs[type](values, data, params));
|
||||
}
|
||||
});
|
||||
|
||||
return rowData;
|
||||
}
|
||||
|
||||
hasTopCalcs(){
|
||||
return !!(this.topCalcs.length);
|
||||
}
|
||||
|
||||
hasBottomCalcs(){
|
||||
return !!(this.botCalcs.length);
|
||||
}
|
||||
|
||||
//handle table redraw
|
||||
redraw(){
|
||||
if(this.topRow){
|
||||
this.topRow.normalizeHeight(true);
|
||||
}
|
||||
if(this.botRow){
|
||||
this.botRow.normalizeHeight(true);
|
||||
}
|
||||
}
|
||||
|
||||
//return the calculated
|
||||
getResults(){
|
||||
var results = {},
|
||||
groups;
|
||||
|
||||
if(this.table.options.groupBy && this.table.modExists("groupRows")){
|
||||
groups = this.table.modules.groupRows.getGroups(true);
|
||||
|
||||
groups.forEach((group) => {
|
||||
results[group.getKey()] = this.getGroupResults(group);
|
||||
});
|
||||
}else{
|
||||
results = {
|
||||
top: this.topRow ? this.topRow.getData() : {},
|
||||
bottom: this.botRow ? this.botRow.getData() : {},
|
||||
};
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
//get results from a group
|
||||
getGroupResults(group){
|
||||
var groupObj = group._getSelf(),
|
||||
subGroups = group.getSubGroups(),
|
||||
subGroupResults = {},
|
||||
results = {};
|
||||
|
||||
subGroups.forEach((subgroup) => {
|
||||
subGroupResults[subgroup.getKey()] = this.getGroupResults(subgroup);
|
||||
});
|
||||
|
||||
results = {
|
||||
top: groupObj.calcs.top ? groupObj.calcs.top.getData() : {},
|
||||
bottom: groupObj.calcs.bottom ? groupObj.calcs.bottom.getData() : {},
|
||||
groups: subGroupResults,
|
||||
};
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
adjustForScrollbar(width){
|
||||
if(this.botRow){
|
||||
if(this.table.rtl){
|
||||
this.botElement.style.paddingLeft = width + "px";
|
||||
}else{
|
||||
this.botElement.style.paddingRight = width + "px";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
export default {
|
||||
"avg":function(values, data, calcParams){
|
||||
var output = 0,
|
||||
precision = typeof calcParams.precision !== "undefined" ? calcParams.precision : 2;
|
||||
|
||||
if(values.length){
|
||||
output = values.reduce(function(sum, value){
|
||||
return Number(sum) + Number(value);
|
||||
});
|
||||
|
||||
output = output / values.length;
|
||||
|
||||
output = precision !== false ? output.toFixed(precision) : output;
|
||||
}
|
||||
|
||||
return parseFloat(output).toString();
|
||||
},
|
||||
"max":function(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(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(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(values, data, calcParams){
|
||||
var output = 0;
|
||||
|
||||
if(values.length){
|
||||
output = values.reduce(function(sum, value){
|
||||
return String(sum) + String(value);
|
||||
});
|
||||
}
|
||||
|
||||
return output;
|
||||
},
|
||||
"count":function(values, data, calcParams){
|
||||
var output = 0;
|
||||
|
||||
if(values.length){
|
||||
values.forEach(function(value){
|
||||
if(value){
|
||||
output ++;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return output;
|
||||
},
|
||||
"unique":function(values, data, calcParams){
|
||||
var unique = values.filter((value, index) => {
|
||||
return (values || value === 0) && values.indexOf(value) === index;
|
||||
});
|
||||
|
||||
return unique.length;
|
||||
},
|
||||
};
|
||||
49
public/libs/tabulator-master/src/js/modules/Comms/Comms.js
Normal file
49
public/libs/tabulator-master/src/js/modules/Comms/Comms.js
Normal file
@@ -0,0 +1,49 @@
|
||||
import Module from '../../core/Module.js';
|
||||
|
||||
export default class Comms extends Module{
|
||||
|
||||
static moduleName = "comms";
|
||||
|
||||
constructor(table){
|
||||
super(table);
|
||||
}
|
||||
|
||||
initialize(){
|
||||
this.registerTableFunction("tableComms", this.receive.bind(this));
|
||||
}
|
||||
|
||||
getConnections(selectors){
|
||||
var connections = [],
|
||||
connection;
|
||||
|
||||
connection = this.table.constructor.registry.lookupTable(selectors);
|
||||
|
||||
connection.forEach((con) =>{
|
||||
if(this.table !== con){
|
||||
connections.push(con);
|
||||
}
|
||||
});
|
||||
|
||||
return connections;
|
||||
}
|
||||
|
||||
send(selectors, module, action, data){
|
||||
var connections = this.getConnections(selectors);
|
||||
|
||||
connections.forEach((connection) => {
|
||||
connection.tableComms(this.table.element, module, action, data);
|
||||
});
|
||||
|
||||
if(!connections.length && selectors){
|
||||
console.warn("Table Connection Error - No tables matching selector found", selectors);
|
||||
}
|
||||
}
|
||||
|
||||
receive(table, module, action, data){
|
||||
if(this.table.modExists(module)){
|
||||
return this.table.modules[module].commsReceived(table, action, data);
|
||||
}else{
|
||||
console.warn("Inter-table Comms Error - no such module:", module);
|
||||
}
|
||||
}
|
||||
}
|
||||
620
public/libs/tabulator-master/src/js/modules/DataTree/DataTree.js
Normal file
620
public/libs/tabulator-master/src/js/modules/DataTree/DataTree.js
Normal file
@@ -0,0 +1,620 @@
|
||||
import Module from '../../core/Module.js';
|
||||
|
||||
import Row from '../../core/row/Row.js';
|
||||
|
||||
import RowComponent from '../../core/row/RowComponent.js';
|
||||
|
||||
export default class DataTree extends Module{
|
||||
|
||||
static moduleName = "dataTree";
|
||||
|
||||
constructor(table){
|
||||
super(table);
|
||||
|
||||
this.indent = 10;
|
||||
this.field = "";
|
||||
this.collapseEl = null;
|
||||
this.expandEl = null;
|
||||
this.branchEl = null;
|
||||
this.elementField = false;
|
||||
|
||||
this.startOpen = function(){};
|
||||
|
||||
this.registerTableOption("dataTree", false); //enable data tree
|
||||
this.registerTableOption("dataTreeFilter", true); //filter child rows
|
||||
this.registerTableOption("dataTreeSort", true); //sort child rows
|
||||
this.registerTableOption("dataTreeElementColumn", false);
|
||||
this.registerTableOption("dataTreeBranchElement", true);//show data tree branch element
|
||||
this.registerTableOption("dataTreeChildIndent", 9); //data tree child indent in px
|
||||
this.registerTableOption("dataTreeChildField", "_children");//data tre column field to look for child rows
|
||||
this.registerTableOption("dataTreeCollapseElement", false);//data tree row collapse element
|
||||
this.registerTableOption("dataTreeExpandElement", false);//data tree row expand element
|
||||
this.registerTableOption("dataTreeStartExpanded", false);
|
||||
this.registerTableOption("dataTreeChildColumnCalcs", false);//include visible data tree rows in column calculations
|
||||
this.registerTableOption("dataTreeSelectPropagate", false);//selecting a parent row selects its children
|
||||
|
||||
//register component functions
|
||||
this.registerComponentFunction("row", "treeCollapse", this.collapseRow.bind(this));
|
||||
this.registerComponentFunction("row", "treeExpand", this.expandRow.bind(this));
|
||||
this.registerComponentFunction("row", "treeToggle", this.toggleRow.bind(this));
|
||||
this.registerComponentFunction("row", "getTreeParent", this.getTreeParent.bind(this));
|
||||
this.registerComponentFunction("row", "getTreeChildren", this.getRowChildren.bind(this));
|
||||
this.registerComponentFunction("row", "addTreeChild", this.addTreeChildRow.bind(this));
|
||||
this.registerComponentFunction("row", "isTreeExpanded", this.isRowExpanded.bind(this));
|
||||
}
|
||||
|
||||
initialize(){
|
||||
if(this.table.options.dataTree){
|
||||
var dummyEl = null,
|
||||
options = this.table.options;
|
||||
|
||||
this.field = options.dataTreeChildField;
|
||||
this.indent = options.dataTreeChildIndent;
|
||||
|
||||
if(this.options("movableRows")){
|
||||
console.warn("The movableRows option is not available with dataTree enabled, moving of child rows could result in unpredictable behavior");
|
||||
}
|
||||
|
||||
if(options.dataTreeBranchElement){
|
||||
|
||||
if(options.dataTreeBranchElement === true){
|
||||
this.branchEl = document.createElement("div");
|
||||
this.branchEl.classList.add("tabulator-data-tree-branch");
|
||||
}else{
|
||||
if(typeof options.dataTreeBranchElement === "string"){
|
||||
dummyEl = document.createElement("div");
|
||||
dummyEl.innerHTML = options.dataTreeBranchElement;
|
||||
this.branchEl = dummyEl.firstChild;
|
||||
}else{
|
||||
this.branchEl = options.dataTreeBranchElement;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
this.branchEl = document.createElement("div");
|
||||
this.branchEl.classList.add("tabulator-data-tree-branch-empty");
|
||||
}
|
||||
|
||||
if(options.dataTreeCollapseElement){
|
||||
if(typeof options.dataTreeCollapseElement === "string"){
|
||||
dummyEl = document.createElement("div");
|
||||
dummyEl.innerHTML = options.dataTreeCollapseElement;
|
||||
this.collapseEl = dummyEl.firstChild;
|
||||
}else{
|
||||
this.collapseEl = options.dataTreeCollapseElement;
|
||||
}
|
||||
}else{
|
||||
this.collapseEl = document.createElement("div");
|
||||
this.collapseEl.classList.add("tabulator-data-tree-control");
|
||||
this.collapseEl.tabIndex = 0;
|
||||
this.collapseEl.innerHTML = "<div class='tabulator-data-tree-control-collapse'></div>";
|
||||
}
|
||||
|
||||
if(options.dataTreeExpandElement){
|
||||
if(typeof options.dataTreeExpandElement === "string"){
|
||||
dummyEl = document.createElement("div");
|
||||
dummyEl.innerHTML = options.dataTreeExpandElement;
|
||||
this.expandEl = dummyEl.firstChild;
|
||||
}else{
|
||||
this.expandEl = options.dataTreeExpandElement;
|
||||
}
|
||||
}else{
|
||||
this.expandEl = document.createElement("div");
|
||||
this.expandEl.classList.add("tabulator-data-tree-control");
|
||||
this.expandEl.tabIndex = 0;
|
||||
this.expandEl.innerHTML = "<div class='tabulator-data-tree-control-expand'></div>";
|
||||
}
|
||||
|
||||
|
||||
switch(typeof options.dataTreeStartExpanded){
|
||||
case "boolean":
|
||||
this.startOpen = function(row, index){
|
||||
return options.dataTreeStartExpanded;
|
||||
};
|
||||
break;
|
||||
|
||||
case "function":
|
||||
this.startOpen = options.dataTreeStartExpanded;
|
||||
break;
|
||||
|
||||
default:
|
||||
this.startOpen = function(row, index){
|
||||
return options.dataTreeStartExpanded[index];
|
||||
};
|
||||
break;
|
||||
}
|
||||
|
||||
this.subscribe("row-init", this.initializeRow.bind(this));
|
||||
this.subscribe("row-layout-after", this.layoutRow.bind(this));
|
||||
this.subscribe("row-deleting", this.rowDeleting.bind(this));
|
||||
this.subscribe("row-deleted", this.rowDelete.bind(this),0);
|
||||
this.subscribe("row-data-changed", this.rowDataChanged.bind(this), 10);
|
||||
this.subscribe("cell-value-updated", this.cellValueChanged.bind(this));
|
||||
this.subscribe("edit-cancelled", this.cellValueChanged.bind(this));
|
||||
this.subscribe("column-moving-rows", this.columnMoving.bind(this));
|
||||
this.subscribe("table-built", this.initializeElementField.bind(this));
|
||||
this.subscribe("table-redrawing", this.tableRedrawing.bind(this));
|
||||
|
||||
this.registerDisplayHandler(this.getRows.bind(this), 30);
|
||||
}
|
||||
}
|
||||
|
||||
tableRedrawing(force){
|
||||
var rows;
|
||||
|
||||
if(force){
|
||||
rows = this.table.rowManager.getRows();
|
||||
|
||||
rows.forEach((row) => {
|
||||
this.reinitializeRowChildren(row);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
initializeElementField(){
|
||||
var firstCol = this.table.columnManager.getFirstVisibleColumn();
|
||||
|
||||
this.elementField = this.table.options.dataTreeElementColumn || (firstCol ? firstCol.field : false);
|
||||
}
|
||||
|
||||
getRowChildren(row){
|
||||
return this.getTreeChildren(row, true);
|
||||
}
|
||||
|
||||
columnMoving(){
|
||||
var rows = [];
|
||||
|
||||
this.table.rowManager.rows.forEach((row) => {
|
||||
rows = rows.concat(this.getTreeChildren(row, false, true));
|
||||
});
|
||||
|
||||
return rows;
|
||||
}
|
||||
|
||||
rowDataChanged(row, visible, updatedData){
|
||||
if(this.redrawNeeded(updatedData)){
|
||||
this.initializeRow(row);
|
||||
|
||||
if(visible){
|
||||
this.layoutRow(row);
|
||||
this.refreshData(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cellValueChanged(cell){
|
||||
var field = cell.column.getField();
|
||||
|
||||
if(field === this.elementField){
|
||||
this.layoutRow(cell.row);
|
||||
}
|
||||
}
|
||||
|
||||
initializeRow(row){
|
||||
var childArray = row.getData()[this.field];
|
||||
var isArray = Array.isArray(childArray);
|
||||
|
||||
var children = isArray || (!isArray && typeof childArray === "object" && childArray !== null);
|
||||
|
||||
if(!children && row.modules.dataTree && row.modules.dataTree.branchEl && row.modules.dataTree.branchEl.parentNode){
|
||||
row.modules.dataTree.branchEl.parentNode.removeChild(row.modules.dataTree.branchEl);
|
||||
}
|
||||
|
||||
if(!children && row.modules.dataTree && row.modules.dataTree.controlEl && row.modules.dataTree.controlEl.parentNode){
|
||||
row.modules.dataTree.controlEl.parentNode.removeChild(row.modules.dataTree.controlEl);
|
||||
}
|
||||
|
||||
row.modules.dataTree = {
|
||||
index: row.modules.dataTree ? row.modules.dataTree.index : 0,
|
||||
open: children ? (row.modules.dataTree ? row.modules.dataTree.open : this.startOpen(row.getComponent(), 0)) : false,
|
||||
controlEl: row.modules.dataTree && children ? row.modules.dataTree.controlEl : false,
|
||||
branchEl: row.modules.dataTree && children ? row.modules.dataTree.branchEl : false,
|
||||
parent: row.modules.dataTree ? row.modules.dataTree.parent : false,
|
||||
children:children,
|
||||
};
|
||||
}
|
||||
|
||||
reinitializeRowChildren(row){
|
||||
var children = this.getTreeChildren(row, false, true);
|
||||
|
||||
children.forEach(function(child){
|
||||
child.reinitialize(true);
|
||||
});
|
||||
}
|
||||
|
||||
layoutRow(row){
|
||||
var cell = this.elementField ? row.getCell(this.elementField) : row.getCells()[0],
|
||||
el = cell.getElement(),
|
||||
config = row.modules.dataTree;
|
||||
|
||||
if(config.branchEl){
|
||||
if(config.branchEl.parentNode){
|
||||
config.branchEl.parentNode.removeChild(config.branchEl);
|
||||
}
|
||||
config.branchEl = false;
|
||||
}
|
||||
|
||||
if(config.controlEl){
|
||||
if(config.controlEl.parentNode){
|
||||
config.controlEl.parentNode.removeChild(config.controlEl);
|
||||
}
|
||||
config.controlEl = false;
|
||||
}
|
||||
|
||||
this.generateControlElement(row, el);
|
||||
|
||||
row.getElement().classList.add("tabulator-tree-level-" + config.index);
|
||||
|
||||
if(config.index){
|
||||
if(this.branchEl){
|
||||
config.branchEl = this.branchEl.cloneNode(true);
|
||||
el.insertBefore(config.branchEl, el.firstChild);
|
||||
|
||||
if(this.table.rtl){
|
||||
config.branchEl.style.marginRight = (((config.branchEl.offsetWidth + config.branchEl.style.marginLeft) * (config.index - 1)) + (config.index * this.indent)) + "px";
|
||||
}else{
|
||||
config.branchEl.style.marginLeft = (((config.branchEl.offsetWidth + config.branchEl.style.marginRight) * (config.index - 1)) + (config.index * this.indent)) + "px";
|
||||
}
|
||||
}else{
|
||||
|
||||
if(this.table.rtl){
|
||||
el.style.paddingRight = parseInt(window.getComputedStyle(el, null).getPropertyValue('padding-right')) + (config.index * this.indent) + "px";
|
||||
}else{
|
||||
el.style.paddingLeft = parseInt(window.getComputedStyle(el, null).getPropertyValue('padding-left')) + (config.index * this.indent) + "px";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
generateControlElement(row, el){
|
||||
var config = row.modules.dataTree,
|
||||
oldControl = config.controlEl;
|
||||
|
||||
el = el || row.getCells()[0].getElement();
|
||||
|
||||
if(config.children !== false){
|
||||
|
||||
if(config.open){
|
||||
config.controlEl = this.collapseEl.cloneNode(true);
|
||||
config.controlEl.addEventListener("click", (e) => {
|
||||
e.stopPropagation();
|
||||
this.collapseRow(row);
|
||||
});
|
||||
}else{
|
||||
config.controlEl = this.expandEl.cloneNode(true);
|
||||
config.controlEl.addEventListener("click", (e) => {
|
||||
e.stopPropagation();
|
||||
this.expandRow(row);
|
||||
});
|
||||
}
|
||||
|
||||
config.controlEl.addEventListener("mousedown", (e) => {
|
||||
e.stopPropagation();
|
||||
});
|
||||
|
||||
if(oldControl && oldControl.parentNode === el){
|
||||
oldControl.parentNode.replaceChild(config.controlEl,oldControl);
|
||||
}else{
|
||||
el.insertBefore(config.controlEl, el.firstChild);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getRows(rows){
|
||||
var output = [];
|
||||
|
||||
rows.forEach((row, i) => {
|
||||
var config, children;
|
||||
|
||||
output.push(row);
|
||||
|
||||
if(row instanceof Row){
|
||||
|
||||
row.create();
|
||||
|
||||
config = row.modules.dataTree;
|
||||
|
||||
if(!config.index && config.children !== false){
|
||||
children = this.getChildren(row, false, true);
|
||||
|
||||
children.forEach((child) => {
|
||||
child.create();
|
||||
output.push(child);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
getChildren(row, allChildren, sortOnly){
|
||||
var config = row.modules.dataTree,
|
||||
children = [],
|
||||
output = [];
|
||||
|
||||
if(config.children !== false && (config.open || allChildren)){
|
||||
if(!Array.isArray(config.children)){
|
||||
config.children = this.generateChildren(row);
|
||||
}
|
||||
|
||||
if(this.table.modExists("filter") && this.table.options.dataTreeFilter){
|
||||
children = this.table.modules.filter.filter(config.children);
|
||||
}else{
|
||||
children = config.children;
|
||||
}
|
||||
|
||||
if(this.table.modExists("sort") && this.table.options.dataTreeSort){
|
||||
this.table.modules.sort.sort(children, sortOnly);
|
||||
}
|
||||
|
||||
children.forEach((child) => {
|
||||
output.push(child);
|
||||
|
||||
var subChildren = this.getChildren(child, false, true);
|
||||
|
||||
subChildren.forEach((sub) => {
|
||||
output.push(sub);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
generateChildren(row){
|
||||
var children = [];
|
||||
|
||||
var childArray = row.getData()[this.field];
|
||||
|
||||
if(!Array.isArray(childArray)){
|
||||
childArray = [childArray];
|
||||
}
|
||||
|
||||
childArray.forEach((childData) => {
|
||||
var childRow = new Row(childData || {}, this.table.rowManager);
|
||||
|
||||
childRow.create();
|
||||
|
||||
childRow.modules.dataTree.index = row.modules.dataTree.index + 1;
|
||||
childRow.modules.dataTree.parent = row;
|
||||
|
||||
if(childRow.modules.dataTree.children){
|
||||
childRow.modules.dataTree.open = this.startOpen(childRow.getComponent(), childRow.modules.dataTree.index);
|
||||
}
|
||||
children.push(childRow);
|
||||
});
|
||||
|
||||
return children;
|
||||
}
|
||||
|
||||
expandRow(row, silent){
|
||||
var config = row.modules.dataTree;
|
||||
|
||||
if(config.children !== false){
|
||||
config.open = true;
|
||||
|
||||
row.reinitialize();
|
||||
|
||||
this.refreshData(true);
|
||||
|
||||
this.dispatchExternal("dataTreeRowExpanded", row.getComponent(), row.modules.dataTree.index);
|
||||
}
|
||||
}
|
||||
|
||||
collapseRow(row){
|
||||
var config = row.modules.dataTree;
|
||||
|
||||
if(config.children !== false){
|
||||
config.open = false;
|
||||
|
||||
row.reinitialize();
|
||||
|
||||
this.refreshData(true);
|
||||
|
||||
this.dispatchExternal("dataTreeRowCollapsed", row.getComponent(), row.modules.dataTree.index);
|
||||
}
|
||||
}
|
||||
|
||||
toggleRow(row){
|
||||
var config = row.modules.dataTree;
|
||||
|
||||
if(config.children !== false){
|
||||
if(config.open){
|
||||
this.collapseRow(row);
|
||||
}else{
|
||||
this.expandRow(row);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
isRowExpanded(row){
|
||||
return row.modules.dataTree.open;
|
||||
}
|
||||
|
||||
getTreeParent(row){
|
||||
return row.modules.dataTree.parent ? row.modules.dataTree.parent.getComponent() : false;
|
||||
}
|
||||
|
||||
getTreeParentRoot(row){
|
||||
return row.modules.dataTree && row.modules.dataTree.parent ? this.getTreeParentRoot(row.modules.dataTree.parent) : row;
|
||||
}
|
||||
|
||||
getFilteredTreeChildren(row){
|
||||
var config = row.modules.dataTree,
|
||||
output = [], children;
|
||||
|
||||
if(config.children){
|
||||
|
||||
if(!Array.isArray(config.children)){
|
||||
config.children = this.generateChildren(row);
|
||||
}
|
||||
|
||||
if(this.table.modExists("filter") && this.table.options.dataTreeFilter){
|
||||
children = this.table.modules.filter.filter(config.children);
|
||||
}else{
|
||||
children = config.children;
|
||||
}
|
||||
|
||||
children.forEach((childRow) => {
|
||||
if(childRow instanceof Row){
|
||||
output.push(childRow);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
rowDeleting(row){
|
||||
var config = row.modules.dataTree;
|
||||
|
||||
if (config && config.children && Array.isArray(config.children)){
|
||||
config.children.forEach((childRow) => {
|
||||
if(childRow instanceof Row){
|
||||
childRow.wipe();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
rowDelete(row){
|
||||
var parent = row.modules.dataTree.parent,
|
||||
childIndex;
|
||||
|
||||
if(parent){
|
||||
childIndex = this.findChildIndex(row, parent);
|
||||
|
||||
if(childIndex !== false){
|
||||
parent.data[this.field].splice(childIndex, 1);
|
||||
}
|
||||
|
||||
if(!parent.data[this.field].length){
|
||||
delete parent.data[this.field];
|
||||
}
|
||||
|
||||
this.initializeRow(parent);
|
||||
this.layoutRow(parent);
|
||||
}
|
||||
|
||||
this.refreshData(true);
|
||||
}
|
||||
|
||||
addTreeChildRow(row, data, top, index){
|
||||
var childIndex = false;
|
||||
|
||||
if(typeof data === "string"){
|
||||
data = JSON.parse(data);
|
||||
}
|
||||
|
||||
if(!Array.isArray(row.data[this.field])){
|
||||
row.data[this.field] = [];
|
||||
|
||||
row.modules.dataTree.open = this.startOpen(row.getComponent(), row.modules.dataTree.index);
|
||||
}
|
||||
|
||||
if(typeof index !== "undefined"){
|
||||
childIndex = this.findChildIndex(index, row);
|
||||
|
||||
if(childIndex !== false){
|
||||
row.data[this.field].splice((top ? childIndex : childIndex + 1), 0, data);
|
||||
}
|
||||
}
|
||||
|
||||
if(childIndex === false){
|
||||
if(top){
|
||||
row.data[this.field].unshift(data);
|
||||
}else{
|
||||
row.data[this.field].push(data);
|
||||
}
|
||||
}
|
||||
|
||||
this.initializeRow(row);
|
||||
this.layoutRow(row);
|
||||
|
||||
this.refreshData(true);
|
||||
}
|
||||
|
||||
findChildIndex(subject, parent){
|
||||
var match = false;
|
||||
|
||||
if(typeof subject == "object"){
|
||||
|
||||
if(subject instanceof Row){
|
||||
//subject is row element
|
||||
match = subject.data;
|
||||
}else if(subject instanceof RowComponent){
|
||||
//subject is public row component
|
||||
match = subject._getSelf().data;
|
||||
}else if(typeof HTMLElement !== "undefined" && subject instanceof HTMLElement){
|
||||
if(parent.modules.dataTree){
|
||||
match = parent.modules.dataTree.children.find((childRow) => {
|
||||
return childRow instanceof Row ? childRow.element === subject : false;
|
||||
});
|
||||
|
||||
if(match){
|
||||
match = match.data;
|
||||
}
|
||||
}
|
||||
}else if(subject === null){
|
||||
match = false;
|
||||
}
|
||||
|
||||
}else if(typeof subject == "undefined"){
|
||||
match = false;
|
||||
}else{
|
||||
//subject should be treated as the index of the row
|
||||
match = parent.data[this.field].find((row) => {
|
||||
return row.data[this.table.options.index] == subject;
|
||||
});
|
||||
}
|
||||
|
||||
if(match){
|
||||
|
||||
if(Array.isArray(parent.data[this.field])){
|
||||
match = parent.data[this.field].indexOf(match);
|
||||
}
|
||||
|
||||
if(match == -1){
|
||||
match = false;
|
||||
}
|
||||
}
|
||||
|
||||
//catch all for any other type of input
|
||||
|
||||
return match;
|
||||
}
|
||||
|
||||
getTreeChildren(row, component, recurse){
|
||||
var config = row.modules.dataTree,
|
||||
output = [];
|
||||
|
||||
if(config && config.children){
|
||||
|
||||
if(!Array.isArray(config.children)){
|
||||
config.children = this.generateChildren(row);
|
||||
}
|
||||
|
||||
config.children.forEach((childRow) => {
|
||||
if(childRow instanceof Row){
|
||||
output.push(component ? childRow.getComponent() : childRow);
|
||||
|
||||
if(recurse){
|
||||
this.getTreeChildren(childRow, component, recurse).forEach(child => {
|
||||
output.push(child);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
getChildField(){
|
||||
return this.field;
|
||||
}
|
||||
|
||||
redrawNeeded(data){
|
||||
return (this.field ? typeof data[this.field] !== "undefined" : false) || (this.elementField ? typeof data[this.elementField] !== "undefined" : false);
|
||||
}
|
||||
}
|
||||
146
public/libs/tabulator-master/src/js/modules/Download/Download.js
Normal file
146
public/libs/tabulator-master/src/js/modules/Download/Download.js
Normal file
@@ -0,0 +1,146 @@
|
||||
import Module from '../../core/Module.js';
|
||||
|
||||
import defaultDownloaders from './defaults/downloaders.js';
|
||||
|
||||
export default class Download extends Module{
|
||||
|
||||
static moduleName = "download";
|
||||
|
||||
//load defaults
|
||||
static downloaders = defaultDownloaders;
|
||||
|
||||
constructor(table){
|
||||
super(table);
|
||||
|
||||
this.registerTableOption("downloadEncoder", function(data, mimeType){
|
||||
return new Blob([data],{type:mimeType});
|
||||
}); //function to manipulate download data
|
||||
this.registerTableOption("downloadConfig", {}); //download config
|
||||
this.registerTableOption("downloadRowRange", "active"); //restrict download to active rows only
|
||||
|
||||
this.registerColumnOption("download");
|
||||
this.registerColumnOption("titleDownload");
|
||||
}
|
||||
|
||||
initialize(){
|
||||
this.deprecatedOptionsCheck();
|
||||
|
||||
this.registerTableFunction("download", this.download.bind(this));
|
||||
this.registerTableFunction("downloadToTab", this.downloadToTab.bind(this));
|
||||
}
|
||||
|
||||
deprecatedOptionsCheck(){
|
||||
|
||||
}
|
||||
|
||||
///////////////////////////////////
|
||||
///////// Table Functions /////////
|
||||
///////////////////////////////////
|
||||
|
||||
downloadToTab(type, filename, options, active){
|
||||
this.download(type, filename, options, active, true);
|
||||
}
|
||||
|
||||
///////////////////////////////////
|
||||
///////// Internal Logic //////////
|
||||
///////////////////////////////////
|
||||
|
||||
//trigger file download
|
||||
download(type, filename, options, range, interceptCallback){
|
||||
var downloadFunc = false;
|
||||
|
||||
function buildLink(data, mime){
|
||||
if(interceptCallback){
|
||||
if(interceptCallback === true){
|
||||
this.triggerDownload(data, mime, type, filename, true);
|
||||
}else{
|
||||
interceptCallback(data);
|
||||
}
|
||||
|
||||
}else{
|
||||
this.triggerDownload(data, mime, type, filename);
|
||||
}
|
||||
}
|
||||
|
||||
if(typeof type == "function"){
|
||||
downloadFunc = type;
|
||||
}else{
|
||||
if(Download.downloaders[type]){
|
||||
downloadFunc = Download.downloaders[type];
|
||||
}else{
|
||||
console.warn("Download Error - No such download type found: ", type);
|
||||
}
|
||||
}
|
||||
|
||||
if(downloadFunc){
|
||||
var list = this.generateExportList(range);
|
||||
|
||||
downloadFunc.call(this.table, list , options || {}, buildLink.bind(this));
|
||||
}
|
||||
}
|
||||
|
||||
generateExportList(range){
|
||||
var list = this.table.modules.export.generateExportList(this.table.options.downloadConfig, false, range || this.table.options.downloadRowRange, "download");
|
||||
|
||||
//assign group header formatter
|
||||
var groupHeader = this.table.options.groupHeaderDownload;
|
||||
|
||||
if(groupHeader && !Array.isArray(groupHeader)){
|
||||
groupHeader = [groupHeader];
|
||||
}
|
||||
|
||||
list.forEach((row) => {
|
||||
var group;
|
||||
|
||||
if(row.type === "group"){
|
||||
group = row.columns[0];
|
||||
|
||||
if(groupHeader && groupHeader[row.indent]){
|
||||
group.value = groupHeader[row.indent](group.value, row.component._group.getRowCount(), row.component._group.getData(), row.component);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
triggerDownload(data, mime, type, filename, newTab){
|
||||
var element = document.createElement('a'),
|
||||
blob = this.table.options.downloadEncoder(data, mime);
|
||||
|
||||
if(blob){
|
||||
if(newTab){
|
||||
window.open(window.URL.createObjectURL(blob));
|
||||
}else{
|
||||
filename = filename || "Tabulator." + (typeof type === "function" ? "txt" : type);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
this.dispatchExternal("downloadComplete");
|
||||
}
|
||||
}
|
||||
|
||||
commsReceived(table, action, data){
|
||||
switch(action){
|
||||
case "intercept":
|
||||
this.download(data.type, "", data.options, data.active, data.intercept);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
import csv from './downloaders/csv.js';
|
||||
import json from './downloaders/json.js';
|
||||
import pdf from './downloaders/pdf.js';
|
||||
import xlsx from './downloaders/xlsx.js';
|
||||
import html from './downloaders/html.js';
|
||||
import jsonLines from './downloaders/jsonLines.js';
|
||||
|
||||
export default {
|
||||
csv:csv,
|
||||
json:json,
|
||||
jsonLines:jsonLines,
|
||||
pdf:pdf,
|
||||
xlsx:xlsx,
|
||||
html:html,
|
||||
};
|
||||
@@ -0,0 +1,61 @@
|
||||
export default function(list, options = {}, setFileContents){
|
||||
var delimiter = options.delimiter ? options.delimiter : ",",
|
||||
fileContents = [],
|
||||
headers = [];
|
||||
|
||||
list.forEach((row) => {
|
||||
var item = [];
|
||||
|
||||
switch(row.type){
|
||||
case "group":
|
||||
console.warn("Download Warning - CSV downloader cannot process row groups");
|
||||
break;
|
||||
|
||||
case "calc":
|
||||
console.warn("Download Warning - CSV downloader cannot process column calculations");
|
||||
break;
|
||||
|
||||
case "header":
|
||||
row.columns.forEach((col, i) => {
|
||||
if(col && col.depth === 1){
|
||||
headers[i] = typeof col.value == "undefined" || col.value === null ? "" : ('"' + String(col.value).split('"').join('""') + '"');
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
||||
case "row":
|
||||
row.columns.forEach((col) => {
|
||||
|
||||
if(col){
|
||||
|
||||
switch(typeof col.value){
|
||||
case "object":
|
||||
col.value = col.value !== null ? JSON.stringify(col.value) : "";
|
||||
break;
|
||||
|
||||
case "undefined":
|
||||
col.value = "";
|
||||
break;
|
||||
}
|
||||
|
||||
item.push('"' + String(col.value).split('"').join('""') + '"');
|
||||
}
|
||||
});
|
||||
|
||||
fileContents.push(item.join(delimiter));
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
if(headers.length){
|
||||
fileContents.unshift(headers.join(delimiter));
|
||||
}
|
||||
|
||||
fileContents = fileContents.join("\n");
|
||||
|
||||
if(options.bom){
|
||||
fileContents = "\ufeff" + fileContents;
|
||||
}
|
||||
|
||||
setFileContents(fileContents, "text/csv");
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
export default function(list, options, setFileContents){
|
||||
if(this.modExists("export", true)){
|
||||
setFileContents(this.modules.export.generateHTMLTable(list), "text/html");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
export default function(list, options, setFileContents){
|
||||
var fileContents = [];
|
||||
|
||||
list.forEach((row) => {
|
||||
var item = {};
|
||||
|
||||
switch(row.type){
|
||||
case "header":
|
||||
break;
|
||||
|
||||
case "group":
|
||||
console.warn("Download Warning - JSON downloader cannot process row groups");
|
||||
break;
|
||||
|
||||
case "calc":
|
||||
console.warn("Download Warning - JSON downloader cannot process column calculations");
|
||||
break;
|
||||
|
||||
case "row":
|
||||
row.columns.forEach((col) => {
|
||||
if(col){
|
||||
item[col.component.getTitleDownload() || col.component.getField()] = col.value;
|
||||
}
|
||||
});
|
||||
|
||||
fileContents.push(item);
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
fileContents = JSON.stringify(fileContents, null, '\t');
|
||||
|
||||
setFileContents(fileContents, "application/json");
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
export default function (list, options, setFileContents) {
|
||||
const fileContents = [];
|
||||
|
||||
list.forEach((row) => {
|
||||
const item = {};
|
||||
|
||||
switch (row.type) {
|
||||
case "header":
|
||||
break;
|
||||
|
||||
case "group":
|
||||
console.warn("Download Warning - JSON downloader cannot process row groups");
|
||||
break;
|
||||
|
||||
case "calc":
|
||||
console.warn("Download Warning - JSON downloader cannot process column calculations");
|
||||
break;
|
||||
|
||||
case "row":
|
||||
row.columns.forEach((col) => {
|
||||
if (col) {
|
||||
item[col.component.getTitleDownload() || col.component.getField()] = col.value;
|
||||
}
|
||||
});
|
||||
|
||||
fileContents.push(JSON.stringify(item));
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
setFileContents(fileContents.join("\n"), "application/x-ndjson");
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
export default function(list, options = {}, setFileContents){
|
||||
var header = [],
|
||||
body = [],
|
||||
autoTableParams = {},
|
||||
rowGroupStyles = options.rowGroupStyles || {
|
||||
fontStyle: "bold",
|
||||
fontSize: 12,
|
||||
cellPadding: 6,
|
||||
fillColor: 220,
|
||||
},
|
||||
rowCalcStyles = options.rowCalcStyles || {
|
||||
fontStyle: "bold",
|
||||
fontSize: 10,
|
||||
cellPadding: 4,
|
||||
fillColor: 232,
|
||||
},
|
||||
jsPDFParams = options.jsPDF || {},
|
||||
title = options.title ? options.title : "",
|
||||
jspdfLib, doc;
|
||||
|
||||
if(!jsPDFParams.orientation){
|
||||
jsPDFParams.orientation = options.orientation || "landscape";
|
||||
}
|
||||
|
||||
if(!jsPDFParams.unit){
|
||||
jsPDFParams.unit = "pt";
|
||||
}
|
||||
|
||||
//parse row list
|
||||
list.forEach((row) => {
|
||||
switch(row.type){
|
||||
case "header":
|
||||
header.push(parseRow(row));
|
||||
break;
|
||||
|
||||
case "group":
|
||||
body.push(parseRow(row, rowGroupStyles));
|
||||
break;
|
||||
|
||||
case "calc":
|
||||
body.push(parseRow(row, rowCalcStyles));
|
||||
break;
|
||||
|
||||
case "row":
|
||||
body.push(parseRow(row));
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
function parseRow(row, styles){
|
||||
var rowData = [];
|
||||
|
||||
row.columns.forEach((col) =>{
|
||||
var cell;
|
||||
|
||||
if(col){
|
||||
switch(typeof col.value){
|
||||
case "object":
|
||||
col.value = col.value !== null ? JSON.stringify(col.value) : "";
|
||||
break;
|
||||
|
||||
case "undefined":
|
||||
col.value = "";
|
||||
break;
|
||||
}
|
||||
|
||||
cell = {
|
||||
content:col.value,
|
||||
colSpan:col.width,
|
||||
rowSpan:col.height,
|
||||
};
|
||||
|
||||
if(styles){
|
||||
cell.styles = styles;
|
||||
}
|
||||
|
||||
rowData.push(cell);
|
||||
}
|
||||
});
|
||||
|
||||
return rowData;
|
||||
}
|
||||
|
||||
|
||||
//configure PDF
|
||||
jspdfLib = this.dependencyRegistry.lookup("jspdf", "jsPDF");
|
||||
doc = new jspdfLib(jsPDFParams); //set document to landscape, better for most tables
|
||||
|
||||
if(options.autoTable){
|
||||
if(typeof options.autoTable === "function"){
|
||||
autoTableParams = options.autoTable(doc) || {};
|
||||
}else{
|
||||
autoTableParams = options.autoTable;
|
||||
}
|
||||
}
|
||||
|
||||
if(title){
|
||||
autoTableParams.didDrawPage = function(data) {
|
||||
doc.text(title, 40, 30);
|
||||
};
|
||||
}
|
||||
|
||||
autoTableParams.head = header;
|
||||
autoTableParams.body = body;
|
||||
|
||||
doc.autoTable(autoTableParams);
|
||||
|
||||
if(options.documentProcessing){
|
||||
options.documentProcessing(doc);
|
||||
}
|
||||
|
||||
setFileContents(doc.output("arraybuffer"), "application/pdf");
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
import CoreFeature from '../../../../core/CoreFeature.js';
|
||||
|
||||
export default function(list, options, setFileContents){
|
||||
var self = this,
|
||||
sheetName = options.sheetName || "Sheet1",
|
||||
XLSXLib = this.dependencyRegistry.lookup("XLSX"),
|
||||
workbook = XLSXLib.utils.book_new(),
|
||||
tableFeatures = new CoreFeature(this),
|
||||
compression = 'compress' in options ? options.compress : true,
|
||||
writeOptions = options.writeOptions || {bookType:'xlsx', bookSST:true, compression},
|
||||
output;
|
||||
|
||||
writeOptions.type = 'binary';
|
||||
|
||||
workbook.SheetNames = [];
|
||||
workbook.Sheets = {};
|
||||
|
||||
function generateSheet(){
|
||||
var rows = [],
|
||||
merges = [],
|
||||
worksheet = {},
|
||||
range = {s: {c:0, r:0}, e: {c:(list[0] ? list[0].columns.reduce((a, b) => a + (b && b.width ? b.width : 1), 0) : 0), r:list.length }};
|
||||
|
||||
//parse row list
|
||||
list.forEach((row, i) => {
|
||||
var rowData = [];
|
||||
|
||||
row.columns.forEach(function(col, j){
|
||||
|
||||
if(col){
|
||||
rowData.push(!(col.value instanceof Date) && typeof col.value === "object" ? JSON.stringify(col.value) : col.value);
|
||||
|
||||
if(col.width > 1 || col.height > -1){
|
||||
if(col.height > 1 || col.width > 1){
|
||||
merges.push({s:{r:i,c:j},e:{r:i + col.height - 1,c:j + col.width - 1}});
|
||||
}
|
||||
}
|
||||
}else{
|
||||
rowData.push("");
|
||||
}
|
||||
});
|
||||
|
||||
rows.push(rowData);
|
||||
});
|
||||
|
||||
//convert rows to worksheet
|
||||
XLSXLib.utils.sheet_add_aoa(worksheet, rows);
|
||||
|
||||
worksheet['!ref'] = XLSXLib.utils.encode_range(range);
|
||||
|
||||
if(merges.length){
|
||||
worksheet["!merges"] = merges;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
tableFeatures.commsSend(options.sheets[sheet], "download", "intercept",{
|
||||
type:"xlsx",
|
||||
options:{sheetOnly:true},
|
||||
active:self.active,
|
||||
intercept:function(data){
|
||||
workbook.Sheets[sheet] = data;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}else{
|
||||
workbook.SheetNames.push(sheetName);
|
||||
workbook.Sheets[sheetName] = generateSheet();
|
||||
}
|
||||
|
||||
if(options.documentProcessing){
|
||||
workbook = options.documentProcessing(workbook);
|
||||
}
|
||||
|
||||
//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 = XLSXLib.write(workbook, writeOptions);
|
||||
|
||||
setFileContents(s2ab(output), "application/octet-stream");
|
||||
}
|
||||
842
public/libs/tabulator-master/src/js/modules/Edit/Edit.js
Normal file
842
public/libs/tabulator-master/src/js/modules/Edit/Edit.js
Normal file
@@ -0,0 +1,842 @@
|
||||
import Module from '../../core/Module.js';
|
||||
import Helpers from '../../core/tools/Helpers.js';
|
||||
|
||||
import defaultEditors from './defaults/editors.js';
|
||||
|
||||
export default class Edit extends Module{
|
||||
|
||||
static moduleName = "edit";
|
||||
|
||||
//load defaults
|
||||
static editors = defaultEditors;
|
||||
|
||||
constructor(table){
|
||||
super(table);
|
||||
|
||||
this.currentCell = false; //hold currently editing cell
|
||||
this.mouseClick = false; //hold mousedown state to prevent click binding being overridden by editor opening
|
||||
this.recursionBlock = false; //prevent focus recursion
|
||||
this.invalidEdit = false;
|
||||
this.editedCells = [];
|
||||
this.convertEmptyValues = false;
|
||||
|
||||
this.editors = Edit.editors;
|
||||
|
||||
this.registerTableOption("editTriggerEvent", "focus");
|
||||
this.registerTableOption("editorEmptyValue");
|
||||
this.registerTableOption("editorEmptyValueFunc", this.emptyValueCheck.bind(this));
|
||||
|
||||
this.registerColumnOption("editable");
|
||||
this.registerColumnOption("editor");
|
||||
this.registerColumnOption("editorParams");
|
||||
this.registerColumnOption("editorEmptyValue");
|
||||
this.registerColumnOption("editorEmptyValueFunc");
|
||||
|
||||
this.registerColumnOption("cellEditing");
|
||||
this.registerColumnOption("cellEdited");
|
||||
this.registerColumnOption("cellEditCancelled");
|
||||
|
||||
this.registerTableFunction("getEditedCells", this.getEditedCells.bind(this));
|
||||
this.registerTableFunction("clearCellEdited", this.clearCellEdited.bind(this));
|
||||
this.registerTableFunction("navigatePrev", this.navigatePrev.bind(this));
|
||||
this.registerTableFunction("navigateNext", this.navigateNext.bind(this));
|
||||
this.registerTableFunction("navigateLeft", this.navigateLeft.bind(this));
|
||||
this.registerTableFunction("navigateRight", this.navigateRight.bind(this));
|
||||
this.registerTableFunction("navigateUp", this.navigateUp.bind(this));
|
||||
this.registerTableFunction("navigateDown", this.navigateDown.bind(this));
|
||||
|
||||
this.registerComponentFunction("cell", "isEdited", this.cellIsEdited.bind(this));
|
||||
this.registerComponentFunction("cell", "clearEdited", this.clearEdited.bind(this));
|
||||
this.registerComponentFunction("cell", "edit", this.editCell.bind(this));
|
||||
this.registerComponentFunction("cell", "cancelEdit", this.cellCancelEdit.bind(this));
|
||||
|
||||
this.registerComponentFunction("cell", "navigatePrev", this.navigatePrev.bind(this));
|
||||
this.registerComponentFunction("cell", "navigateNext", this.navigateNext.bind(this));
|
||||
this.registerComponentFunction("cell", "navigateLeft", this.navigateLeft.bind(this));
|
||||
this.registerComponentFunction("cell", "navigateRight", this.navigateRight.bind(this));
|
||||
this.registerComponentFunction("cell", "navigateUp", this.navigateUp.bind(this));
|
||||
this.registerComponentFunction("cell", "navigateDown", this.navigateDown.bind(this));
|
||||
}
|
||||
|
||||
initialize(){
|
||||
this.subscribe("cell-init", this.bindEditor.bind(this));
|
||||
this.subscribe("cell-delete", this.clearEdited.bind(this));
|
||||
this.subscribe("cell-value-changed", this.updateCellClass.bind(this));
|
||||
this.subscribe("column-layout", this.initializeColumnCheck.bind(this));
|
||||
this.subscribe("column-delete", this.columnDeleteCheck.bind(this));
|
||||
this.subscribe("row-deleting", this.rowDeleteCheck.bind(this));
|
||||
this.subscribe("row-layout", this.rowEditableCheck.bind(this));
|
||||
this.subscribe("data-refreshing", this.cancelEdit.bind(this));
|
||||
this.subscribe("clipboard-paste", this.pasteBlocker.bind(this));
|
||||
|
||||
if (!this.confirm("edit-nav-disabled")) {
|
||||
this.subscribe("keybinding-nav-prev", this.navigatePrev.bind(this, undefined));
|
||||
this.subscribe("keybinding-nav-next", this.keybindingNavigateNext.bind(this));
|
||||
|
||||
// this.subscribe("keybinding-nav-left", this.navigateLeft.bind(this, undefined));
|
||||
// this.subscribe("keybinding-nav-right", this.navigateRight.bind(this, undefined));
|
||||
this.subscribe("keybinding-nav-up", this.navigateUp.bind(this, undefined));
|
||||
this.subscribe("keybinding-nav-down", this.navigateDown.bind(this, undefined));
|
||||
}
|
||||
|
||||
// Add event handlers for other modules to access editing state and functionality
|
||||
this.subscribe("edit-check-editing", this.checkEditing.bind(this));
|
||||
this.subscribe("edit-cancel-cell", this.cancelEditEvent.bind(this));
|
||||
|
||||
if(Object.keys(this.table.options).includes("editorEmptyValue")){
|
||||
this.convertEmptyValues = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////
|
||||
///////// Paste Negation //////////
|
||||
///////////////////////////////////
|
||||
|
||||
pasteBlocker(e){
|
||||
if(this.currentCell){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////
|
||||
////// Keybinding Functions ///////
|
||||
///////////////////////////////////
|
||||
|
||||
keybindingNavigateNext(e){
|
||||
var cell = this.currentCell,
|
||||
newRow = this.options("tabEndNewRow");
|
||||
|
||||
if(cell){
|
||||
if(!this.navigateNext(cell, e)){
|
||||
if(newRow){
|
||||
cell.getElement().firstChild.blur();
|
||||
|
||||
if(!this.invalidEdit){
|
||||
|
||||
if(newRow === true){
|
||||
newRow = this.table.addRow({});
|
||||
}else{
|
||||
if(typeof newRow == "function"){
|
||||
newRow = this.table.addRow(newRow(cell.row.getComponent()));
|
||||
}else{
|
||||
newRow = this.table.addRow(Object.assign({}, newRow));
|
||||
}
|
||||
}
|
||||
|
||||
newRow.then(() => {
|
||||
setTimeout(() => {
|
||||
cell.getComponent().navigateNext();
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////
|
||||
///////// Cell Functions //////////
|
||||
///////////////////////////////////
|
||||
|
||||
cellIsEdited(cell){
|
||||
return !! cell.modules.edit && cell.modules.edit.edited;
|
||||
}
|
||||
|
||||
cellCancelEdit(cell){
|
||||
if(cell === this.currentCell){
|
||||
this.table.modules.edit.cancelEdit();
|
||||
}else{
|
||||
console.warn("Cancel Editor Error - This cell is not currently being edited ");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////
|
||||
///////// Table Functions /////////
|
||||
///////////////////////////////////
|
||||
updateCellClass(cell){
|
||||
if(this.allowEdit(cell)) {
|
||||
cell.getElement().classList.add("tabulator-editable");
|
||||
}
|
||||
else {
|
||||
cell.getElement().classList.remove("tabulator-editable");
|
||||
}
|
||||
}
|
||||
|
||||
clearCellEdited(cells){
|
||||
if(!cells){
|
||||
cells = this.table.modules.edit.getEditedCells();
|
||||
}
|
||||
|
||||
if(!Array.isArray(cells)){
|
||||
cells = [cells];
|
||||
}
|
||||
|
||||
cells.forEach((cell) => {
|
||||
this.table.modules.edit.clearEdited(cell._getSelf());
|
||||
});
|
||||
}
|
||||
|
||||
navigatePrev(cell = this.currentCell, e){
|
||||
var nextCell, prevRow;
|
||||
|
||||
if(cell){
|
||||
|
||||
if(e){
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
nextCell = this.navigateLeft();
|
||||
|
||||
if(nextCell){
|
||||
return true;
|
||||
}else{
|
||||
prevRow = this.table.rowManager.prevDisplayRow(cell.row, true);
|
||||
|
||||
if(prevRow){
|
||||
nextCell = this.findPrevEditableCell(prevRow, prevRow.cells.length);
|
||||
|
||||
if(nextCell){
|
||||
nextCell.getComponent().edit();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
navigateNext(cell = this.currentCell, e){
|
||||
var nextCell, nextRow;
|
||||
|
||||
if(cell){
|
||||
|
||||
if(e){
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
nextCell = this.navigateRight();
|
||||
|
||||
if(nextCell){
|
||||
return true;
|
||||
}else{
|
||||
nextRow = this.table.rowManager.nextDisplayRow(cell.row, true);
|
||||
|
||||
if(nextRow){
|
||||
nextCell = this.findNextEditableCell(nextRow, -1);
|
||||
|
||||
if(nextCell){
|
||||
nextCell.getComponent().edit();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
navigateLeft(cell = this.currentCell, e){
|
||||
var index, nextCell;
|
||||
|
||||
if(cell){
|
||||
|
||||
if(e){
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
index = cell.getIndex();
|
||||
nextCell = this.findPrevEditableCell(cell.row, index);
|
||||
|
||||
if(nextCell){
|
||||
nextCell.getComponent().edit();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
navigateRight(cell = this.currentCell, e){
|
||||
var index, nextCell;
|
||||
|
||||
if(cell){
|
||||
|
||||
if(e){
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
index = cell.getIndex();
|
||||
nextCell = this.findNextEditableCell(cell.row, index);
|
||||
|
||||
if(nextCell){
|
||||
nextCell.getComponent().edit();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
navigateUp(cell = this.currentCell, e){
|
||||
var index, nextRow;
|
||||
|
||||
if(cell){
|
||||
|
||||
if(e){
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
index = cell.getIndex();
|
||||
nextRow = this.table.rowManager.prevDisplayRow(cell.row, true);
|
||||
|
||||
if(nextRow){
|
||||
nextRow.cells[index].getComponent().edit();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
navigateDown(cell = this.currentCell, e){
|
||||
var index, nextRow;
|
||||
|
||||
if(cell){
|
||||
|
||||
if(e){
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
index = cell.getIndex();
|
||||
nextRow = this.table.rowManager.nextDisplayRow(cell.row, true);
|
||||
|
||||
if(nextRow){
|
||||
nextRow.cells[index].getComponent().edit();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
findNextEditableCell(row, index){
|
||||
var nextCell = false;
|
||||
|
||||
if(index < row.cells.length-1){
|
||||
for(var i = index+1; i < row.cells.length; i++){
|
||||
let cell = row.cells[i];
|
||||
|
||||
if(cell.column.modules.edit && Helpers.elVisible(cell.getElement())){
|
||||
let allowEdit = this.allowEdit(cell);
|
||||
|
||||
if(allowEdit){
|
||||
nextCell = cell;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nextCell;
|
||||
}
|
||||
|
||||
findPrevEditableCell(row, index){
|
||||
var prevCell = false;
|
||||
|
||||
if(index > 0){
|
||||
for(var i = index-1; i >= 0; i--){
|
||||
let cell = row.cells[i];
|
||||
|
||||
if(cell.column.modules.edit && Helpers.elVisible(cell.getElement())){
|
||||
let allowEdit = this.allowEdit(cell);
|
||||
|
||||
if(allowEdit){
|
||||
prevCell = cell;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return prevCell;
|
||||
}
|
||||
|
||||
///////////////////////////////////
|
||||
///////// Internal Logic //////////
|
||||
///////////////////////////////////
|
||||
|
||||
initializeColumnCheck(column){
|
||||
if(typeof column.definition.editor !== "undefined"){
|
||||
this.initializeColumn(column);
|
||||
}
|
||||
}
|
||||
|
||||
columnDeleteCheck(column){
|
||||
if(this.currentCell && this.currentCell.column === column){
|
||||
this.cancelEdit();
|
||||
}
|
||||
}
|
||||
|
||||
rowDeleteCheck(row){
|
||||
if(this.currentCell && this.currentCell.row === row){
|
||||
this.cancelEdit();
|
||||
}
|
||||
}
|
||||
|
||||
rowEditableCheck(row){
|
||||
row.getCells().forEach((cell) => {
|
||||
if(cell.column.modules.edit && typeof cell.column.modules.edit.check === "function"){
|
||||
this.updateCellClass(cell);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//initialize column editor
|
||||
initializeColumn(column){
|
||||
var convertEmpty = Object.keys(column.definition).includes("editorEmptyValue");
|
||||
|
||||
var config = {
|
||||
editor:false,
|
||||
blocked:false,
|
||||
check:column.definition.editable,
|
||||
params:column.definition.editorParams || {},
|
||||
convertEmptyValues:convertEmpty,
|
||||
editorEmptyValue:column.definition.editorEmptyValue,
|
||||
editorEmptyValueFunc:column.definition.editorEmptyValueFunc,
|
||||
};
|
||||
|
||||
//set column editor
|
||||
config.editor = this.lookupEditor(column.definition.editor, column);
|
||||
|
||||
if(config.editor){
|
||||
column.modules.edit = config;
|
||||
}
|
||||
}
|
||||
|
||||
lookupEditor(editor, column){
|
||||
var editorFunc;
|
||||
|
||||
switch(typeof editor){
|
||||
case "string":
|
||||
if(this.editors[editor]){
|
||||
editorFunc = this.editors[editor];
|
||||
}else{
|
||||
console.warn("Editor Error - No such editor found: ", editor);
|
||||
}
|
||||
break;
|
||||
|
||||
case "function":
|
||||
editorFunc = editor;
|
||||
break;
|
||||
|
||||
case "boolean":
|
||||
if(editor === true){
|
||||
if(typeof column.definition.formatter !== "function"){
|
||||
if(this.editors[column.definition.formatter]){
|
||||
editorFunc = this.editors[column.definition.formatter];
|
||||
}else{
|
||||
editorFunc = this.editors["input"];
|
||||
}
|
||||
}else{
|
||||
console.warn("Editor Error - Cannot auto lookup editor for a custom formatter: ", column.definition.formatter);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return editorFunc;
|
||||
}
|
||||
|
||||
getCurrentCell(){
|
||||
return this.currentCell ? this.currentCell.getComponent() : false;
|
||||
}
|
||||
|
||||
checkEditing(){
|
||||
return !!this.currentCell;
|
||||
}
|
||||
|
||||
cancelEditEvent(){
|
||||
if(this.currentCell){
|
||||
this.cancelEdit();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
clearEditor(cancel){
|
||||
var cell = this.currentCell,
|
||||
cellEl;
|
||||
|
||||
this.invalidEdit = false;
|
||||
|
||||
if(cell){
|
||||
this.currentCell = false;
|
||||
|
||||
cellEl = cell.getElement();
|
||||
|
||||
this.dispatch("edit-editor-clear", cell, cancel);
|
||||
|
||||
cellEl.classList.remove("tabulator-editing");
|
||||
|
||||
while(cellEl.firstChild) cellEl.removeChild(cellEl.firstChild);
|
||||
|
||||
cell.row.getElement().classList.remove("tabulator-editing");
|
||||
|
||||
cell.table.element.classList.remove("tabulator-editing");
|
||||
}
|
||||
}
|
||||
|
||||
cancelEdit(){
|
||||
if(this.currentCell){
|
||||
var cell = this.currentCell;
|
||||
var component = this.currentCell.getComponent();
|
||||
|
||||
this.clearEditor(true);
|
||||
cell.setValueActual(cell.getValue());
|
||||
cell.cellRendered();
|
||||
|
||||
if(cell.column.definition.editor == "textarea" || cell.column.definition.variableHeight){
|
||||
cell.row.normalizeHeight(true);
|
||||
}
|
||||
|
||||
if(cell.column.definition.cellEditCancelled){
|
||||
cell.column.definition.cellEditCancelled.call(this.table, component);
|
||||
}
|
||||
|
||||
this.dispatch("edit-cancelled", cell);
|
||||
this.dispatchExternal("cellEditCancelled", component);
|
||||
}
|
||||
}
|
||||
|
||||
//return a formatted value for a cell
|
||||
bindEditor(cell){
|
||||
if(cell.column.modules.edit){
|
||||
var self = this,
|
||||
element = cell.getElement(true);
|
||||
|
||||
this.updateCellClass(cell);
|
||||
element.setAttribute("tabindex", 0);
|
||||
|
||||
element.addEventListener("mousedown", function(e){
|
||||
if (e.button === 2) {
|
||||
e.preventDefault();
|
||||
}else{
|
||||
self.mouseClick = true;
|
||||
}
|
||||
});
|
||||
|
||||
if(this.options("editTriggerEvent") === "dblclick"){
|
||||
element.addEventListener("dblclick", function(e){
|
||||
if(!element.classList.contains("tabulator-editing")){
|
||||
element.focus({preventScroll: true});
|
||||
self.edit(cell, e, false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
if(this.options("editTriggerEvent") === "focus" || this.options("editTriggerEvent") === "click"){
|
||||
element.addEventListener("click", function(e){
|
||||
if(!element.classList.contains("tabulator-editing")){
|
||||
element.focus({preventScroll: true});
|
||||
self.edit(cell, e, false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if(this.options("editTriggerEvent") === "focus"){
|
||||
element.addEventListener("focus", function(e){
|
||||
if(!self.recursionBlock){
|
||||
self.edit(cell, e, false);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
focusCellNoEvent(cell, block){
|
||||
this.recursionBlock = true;
|
||||
|
||||
if(!(block && this.table.browser === "ie")){
|
||||
cell.getElement().focus({preventScroll: true});
|
||||
}
|
||||
|
||||
this.recursionBlock = false;
|
||||
}
|
||||
|
||||
editCell(cell, forceEdit){
|
||||
this.focusCellNoEvent(cell);
|
||||
this.edit(cell, false, forceEdit);
|
||||
}
|
||||
|
||||
focusScrollAdjust(cell){
|
||||
if(this.table.rowManager.getRenderMode() == "virtual"){
|
||||
var topEdge = this.table.rowManager.element.scrollTop,
|
||||
bottomEdge = this.table.rowManager.element.clientHeight + this.table.rowManager.element.scrollTop,
|
||||
rowEl = cell.row.getElement();
|
||||
|
||||
if(rowEl.offsetTop < topEdge){
|
||||
this.table.rowManager.element.scrollTop -= (topEdge - rowEl.offsetTop);
|
||||
}else{
|
||||
if(rowEl.offsetTop + rowEl.offsetHeight > bottomEdge){
|
||||
this.table.rowManager.element.scrollTop += (rowEl.offsetTop + rowEl.offsetHeight - bottomEdge);
|
||||
}
|
||||
}
|
||||
|
||||
var leftEdge = this.table.rowManager.element.scrollLeft,
|
||||
rightEdge = this.table.rowManager.element.clientWidth + this.table.rowManager.element.scrollLeft,
|
||||
cellEl = cell.getElement();
|
||||
|
||||
if(this.table.modExists("frozenColumns")){
|
||||
leftEdge += parseInt(this.table.modules.frozenColumns.leftMargin || 0);
|
||||
rightEdge -= parseInt(this.table.modules.frozenColumns.rightMargin || 0);
|
||||
}
|
||||
|
||||
if(this.table.options.renderHorizontal === "virtual"){
|
||||
leftEdge -= parseInt(this.table.columnManager.renderer.vDomPadLeft);
|
||||
rightEdge -= parseInt(this.table.columnManager.renderer.vDomPadLeft);
|
||||
}
|
||||
|
||||
if(cellEl.offsetLeft < leftEdge){
|
||||
this.table.rowManager.element.scrollLeft -= (leftEdge - cellEl.offsetLeft);
|
||||
}else{
|
||||
if(cellEl.offsetLeft + cellEl.offsetWidth > rightEdge){
|
||||
this.table.rowManager.element.scrollLeft += (cellEl.offsetLeft + cellEl.offsetWidth - rightEdge);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
allowEdit(cell) {
|
||||
var check = cell.column.modules.edit ? true : false;
|
||||
|
||||
if(cell.column.modules.edit){
|
||||
switch(typeof cell.column.modules.edit.check){
|
||||
case "function":
|
||||
if(cell.row.initialized){
|
||||
check = cell.column.modules.edit.check(cell.getComponent());
|
||||
}
|
||||
break;
|
||||
|
||||
case "string":
|
||||
check = !!cell.row.data[cell.column.modules.edit.check];
|
||||
break;
|
||||
|
||||
case "boolean":
|
||||
check = cell.column.modules.edit.check;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return check;
|
||||
}
|
||||
|
||||
edit(cell, e, forceEdit){
|
||||
var self = this,
|
||||
allowEdit = true,
|
||||
rendered = function(){},
|
||||
element = cell.getElement(),
|
||||
editFinished = false,
|
||||
cellEditor, component, params;
|
||||
|
||||
//prevent editing if another cell is refusing to leave focus (eg. validation fail)
|
||||
|
||||
if(this.currentCell){
|
||||
if(!this.invalidEdit && this.currentCell !== cell){
|
||||
this.cancelEdit();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
//handle successful value change
|
||||
function success(value){
|
||||
if(self.currentCell === cell && !editFinished){
|
||||
var valid = self.chain("edit-success", [cell, value], true, true);
|
||||
|
||||
if(valid === true || self.table.options.validationMode === "highlight"){
|
||||
|
||||
editFinished = true;
|
||||
|
||||
self.clearEditor();
|
||||
|
||||
if(!cell.modules.edit){
|
||||
cell.modules.edit = {};
|
||||
}
|
||||
|
||||
cell.modules.edit.edited = true;
|
||||
|
||||
if(self.editedCells.indexOf(cell) == -1){
|
||||
self.editedCells.push(cell);
|
||||
}
|
||||
|
||||
value = self.transformEmptyValues(value, cell);
|
||||
|
||||
cell.setValue(value, true);
|
||||
|
||||
return valid === true;
|
||||
}else{
|
||||
editFinished = true;
|
||||
self.invalidEdit = true;
|
||||
self.focusCellNoEvent(cell, true);
|
||||
rendered();
|
||||
|
||||
setTimeout(() => {
|
||||
editFinished = false;
|
||||
}, 10);
|
||||
return false;
|
||||
}
|
||||
}else{
|
||||
// console.warn("Edit Success Error - cannot call success on a cell that is no longer being edited");
|
||||
}
|
||||
}
|
||||
|
||||
//handle aborted edit
|
||||
function cancel(){
|
||||
// editFinished = true;
|
||||
|
||||
if(self.currentCell === cell && !editFinished){
|
||||
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.modules.edit.blocked){
|
||||
if(e){
|
||||
e.stopPropagation();
|
||||
}
|
||||
|
||||
allowEdit = this.allowEdit(cell);
|
||||
|
||||
if(allowEdit || forceEdit){
|
||||
self.cancelEdit();
|
||||
|
||||
self.currentCell = cell;
|
||||
|
||||
this.focusScrollAdjust(cell);
|
||||
|
||||
component = cell.getComponent();
|
||||
|
||||
if(this.mouseClick){
|
||||
this.mouseClick = false;
|
||||
|
||||
if(cell.column.definition.cellClick){
|
||||
cell.column.definition.cellClick.call(this.table, e, component);
|
||||
}
|
||||
}
|
||||
|
||||
if(cell.column.definition.cellEditing){
|
||||
cell.column.definition.cellEditing.call(this.table, component);
|
||||
}
|
||||
|
||||
this.dispatch("cell-editing", cell);
|
||||
this.dispatchExternal("cellEditing", component);
|
||||
|
||||
params = typeof cell.column.modules.edit.params === "function" ? cell.column.modules.edit.params(component) : cell.column.modules.edit.params;
|
||||
|
||||
cellEditor = cell.column.modules.edit.editor.call(self, component, onRendered, success, cancel, params);
|
||||
|
||||
//if editor returned, add to DOM, if false, abort edit
|
||||
if(this.currentCell && cellEditor !== false){
|
||||
if(cellEditor instanceof Node){
|
||||
element.classList.add("tabulator-editing");
|
||||
cell.row.getElement().classList.add("tabulator-editing");
|
||||
cell.table.element.classList.add("tabulator-editing");
|
||||
while(element.firstChild) element.removeChild(element.firstChild);
|
||||
element.appendChild(cellEditor);
|
||||
|
||||
//trigger onRendered Callback
|
||||
rendered();
|
||||
|
||||
//prevent editing from triggering rowClick event
|
||||
var children = element.children;
|
||||
|
||||
for (var i = 0; i < children.length; i++) {
|
||||
children[i].addEventListener("click", function(e){
|
||||
e.stopPropagation();
|
||||
});
|
||||
}
|
||||
}else{
|
||||
console.warn("Edit Error - Editor should return an instance of Node, the editor returned:", cellEditor);
|
||||
this.blur(element);
|
||||
return false;
|
||||
}
|
||||
}else{
|
||||
this.blur(element);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}else{
|
||||
this.mouseClick = false;
|
||||
this.blur(element);
|
||||
return false;
|
||||
}
|
||||
}else{
|
||||
this.mouseClick = false;
|
||||
this.blur(element);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
emptyValueCheck(value){
|
||||
return value === "" || value === null || typeof value === "undefined";
|
||||
}
|
||||
|
||||
transformEmptyValues(value, cell){
|
||||
var mod = cell.column.modules.edit,
|
||||
convert = mod.convertEmptyValues || this.convertEmptyValues,
|
||||
checkFunc;
|
||||
|
||||
if(convert){
|
||||
checkFunc = mod.editorEmptyValueFunc || this.options("editorEmptyValueFunc");
|
||||
|
||||
if(checkFunc && checkFunc(value)){
|
||||
value = mod.convertEmptyValues ? mod.editorEmptyValue : this.options("editorEmptyValue");
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
blur(element){
|
||||
if(!this.confirm("edit-blur", [element]) ){
|
||||
element.blur();
|
||||
}
|
||||
}
|
||||
|
||||
getEditedCells(){
|
||||
var output = [];
|
||||
|
||||
this.editedCells.forEach((cell) => {
|
||||
output.push(cell.getComponent());
|
||||
});
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
clearEdited(cell){
|
||||
var editIndex;
|
||||
|
||||
if(cell.modules.edit && cell.modules.edit.edited){
|
||||
cell.modules.edit.edited = false;
|
||||
|
||||
this.dispatch("edit-edited-clear", cell);
|
||||
}
|
||||
|
||||
editIndex = this.editedCells.indexOf(cell);
|
||||
|
||||
if(editIndex > -1){
|
||||
this.editedCells.splice(editIndex, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
1060
public/libs/tabulator-master/src/js/modules/Edit/List.js
Normal file
1060
public/libs/tabulator-master/src/js/modules/Edit/List.js
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,27 @@
|
||||
import input from './editors/input.js';
|
||||
import textarea from './editors/textarea.js';
|
||||
import number from './editors/number.js';
|
||||
import range from './editors/range.js';
|
||||
import date from './editors/date.js';
|
||||
import time from './editors/time.js';
|
||||
import datetime from './editors/datetime.js';
|
||||
import list from './editors/list.js';
|
||||
import star from './editors/star.js';
|
||||
import progress from './editors/progress.js';
|
||||
import tickCross from './editors/tickCross.js';
|
||||
import adaptable from './editors/adaptable.js';
|
||||
|
||||
export default {
|
||||
input:input,
|
||||
textarea:textarea,
|
||||
number:number,
|
||||
range:range,
|
||||
date:date,
|
||||
time:time,
|
||||
datetime:datetime,
|
||||
list:list,
|
||||
star:star,
|
||||
progress:progress,
|
||||
tickCross:tickCross,
|
||||
adaptable:adaptable,
|
||||
};
|
||||
@@ -0,0 +1,37 @@
|
||||
export default function(cell, onRendered, success, cancel, params){
|
||||
var column = cell._getSelf().column,
|
||||
lookup, editorFunc, editorParams;
|
||||
|
||||
function defaultLookup(cell){
|
||||
var value = cell.getValue(),
|
||||
editor = "input";
|
||||
|
||||
switch(typeof value){
|
||||
case "number":
|
||||
editor = "number";
|
||||
break;
|
||||
|
||||
case "boolean":
|
||||
editor = "tickCross";
|
||||
break;
|
||||
|
||||
case "string":
|
||||
if(value.includes("\n")){
|
||||
editor = "textarea";
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return editor;
|
||||
}
|
||||
|
||||
lookup = params.editorLookup ? params.editorLookup(cell) : defaultLookup(cell);
|
||||
|
||||
if(params.paramsLookup){
|
||||
editorParams = typeof params.paramsLookup === "function" ? params.paramsLookup(lookup, cell) : params.paramsLookup[lookup];
|
||||
}
|
||||
|
||||
editorFunc = this.table.modules.edit.lookupEditor(lookup, column);
|
||||
|
||||
return editorFunc.call(this, cell, onRendered, success, cancel, editorParams || {});
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
//input element
|
||||
export default function(cell, onRendered, success, cancel, editorParams){
|
||||
var inputFormat = editorParams.format,
|
||||
vertNav = editorParams.verticalNavigation || "editor",
|
||||
DT = inputFormat ? (window.DateTime || luxon.DateTime) : null;
|
||||
|
||||
//create and style input
|
||||
var cellValue = cell.getValue(),
|
||||
input = document.createElement("input");
|
||||
|
||||
function convertDate(value){
|
||||
var newDatetime;
|
||||
|
||||
if(DT.isDateTime(value)){
|
||||
newDatetime = value;
|
||||
}else if(inputFormat === "iso"){
|
||||
newDatetime = DT.fromISO(String(value));
|
||||
}else{
|
||||
newDatetime = DT.fromFormat(String(value), inputFormat);
|
||||
}
|
||||
|
||||
return newDatetime.toFormat("yyyy-MM-dd");
|
||||
}
|
||||
|
||||
input.type = "date";
|
||||
input.style.padding = "4px";
|
||||
input.style.width = "100%";
|
||||
input.style.boxSizing = "border-box";
|
||||
|
||||
if(editorParams.max){
|
||||
input.setAttribute("max", inputFormat ? convertDate(editorParams.max) : editorParams.max);
|
||||
}
|
||||
|
||||
if(editorParams.min){
|
||||
input.setAttribute("min", inputFormat ? convertDate(editorParams.min) : editorParams.min);
|
||||
}
|
||||
|
||||
if(editorParams.elementAttributes && typeof editorParams.elementAttributes == "object"){
|
||||
for (let key in editorParams.elementAttributes){
|
||||
if(key.charAt(0) == "+"){
|
||||
key = key.slice(1);
|
||||
input.setAttribute(key, input.getAttribute(key) + editorParams.elementAttributes["+" + key]);
|
||||
}else{
|
||||
input.setAttribute(key, editorParams.elementAttributes[key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cellValue = typeof cellValue !== "undefined" ? cellValue : "";
|
||||
|
||||
if(inputFormat){
|
||||
if(DT){
|
||||
cellValue = convertDate(cellValue);
|
||||
}else{
|
||||
console.error("Editor Error - 'date' editor 'format' param is dependant on luxon.js");
|
||||
}
|
||||
}
|
||||
|
||||
input.value = cellValue;
|
||||
|
||||
onRendered(function(){
|
||||
if(cell.getType() === "cell"){
|
||||
input.focus({preventScroll: true});
|
||||
input.style.height = "100%";
|
||||
|
||||
if(editorParams.selectContents){
|
||||
input.select();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function onChange(){
|
||||
var value = input.value,
|
||||
luxDate;
|
||||
|
||||
if(((cellValue === null || typeof cellValue === "undefined") && value !== "") || value !== cellValue){
|
||||
|
||||
if(value && inputFormat){
|
||||
luxDate = DT.fromFormat(String(value), "yyyy-MM-dd");
|
||||
|
||||
switch(inputFormat){
|
||||
case true:
|
||||
value = luxDate;
|
||||
break;
|
||||
|
||||
case "iso":
|
||||
value = luxDate.toISO();
|
||||
break;
|
||||
|
||||
default:
|
||||
value = luxDate.toFormat(inputFormat);
|
||||
}
|
||||
}
|
||||
|
||||
if(success(value)){
|
||||
cellValue = input.value; //persist value if successfully validated incase editor is used as header filter
|
||||
}
|
||||
}else{
|
||||
cancel();
|
||||
}
|
||||
}
|
||||
|
||||
//submit new value on blur
|
||||
input.addEventListener("blur", function(e) {
|
||||
if (e.relatedTarget || e.rangeParent || e.explicitOriginalTarget !== input) {
|
||||
onChange(); // only on a "true" blur; not when focusing browser's date/time picker
|
||||
}
|
||||
});
|
||||
|
||||
//submit new value on enter
|
||||
input.addEventListener("keydown", function(e){
|
||||
switch(e.key){
|
||||
// case "Tab":
|
||||
case "Enter":
|
||||
onChange();
|
||||
break;
|
||||
|
||||
case "Escape":
|
||||
cancel();
|
||||
break;
|
||||
|
||||
case "End":
|
||||
case "Home":
|
||||
e.stopPropagation();
|
||||
break;
|
||||
|
||||
case "ArrowUp":
|
||||
case "ArrowDown":
|
||||
if(vertNav == "editor"){
|
||||
e.stopImmediatePropagation();
|
||||
e.stopPropagation();
|
||||
}
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
return input;
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
//input element
|
||||
export default function(cell, onRendered, success, cancel, editorParams){
|
||||
var inputFormat = editorParams.format,
|
||||
vertNav = editorParams.verticalNavigation || "editor",
|
||||
DT = inputFormat ? (this.table.dependencyRegistry.lookup(["luxon", "DateTime"], "DateTime")) : null,
|
||||
newDatetime;
|
||||
|
||||
//create and style input
|
||||
var cellValue = cell.getValue(),
|
||||
input = document.createElement("input");
|
||||
|
||||
input.type = "datetime-local";
|
||||
input.style.padding = "4px";
|
||||
input.style.width = "100%";
|
||||
input.style.boxSizing = "border-box";
|
||||
|
||||
if(editorParams.elementAttributes && typeof editorParams.elementAttributes == "object"){
|
||||
for (let key in editorParams.elementAttributes){
|
||||
if(key.charAt(0) == "+"){
|
||||
key = key.slice(1);
|
||||
input.setAttribute(key, input.getAttribute(key) + editorParams.elementAttributes["+" + key]);
|
||||
}else{
|
||||
input.setAttribute(key, editorParams.elementAttributes[key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cellValue = typeof cellValue !== "undefined" ? cellValue : "";
|
||||
|
||||
if(inputFormat){
|
||||
if(DT){
|
||||
if(DT.isDateTime(cellValue)){
|
||||
newDatetime = cellValue;
|
||||
}else if(inputFormat === "iso"){
|
||||
newDatetime = DT.fromISO(String(cellValue));
|
||||
}else{
|
||||
newDatetime = DT.fromFormat(String(cellValue), inputFormat);
|
||||
}
|
||||
|
||||
cellValue = newDatetime.toFormat("yyyy-MM-dd") + "T" + newDatetime.toFormat("HH:mm");
|
||||
}else{
|
||||
console.error("Editor Error - 'date' editor 'format' param is dependant on luxon.js");
|
||||
}
|
||||
}
|
||||
|
||||
input.value = cellValue;
|
||||
|
||||
onRendered(function(){
|
||||
if(cell.getType() === "cell"){
|
||||
input.focus({preventScroll: true});
|
||||
input.style.height = "100%";
|
||||
|
||||
if(editorParams.selectContents){
|
||||
input.select();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function onChange(){
|
||||
var value = input.value,
|
||||
luxDateTime;
|
||||
|
||||
if(((cellValue === null || typeof cellValue === "undefined") && value !== "") || value !== cellValue){
|
||||
|
||||
if(value && inputFormat){
|
||||
luxDateTime = DT.fromISO(String(value));
|
||||
|
||||
switch(inputFormat){
|
||||
case true:
|
||||
value = luxDateTime;
|
||||
break;
|
||||
|
||||
case "iso":
|
||||
value = luxDateTime.toISO();
|
||||
break;
|
||||
|
||||
default:
|
||||
value = luxDateTime.toFormat(inputFormat);
|
||||
}
|
||||
}
|
||||
|
||||
if(success(value)){
|
||||
cellValue = input.value; //persist value if successfully validated incase editor is used as header filter
|
||||
}
|
||||
}else{
|
||||
cancel();
|
||||
}
|
||||
}
|
||||
|
||||
//submit new value on blur
|
||||
input.addEventListener("blur", function(e) {
|
||||
if (e.relatedTarget || e.rangeParent || e.explicitOriginalTarget !== input) {
|
||||
onChange(); // only on a "true" blur; not when focusing browser's date/time picker
|
||||
}
|
||||
});
|
||||
|
||||
//submit new value on enter
|
||||
input.addEventListener("keydown", function(e){
|
||||
switch(e.key){
|
||||
// case "Tab":
|
||||
case "Enter":
|
||||
onChange();
|
||||
break;
|
||||
|
||||
case "Escape":
|
||||
cancel();
|
||||
break;
|
||||
|
||||
case "End":
|
||||
case "Home":
|
||||
e.stopPropagation();
|
||||
break;
|
||||
|
||||
case "ArrowUp":
|
||||
case "ArrowDown":
|
||||
if(vertNav == "editor"){
|
||||
e.stopImmediatePropagation();
|
||||
e.stopPropagation();
|
||||
}
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
return input;
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
import maskInput from '../../inputMask.js';
|
||||
|
||||
//input element
|
||||
export default function(cell, onRendered, success, cancel, editorParams){
|
||||
//create and style input
|
||||
var cellValue = cell.getValue(),
|
||||
input = document.createElement("input");
|
||||
|
||||
input.setAttribute("type", editorParams.search ? "search" : "text");
|
||||
|
||||
input.style.padding = "4px";
|
||||
input.style.width = "100%";
|
||||
input.style.boxSizing = "border-box";
|
||||
|
||||
if(editorParams.elementAttributes && typeof editorParams.elementAttributes == "object"){
|
||||
for (let key in editorParams.elementAttributes){
|
||||
if(key.charAt(0) == "+"){
|
||||
key = key.slice(1);
|
||||
input.setAttribute(key, input.getAttribute(key) + editorParams.elementAttributes["+" + key]);
|
||||
}else{
|
||||
input.setAttribute(key, editorParams.elementAttributes[key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
input.value = typeof cellValue !== "undefined" ? cellValue : "";
|
||||
|
||||
onRendered(function(){
|
||||
if(cell.getType() === "cell"){
|
||||
input.focus({preventScroll: true});
|
||||
input.style.height = "100%";
|
||||
|
||||
if(editorParams.selectContents){
|
||||
input.select();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function onChange(e){
|
||||
if(((cellValue === null || typeof cellValue === "undefined") && input.value !== "") || input.value !== cellValue){
|
||||
if(success(input.value)){
|
||||
cellValue = input.value; //persist value if successfully validated incase editor is used as header filter
|
||||
}
|
||||
}else{
|
||||
cancel();
|
||||
}
|
||||
}
|
||||
|
||||
//submit new value on blur or change
|
||||
input.addEventListener("change", onChange);
|
||||
input.addEventListener("blur", onChange);
|
||||
|
||||
//submit new value on enter
|
||||
input.addEventListener("keydown", function(e){
|
||||
switch(e.key){
|
||||
// case "Tab":
|
||||
case "Enter":
|
||||
onChange(e);
|
||||
break;
|
||||
|
||||
case "Escape":
|
||||
cancel();
|
||||
break;
|
||||
|
||||
case "End":
|
||||
case "Home":
|
||||
e.stopPropagation();
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
if(editorParams.mask){
|
||||
maskInput(input, editorParams);
|
||||
}
|
||||
|
||||
return input;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
import List from '../../List.js';
|
||||
|
||||
export default function(cell, onRendered, success, cancel, editorParams){
|
||||
var list = new List(this, cell, onRendered, success, cancel, editorParams);
|
||||
|
||||
return list.input;
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
import maskInput from '../../inputMask.js';
|
||||
|
||||
//input element with type of number
|
||||
export default function(cell, onRendered, success, cancel, editorParams){
|
||||
var cellValue = cell.getValue(),
|
||||
vertNav = editorParams.verticalNavigation || "editor",
|
||||
input = document.createElement("input");
|
||||
|
||||
input.setAttribute("type", "number");
|
||||
|
||||
if(typeof editorParams.max != "undefined"){
|
||||
input.setAttribute("max", editorParams.max);
|
||||
}
|
||||
|
||||
if(typeof editorParams.min != "undefined"){
|
||||
input.setAttribute("min", editorParams.min);
|
||||
}
|
||||
|
||||
if(typeof editorParams.step != "undefined"){
|
||||
input.setAttribute("step", editorParams.step);
|
||||
}
|
||||
|
||||
//create and style input
|
||||
input.style.padding = "4px";
|
||||
input.style.width = "100%";
|
||||
input.style.boxSizing = "border-box";
|
||||
|
||||
if(editorParams.elementAttributes && typeof editorParams.elementAttributes == "object"){
|
||||
for (let key in editorParams.elementAttributes){
|
||||
if(key.charAt(0) == "+"){
|
||||
key = key.slice(1);
|
||||
input.setAttribute(key, input.getAttribute(key) + editorParams.elementAttributes["+" + key]);
|
||||
}else{
|
||||
input.setAttribute(key, editorParams.elementAttributes[key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
input.value = cellValue;
|
||||
|
||||
var blurFunc = function(e){
|
||||
onChange();
|
||||
};
|
||||
|
||||
onRendered(function () {
|
||||
if(cell.getType() === "cell"){
|
||||
//submit new value on blur
|
||||
input.removeEventListener("blur", blurFunc);
|
||||
|
||||
input.focus({preventScroll: true});
|
||||
input.style.height = "100%";
|
||||
|
||||
//submit new value on blur
|
||||
input.addEventListener("blur", blurFunc);
|
||||
|
||||
if(editorParams.selectContents){
|
||||
input.select();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function onChange(){
|
||||
var value = input.value;
|
||||
|
||||
if(!isNaN(value) && value !==""){
|
||||
value = Number(value);
|
||||
}
|
||||
|
||||
if(value !== cellValue){
|
||||
if(success(value)){
|
||||
cellValue = value; //persist value if successfully validated incase editor is used as header filter
|
||||
}
|
||||
}else{
|
||||
cancel();
|
||||
}
|
||||
}
|
||||
|
||||
//submit new value on enter
|
||||
input.addEventListener("keydown", function(e){
|
||||
switch(e.key){
|
||||
case "Enter":
|
||||
// case "Tab":
|
||||
onChange();
|
||||
break;
|
||||
|
||||
case "Escape":
|
||||
cancel();
|
||||
break;
|
||||
|
||||
case "ArrowUp":
|
||||
case "ArrowDown":
|
||||
if(vertNav == "editor"){
|
||||
e.stopImmediatePropagation();
|
||||
e.stopPropagation();
|
||||
}
|
||||
break;
|
||||
|
||||
case "End":
|
||||
case "Home":
|
||||
e.stopPropagation();
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
if(editorParams.mask){
|
||||
maskInput(input, editorParams);
|
||||
}
|
||||
|
||||
return input;
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
//draggable progress bar
|
||||
export default function(cell, onRendered, success, cancel, editorParams){
|
||||
var element = cell.getElement(),
|
||||
max = typeof editorParams.max === "undefined" ? ((element.getElementsByTagName("div")[0] && element.getElementsByTagName("div")[0].getAttribute("max")) || 100) : editorParams.max,
|
||||
min = typeof editorParams.min === "undefined" ? ((element.getElementsByTagName("div")[0] && element.getElementsByTagName("div")[0].getAttribute("min")) || 0) : editorParams.min,
|
||||
percent = (max - min) / 100,
|
||||
value = cell.getValue() || 0,
|
||||
handle = document.createElement("div"),
|
||||
bar = document.createElement("div"),
|
||||
mouseDrag, mouseDragWidth;
|
||||
|
||||
//set new value
|
||||
function updateValue(){
|
||||
var style = window.getComputedStyle(element, null);
|
||||
|
||||
var calcVal = (percent * Math.round(bar.offsetWidth / ((element.clientWidth - parseInt(style.getPropertyValue("padding-left")) - parseInt(style.getPropertyValue("padding-right")))/100))) + min;
|
||||
success(calcVal);
|
||||
element.setAttribute("aria-valuenow", calcVal);
|
||||
element.setAttribute("aria-label", value);
|
||||
}
|
||||
|
||||
//style handle
|
||||
handle.style.position = "absolute";
|
||||
handle.style.right = "0";
|
||||
handle.style.top = "0";
|
||||
handle.style.bottom = "0";
|
||||
handle.style.width = "5px";
|
||||
handle.classList.add("tabulator-progress-handle");
|
||||
|
||||
//style bar
|
||||
bar.style.display = "inline-block";
|
||||
bar.style.position = "relative";
|
||||
// bar.style.top = "8px";
|
||||
// bar.style.bottom = "8px";
|
||||
// bar.style.left = "4px";
|
||||
// bar.style.marginRight = "4px";
|
||||
bar.style.height = "100%";
|
||||
bar.style.backgroundColor = "#488CE9";
|
||||
bar.style.maxWidth = "100%";
|
||||
bar.style.minWidth = "0%";
|
||||
|
||||
if(editorParams.elementAttributes && typeof editorParams.elementAttributes == "object"){
|
||||
for (let key in editorParams.elementAttributes){
|
||||
if(key.charAt(0) == "+"){
|
||||
key = key.slice(1);
|
||||
bar.setAttribute(key, bar.getAttribute(key) + editorParams.elementAttributes["+" + key]);
|
||||
}else{
|
||||
bar.setAttribute(key, editorParams.elementAttributes[key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//style cell
|
||||
element.style.padding = "4px 4px";
|
||||
|
||||
//make sure value is in range
|
||||
value = Math.min(parseFloat(value), max);
|
||||
value = Math.max(parseFloat(value), min);
|
||||
|
||||
//workout percentage
|
||||
value = Math.round((value - min) / percent);
|
||||
// bar.style.right = value + "%";
|
||||
bar.style.width = value + "%";
|
||||
|
||||
element.setAttribute("aria-valuemin", min);
|
||||
element.setAttribute("aria-valuemax", max);
|
||||
|
||||
bar.appendChild(handle);
|
||||
|
||||
handle.addEventListener("mousedown", function(e){
|
||||
mouseDrag = e.screenX;
|
||||
mouseDragWidth = bar.offsetWidth;
|
||||
});
|
||||
|
||||
handle.addEventListener("mouseover", function(){
|
||||
handle.style.cursor = "ew-resize";
|
||||
});
|
||||
|
||||
element.addEventListener("mousemove", function(e){
|
||||
if(mouseDrag){
|
||||
bar.style.width = (mouseDragWidth + e.screenX - mouseDrag) + "px";
|
||||
}
|
||||
});
|
||||
|
||||
element.addEventListener("mouseup", function(e){
|
||||
if(mouseDrag){
|
||||
e.stopPropagation();
|
||||
e.stopImmediatePropagation();
|
||||
|
||||
mouseDrag = false;
|
||||
mouseDragWidth = false;
|
||||
|
||||
updateValue();
|
||||
}
|
||||
});
|
||||
|
||||
//allow key based navigation
|
||||
element.addEventListener("keydown", function(e){
|
||||
switch(e.key){
|
||||
case "ArrowRight":
|
||||
e.preventDefault();
|
||||
bar.style.width = (bar.clientWidth + element.clientWidth/100) + "px";
|
||||
break;
|
||||
|
||||
case "ArrowLeft":
|
||||
e.preventDefault();
|
||||
bar.style.width = (bar.clientWidth - element.clientWidth/100) + "px";
|
||||
break;
|
||||
|
||||
case "Tab":
|
||||
case "Enter":
|
||||
updateValue();
|
||||
break;
|
||||
|
||||
case "Escape":
|
||||
cancel();
|
||||
break;
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
element.addEventListener("blur", function(){
|
||||
cancel();
|
||||
});
|
||||
|
||||
return bar;
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
//input element with type of number
|
||||
export default function(cell, onRendered, success, cancel, editorParams){
|
||||
var cellValue = cell.getValue(),
|
||||
input = document.createElement("input");
|
||||
|
||||
input.setAttribute("type", "range");
|
||||
|
||||
if (typeof editorParams.max != "undefined") {
|
||||
input.setAttribute("max", editorParams.max);
|
||||
}
|
||||
|
||||
if (typeof editorParams.min != "undefined") {
|
||||
input.setAttribute("min", editorParams.min);
|
||||
}
|
||||
|
||||
if (typeof editorParams.step != "undefined") {
|
||||
input.setAttribute("step", editorParams.step);
|
||||
}
|
||||
|
||||
//create and style input
|
||||
input.style.padding = "4px";
|
||||
input.style.width = "100%";
|
||||
input.style.boxSizing = "border-box";
|
||||
|
||||
if(editorParams.elementAttributes && typeof editorParams.elementAttributes == "object"){
|
||||
for (let key in editorParams.elementAttributes){
|
||||
if(key.charAt(0) == "+"){
|
||||
key = key.slice(1);
|
||||
input.setAttribute(key, input.getAttribute(key) + editorParams.elementAttributes["+" + key]);
|
||||
}else{
|
||||
input.setAttribute(key, editorParams.elementAttributes[key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
input.value = cellValue;
|
||||
|
||||
onRendered(function () {
|
||||
if(cell.getType() === "cell"){
|
||||
input.focus({preventScroll: true});
|
||||
input.style.height = "100%";
|
||||
}
|
||||
});
|
||||
|
||||
function onChange(){
|
||||
var value = input.value;
|
||||
|
||||
if(!isNaN(value) && value !==""){
|
||||
value = Number(value);
|
||||
}
|
||||
|
||||
if(value != cellValue){
|
||||
if(success(value)){
|
||||
cellValue = value; //persist value if successfully validated incase editor is used as header filter
|
||||
}
|
||||
}else{
|
||||
cancel();
|
||||
}
|
||||
}
|
||||
|
||||
//submit new value on blur
|
||||
input.addEventListener("blur", function(e){
|
||||
onChange();
|
||||
});
|
||||
|
||||
//submit new value on enter
|
||||
input.addEventListener("keydown", function(e){
|
||||
switch(e.key){
|
||||
case "Enter":
|
||||
// case "Tab":
|
||||
onChange();
|
||||
break;
|
||||
|
||||
case "Escape":
|
||||
cancel();
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
return input;
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
//star rating
|
||||
export default function(cell, onRendered, success, cancel, editorParams){
|
||||
var self = this,
|
||||
element = cell.getElement(),
|
||||
value = cell.getValue(),
|
||||
maxStars = element.getElementsByTagName("svg").length || 5,
|
||||
size = element.getElementsByTagName("svg")[0] ? element.getElementsByTagName("svg")[0].getAttribute("width") : 14,
|
||||
stars = [],
|
||||
starsHolder = document.createElement("div"),
|
||||
star = document.createElementNS('http://www.w3.org/2000/svg', "svg");
|
||||
|
||||
|
||||
//change star type
|
||||
function starChange(val){
|
||||
stars.forEach(function(star, i){
|
||||
if(i < val){
|
||||
if(self.table.browser == "ie"){
|
||||
star.setAttribute("class", "tabulator-star-active");
|
||||
}else{
|
||||
star.classList.replace("tabulator-star-inactive", "tabulator-star-active");
|
||||
}
|
||||
|
||||
star.innerHTML = '<polygon fill="#488CE9" stroke="#014AAE" stroke-width="37.6152" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" points="259.216,29.942 330.27,173.919 489.16,197.007 374.185,309.08 401.33,467.31 259.216,392.612 117.104,467.31 144.25,309.08 29.274,197.007 188.165,173.919 "/>';
|
||||
}else{
|
||||
if(self.table.browser == "ie"){
|
||||
star.setAttribute("class", "tabulator-star-inactive");
|
||||
}else{
|
||||
star.classList.replace("tabulator-star-active", "tabulator-star-inactive");
|
||||
}
|
||||
|
||||
star.innerHTML = '<polygon fill="#010155" stroke="#686868" stroke-width="37.6152" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" points="259.216,29.942 330.27,173.919 489.16,197.007 374.185,309.08 401.33,467.31 259.216,392.612 117.104,467.31 144.25,309.08 29.274,197.007 188.165,173.919 "/>';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//build stars
|
||||
function buildStar(i){
|
||||
|
||||
var starHolder = document.createElement("span");
|
||||
var nextStar = star.cloneNode(true);
|
||||
|
||||
stars.push(nextStar);
|
||||
|
||||
starHolder.addEventListener("mouseenter", function(e){
|
||||
e.stopPropagation();
|
||||
e.stopImmediatePropagation();
|
||||
starChange(i);
|
||||
});
|
||||
|
||||
starHolder.addEventListener("mousemove", function(e){
|
||||
e.stopPropagation();
|
||||
e.stopImmediatePropagation();
|
||||
});
|
||||
|
||||
starHolder.addEventListener("click", function(e){
|
||||
e.stopPropagation();
|
||||
e.stopImmediatePropagation();
|
||||
success(i);
|
||||
element.blur();
|
||||
});
|
||||
|
||||
starHolder.appendChild(nextStar);
|
||||
starsHolder.appendChild(starHolder);
|
||||
|
||||
}
|
||||
|
||||
//handle keyboard navigation value change
|
||||
function changeValue(val){
|
||||
value = val;
|
||||
starChange(val);
|
||||
}
|
||||
|
||||
//style cell
|
||||
element.style.whiteSpace = "nowrap";
|
||||
element.style.overflow = "hidden";
|
||||
element.style.textOverflow = "ellipsis";
|
||||
|
||||
//style holding element
|
||||
starsHolder.style.verticalAlign = "middle";
|
||||
starsHolder.style.display = "inline-block";
|
||||
starsHolder.style.padding = "4px";
|
||||
|
||||
//style star
|
||||
star.setAttribute("width", size);
|
||||
star.setAttribute("height", size);
|
||||
star.setAttribute("viewBox", "0 0 512 512");
|
||||
star.setAttribute("xml:space", "preserve");
|
||||
star.style.padding = "0 1px";
|
||||
|
||||
if(editorParams.elementAttributes && typeof editorParams.elementAttributes == "object"){
|
||||
for (let key in editorParams.elementAttributes){
|
||||
if(key.charAt(0) == "+"){
|
||||
key = key.slice(1);
|
||||
starsHolder.setAttribute(key, starsHolder.getAttribute(key) + editorParams.elementAttributes["+" + key]);
|
||||
}else{
|
||||
starsHolder.setAttribute(key, editorParams.elementAttributes[key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//create correct number of stars
|
||||
for(var i=1;i<= maxStars;i++){
|
||||
buildStar(i);
|
||||
}
|
||||
|
||||
//ensure value does not exceed number of stars
|
||||
value = Math.min(parseInt(value), maxStars);
|
||||
|
||||
// set initial styling of stars
|
||||
starChange(value);
|
||||
|
||||
starsHolder.addEventListener("mousemove", function(e){
|
||||
starChange(0);
|
||||
});
|
||||
|
||||
starsHolder.addEventListener("click", function(e){
|
||||
success(0);
|
||||
});
|
||||
|
||||
element.addEventListener("blur", function(e){
|
||||
cancel();
|
||||
});
|
||||
|
||||
//allow key based navigation
|
||||
element.addEventListener("keydown", function(e){
|
||||
switch(e.key){
|
||||
case "ArrowRight":
|
||||
changeValue(value + 1);
|
||||
break;
|
||||
|
||||
case "ArrowLeft":
|
||||
changeValue(value - 1);
|
||||
break;
|
||||
|
||||
case "Enter":
|
||||
success(value);
|
||||
break;
|
||||
|
||||
case "Escape":
|
||||
cancel();
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
return starsHolder;
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
import maskInput from '../../inputMask.js';
|
||||
|
||||
//resizable text area element
|
||||
export default function(cell, onRendered, success, cancel, editorParams){
|
||||
var cellValue = cell.getValue(),
|
||||
vertNav = editorParams.verticalNavigation || "hybrid",
|
||||
value = String(cellValue !== null && typeof cellValue !== "undefined" ? cellValue : ""),
|
||||
input = document.createElement("textarea"),
|
||||
scrollHeight = 0;
|
||||
|
||||
//create and style input
|
||||
input.style.display = "block";
|
||||
input.style.padding = "2px";
|
||||
input.style.height = "100%";
|
||||
input.style.width = "100%";
|
||||
input.style.boxSizing = "border-box";
|
||||
input.style.whiteSpace = "pre-wrap";
|
||||
input.style.resize = "none";
|
||||
|
||||
if(editorParams.elementAttributes && typeof editorParams.elementAttributes == "object"){
|
||||
for (let key in editorParams.elementAttributes){
|
||||
if(key.charAt(0) == "+"){
|
||||
key = key.slice(1);
|
||||
input.setAttribute(key, input.getAttribute(key) + editorParams.elementAttributes["+" + key]);
|
||||
}else{
|
||||
input.setAttribute(key, editorParams.elementAttributes[key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
input.value = value;
|
||||
|
||||
onRendered(function(){
|
||||
if(cell.getType() === "cell"){
|
||||
input.focus({preventScroll: true});
|
||||
input.style.height = "100%";
|
||||
|
||||
input.scrollHeight;
|
||||
input.style.height = input.scrollHeight + "px";
|
||||
cell.getRow().normalizeHeight();
|
||||
|
||||
if(editorParams.selectContents){
|
||||
input.select();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function onChange(e){
|
||||
|
||||
if(((cellValue === null || typeof cellValue === "undefined") && input.value !== "") || input.value !== cellValue){
|
||||
|
||||
if(success(input.value)){
|
||||
cellValue = input.value; //persist value if successfully validated incase editor is used as header filter
|
||||
}
|
||||
|
||||
setTimeout(function(){
|
||||
cell.getRow().normalizeHeight();
|
||||
},300);
|
||||
}else{
|
||||
cancel();
|
||||
}
|
||||
}
|
||||
|
||||
//submit new value on blur or change
|
||||
input.addEventListener("change", onChange);
|
||||
input.addEventListener("blur", onChange);
|
||||
|
||||
input.addEventListener("keyup", function(){
|
||||
|
||||
input.style.height = "";
|
||||
|
||||
var heightNow = input.scrollHeight;
|
||||
|
||||
input.style.height = heightNow + "px";
|
||||
|
||||
if(heightNow != scrollHeight){
|
||||
scrollHeight = heightNow;
|
||||
cell.getRow().normalizeHeight();
|
||||
}
|
||||
});
|
||||
|
||||
input.addEventListener("keydown", function(e){
|
||||
|
||||
switch(e.key){
|
||||
|
||||
case "Enter":
|
||||
if(e.shiftKey && editorParams.shiftEnterSubmit){
|
||||
onChange(e);
|
||||
}
|
||||
break;
|
||||
|
||||
case "Escape":
|
||||
cancel();
|
||||
break;
|
||||
|
||||
case "ArrowUp":
|
||||
if(vertNav == "editor" || (vertNav == "hybrid" && input.selectionStart)){
|
||||
e.stopImmediatePropagation();
|
||||
e.stopPropagation();
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case "ArrowDown":
|
||||
if(vertNav == "editor" || (vertNav == "hybrid" && input.selectionStart !== input.value.length)){
|
||||
e.stopImmediatePropagation();
|
||||
e.stopPropagation();
|
||||
}
|
||||
break;
|
||||
|
||||
case "End":
|
||||
case "Home":
|
||||
e.stopPropagation();
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
if(editorParams.mask){
|
||||
maskInput(input, editorParams);
|
||||
}
|
||||
|
||||
return input;
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
//checkbox
|
||||
export default function(cell, onRendered, success, cancel, editorParams){
|
||||
var value = cell.getValue(),
|
||||
input = document.createElement("input"),
|
||||
tristate = editorParams.tristate,
|
||||
indetermValue = typeof editorParams.indeterminateValue === "undefined" ? null : editorParams.indeterminateValue,
|
||||
indetermState = false,
|
||||
trueValueSet = Object.keys(editorParams).includes("trueValue"),
|
||||
falseValueSet = Object.keys(editorParams).includes("falseValue");
|
||||
|
||||
input.setAttribute("type", "checkbox");
|
||||
input.style.marginTop = "5px";
|
||||
input.style.boxSizing = "border-box";
|
||||
|
||||
if(editorParams.elementAttributes && typeof editorParams.elementAttributes == "object"){
|
||||
for (let key in editorParams.elementAttributes){
|
||||
if(key.charAt(0) == "+"){
|
||||
key = key.slice(1);
|
||||
input.setAttribute(key, input.getAttribute(key) + editorParams.elementAttributes["+" + key]);
|
||||
}else{
|
||||
input.setAttribute(key, editorParams.elementAttributes[key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
input.value = value;
|
||||
|
||||
if(tristate && (typeof value === "undefined" || value === indetermValue || value === "")){
|
||||
indetermState = true;
|
||||
input.indeterminate = true;
|
||||
}
|
||||
|
||||
if(this.table.browser != "firefox" && this.table.browser != "safari"){ //prevent blur issue on mac firefox
|
||||
onRendered(function(){
|
||||
if(cell.getType() === "cell"){
|
||||
input.focus({preventScroll: true});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
input.checked = trueValueSet ? value === editorParams.trueValue : (value === true || value === "true" || value === "True" || value === 1);
|
||||
|
||||
function setValue(blur){
|
||||
var checkedValue = input.checked;
|
||||
|
||||
if(trueValueSet && checkedValue){
|
||||
checkedValue = editorParams.trueValue;
|
||||
}else if(falseValueSet && !checkedValue){
|
||||
checkedValue = editorParams.falseValue;
|
||||
}
|
||||
|
||||
if(tristate){
|
||||
if(!blur){
|
||||
if(input.checked && !indetermState){
|
||||
input.checked = false;
|
||||
input.indeterminate = true;
|
||||
indetermState = true;
|
||||
return indetermValue;
|
||||
}else{
|
||||
indetermState = false;
|
||||
return checkedValue;
|
||||
}
|
||||
}else{
|
||||
if(indetermState){
|
||||
return indetermValue;
|
||||
}else{
|
||||
return checkedValue;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
return checkedValue;
|
||||
}
|
||||
}
|
||||
|
||||
//submit new value on blur
|
||||
input.addEventListener("change", function(e){
|
||||
success(setValue());
|
||||
});
|
||||
|
||||
input.addEventListener("blur", function(e){
|
||||
success(setValue(true));
|
||||
});
|
||||
|
||||
//submit new value on enter
|
||||
input.addEventListener("keydown", function(e){
|
||||
if(e.key == "Enter"){
|
||||
success(setValue());
|
||||
}
|
||||
if(e.key == "Escape"){
|
||||
cancel();
|
||||
}
|
||||
});
|
||||
|
||||
return input;
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
//input element
|
||||
export default function(cell, onRendered, success, cancel, editorParams){
|
||||
var inputFormat = editorParams.format,
|
||||
vertNav = editorParams.verticalNavigation || "editor",
|
||||
DT = inputFormat ? (window.DateTime || luxon.DateTime) : null,
|
||||
newDatetime;
|
||||
|
||||
//create and style input
|
||||
var cellValue = cell.getValue(),
|
||||
input = document.createElement("input");
|
||||
|
||||
input.type = "time";
|
||||
input.style.padding = "4px";
|
||||
input.style.width = "100%";
|
||||
input.style.boxSizing = "border-box";
|
||||
|
||||
if(editorParams.elementAttributes && typeof editorParams.elementAttributes == "object"){
|
||||
for (let key in editorParams.elementAttributes){
|
||||
if(key.charAt(0) == "+"){
|
||||
key = key.slice(1);
|
||||
input.setAttribute(key, input.getAttribute(key) + editorParams.elementAttributes["+" + key]);
|
||||
}else{
|
||||
input.setAttribute(key, editorParams.elementAttributes[key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cellValue = typeof cellValue !== "undefined" ? cellValue : "";
|
||||
|
||||
if(inputFormat){
|
||||
if(DT){
|
||||
if(DT.isDateTime(cellValue)){
|
||||
newDatetime = cellValue;
|
||||
}else if(inputFormat === "iso"){
|
||||
newDatetime = DT.fromISO(String(cellValue));
|
||||
}else{
|
||||
newDatetime = DT.fromFormat(String(cellValue), inputFormat);
|
||||
}
|
||||
|
||||
cellValue = newDatetime.toFormat("HH:mm");
|
||||
|
||||
}else{
|
||||
console.error("Editor Error - 'date' editor 'format' param is dependant on luxon.js");
|
||||
}
|
||||
}
|
||||
|
||||
input.value = cellValue;
|
||||
|
||||
onRendered(function(){
|
||||
if(cell.getType() == "cell"){
|
||||
input.focus({preventScroll: true});
|
||||
input.style.height = "100%";
|
||||
|
||||
if(editorParams.selectContents){
|
||||
input.select();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function onChange(){
|
||||
var value = input.value,
|
||||
luxTime;
|
||||
|
||||
if(((cellValue === null || typeof cellValue === "undefined") && value !== "") || value !== cellValue){
|
||||
|
||||
if(value && inputFormat){
|
||||
luxTime = DT.fromFormat(String(value), "hh:mm");
|
||||
|
||||
switch(inputFormat){
|
||||
case true:
|
||||
value = luxTime;
|
||||
break;
|
||||
|
||||
case "iso":
|
||||
value = luxTime.toISO();
|
||||
break;
|
||||
|
||||
default:
|
||||
value = luxTime.toFormat(inputFormat);
|
||||
}
|
||||
}
|
||||
|
||||
if(success(value)){
|
||||
cellValue = input.value; //persist value if successfully validated incase editor is used as header filter
|
||||
}
|
||||
}else{
|
||||
cancel();
|
||||
}
|
||||
}
|
||||
|
||||
//submit new value on blur
|
||||
input.addEventListener("blur", function(e) {
|
||||
if (e.relatedTarget || e.rangeParent || e.explicitOriginalTarget !== input) {
|
||||
onChange(); // only on a "true" blur; not when focusing browser's date/time picker
|
||||
}
|
||||
});
|
||||
|
||||
//submit new value on enter
|
||||
input.addEventListener("keydown", function(e){
|
||||
switch(e.key){
|
||||
// case "Tab":
|
||||
case "Enter":
|
||||
onChange();
|
||||
break;
|
||||
|
||||
case "Escape":
|
||||
cancel();
|
||||
break;
|
||||
|
||||
case "End":
|
||||
case "Home":
|
||||
e.stopPropagation();
|
||||
break;
|
||||
|
||||
case "ArrowUp":
|
||||
case "ArrowDown":
|
||||
if(vertNav == "editor"){
|
||||
e.stopImmediatePropagation();
|
||||
e.stopPropagation();
|
||||
}
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
return input;
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
export default function maskInput(el, options){
|
||||
var mask = options.mask,
|
||||
maskLetter = typeof options.maskLetterChar !== "undefined" ? options.maskLetterChar : "A",
|
||||
maskNumber = typeof options.maskNumberChar !== "undefined" ? options.maskNumberChar : "9",
|
||||
maskWildcard = typeof options.maskWildcardChar !== "undefined" ? options.maskWildcardChar : "*";
|
||||
|
||||
function fillSymbols(index){
|
||||
var symbol = mask[index];
|
||||
if(typeof symbol !== "undefined" && symbol !== maskWildcard && symbol !== maskLetter && symbol !== maskNumber){
|
||||
el.value = el.value + "" + symbol;
|
||||
fillSymbols(index+1);
|
||||
}
|
||||
}
|
||||
|
||||
el.addEventListener("keydown", (e) => {
|
||||
var index = el.value.length,
|
||||
char = e.key;
|
||||
|
||||
if(e.key.length === 1 && !e.ctrlKey && !e.metaKey){
|
||||
if(index >= mask.length){
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
return false;
|
||||
}else{
|
||||
switch(mask[index]){
|
||||
case maskLetter:
|
||||
if(char.toUpperCase() == char.toLowerCase()){
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
case maskNumber:
|
||||
if(isNaN(char)){
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
case maskWildcard:
|
||||
break;
|
||||
|
||||
default:
|
||||
if(char !== mask[index]){
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
});
|
||||
|
||||
el.addEventListener("keyup", (e) => {
|
||||
if(e.key.length === 1){
|
||||
if(options.maskAutoFill){
|
||||
fillSymbols(el.value.length);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
if(!el.placeholder){
|
||||
el.placeholder = mask;
|
||||
}
|
||||
|
||||
if(options.maskAutoFill){
|
||||
fillSymbols(el.value.length);
|
||||
}
|
||||
}
|
||||
654
public/libs/tabulator-master/src/js/modules/Export/Export.js
Normal file
654
public/libs/tabulator-master/src/js/modules/Export/Export.js
Normal file
@@ -0,0 +1,654 @@
|
||||
import Module from '../../core/Module.js';
|
||||
|
||||
import ExportRow from './ExportRow.js';
|
||||
import ExportColumn from './ExportColumn.js';
|
||||
|
||||
import columnLookups from './defaults/columnLookups.js';
|
||||
import rowLookups from './defaults/rowLookups.js';
|
||||
|
||||
export default class Export extends Module{
|
||||
|
||||
static moduleName = "export";
|
||||
|
||||
static columnLookups = columnLookups;
|
||||
static rowLookups = rowLookups;
|
||||
|
||||
constructor(table){
|
||||
super(table);
|
||||
|
||||
this.config = {};
|
||||
this.cloneTableStyle = true;
|
||||
this.colVisProp = "";
|
||||
this.colVisPropAttach = "";
|
||||
|
||||
this.registerTableOption("htmlOutputConfig", false); //html output config
|
||||
|
||||
this.registerColumnOption("htmlOutput");
|
||||
this.registerColumnOption("titleHtmlOutput");
|
||||
}
|
||||
|
||||
initialize(){
|
||||
this.registerTableFunction("getHtml", this.getHtml.bind(this));
|
||||
}
|
||||
|
||||
///////////////////////////////////
|
||||
///////// Internal Logic //////////
|
||||
///////////////////////////////////
|
||||
|
||||
generateExportList(config, style, range, colVisProp){
|
||||
var headers, body, columns, colLookup;
|
||||
|
||||
this.cloneTableStyle = style;
|
||||
this.config = config || {};
|
||||
this.colVisProp = colVisProp;
|
||||
this.colVisPropAttach = this.colVisProp.charAt(0).toUpperCase() + this.colVisProp.slice(1);
|
||||
|
||||
colLookup = Export.columnLookups[range];
|
||||
|
||||
if(colLookup){
|
||||
columns = colLookup.call(this.table);
|
||||
columns = columns.filter(col => this.columnVisCheck(col));
|
||||
}
|
||||
|
||||
headers = this.config.columnHeaders !== false ? this.headersToExportRows(this.generateColumnGroupHeaders(columns)) : [];
|
||||
|
||||
if(columns){
|
||||
columns = columns.map(col => col.getComponent());
|
||||
}
|
||||
|
||||
body = this.bodyToExportRows(this.rowLookup(range), columns);
|
||||
|
||||
return headers.concat(body);
|
||||
}
|
||||
|
||||
generateTable(config, style, range, colVisProp){
|
||||
var list = this.generateExportList(config, style, range, colVisProp);
|
||||
|
||||
return this.generateTableElement(list);
|
||||
}
|
||||
|
||||
rowLookup(range){
|
||||
var rows = [],
|
||||
rowLookup;
|
||||
|
||||
if(typeof range == "function"){
|
||||
range.call(this.table).forEach((row) =>{
|
||||
row = this.table.rowManager.findRow(row);
|
||||
|
||||
if(row){
|
||||
rows.push(row);
|
||||
}
|
||||
});
|
||||
}else{
|
||||
rowLookup = Export.rowLookups[range] || Export.rowLookups["active"];
|
||||
|
||||
rows = rowLookup.call(this.table);
|
||||
}
|
||||
|
||||
return Object.assign([], rows);
|
||||
}
|
||||
|
||||
generateColumnGroupHeaders(columns){
|
||||
var output = [];
|
||||
|
||||
if (!columns) {
|
||||
columns = this.config.columnGroups !== false ? this.table.columnManager.columns : this.table.columnManager.columnsByIndex;
|
||||
}
|
||||
|
||||
columns.forEach((column) => {
|
||||
var colData = this.processColumnGroup(column);
|
||||
|
||||
if(colData){
|
||||
output.push(colData);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
processColumnGroup(column){
|
||||
var subGroups = column.columns,
|
||||
maxDepth = 0,
|
||||
title = column.definition["title" + (this.colVisPropAttach)] || column.definition.title;
|
||||
|
||||
var groupData = {
|
||||
title:title,
|
||||
column:column,
|
||||
depth:1,
|
||||
};
|
||||
|
||||
if(subGroups.length){
|
||||
groupData.subGroups = [];
|
||||
groupData.width = 0;
|
||||
|
||||
subGroups.forEach((subGroup) => {
|
||||
var subGroupData = this.processColumnGroup(subGroup);
|
||||
|
||||
if(subGroupData){
|
||||
groupData.width += subGroupData.width;
|
||||
groupData.subGroups.push(subGroupData);
|
||||
|
||||
if(subGroupData.depth > maxDepth){
|
||||
maxDepth = subGroupData.depth;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
groupData.depth += maxDepth;
|
||||
|
||||
if(!groupData.width){
|
||||
return false;
|
||||
}
|
||||
}else{
|
||||
if(this.columnVisCheck(column)){
|
||||
groupData.width = 1;
|
||||
}else{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return groupData;
|
||||
}
|
||||
|
||||
columnVisCheck(column){
|
||||
var visProp = column.definition[this.colVisProp];
|
||||
|
||||
if(this.config.rowHeaders === false && column.isRowHeader){
|
||||
return false;
|
||||
}
|
||||
|
||||
if(typeof visProp === "function"){
|
||||
visProp = visProp.call(this.table, column.getComponent());
|
||||
}
|
||||
|
||||
if(visProp === false || visProp === true){
|
||||
return visProp;
|
||||
}
|
||||
|
||||
return column.visible && column.field;
|
||||
}
|
||||
|
||||
headersToExportRows(columns){
|
||||
var headers = [],
|
||||
headerDepth = 0,
|
||||
exportRows = [];
|
||||
|
||||
function parseColumnGroup(column, level){
|
||||
|
||||
var depth = headerDepth - level;
|
||||
|
||||
if(typeof headers[level] === "undefined"){
|
||||
headers[level] = [];
|
||||
}
|
||||
|
||||
column.height = column.subGroups ? 1 : (depth - column.depth) + 1;
|
||||
|
||||
headers[level].push(column);
|
||||
|
||||
if(column.height > 1){
|
||||
for(let i = 1; i < column.height; i ++){
|
||||
|
||||
if(typeof headers[level + i] === "undefined"){
|
||||
headers[level + i] = [];
|
||||
}
|
||||
|
||||
headers[level + i].push(false);
|
||||
}
|
||||
}
|
||||
|
||||
if(column.width > 1){
|
||||
for(let i = 1; i < column.width; i ++){
|
||||
headers[level].push(false);
|
||||
}
|
||||
}
|
||||
|
||||
if(column.subGroups){
|
||||
column.subGroups.forEach(function(subGroup){
|
||||
parseColumnGroup(subGroup, level+1);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
//calculate maximum header depth
|
||||
columns.forEach(function(column){
|
||||
if(column.depth > headerDepth){
|
||||
headerDepth = column.depth;
|
||||
}
|
||||
});
|
||||
|
||||
columns.forEach(function(column){
|
||||
parseColumnGroup(column,0);
|
||||
});
|
||||
|
||||
headers.forEach((header) => {
|
||||
var columns = [];
|
||||
|
||||
header.forEach((col) => {
|
||||
if(col){
|
||||
let title = typeof col.title === "undefined" ? "" : col.title;
|
||||
columns.push(new ExportColumn(title, col.column.getComponent(), col.width, col.height, col.depth));
|
||||
}else{
|
||||
columns.push(null);
|
||||
}
|
||||
});
|
||||
|
||||
exportRows.push(new ExportRow("header", columns));
|
||||
});
|
||||
|
||||
return exportRows;
|
||||
}
|
||||
|
||||
bodyToExportRows(rows, columns = []){
|
||||
var exportRows = [];
|
||||
|
||||
if (columns.length === 0) {
|
||||
this.table.columnManager.columnsByIndex.forEach((column) => {
|
||||
if (this.columnVisCheck(column)) {
|
||||
columns.push(column.getComponent());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if(this.config.columnCalcs !== false && this.table.modExists("columnCalcs")){
|
||||
if(this.table.modules.columnCalcs.topInitialized){
|
||||
rows.unshift(this.table.modules.columnCalcs.topRow);
|
||||
}
|
||||
|
||||
if(this.table.modules.columnCalcs.botInitialized){
|
||||
rows.push(this.table.modules.columnCalcs.botRow);
|
||||
}
|
||||
}
|
||||
|
||||
rows = rows.filter((row) => {
|
||||
switch(row.type){
|
||||
case "group":
|
||||
return this.config.rowGroups !== false;
|
||||
|
||||
case "calc":
|
||||
return this.config.columnCalcs !== false;
|
||||
|
||||
case "row":
|
||||
return !(this.table.options.dataTree && this.config.dataTree === false && row.modules.dataTree.parent);
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
rows.forEach((row, i) => {
|
||||
var rowData = row.getData(this.colVisProp);
|
||||
var exportCols = [];
|
||||
var indent = 0;
|
||||
|
||||
switch(row.type){
|
||||
case "group":
|
||||
indent = row.level;
|
||||
exportCols.push(new ExportColumn(row.key, row.getComponent(), columns.length, 1));
|
||||
break;
|
||||
|
||||
case "calc" :
|
||||
case "row" :
|
||||
columns.forEach((col) => {
|
||||
exportCols.push(new ExportColumn(col._column.getFieldValue(rowData), col, 1, 1));
|
||||
});
|
||||
|
||||
if(this.table.options.dataTree && this.config.dataTree !== false){
|
||||
indent = row.modules.dataTree.index;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
exportRows.push(new ExportRow(row.type, exportCols, row.getComponent(), indent));
|
||||
});
|
||||
|
||||
return exportRows;
|
||||
}
|
||||
|
||||
generateTableElement(list){
|
||||
var table = document.createElement("table"),
|
||||
headerEl = document.createElement("thead"),
|
||||
bodyEl = document.createElement("tbody"),
|
||||
styles = this.lookupTableStyles(),
|
||||
rowFormatter = this.table.options["rowFormatter" + (this.colVisPropAttach)],
|
||||
setup = {};
|
||||
|
||||
setup.rowFormatter = rowFormatter !== null ? rowFormatter : this.table.options.rowFormatter;
|
||||
|
||||
if(this.table.options.dataTree &&this.config.dataTree !== false && this.table.modExists("columnCalcs")){
|
||||
setup.treeElementField = this.table.modules.dataTree.elementField;
|
||||
}
|
||||
|
||||
//assign group header formatter
|
||||
setup.groupHeader = this.table.options["groupHeader" + (this.colVisPropAttach)];
|
||||
|
||||
if(setup.groupHeader && !Array.isArray(setup.groupHeader)){
|
||||
setup.groupHeader = [setup.groupHeader];
|
||||
}
|
||||
|
||||
table.classList.add("tabulator-print-table");
|
||||
|
||||
this.mapElementStyles(this.table.columnManager.getHeadersElement(), headerEl, ["border-top", "border-left", "border-right", "border-bottom", "background-color", "color", "font-weight", "font-family", "font-size"]);
|
||||
|
||||
if(list.length > 1000){
|
||||
console.warn("It may take a long time to render an HTML table with more than 1000 rows");
|
||||
}
|
||||
|
||||
list.forEach((row, i) => {
|
||||
let rowEl;
|
||||
|
||||
switch(row.type){
|
||||
case "header":
|
||||
headerEl.appendChild(this.generateHeaderElement(row, setup, styles));
|
||||
break;
|
||||
|
||||
case "group":
|
||||
bodyEl.appendChild(this.generateGroupElement(row, setup, styles));
|
||||
break;
|
||||
|
||||
case "calc":
|
||||
bodyEl.appendChild(this.generateCalcElement(row, setup, styles));
|
||||
break;
|
||||
|
||||
case "row":
|
||||
rowEl = this.generateRowElement(row, setup, styles);
|
||||
|
||||
this.mapElementStyles(((i % 2) && styles.evenRow) ? styles.evenRow : styles.oddRow, rowEl, ["border-top", "border-left", "border-right", "border-bottom", "color", "font-weight", "font-family", "font-size", "background-color"]);
|
||||
bodyEl.appendChild(rowEl);
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
if(headerEl.innerHTML){
|
||||
table.appendChild(headerEl);
|
||||
}
|
||||
|
||||
table.appendChild(bodyEl);
|
||||
|
||||
|
||||
this.mapElementStyles(this.table.element, table, ["border-top", "border-left", "border-right", "border-bottom"]);
|
||||
return table;
|
||||
}
|
||||
|
||||
lookupTableStyles(){
|
||||
var styles = {};
|
||||
|
||||
//lookup row styles
|
||||
if(this.cloneTableStyle && window.getComputedStyle){
|
||||
styles.oddRow = this.table.element.querySelector(".tabulator-row-odd:not(.tabulator-group):not(.tabulator-calcs)");
|
||||
styles.evenRow = this.table.element.querySelector(".tabulator-row-even:not(.tabulator-group):not(.tabulator-calcs)");
|
||||
styles.calcRow = this.table.element.querySelector(".tabulator-row.tabulator-calcs");
|
||||
styles.firstRow = this.table.element.querySelector(".tabulator-row:not(.tabulator-group):not(.tabulator-calcs)");
|
||||
styles.firstGroup = this.table.element.getElementsByClassName("tabulator-group")[0];
|
||||
|
||||
if(styles.firstRow){
|
||||
styles.styleCells = styles.firstRow.getElementsByClassName("tabulator-cell");
|
||||
styles.styleRowHeader = styles.firstRow.getElementsByClassName("tabulator-row-header")[0];
|
||||
styles.firstCell = styles.styleCells[0];
|
||||
styles.lastCell = styles.styleCells[styles.styleCells.length - 1];
|
||||
}
|
||||
}
|
||||
|
||||
return styles;
|
||||
}
|
||||
|
||||
generateHeaderElement(row, setup, styles){
|
||||
var rowEl = document.createElement("tr");
|
||||
|
||||
row.columns.forEach((column) => {
|
||||
if(column){
|
||||
var cellEl = document.createElement("th");
|
||||
var classNames = column.component._column.definition.cssClass ? column.component._column.definition.cssClass.split(" ") : [];
|
||||
|
||||
cellEl.colSpan = column.width;
|
||||
cellEl.rowSpan = column.height;
|
||||
|
||||
cellEl.innerHTML = column.value;
|
||||
|
||||
if(this.cloneTableStyle){
|
||||
cellEl.style.boxSizing = "border-box";
|
||||
}
|
||||
|
||||
classNames.forEach(function(className) {
|
||||
cellEl.classList.add(className);
|
||||
});
|
||||
|
||||
this.mapElementStyles(column.component.getElement(), cellEl, ["text-align", "border-left", "border-right", "background-color", "color", "font-weight", "font-family", "font-size"]);
|
||||
this.mapElementStyles(column.component._column.contentElement, cellEl, ["padding-top", "padding-left", "padding-right", "padding-bottom"]);
|
||||
|
||||
if(column.component._column.visible){
|
||||
this.mapElementStyles(column.component.getElement(), cellEl, ["width"]);
|
||||
}else{
|
||||
if(column.component._column.definition.width){
|
||||
cellEl.style.width = column.component._column.definition.width + "px";
|
||||
}
|
||||
}
|
||||
|
||||
if(column.component._column.parent && column.component._column.parent.isGroup){
|
||||
this.mapElementStyles(column.component._column.parent.groupElement, cellEl, ["border-top"]);
|
||||
}else{
|
||||
this.mapElementStyles(column.component.getElement(), cellEl, ["border-top"]);
|
||||
}
|
||||
|
||||
if(column.component._column.isGroup){
|
||||
this.mapElementStyles(column.component.getElement(), cellEl, ["border-bottom"]);
|
||||
}else{
|
||||
this.mapElementStyles(this.table.columnManager.getElement(), cellEl, ["border-bottom"]);
|
||||
}
|
||||
|
||||
rowEl.appendChild(cellEl);
|
||||
}
|
||||
});
|
||||
|
||||
return rowEl;
|
||||
}
|
||||
|
||||
generateGroupElement(row, setup, styles){
|
||||
|
||||
var rowEl = document.createElement("tr"),
|
||||
cellEl = document.createElement("td"),
|
||||
group = row.columns[0];
|
||||
|
||||
rowEl.classList.add("tabulator-print-table-row");
|
||||
|
||||
if(setup.groupHeader && setup.groupHeader[row.indent]){
|
||||
group.value = setup.groupHeader[row.indent](group.value, row.component._group.getRowCount(), row.component._group.getData(), row.component);
|
||||
}else{
|
||||
if(setup.groupHeader !== false){
|
||||
group.value = row.component._group.generator(group.value, row.component._group.getRowCount(), row.component._group.getData(), row.component);
|
||||
}
|
||||
}
|
||||
|
||||
cellEl.colSpan = group.width;
|
||||
cellEl.innerHTML = group.value;
|
||||
|
||||
rowEl.classList.add("tabulator-print-table-group");
|
||||
rowEl.classList.add("tabulator-group-level-" + row.indent);
|
||||
|
||||
if(group.component.isVisible()){
|
||||
rowEl.classList.add("tabulator-group-visible");
|
||||
}
|
||||
|
||||
this.mapElementStyles(styles.firstGroup, rowEl, ["border-top", "border-left", "border-right", "border-bottom", "color", "font-weight", "font-family", "font-size", "background-color"]);
|
||||
this.mapElementStyles(styles.firstGroup, cellEl, ["padding-top", "padding-left", "padding-right", "padding-bottom"]);
|
||||
|
||||
rowEl.appendChild(cellEl);
|
||||
|
||||
return rowEl;
|
||||
}
|
||||
|
||||
generateCalcElement(row, setup, styles){
|
||||
var rowEl = this.generateRowElement(row, setup, styles);
|
||||
|
||||
rowEl.classList.add("tabulator-print-table-calcs");
|
||||
this.mapElementStyles(styles.calcRow, rowEl, ["border-top", "border-left", "border-right", "border-bottom", "color", "font-weight", "font-family", "font-size", "background-color"]);
|
||||
|
||||
return rowEl;
|
||||
}
|
||||
|
||||
generateRowElement(row, setup, styles){
|
||||
var rowEl = document.createElement("tr");
|
||||
|
||||
rowEl.classList.add("tabulator-print-table-row");
|
||||
|
||||
row.columns.forEach((col, i) => {
|
||||
if(col){
|
||||
var cellEl = document.createElement("td"),
|
||||
column = col.component._column,
|
||||
table = this.table,
|
||||
index = table.columnManager.findColumnIndex(column),
|
||||
value = col.value,
|
||||
cellStyle, styleProps;
|
||||
|
||||
var cellWrapper = {
|
||||
modules:{},
|
||||
getValue:function(){
|
||||
return value;
|
||||
},
|
||||
getField:function(){
|
||||
return column.definition.field;
|
||||
},
|
||||
getElement:function(){
|
||||
return cellEl;
|
||||
},
|
||||
getType:function(){
|
||||
return "cell";
|
||||
},
|
||||
getColumn:function(){
|
||||
return column.getComponent();
|
||||
},
|
||||
getData:function(){
|
||||
return row.component.getData();
|
||||
},
|
||||
getRow:function(){
|
||||
return row.component;
|
||||
},
|
||||
getTable:function(){
|
||||
return table;
|
||||
},
|
||||
getComponent:function(){
|
||||
return cellWrapper;
|
||||
},
|
||||
column:column,
|
||||
};
|
||||
|
||||
var classNames = column.definition.cssClass ? column.definition.cssClass.split(" ") : [];
|
||||
|
||||
classNames.forEach(function(className) {
|
||||
cellEl.classList.add(className);
|
||||
});
|
||||
|
||||
if(this.table.modExists("format") && this.config.formatCells !== false){
|
||||
value = this.table.modules.format.formatExportValue(cellWrapper, this.colVisProp);
|
||||
}else{
|
||||
switch(typeof value){
|
||||
case "object":
|
||||
value = value !== null ? JSON.stringify(value) : "";
|
||||
break;
|
||||
|
||||
case "undefined":
|
||||
value = "";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(value instanceof Node){
|
||||
cellEl.appendChild(value);
|
||||
}else{
|
||||
cellEl.innerHTML = value;
|
||||
}
|
||||
|
||||
styleProps = ["padding-top", "padding-left", "padding-right", "padding-bottom", "border-top", "border-left", "border-right", "border-bottom", "color", "font-weight", "font-family", "font-size", "text-align"];
|
||||
|
||||
if(column.isRowHeader){
|
||||
cellStyle = styles.styleRowHeader;
|
||||
styleProps.push("background-color");
|
||||
}else{
|
||||
cellStyle = styles.styleCells && styles.styleCells[index] ? styles.styleCells[index] : styles.firstCell;
|
||||
}
|
||||
|
||||
if(cellStyle){
|
||||
this.mapElementStyles(cellStyle, cellEl, styleProps);
|
||||
|
||||
if(column.definition.align){
|
||||
cellEl.style.textAlign = column.definition.align;
|
||||
}
|
||||
}
|
||||
|
||||
if(this.table.options.dataTree && this.config.dataTree !== false){
|
||||
if((setup.treeElementField && setup.treeElementField == column.field) || (!setup.treeElementField && i == 0)){
|
||||
if(row.component._row.modules.dataTree.controlEl){
|
||||
cellEl.insertBefore(row.component._row.modules.dataTree.controlEl.cloneNode(true), cellEl.firstChild);
|
||||
}
|
||||
if(row.component._row.modules.dataTree.branchEl){
|
||||
cellEl.insertBefore(row.component._row.modules.dataTree.branchEl.cloneNode(true), cellEl.firstChild);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rowEl.appendChild(cellEl);
|
||||
|
||||
if(cellWrapper.modules.format && cellWrapper.modules.format.renderedCallback){
|
||||
cellWrapper.modules.format.renderedCallback();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if(setup.rowFormatter && row.type === "row" && this.config.formatCells !== false){
|
||||
let formatComponent = Object.assign(row.component);
|
||||
|
||||
formatComponent.getElement = function(){return rowEl;};
|
||||
|
||||
setup.rowFormatter(row.component);
|
||||
}
|
||||
|
||||
return rowEl;
|
||||
}
|
||||
|
||||
generateHTMLTable(list){
|
||||
var holder = document.createElement("div");
|
||||
|
||||
holder.appendChild(this.generateTableElement(list));
|
||||
|
||||
return holder.innerHTML;
|
||||
}
|
||||
|
||||
getHtml(visible, style, config, colVisProp){
|
||||
var list = this.generateExportList(config || this.table.options.htmlOutputConfig, style, visible, colVisProp || "htmlOutput");
|
||||
|
||||
return this.generateHTMLTable(list);
|
||||
}
|
||||
|
||||
mapElementStyles(from, to, props){
|
||||
if(this.cloneTableStyle && from && to){
|
||||
|
||||
var lookup = {
|
||||
"background-color" : "backgroundColor",
|
||||
"color" : "fontColor",
|
||||
"width" : "width",
|
||||
"font-weight" : "fontWeight",
|
||||
"font-family" : "fontFamily",
|
||||
"font-size" : "fontSize",
|
||||
"text-align" : "textAlign",
|
||||
"border-top" : "borderTop",
|
||||
"border-left" : "borderLeft",
|
||||
"border-right" : "borderRight",
|
||||
"border-bottom" : "borderBottom",
|
||||
"padding-top" : "paddingTop",
|
||||
"padding-left" : "paddingLeft",
|
||||
"padding-right" : "paddingRight",
|
||||
"padding-bottom" : "paddingBottom",
|
||||
};
|
||||
|
||||
if(window.getComputedStyle){
|
||||
var fromStyle = window.getComputedStyle(from);
|
||||
|
||||
props.forEach(function(prop){
|
||||
if(!to.style[lookup[prop]]){
|
||||
to.style[lookup[prop]] = fromStyle.getPropertyValue(prop);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
export default class ExportColumn{
|
||||
constructor(value, component, width, height, depth){
|
||||
this.value = value;
|
||||
this.component = component || false;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.depth = depth;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
export default class ExportRow{
|
||||
constructor(type, columns, component, indent){
|
||||
this.type = type;
|
||||
this.columns = columns;
|
||||
this.component = component || false;
|
||||
this.indent = indent || 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
export default {
|
||||
|
||||
};
|
||||
@@ -0,0 +1,18 @@
|
||||
export default {
|
||||
visible:function(){
|
||||
return this.rowManager.getVisibleRows(false, true);
|
||||
},
|
||||
all:function(){
|
||||
return this.rowManager.rows;
|
||||
},
|
||||
selected:function(){
|
||||
return this.modules.selectRow.selectedRows;
|
||||
},
|
||||
active:function(){
|
||||
if(this.options.pagination){
|
||||
return this.rowManager.getDisplayRows(this.rowManager.displayRows.length - 2);
|
||||
}else{
|
||||
return this.rowManager.getDisplayRows();
|
||||
}
|
||||
},
|
||||
};
|
||||
902
public/libs/tabulator-master/src/js/modules/Filter/Filter.js
Normal file
902
public/libs/tabulator-master/src/js/modules/Filter/Filter.js
Normal file
@@ -0,0 +1,902 @@
|
||||
import Module from '../../core/Module.js';
|
||||
|
||||
import defaultFilters from './defaults/filters.js';
|
||||
|
||||
export default class Filter extends Module{
|
||||
|
||||
static moduleName = "filter";
|
||||
|
||||
//load defaults
|
||||
static filters = defaultFilters;
|
||||
|
||||
constructor(table){
|
||||
super(table);
|
||||
|
||||
this.filterList = []; //hold filter list
|
||||
this.headerFilters = {}; //hold column filters
|
||||
this.headerFilterColumns = []; //hold columns that use header filters
|
||||
|
||||
this.prevHeaderFilterChangeCheck = "";
|
||||
this.prevHeaderFilterChangeCheck = "{}";
|
||||
|
||||
this.changed = false; //has filtering changed since last render
|
||||
this.tableInitialized = false;
|
||||
|
||||
this.registerTableOption("filterMode", "local"); //local or remote filtering
|
||||
|
||||
this.registerTableOption("initialFilter", false); //initial filtering criteria
|
||||
this.registerTableOption("initialHeaderFilter", false); //initial header filtering criteria
|
||||
this.registerTableOption("headerFilterLiveFilterDelay", 300); //delay before updating column after user types in header filter
|
||||
this.registerTableOption("placeholderHeaderFilter", false); //placeholder when header filter is empty
|
||||
|
||||
this.registerColumnOption("headerFilter");
|
||||
this.registerColumnOption("headerFilterPlaceholder");
|
||||
this.registerColumnOption("headerFilterParams");
|
||||
this.registerColumnOption("headerFilterEmptyCheck");
|
||||
this.registerColumnOption("headerFilterFunc");
|
||||
this.registerColumnOption("headerFilterFuncParams");
|
||||
this.registerColumnOption("headerFilterLiveFilter");
|
||||
|
||||
this.registerTableFunction("searchRows", this.searchRows.bind(this));
|
||||
this.registerTableFunction("searchData", this.searchData.bind(this));
|
||||
|
||||
this.registerTableFunction("setFilter", this.userSetFilter.bind(this));
|
||||
this.registerTableFunction("refreshFilter", this.userRefreshFilter.bind(this));
|
||||
this.registerTableFunction("addFilter", this.userAddFilter.bind(this));
|
||||
this.registerTableFunction("getFilters", this.getFilters.bind(this));
|
||||
this.registerTableFunction("setHeaderFilterFocus", this.userSetHeaderFilterFocus.bind(this));
|
||||
this.registerTableFunction("getHeaderFilterValue", this.userGetHeaderFilterValue.bind(this));
|
||||
this.registerTableFunction("setHeaderFilterValue", this.userSetHeaderFilterValue.bind(this));
|
||||
this.registerTableFunction("getHeaderFilters", this.getHeaderFilters.bind(this));
|
||||
this.registerTableFunction("removeFilter", this.userRemoveFilter.bind(this));
|
||||
this.registerTableFunction("clearFilter", this.userClearFilter.bind(this));
|
||||
this.registerTableFunction("clearHeaderFilter", this.userClearHeaderFilter.bind(this));
|
||||
|
||||
this.registerComponentFunction("column", "headerFilterFocus", this.setHeaderFilterFocus.bind(this));
|
||||
this.registerComponentFunction("column", "reloadHeaderFilter", this.reloadHeaderFilter.bind(this));
|
||||
this.registerComponentFunction("column", "getHeaderFilterValue", this.getHeaderFilterValue.bind(this));
|
||||
this.registerComponentFunction("column", "setHeaderFilterValue", this.setHeaderFilterValue.bind(this));
|
||||
}
|
||||
|
||||
initialize(){
|
||||
this.subscribe("column-init", this.initializeColumnHeaderFilter.bind(this));
|
||||
this.subscribe("column-width-fit-before", this.hideHeaderFilterElements.bind(this));
|
||||
this.subscribe("column-width-fit-after", this.showHeaderFilterElements.bind(this));
|
||||
this.subscribe("table-built", this.tableBuilt.bind(this));
|
||||
this.subscribe("placeholder", this.generatePlaceholder.bind(this));
|
||||
|
||||
if(this.table.options.filterMode === "remote"){
|
||||
this.subscribe("data-params", this.remoteFilterParams.bind(this));
|
||||
}
|
||||
|
||||
this.registerDataHandler(this.filter.bind(this), 10);
|
||||
}
|
||||
|
||||
tableBuilt(){
|
||||
if(this.table.options.initialFilter){
|
||||
this.setFilter(this.table.options.initialFilter);
|
||||
}
|
||||
|
||||
if(this.table.options.initialHeaderFilter){
|
||||
this.table.options.initialHeaderFilter.forEach((item) => {
|
||||
|
||||
var column = this.table.columnManager.findColumn(item.field);
|
||||
|
||||
if(column){
|
||||
this.setHeaderFilterValue(column, item.value);
|
||||
}else{
|
||||
console.warn("Column Filter Error - No matching column found:", item.field);
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
this.tableInitialized = true;
|
||||
}
|
||||
|
||||
remoteFilterParams(data, config, silent, params){
|
||||
params.filter = this.getFilters(true, true);
|
||||
return params;
|
||||
}
|
||||
|
||||
generatePlaceholder(text){
|
||||
if(this.table.options.placeholderHeaderFilter && Object.keys(this.headerFilters).length){
|
||||
return this.table.options.placeholderHeaderFilter;
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////
|
||||
///////// Table Functions /////////
|
||||
///////////////////////////////////
|
||||
|
||||
//set standard filters
|
||||
userSetFilter(field, type, value, params){
|
||||
this.setFilter(field, type, value, params);
|
||||
this.refreshFilter();
|
||||
}
|
||||
|
||||
//set standard filters
|
||||
userRefreshFilter(){
|
||||
this.refreshFilter();
|
||||
}
|
||||
|
||||
//add filter to array
|
||||
userAddFilter(field, type, value, params){
|
||||
this.addFilter(field, type, value, params);
|
||||
this.refreshFilter();
|
||||
}
|
||||
|
||||
userSetHeaderFilterFocus(field){
|
||||
var column = this.table.columnManager.findColumn(field);
|
||||
|
||||
if(column){
|
||||
this.setHeaderFilterFocus(column);
|
||||
}else{
|
||||
console.warn("Column Filter Focus Error - No matching column found:", field);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
userGetHeaderFilterValue(field) {
|
||||
var column = this.table.columnManager.findColumn(field);
|
||||
|
||||
if(column){
|
||||
return this.getHeaderFilterValue(column);
|
||||
}else{
|
||||
console.warn("Column Filter Error - No matching column found:", field);
|
||||
}
|
||||
}
|
||||
|
||||
userSetHeaderFilterValue(field, value){
|
||||
var column = this.table.columnManager.findColumn(field);
|
||||
|
||||
if(column){
|
||||
this.setHeaderFilterValue(column, value);
|
||||
}else{
|
||||
console.warn("Column Filter Error - No matching column found:", field);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//remove filter from array
|
||||
userRemoveFilter(field, type, value){
|
||||
this.removeFilter(field, type, value);
|
||||
this.refreshFilter();
|
||||
}
|
||||
|
||||
//clear filters
|
||||
userClearFilter(all){
|
||||
this.clearFilter(all);
|
||||
this.refreshFilter();
|
||||
}
|
||||
|
||||
//clear header filters
|
||||
userClearHeaderFilter(){
|
||||
this.clearHeaderFilter();
|
||||
this.refreshFilter();
|
||||
}
|
||||
|
||||
|
||||
//search for specific row components
|
||||
searchRows(field, type, value){
|
||||
return this.search("rows", field, type, value);
|
||||
}
|
||||
|
||||
//search for specific data
|
||||
searchData(field, type, value){
|
||||
return this.search("data", field, type, value);
|
||||
}
|
||||
|
||||
///////////////////////////////////
|
||||
///////// Internal Logic //////////
|
||||
///////////////////////////////////
|
||||
|
||||
initializeColumnHeaderFilter(column){
|
||||
var def = column.definition;
|
||||
|
||||
if(def.headerFilter){
|
||||
this.initializeColumn(column);
|
||||
}
|
||||
}
|
||||
|
||||
//initialize column header filter
|
||||
initializeColumn(column, value){
|
||||
var self = this,
|
||||
field = column.getField();
|
||||
|
||||
//handle successfully value change
|
||||
function success(value){
|
||||
var filterType = (column.modules.filter.tagType == "input" && column.modules.filter.attrType == "text") || column.modules.filter.tagType == "textarea" ? "partial" : "match",
|
||||
type = "",
|
||||
filterChangeCheck = "",
|
||||
filterFunc;
|
||||
|
||||
if(typeof column.modules.filter.prevSuccess === "undefined" || column.modules.filter.prevSuccess !== value){
|
||||
|
||||
column.modules.filter.prevSuccess = value;
|
||||
|
||||
if(!column.modules.filter.emptyFunc(value)){
|
||||
column.modules.filter.value = value;
|
||||
|
||||
switch(typeof column.definition.headerFilterFunc){
|
||||
case "string":
|
||||
if(Filter.filters[column.definition.headerFilterFunc]){
|
||||
type = column.definition.headerFilterFunc;
|
||||
filterFunc = function(data){
|
||||
var params = column.definition.headerFilterFuncParams || {};
|
||||
var fieldVal = column.getFieldValue(data);
|
||||
|
||||
params = typeof params === "function" ? params(value, fieldVal, data) : params;
|
||||
|
||||
return Filter.filters[column.definition.headerFilterFunc](value, fieldVal, data, params);
|
||||
};
|
||||
}else{
|
||||
console.warn("Header Filter Error - Matching filter function not found: ", column.definition.headerFilterFunc);
|
||||
}
|
||||
break;
|
||||
|
||||
case "function":
|
||||
filterFunc = function(data){
|
||||
var params = column.definition.headerFilterFuncParams || {};
|
||||
var fieldVal = column.getFieldValue(data);
|
||||
|
||||
params = typeof params === "function" ? params(value, fieldVal, data) : params;
|
||||
|
||||
return column.definition.headerFilterFunc(value, fieldVal, data, params);
|
||||
};
|
||||
|
||||
type = filterFunc;
|
||||
break;
|
||||
}
|
||||
|
||||
if(!filterFunc){
|
||||
switch(filterType){
|
||||
case "partial":
|
||||
filterFunc = function(data){
|
||||
var colVal = column.getFieldValue(data);
|
||||
|
||||
if(typeof colVal !== 'undefined' && colVal !== null){
|
||||
return String(colVal).toLowerCase().indexOf(String(value).toLowerCase()) > -1;
|
||||
}else{
|
||||
return false;
|
||||
}
|
||||
};
|
||||
type = "like";
|
||||
break;
|
||||
|
||||
default:
|
||||
filterFunc = function(data){
|
||||
return column.getFieldValue(data) == value;
|
||||
};
|
||||
type = "=";
|
||||
}
|
||||
}
|
||||
|
||||
self.headerFilters[field] = {value:value, func:filterFunc, type:type};
|
||||
}else{
|
||||
delete self.headerFilters[field];
|
||||
}
|
||||
|
||||
column.modules.filter.value = value;
|
||||
|
||||
filterChangeCheck = JSON.stringify(self.headerFilters);
|
||||
|
||||
if(self.prevHeaderFilterChangeCheck !== filterChangeCheck){
|
||||
self.prevHeaderFilterChangeCheck = filterChangeCheck;
|
||||
|
||||
self.trackChanges();
|
||||
self.refreshFilter();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
column.modules.filter = {
|
||||
success:success,
|
||||
attrType:false,
|
||||
tagType:false,
|
||||
emptyFunc:false,
|
||||
};
|
||||
|
||||
this.generateHeaderFilterElement(column);
|
||||
}
|
||||
|
||||
generateHeaderFilterElement(column, initialValue, reinitialize){
|
||||
var self = this,
|
||||
success = column.modules.filter.success,
|
||||
field = column.getField(),
|
||||
filterElement, editor, editorElement, cellWrapper, typingTimer, searchTrigger, params, onRenderedCallback;
|
||||
|
||||
column.modules.filter.value = initialValue;
|
||||
|
||||
//handle aborted edit
|
||||
function cancel(){}
|
||||
|
||||
function onRendered(callback){
|
||||
onRenderedCallback = callback;
|
||||
}
|
||||
|
||||
if(column.modules.filter.headerElement && column.modules.filter.headerElement.parentNode){
|
||||
column.contentElement.removeChild(column.modules.filter.headerElement.parentNode);
|
||||
}
|
||||
|
||||
if(field){
|
||||
|
||||
//set empty value function
|
||||
column.modules.filter.emptyFunc = column.definition.headerFilterEmptyCheck || function(value){
|
||||
return !value && value !== 0;
|
||||
};
|
||||
|
||||
filterElement = document.createElement("div");
|
||||
filterElement.classList.add("tabulator-header-filter");
|
||||
|
||||
//set column editor
|
||||
switch(typeof column.definition.headerFilter){
|
||||
case "string":
|
||||
if(self.table.modules.edit.editors[column.definition.headerFilter]){
|
||||
editor = self.table.modules.edit.editors[column.definition.headerFilter];
|
||||
|
||||
if((column.definition.headerFilter === "tick" || column.definition.headerFilter === "tickCross") && !column.definition.headerFilterEmptyCheck){
|
||||
column.modules.filter.emptyFunc = function(value){
|
||||
return value !== true && value !== false;
|
||||
};
|
||||
}
|
||||
}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.modules.edit && column.modules.edit.editor){
|
||||
editor = column.modules.edit.editor;
|
||||
}else{
|
||||
if(column.definition.formatter && self.table.modules.edit.editors[column.definition.formatter]){
|
||||
editor = self.table.modules.edit.editors[column.definition.formatter];
|
||||
|
||||
if((column.definition.formatter === "tick" || column.definition.formatter === "tickCross") && !column.definition.headerFilterEmptyCheck){
|
||||
column.modules.filter.emptyFunc = function(value){
|
||||
return value !== true && value !== false;
|
||||
};
|
||||
}
|
||||
}else{
|
||||
editor = self.table.modules.edit.editors["input"];
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if(editor){
|
||||
|
||||
cellWrapper = {
|
||||
getValue:function(){
|
||||
return typeof initialValue !== "undefined" ? initialValue : "";
|
||||
},
|
||||
getField:function(){
|
||||
return column.definition.field;
|
||||
},
|
||||
getElement:function(){
|
||||
return filterElement;
|
||||
},
|
||||
getColumn:function(){
|
||||
return column.getComponent();
|
||||
},
|
||||
getTable:() => {
|
||||
return this.table;
|
||||
},
|
||||
getType:() => {
|
||||
return "header";
|
||||
},
|
||||
getRow:function(){
|
||||
return {
|
||||
normalizeHeight:function(){
|
||||
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
params = column.definition.headerFilterParams || {};
|
||||
|
||||
params = typeof params === "function" ? params.call(self.table, cellWrapper) : params;
|
||||
|
||||
editorElement = editor.call(this.table.modules.edit, cellWrapper, onRendered, success, cancel, params);
|
||||
|
||||
if(!editorElement){
|
||||
console.warn("Filter Error - Cannot add filter to " + field + " column, editor returned a value of false");
|
||||
return;
|
||||
}
|
||||
|
||||
if(!(editorElement instanceof Node)){
|
||||
console.warn("Filter Error - Cannot add filter to " + field + " column, editor should return an instance of Node, the editor returned:", editorElement);
|
||||
return;
|
||||
}
|
||||
|
||||
//set Placeholder Text
|
||||
self.langBind("headerFilters|columns|" + column.definition.field, function(value){
|
||||
editorElement.setAttribute("placeholder", typeof value !== "undefined" && value ? value : (column.definition.headerFilterPlaceholder || self.langText("headerFilters|default")));
|
||||
});
|
||||
|
||||
//focus on element on click
|
||||
editorElement.addEventListener("click", function(e){
|
||||
e.stopPropagation();
|
||||
editorElement.focus();
|
||||
});
|
||||
|
||||
editorElement.addEventListener("focus", (e) => {
|
||||
var left = this.table.columnManager.contentsElement.scrollLeft;
|
||||
|
||||
var headerPos = this.table.rowManager.element.scrollLeft;
|
||||
|
||||
if(left !== headerPos){
|
||||
this.table.rowManager.scrollHorizontal(left);
|
||||
this.table.columnManager.scrollHorizontal(left);
|
||||
}
|
||||
});
|
||||
|
||||
//live update filters as user types
|
||||
typingTimer = false;
|
||||
|
||||
searchTrigger = function(e){
|
||||
if(typingTimer){
|
||||
clearTimeout(typingTimer);
|
||||
}
|
||||
|
||||
typingTimer = setTimeout(function(){
|
||||
success(editorElement.value);
|
||||
},self.table.options.headerFilterLiveFilterDelay);
|
||||
};
|
||||
|
||||
column.modules.filter.headerElement = editorElement;
|
||||
column.modules.filter.attrType = editorElement.hasAttribute("type") ? editorElement.getAttribute("type").toLowerCase() : "" ;
|
||||
column.modules.filter.tagType = editorElement.tagName.toLowerCase();
|
||||
|
||||
if(column.definition.headerFilterLiveFilter !== false){
|
||||
|
||||
if (
|
||||
!(
|
||||
column.definition.headerFilter === 'autocomplete' ||
|
||||
column.definition.headerFilter === 'tickCross' ||
|
||||
((column.definition.editor === 'autocomplete' ||
|
||||
column.definition.editor === 'tickCross') &&
|
||||
column.definition.headerFilter === true)
|
||||
)
|
||||
) {
|
||||
editorElement.addEventListener("keyup", searchTrigger);
|
||||
editorElement.addEventListener("search", searchTrigger);
|
||||
|
||||
|
||||
//update number filtered columns on change
|
||||
if(column.modules.filter.attrType == "number"){
|
||||
editorElement.addEventListener("change", function(e){
|
||||
success(editorElement.value);
|
||||
});
|
||||
}
|
||||
|
||||
//change text inputs to search inputs to allow for clearing of field
|
||||
if(column.modules.filter.attrType == "text" && this.table.browser !== "ie"){
|
||||
editorElement.setAttribute("type", "search");
|
||||
// editorElement.off("change blur"); //prevent blur from triggering filter and preventing selection click
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//prevent input and select elements from propagating click to column sorters etc
|
||||
if(column.modules.filter.tagType == "input" || column.modules.filter.tagType == "select" || column.modules.filter.tagType == "textarea"){
|
||||
editorElement.addEventListener("mousedown",function(e){
|
||||
e.stopPropagation();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
filterElement.appendChild(editorElement);
|
||||
|
||||
column.contentElement.appendChild(filterElement);
|
||||
|
||||
if(!reinitialize){
|
||||
self.headerFilterColumns.push(column);
|
||||
}
|
||||
|
||||
if(onRenderedCallback){
|
||||
onRenderedCallback();
|
||||
}
|
||||
}
|
||||
}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)
|
||||
hideHeaderFilterElements(){
|
||||
this.headerFilterColumns.forEach(function(column){
|
||||
if(column.modules.filter && column.modules.filter.headerElement){
|
||||
column.modules.filter.headerElement.style.display = 'none';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//show all header filter elements (used to ensure correct column widths in "fitData" layout mode)
|
||||
showHeaderFilterElements(){
|
||||
this.headerFilterColumns.forEach(function(column){
|
||||
if(column.modules.filter && column.modules.filter.headerElement){
|
||||
column.modules.filter.headerElement.style.display = '';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//programmatically set focus of header filter
|
||||
setHeaderFilterFocus(column){
|
||||
if(column.modules.filter && column.modules.filter.headerElement){
|
||||
column.modules.filter.headerElement.focus();
|
||||
}else{
|
||||
console.warn("Column Filter Focus Error - No header filter set on column:", column.getField());
|
||||
}
|
||||
}
|
||||
|
||||
//programmatically get value of header filter
|
||||
getHeaderFilterValue(column){
|
||||
if(column.modules.filter && column.modules.filter.headerElement){
|
||||
return column.modules.filter.value;
|
||||
} else {
|
||||
console.warn("Column Filter Error - No header filter set on column:", column.getField());
|
||||
}
|
||||
}
|
||||
|
||||
//programmatically set value of header filter
|
||||
setHeaderFilterValue(column, value){
|
||||
if (column){
|
||||
if(column.modules.filter && column.modules.filter.headerElement){
|
||||
this.generateHeaderFilterElement(column, value, true);
|
||||
column.modules.filter.success(value);
|
||||
}else{
|
||||
console.warn("Column Filter Error - No header filter set on column:", column.getField());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
reloadHeaderFilter(column){
|
||||
if (column){
|
||||
if(column.modules.filter && column.modules.filter.headerElement){
|
||||
this.generateHeaderFilterElement(column, column.modules.filter.value, true);
|
||||
}else{
|
||||
console.warn("Column Filter Error - No header filter set on column:", column.getField());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
refreshFilter(){
|
||||
if(this.tableInitialized){
|
||||
if(this.table.options.filterMode === "remote"){
|
||||
this.reloadData(null, false, false);
|
||||
}else{
|
||||
this.refreshData(true);
|
||||
}
|
||||
}
|
||||
|
||||
//TODO - Persist left position of row manager
|
||||
// left = this.scrollLeft;
|
||||
// this.scrollHorizontal(left);
|
||||
}
|
||||
|
||||
//check if the filters has changed since last use
|
||||
trackChanges(){
|
||||
this.changed = true;
|
||||
this.dispatch("filter-changed");
|
||||
}
|
||||
|
||||
//check if the filters has changed since last use
|
||||
hasChanged(){
|
||||
var changed = this.changed;
|
||||
this.changed = false;
|
||||
return changed;
|
||||
}
|
||||
|
||||
//set standard filters
|
||||
setFilter(field, type, value, params){
|
||||
this.filterList = [];
|
||||
|
||||
if(!Array.isArray(field)){
|
||||
field = [{field:field, type:type, value:value, params:params}];
|
||||
}
|
||||
|
||||
this.addFilter(field);
|
||||
}
|
||||
|
||||
//add filter to array
|
||||
addFilter(field, type, value, params){
|
||||
var changed = false;
|
||||
|
||||
if(!Array.isArray(field)){
|
||||
field = [{field:field, type:type, value:value, params:params}];
|
||||
}
|
||||
|
||||
field.forEach((filter) => {
|
||||
filter = this.findFilter(filter);
|
||||
|
||||
if(filter){
|
||||
this.filterList.push(filter);
|
||||
changed = true;
|
||||
}
|
||||
});
|
||||
|
||||
if(changed){
|
||||
this.trackChanges();
|
||||
}
|
||||
}
|
||||
|
||||
findFilter(filter){
|
||||
var column;
|
||||
|
||||
if(Array.isArray(filter)){
|
||||
return this.findSubFilters(filter);
|
||||
}
|
||||
|
||||
var filterFunc = false;
|
||||
|
||||
if(typeof filter.field == "function"){
|
||||
filterFunc = function(data){
|
||||
return filter.field(data, filter.type || {});// pass params to custom filter function
|
||||
};
|
||||
}else{
|
||||
|
||||
if(Filter.filters[filter.type]){
|
||||
|
||||
column = this.table.columnManager.getColumnByField(filter.field);
|
||||
|
||||
if(column){
|
||||
filterFunc = function(data){
|
||||
return Filter.filters[filter.type](filter.value, column.getFieldValue(data), data, filter.params || {});
|
||||
};
|
||||
}else{
|
||||
filterFunc = function(data){
|
||||
return Filter.filters[filter.type](filter.value, data[filter.field], data, filter.params || {});
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
}else{
|
||||
console.warn("Filter Error - No such filter type found, ignoring: ", filter.type);
|
||||
}
|
||||
}
|
||||
|
||||
filter.func = filterFunc;
|
||||
|
||||
return filter.func ? filter : false;
|
||||
}
|
||||
|
||||
findSubFilters(filters){
|
||||
var output = [];
|
||||
|
||||
filters.forEach((filter) => {
|
||||
filter = this.findFilter(filter);
|
||||
|
||||
if(filter){
|
||||
output.push(filter);
|
||||
}
|
||||
});
|
||||
|
||||
return output.length ? output : false;
|
||||
}
|
||||
|
||||
//get all filters
|
||||
getFilters(all, ajax){
|
||||
var output = [];
|
||||
|
||||
if(all){
|
||||
output = this.getHeaderFilters();
|
||||
}
|
||||
|
||||
if(ajax){
|
||||
output.forEach(function(item){
|
||||
if(typeof item.type == "function"){
|
||||
item.type = "function";
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
output = output.concat(this.filtersToArray(this.filterList, ajax));
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
//filter to Object
|
||||
filtersToArray(filterList, ajax){
|
||||
var output = [];
|
||||
|
||||
filterList.forEach((filter) => {
|
||||
var item;
|
||||
|
||||
if(Array.isArray(filter)){
|
||||
output.push(this.filtersToArray(filter, ajax));
|
||||
}else{
|
||||
item = {field:filter.field, type:filter.type, value:filter.value};
|
||||
|
||||
if(ajax){
|
||||
if(typeof item.type == "function"){
|
||||
item.type = "function";
|
||||
}
|
||||
}
|
||||
|
||||
output.push(item);
|
||||
}
|
||||
});
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
//get all filters
|
||||
getHeaderFilters(){
|
||||
var 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
|
||||
removeFilter(field, type, value){
|
||||
if(!Array.isArray(field)){
|
||||
field = [{field:field, type:type, value:value}];
|
||||
}
|
||||
|
||||
field.forEach((filter) => {
|
||||
var index = -1;
|
||||
|
||||
if(typeof filter.field == "object"){
|
||||
index = this.filterList.findIndex((element) => {
|
||||
return filter === element;
|
||||
});
|
||||
}else{
|
||||
index = this.filterList.findIndex((element) => {
|
||||
return filter.field === element.field && filter.type === element.type && filter.value === element.value;
|
||||
});
|
||||
}
|
||||
|
||||
if(index > -1){
|
||||
this.filterList.splice(index, 1);
|
||||
}else{
|
||||
console.warn("Filter Error - No matching filter type found, ignoring: ", filter.type);
|
||||
}
|
||||
});
|
||||
|
||||
this.trackChanges();
|
||||
}
|
||||
|
||||
//clear filters
|
||||
clearFilter(all){
|
||||
this.filterList = [];
|
||||
|
||||
if(all){
|
||||
this.clearHeaderFilter();
|
||||
}
|
||||
|
||||
this.trackChanges();
|
||||
}
|
||||
|
||||
//clear header filters
|
||||
clearHeaderFilter(){
|
||||
this.headerFilters = {};
|
||||
this.prevHeaderFilterChangeCheck = "{}";
|
||||
|
||||
this.headerFilterColumns.forEach((column) => {
|
||||
if(typeof column.modules.filter.value !== "undefined"){
|
||||
delete column.modules.filter.value;
|
||||
}
|
||||
column.modules.filter.prevSuccess = undefined;
|
||||
this.reloadHeaderFilter(column);
|
||||
});
|
||||
|
||||
this.trackChanges();
|
||||
}
|
||||
|
||||
//search data and return matching rows
|
||||
search (searchType, field, type, value){
|
||||
var activeRows = [],
|
||||
filterList = [];
|
||||
|
||||
if(!Array.isArray(field)){
|
||||
field = [{field:field, type:type, value:value}];
|
||||
}
|
||||
|
||||
field.forEach((filter) => {
|
||||
filter = this.findFilter(filter);
|
||||
|
||||
if(filter){
|
||||
filterList.push(filter);
|
||||
}
|
||||
});
|
||||
|
||||
this.table.rowManager.rows.forEach((row) => {
|
||||
var match = true;
|
||||
|
||||
filterList.forEach((filter) => {
|
||||
if(!this.filterRecurse(filter, row.getData())){
|
||||
match = false;
|
||||
}
|
||||
});
|
||||
|
||||
if(match){
|
||||
activeRows.push(searchType === "data" ? row.getData("data") : row.getComponent());
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
return activeRows;
|
||||
}
|
||||
|
||||
//filter row array
|
||||
filter(rowList, filters){
|
||||
var activeRows = [],
|
||||
activeRowComponents = [];
|
||||
|
||||
if(this.subscribedExternal("dataFiltering")){
|
||||
this.dispatchExternal("dataFiltering", this.getFilters(true));
|
||||
}
|
||||
|
||||
if(this.table.options.filterMode !== "remote" && (this.filterList.length || Object.keys(this.headerFilters).length)){
|
||||
|
||||
rowList.forEach((row) => {
|
||||
if(this.filterRow(row)){
|
||||
activeRows.push(row);
|
||||
}
|
||||
});
|
||||
|
||||
}else{
|
||||
activeRows = rowList.slice(0);
|
||||
}
|
||||
|
||||
if(this.subscribedExternal("dataFiltered")){
|
||||
|
||||
activeRows.forEach((row) => {
|
||||
activeRowComponents.push(row.getComponent());
|
||||
});
|
||||
|
||||
this.dispatchExternal("dataFiltered", this.getFilters(true), activeRowComponents);
|
||||
}
|
||||
|
||||
return activeRows;
|
||||
}
|
||||
|
||||
//filter individual row
|
||||
filterRow(row, filters){
|
||||
var match = true,
|
||||
data = row.getData();
|
||||
|
||||
this.filterList.forEach((filter) => {
|
||||
if(!this.filterRecurse(filter, data)){
|
||||
match = false;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
for(var field in this.headerFilters){
|
||||
if(!this.headerFilters[field].func(data)){
|
||||
match = false;
|
||||
}
|
||||
}
|
||||
|
||||
return match;
|
||||
}
|
||||
|
||||
filterRecurse(filter, data){
|
||||
var match = false;
|
||||
|
||||
if(Array.isArray(filter)){
|
||||
filter.forEach((subFilter) => {
|
||||
if(this.filterRecurse(subFilter, data)){
|
||||
match = true;
|
||||
}
|
||||
});
|
||||
}else{
|
||||
match = filter.func(data);
|
||||
}
|
||||
|
||||
return match;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
export default {
|
||||
|
||||
//equal to
|
||||
"=":function(filterVal, rowVal, rowData, filterParams){
|
||||
return rowVal == filterVal ? true : false;
|
||||
},
|
||||
|
||||
//less than
|
||||
"<":function(filterVal, rowVal, rowData, filterParams){
|
||||
return rowVal < filterVal ? true : false;
|
||||
},
|
||||
|
||||
//less than or equal to
|
||||
"<=":function(filterVal, rowVal, rowData, filterParams){
|
||||
return rowVal <= filterVal ? true : false;
|
||||
},
|
||||
|
||||
//greater than
|
||||
">":function(filterVal, rowVal, rowData, filterParams){
|
||||
return rowVal > filterVal ? true : false;
|
||||
},
|
||||
|
||||
//greater than or equal to
|
||||
">=":function(filterVal, rowVal, rowData, filterParams){
|
||||
return rowVal >= filterVal ? true : false;
|
||||
},
|
||||
|
||||
//not equal to
|
||||
"!=":function(filterVal, rowVal, rowData, filterParams){
|
||||
return rowVal != filterVal ? true : false;
|
||||
},
|
||||
|
||||
"regex":function(filterVal, rowVal, rowData, filterParams){
|
||||
|
||||
if(typeof filterVal == "string"){
|
||||
filterVal = new RegExp(filterVal);
|
||||
}
|
||||
|
||||
return filterVal.test(rowVal);
|
||||
},
|
||||
|
||||
//contains the string
|
||||
"like":function(filterVal, rowVal, rowData, filterParams){
|
||||
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;
|
||||
}
|
||||
else{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
//contains the keywords
|
||||
"keywords":function(filterVal, rowVal, rowData, filterParams){
|
||||
var keywords = filterVal.toLowerCase().split(typeof filterParams.separator === "undefined" ? " " : filterParams.separator),
|
||||
value = String(rowVal === null || typeof rowVal === "undefined" ? "" : rowVal).toLowerCase(),
|
||||
matches = [];
|
||||
|
||||
keywords.forEach((keyword) =>{
|
||||
if(value.includes(keyword)){
|
||||
matches.push(true);
|
||||
}
|
||||
});
|
||||
|
||||
return filterParams.matchAll ? matches.length === keywords.length : !!matches.length;
|
||||
},
|
||||
|
||||
//starts with the string
|
||||
"starts":function(filterVal, rowVal, rowData, filterParams){
|
||||
if(filterVal === null || typeof filterVal === "undefined"){
|
||||
return rowVal === filterVal ? true : false;
|
||||
}else{
|
||||
if(typeof rowVal !== 'undefined' && rowVal !== null){
|
||||
return String(rowVal).toLowerCase().startsWith(filterVal.toLowerCase());
|
||||
}
|
||||
else{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
//ends with the string
|
||||
"ends":function(filterVal, rowVal, rowData, filterParams){
|
||||
if(filterVal === null || typeof filterVal === "undefined"){
|
||||
return rowVal === filterVal ? true : false;
|
||||
}else{
|
||||
if(typeof rowVal !== 'undefined' && rowVal !== null){
|
||||
return String(rowVal).toLowerCase().endsWith(filterVal.toLowerCase());
|
||||
}
|
||||
else{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
//in array
|
||||
"in":function(filterVal, rowVal, rowData, filterParams){
|
||||
if(Array.isArray(filterVal)){
|
||||
return filterVal.length ? filterVal.indexOf(rowVal) > -1 : true;
|
||||
}else{
|
||||
console.warn("Filter Error - filter value is not an array:", filterVal);
|
||||
return false;
|
||||
}
|
||||
},
|
||||
};
|
||||
200
public/libs/tabulator-master/src/js/modules/Format/Format.js
Normal file
200
public/libs/tabulator-master/src/js/modules/Format/Format.js
Normal file
@@ -0,0 +1,200 @@
|
||||
import Module from '../../core/Module.js';
|
||||
|
||||
import defaultFormatters from './defaults/formatters.js';
|
||||
|
||||
export default class Format extends Module{
|
||||
|
||||
static moduleName = "format";
|
||||
|
||||
//load defaults
|
||||
static formatters = defaultFormatters;
|
||||
|
||||
constructor(table){
|
||||
super(table);
|
||||
|
||||
this.registerColumnOption("formatter");
|
||||
this.registerColumnOption("formatterParams");
|
||||
|
||||
this.registerColumnOption("formatterPrint");
|
||||
this.registerColumnOption("formatterPrintParams");
|
||||
this.registerColumnOption("formatterClipboard");
|
||||
this.registerColumnOption("formatterClipboardParams");
|
||||
this.registerColumnOption("formatterHtmlOutput");
|
||||
this.registerColumnOption("formatterHtmlOutputParams");
|
||||
this.registerColumnOption("titleFormatter");
|
||||
this.registerColumnOption("titleFormatterParams");
|
||||
}
|
||||
|
||||
initialize(){
|
||||
this.subscribe("cell-format", this.formatValue.bind(this));
|
||||
this.subscribe("cell-rendered", this.cellRendered.bind(this));
|
||||
this.subscribe("column-layout", this.initializeColumn.bind(this));
|
||||
this.subscribe("column-format", this.formatHeader.bind(this));
|
||||
}
|
||||
|
||||
//initialize column formatter
|
||||
initializeColumn(column){
|
||||
column.modules.format = this.lookupTypeFormatter(column, "");
|
||||
|
||||
if(typeof column.definition.formatterPrint !== "undefined"){
|
||||
column.modules.format.print = this.lookupTypeFormatter(column, "Print");
|
||||
}
|
||||
|
||||
if(typeof column.definition.formatterClipboard !== "undefined"){
|
||||
column.modules.format.clipboard = this.lookupTypeFormatter(column, "Clipboard");
|
||||
}
|
||||
|
||||
if(typeof column.definition.formatterHtmlOutput !== "undefined"){
|
||||
column.modules.format.htmlOutput = this.lookupTypeFormatter(column, "HtmlOutput");
|
||||
}
|
||||
}
|
||||
|
||||
lookupTypeFormatter(column, type){
|
||||
var config = {params:column.definition["formatter" + type + "Params"] || {}},
|
||||
formatter = column.definition["formatter" + type];
|
||||
|
||||
config.formatter = this.lookupFormatter(formatter);
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
|
||||
lookupFormatter(formatter){
|
||||
var formatterFunc;
|
||||
|
||||
//set column formatter
|
||||
switch(typeof formatter){
|
||||
case "string":
|
||||
if(Format.formatters[formatter]){
|
||||
formatterFunc = Format.formatters[formatter];
|
||||
}else{
|
||||
console.warn("Formatter Error - No such formatter found: ", formatter);
|
||||
formatterFunc = Format.formatters.plaintext;
|
||||
}
|
||||
break;
|
||||
|
||||
case "function":
|
||||
formatterFunc = formatter;
|
||||
break;
|
||||
|
||||
default:
|
||||
formatterFunc = Format.formatters.plaintext;
|
||||
break;
|
||||
}
|
||||
|
||||
return formatterFunc;
|
||||
}
|
||||
|
||||
cellRendered(cell){
|
||||
if(cell.modules.format && cell.modules.format.renderedCallback && !cell.modules.format.rendered){
|
||||
cell.modules.format.renderedCallback();
|
||||
cell.modules.format.rendered = true;
|
||||
}
|
||||
}
|
||||
|
||||
//return a formatted value for a column header
|
||||
formatHeader(column, title, el){
|
||||
var formatter, params, onRendered, mockCell;
|
||||
|
||||
if(column.definition.titleFormatter){
|
||||
formatter = this.lookupFormatter(column.definition.titleFormatter);
|
||||
|
||||
onRendered = (callback) => {
|
||||
column.titleFormatterRendered = callback;
|
||||
};
|
||||
|
||||
mockCell = {
|
||||
getValue:function(){
|
||||
return title;
|
||||
},
|
||||
getElement:function(){
|
||||
return el;
|
||||
},
|
||||
getType:function(){
|
||||
return "header";
|
||||
},
|
||||
getColumn:function(){
|
||||
return column.getComponent();
|
||||
},
|
||||
getTable:() => {
|
||||
return this.table;
|
||||
}
|
||||
};
|
||||
|
||||
params = column.definition.titleFormatterParams || {};
|
||||
|
||||
params = typeof params === "function" ? params() : params;
|
||||
|
||||
return formatter.call(this, mockCell, params, onRendered);
|
||||
}else{
|
||||
return title;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//return a formatted value for a cell
|
||||
formatValue(cell){
|
||||
var component = cell.getComponent(),
|
||||
params = typeof cell.column.modules.format.params === "function" ? cell.column.modules.format.params(component) : cell.column.modules.format.params;
|
||||
|
||||
function onRendered(callback){
|
||||
if(!cell.modules.format){
|
||||
cell.modules.format = {};
|
||||
}
|
||||
|
||||
cell.modules.format.renderedCallback = callback;
|
||||
cell.modules.format.rendered = false;
|
||||
}
|
||||
|
||||
return cell.column.modules.format.formatter.call(this, component, params, onRendered);
|
||||
}
|
||||
|
||||
formatExportValue(cell, type){
|
||||
var formatter = cell.column.modules.format[type],
|
||||
params;
|
||||
|
||||
if(formatter){
|
||||
params = typeof formatter.params === "function" ? formatter.params(cell.getComponent()) : formatter.params;
|
||||
|
||||
function onRendered(callback){
|
||||
if(!cell.modules.format){
|
||||
cell.modules.format = {};
|
||||
}
|
||||
|
||||
cell.modules.format.renderedCallback = callback;
|
||||
cell.modules.format.rendered = false;
|
||||
}
|
||||
|
||||
return formatter.formatter.call(this, cell.getComponent(), params, onRendered);
|
||||
|
||||
}else{
|
||||
return this.formatValue(cell);
|
||||
}
|
||||
}
|
||||
|
||||
sanitizeHTML(value){
|
||||
if(value){
|
||||
var entityMap = {
|
||||
'&': '&',
|
||||
'<': '<',
|
||||
'>': '>',
|
||||
'"': '"',
|
||||
"'": ''',
|
||||
'/': '/',
|
||||
'`': '`',
|
||||
'=': '='
|
||||
};
|
||||
|
||||
return String(value).replace(/[&<>"'`=/]/g, function (s) {
|
||||
return entityMap[s];
|
||||
});
|
||||
}else{
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
emptyToSpace(value){
|
||||
return value === null || typeof value === "undefined" || value === "" ? " " : value;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
import plaintext from './formatters/plaintext.js';
|
||||
import html from './formatters/html.js';
|
||||
import textarea from './formatters/textarea.js';
|
||||
import money from './formatters/money.js';
|
||||
import link from './formatters/link.js';
|
||||
import image from './formatters/image.js';
|
||||
import tickCross from './formatters/tickCross.js';
|
||||
import datetime from './formatters/datetime.js';
|
||||
import datetimediff from './formatters/datetimediff.js';
|
||||
import lookup from './formatters/lookup.js';
|
||||
import star from './formatters/star.js';
|
||||
import traffic from './formatters/traffic.js';
|
||||
import progress from './formatters/progress.js';
|
||||
import color from './formatters/color.js';
|
||||
import buttonTick from './formatters/buttonTick.js';
|
||||
import buttonCross from './formatters/buttonCross.js';
|
||||
import toggle from './formatters/toggle.js';
|
||||
import rownum from './formatters/rownum.js';
|
||||
import handle from './formatters/handle.js';
|
||||
import adaptable from './formatters/adaptable.js';
|
||||
import array from './formatters/array.js';
|
||||
import json from './formatters/json.js';
|
||||
|
||||
export default {
|
||||
plaintext:plaintext,
|
||||
html:html,
|
||||
textarea:textarea,
|
||||
money:money,
|
||||
link:link,
|
||||
image:image,
|
||||
tickCross:tickCross,
|
||||
datetime:datetime,
|
||||
datetimediff:datetimediff,
|
||||
lookup:lookup,
|
||||
star:star,
|
||||
traffic:traffic,
|
||||
progress:progress,
|
||||
color:color,
|
||||
buttonTick:buttonTick,
|
||||
buttonCross:buttonCross,
|
||||
toggle:toggle,
|
||||
rownum:rownum,
|
||||
handle:handle,
|
||||
adaptable:adaptable,
|
||||
array:array,
|
||||
json:json,
|
||||
};
|
||||
@@ -0,0 +1,32 @@
|
||||
export default function(cell, params, onRendered){
|
||||
var lookup, formatterFunc, formatterParams;
|
||||
|
||||
function defaultLookup(cell){
|
||||
var value = cell.getValue(),
|
||||
formatter = "plaintext";
|
||||
|
||||
switch(typeof value){
|
||||
case "boolean":
|
||||
formatter = "tickCross";
|
||||
break;
|
||||
|
||||
case "string":
|
||||
if(value.includes("\n")){
|
||||
formatter = "textarea";
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return formatter;
|
||||
}
|
||||
|
||||
lookup = params.formatterLookup ? params.formatterLookup(cell) : defaultLookup(cell);
|
||||
|
||||
if(params.paramsLookup){
|
||||
formatterParams = typeof params.paramsLookup === "function" ? params.paramsLookup(lookup, cell) : params.paramsLookup[lookup];
|
||||
}
|
||||
|
||||
formatterFunc = this.table.modules.format.lookupFormatter(lookup);
|
||||
|
||||
return formatterFunc.call(this, cell, formatterParams || {}, onRendered);
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
import Helpers from '../../../../core/tools/Helpers.js';
|
||||
|
||||
export default function(cell, formatterParams, onRendered){
|
||||
var delimiter = formatterParams.delimiter || ",",
|
||||
value = cell.getValue(),
|
||||
table = this.table,
|
||||
valueMap;
|
||||
|
||||
if(formatterParams.valueMap){
|
||||
if(typeof formatterParams.valueMap === "string"){
|
||||
valueMap = function(value){
|
||||
return value.map((item) => {
|
||||
return Helpers.retrieveNestedData(table.options.nestedFieldSeparator, formatterParams.valueMap, item);
|
||||
});
|
||||
};
|
||||
}else{
|
||||
valueMap = formatterParams.valueMap;
|
||||
}
|
||||
}
|
||||
|
||||
if(Array.isArray(value)){
|
||||
if(valueMap){
|
||||
value = valueMap(value);
|
||||
}
|
||||
|
||||
return value.join(delimiter);
|
||||
}else{
|
||||
return value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
export default function(cell, formatterParams, onRendered){
|
||||
return '<svg enable-background="new 0 0 24 24" height="14" width="14" viewBox="0 0 24 24" xml:space="preserve" ><path fill="#CE1515" d="M22.245,4.015c0.313,0.313,0.313,0.826,0,1.139l-6.276,6.27c-0.313,0.312-0.313,0.826,0,1.14l6.273,6.272 c0.313,0.313,0.313,0.826,0,1.14l-2.285,2.277c-0.314,0.312-0.828,0.312-1.142,0l-6.271-6.271c-0.313-0.313-0.828-0.313-1.141,0 l-6.276,6.267c-0.313,0.313-0.828,0.313-1.141,0l-2.282-2.28c-0.313-0.313-0.313-0.826,0-1.14l6.278-6.269 c0.313-0.312,0.313-0.826,0-1.14L1.709,5.147c-0.314-0.313-0.314-0.827,0-1.14l2.284-2.278C4.308,1.417,4.821,1.417,5.135,1.73 L11.405,8c0.314,0.314,0.828,0.314,1.141,0.001l6.276-6.267c0.312-0.312,0.826-0.312,1.141,0L22.245,4.015z"/></svg>';
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
export default function(cell, formatterParams, onRendered){
|
||||
return '<svg enable-background="new 0 0 24 24" height="14" width="14" viewBox="0 0 24 24" xml:space="preserve" ><path fill="#2DC214" clip-rule="evenodd" d="M21.652,3.211c-0.293-0.295-0.77-0.295-1.061,0L9.41,14.34 c-0.293,0.297-0.771,0.297-1.062,0L3.449,9.351C3.304,9.203,3.114,9.13,2.923,9.129C2.73,9.128,2.534,9.201,2.387,9.351 l-2.165,1.946C0.078,11.445,0,11.63,0,11.823c0,0.194,0.078,0.397,0.223,0.544l4.94,5.184c0.292,0.296,0.771,0.776,1.062,1.07 l2.124,2.141c0.292,0.293,0.769,0.293,1.062,0l14.366-14.34c0.293-0.294,0.293-0.777,0-1.071L21.652,3.211z" fill-rule="evenodd"/></svg>';
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
export default function(cell, formatterParams, onRendered){
|
||||
cell.getElement().style.backgroundColor = this.sanitizeHTML(cell.getValue());
|
||||
return "";
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
export default function(cell, formatterParams, onRendered){
|
||||
var DT = this.table.dependencyRegistry.lookup(["luxon", "DateTime"], "DateTime");
|
||||
var inputFormat = formatterParams.inputFormat || "yyyy-MM-dd HH:mm:ss";
|
||||
var outputFormat = formatterParams.outputFormat || "dd/MM/yyyy HH:mm:ss";
|
||||
var invalid = typeof formatterParams.invalidPlaceholder !== "undefined" ? formatterParams.invalidPlaceholder : "";
|
||||
var value = cell.getValue();
|
||||
|
||||
if(typeof DT != "undefined"){
|
||||
var newDatetime;
|
||||
|
||||
if(DT.isDateTime(value)){
|
||||
newDatetime = value;
|
||||
}else if(inputFormat === "iso"){
|
||||
newDatetime = DT.fromISO(String(value));
|
||||
}else{
|
||||
newDatetime = DT.fromFormat(String(value), inputFormat);
|
||||
}
|
||||
|
||||
if(newDatetime.isValid){
|
||||
if(formatterParams.timezone){
|
||||
newDatetime = newDatetime.setZone(formatterParams.timezone);
|
||||
}
|
||||
|
||||
return newDatetime.toFormat(outputFormat);
|
||||
}else{
|
||||
if(invalid === true || !value){
|
||||
return value;
|
||||
}else if(typeof invalid === "function"){
|
||||
return invalid(value);
|
||||
}else{
|
||||
return invalid;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
console.error("Format Error - 'datetime' formatter is dependant on luxon.js");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
export default function (cell, formatterParams, onRendered) {
|
||||
var DT = this.table.dependencyRegistry.lookup(["luxon", "DateTime"], "DateTime");
|
||||
var inputFormat = formatterParams.inputFormat || "yyyy-MM-dd HH:mm:ss";
|
||||
var invalid = typeof formatterParams.invalidPlaceholder !== "undefined" ? formatterParams.invalidPlaceholder : "";
|
||||
var suffix = typeof formatterParams.suffix !== "undefined" ? formatterParams.suffix : false;
|
||||
var unit = typeof formatterParams.unit !== "undefined" ? formatterParams.unit : "days";
|
||||
var humanize = typeof formatterParams.humanize !== "undefined" ? formatterParams.humanize : false;
|
||||
var date = typeof formatterParams.date !== "undefined" ? formatterParams.date : DT.now();
|
||||
var value = cell.getValue();
|
||||
|
||||
if(typeof DT != "undefined"){
|
||||
var newDatetime;
|
||||
|
||||
if(DT.isDateTime(value)){
|
||||
newDatetime = value;
|
||||
}else if(inputFormat === "iso"){
|
||||
newDatetime = DT.fromISO(String(value));
|
||||
}else{
|
||||
newDatetime = DT.fromFormat(String(value), inputFormat);
|
||||
}
|
||||
|
||||
if (newDatetime.isValid){
|
||||
if(humanize){
|
||||
return newDatetime.diff(date, unit).toHuman() + (suffix ? " " + suffix : "");
|
||||
}else{
|
||||
return parseInt(newDatetime.diff(date, unit)[unit]) + (suffix ? " " + suffix : "");
|
||||
}
|
||||
} else {
|
||||
|
||||
if (invalid === true) {
|
||||
return value;
|
||||
} else if (typeof invalid === "function") {
|
||||
return invalid(value);
|
||||
} else {
|
||||
return invalid;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
console.error("Format Error - 'datetimediff' formatter is dependant on luxon.js");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
export default function(cell, formatterParams, onRendered){
|
||||
cell.getElement().classList.add("tabulator-row-handle");
|
||||
return "<div class='tabulator-row-handle-box'><div class='tabulator-row-handle-bar'></div><div class='tabulator-row-handle-bar'></div><div class='tabulator-row-handle-bar'></div></div>";
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
export default function(cell, formatterParams, onRendered){
|
||||
return cell.getValue();
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
export default function(cell, formatterParams, onRendered){
|
||||
var el = document.createElement("img"),
|
||||
src = cell.getValue();
|
||||
|
||||
if(formatterParams.urlPrefix){
|
||||
src = formatterParams.urlPrefix + cell.getValue();
|
||||
}
|
||||
|
||||
if(formatterParams.urlSuffix){
|
||||
src = src + formatterParams.urlSuffix;
|
||||
}
|
||||
|
||||
el.setAttribute("src", src);
|
||||
|
||||
switch(typeof formatterParams.height){
|
||||
case "number":
|
||||
el.style.height = formatterParams.height + "px";
|
||||
break;
|
||||
|
||||
case "string":
|
||||
el.style.height = formatterParams.height;
|
||||
break;
|
||||
}
|
||||
|
||||
switch(typeof formatterParams.width){
|
||||
case "number":
|
||||
el.style.width = formatterParams.width + "px";
|
||||
break;
|
||||
|
||||
case "string":
|
||||
el.style.width = formatterParams.width;
|
||||
break;
|
||||
}
|
||||
|
||||
el.addEventListener("load", function(){
|
||||
cell.getRow().normalizeHeight();
|
||||
});
|
||||
|
||||
return el;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user