UNPKG

tabulator-tables

Version:

Interactive table generation JavaScript library

326 lines (249 loc) 7.2 kB
var ReactiveData = function(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 () { 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 () { 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 () { 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 () { 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 () { 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(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(){ 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);