tabulator-tables
Version:
Interactive table generation JavaScript library
323 lines (251 loc) • 7.08 kB
JavaScript
/* Tabulator v4.9.3 (c) Oliver Folkerd */
var ReactiveData = function ReactiveData(table) {
this.table = table; //hold Tabulator object
this.data = false;
this.blocked = false; //block reactivity while performing update
this.origFuncs = {}; // hold original data array functions to allow replacement after data is done with
this.currentVersion = 0;
};
ReactiveData.prototype.watchData = function (data) {
var self = this,
pushFunc,
version;
this.currentVersion++;
version = this.currentVersion;
self.unwatchData();
self.data = data;
//override array push function
self.origFuncs.push = data.push;
Object.defineProperty(self.data, "push", {
enumerable: false,
configurable: true,
value: function value() {
var args = Array.from(arguments);
if (!self.blocked && version === self.currentVersion) {
args.forEach(function (arg) {
self.table.rowManager.addRowActual(arg, false);
});
}
return self.origFuncs.push.apply(data, arguments);
}
});
//override array unshift function
self.origFuncs.unshift = data.unshift;
Object.defineProperty(self.data, "unshift", {
enumerable: false,
configurable: true,
value: function value() {
var args = Array.from(arguments);
if (!self.blocked && version === self.currentVersion) {
args.forEach(function (arg) {
self.table.rowManager.addRowActual(arg, true);
});
}
return self.origFuncs.unshift.apply(data, arguments);
}
});
//override array shift function
self.origFuncs.shift = data.shift;
Object.defineProperty(self.data, "shift", {
enumerable: false,
configurable: true,
value: function value() {
var row;
if (!self.blocked && version === self.currentVersion) {
if (self.data.length) {
row = self.table.rowManager.getRowFromDataObject(self.data[0]);
if (row) {
row.deleteActual();
}
}
}
return self.origFuncs.shift.call(data);
}
});
//override array pop function
self.origFuncs.pop = data.pop;
Object.defineProperty(self.data, "pop", {
enumerable: false,
configurable: true,
value: function value() {
var row;
if (!self.blocked && version === self.currentVersion) {
if (self.data.length) {
row = self.table.rowManager.getRowFromDataObject(self.data[self.data.length - 1]);
if (row) {
row.deleteActual();
}
}
}
return self.origFuncs.pop.call(data);
}
});
//override array splice function
self.origFuncs.splice = data.splice;
Object.defineProperty(self.data, "splice", {
enumerable: false,
configurable: true,
value: function value() {
var args = Array.from(arguments),
start = args[0] < 0 ? data.length + args[0] : args[0],
end = args[1],
newRows = args[2] ? args.slice(2) : false,
startRow;
if (!self.blocked && version === self.currentVersion) {
//add new rows
if (newRows) {
startRow = data[start] ? self.table.rowManager.getRowFromDataObject(data[start]) : false;
if (startRow) {
newRows.forEach(function (rowData) {
self.table.rowManager.addRowActual(rowData, true, startRow, true);
});
} else {
newRows = newRows.slice().reverse();
newRows.forEach(function (rowData) {
self.table.rowManager.addRowActual(rowData, true, false, true);
});
}
}
//delete removed rows
if (end !== 0) {
var oldRows = data.slice(start, typeof args[1] === "undefined" ? args[1] : start + end);
oldRows.forEach(function (rowData, i) {
var row = self.table.rowManager.getRowFromDataObject(rowData);
if (row) {
row.deleteActual(i !== oldRows.length - 1);
}
});
}
if (newRows || end !== 0) {
self.table.rowManager.reRenderInPosition();
}
}
return self.origFuncs.splice.apply(data, arguments);
}
});
};
ReactiveData.prototype.unwatchData = function () {
if (this.data !== false) {
for (var key in this.origFuncs) {
Object.defineProperty(this.data, key, {
enumerable: true,
configurable: true,
writable: true,
value: this.origFuncs.key
});
}
}
};
ReactiveData.prototype.watchRow = function (row) {
var data = row.getData();
this.blocked = true;
for (var key in data) {
this.watchKey(row, data, key);
}
if (this.table.options.dataTree) {
this.watchTreeChildren(row);
}
this.blocked = false;
};
ReactiveData.prototype.watchTreeChildren = function (row) {
var self = this,
childField = row.getData()[this.table.options.dataTreeChildField],
origFuncs = {};
function rebuildTree() {
self.table.modules.dataTree.initializeRow(row);
self.table.modules.dataTree.layoutRow(row);
self.table.rowManager.refreshActiveData("tree", false, true);
}
if (childField) {
origFuncs.push = childField.push;
Object.defineProperty(childField, "push", {
enumerable: false,
configurable: true,
value: function value() {
var result = origFuncs.push.apply(childField, arguments);
rebuildTree();
return result;
}
});
origFuncs.unshift = childField.unshift;
Object.defineProperty(childField, "unshift", {
enumerable: false,
configurable: true,
value: function value() {
var result = origFuncs.unshift.apply(childField, arguments);
rebuildTree();
return result;
}
});
origFuncs.shift = childField.shift;
Object.defineProperty(childField, "shift", {
enumerable: false,
configurable: true,
value: function value() {
var result = origFuncs.shift.call(childField);
rebuildTree();
return result;
}
});
origFuncs.pop = childField.pop;
Object.defineProperty(childField, "pop", {
enumerable: false,
configurable: true,
value: function value() {
var result = origFuncs.pop.call(childField);
rebuildTree();
return result;
}
});
origFuncs.splice = childField.splice;
Object.defineProperty(childField, "splice", {
enumerable: false,
configurable: true,
value: function value() {
var result = origFuncs.splice.apply(childField, arguments);
rebuildTree();
return result;
}
});
}
};
ReactiveData.prototype.watchKey = function (row, data, key) {
var self = this,
props = Object.getOwnPropertyDescriptor(data, key),
value = data[key],
version = this.currentVersion;
Object.defineProperty(data, key, {
set: function set(newValue) {
value = newValue;
if (!self.blocked && version === self.currentVersion) {
var update = {};
update[key] = newValue;
row.updateData(update);
}
if (props.set) {
props.set(newValue);
}
},
get: function get() {
if (props.get) {
props.get();
}
return value;
}
});
};
ReactiveData.prototype.unwatchRow = function (row) {
var data = row.getData();
for (var key in data) {
Object.defineProperty(data, key, {
value: data[key]
});
}
};
ReactiveData.prototype.block = function () {
this.blocked = true;
};
ReactiveData.prototype.unblock = function () {
this.blocked = false;
};
Tabulator.prototype.registerModule("reactiveData", ReactiveData);