tabulator-tables
Version:
Interactive table generation JavaScript library
457 lines (365 loc) • 12.5 kB
JavaScript
import Module from '../../core/Module.js';
import defaultReaders from './defaults/readers.js';
import defaultWriters from './defaults/writers.js';
class Persistence extends Module{
constructor(table){
super(table);
this.mode = "";
this.id = "";
// this.persistProps = ["field", "width", "visible"];
this.defWatcherBlock = false;
this.config = {};
this.readFunc = false;
this.writeFunc = false;
this.registerTableOption("persistence", false);
this.registerTableOption("persistenceID", ""); //key for persistent storage
this.registerTableOption("persistenceMode", true); //mode for storing persistence information
this.registerTableOption("persistenceReaderFunc", false); //function for handling persistence data reading
this.registerTableOption("persistenceWriterFunc", false); //function for handling persistence data writing
}
// Test for whether localStorage is available for use.
localStorageTest() {
var testKey = "_tabulator_test";
try {
window.localStorage.setItem( testKey, testKey);
window.localStorage.removeItem( testKey );
return true;
} catch(e) {
return false;
}
}
//setup parameters
initialize(){
if(this.table.options.persistence){
//determine persistent layout storage type
var mode = this.table.options.persistenceMode,
id = this.table.options.persistenceID,
retrievedData;
this.mode = mode !== true ? mode : (this.localStorageTest() ? "local" : "cookie");
if(this.table.options.persistenceReaderFunc){
if(typeof this.table.options.persistenceReaderFunc === "function"){
this.readFunc = this.table.options.persistenceReaderFunc;
}else{
if(Persistence.readers[this.table.options.persistenceReaderFunc]){
this.readFunc = Persistence.readers[this.table.options.persistenceReaderFunc];
}else{
console.warn("Persistence Read Error - invalid reader set", this.table.options.persistenceReaderFunc);
}
}
}else{
if(Persistence.readers[this.mode]){
this.readFunc = Persistence.readers[this.mode];
}else{
console.warn("Persistence Read Error - invalid reader set", this.mode);
}
}
if(this.table.options.persistenceWriterFunc){
if(typeof this.table.options.persistenceWriterFunc === "function"){
this.writeFunc = this.table.options.persistenceWriterFunc;
}else{
if(Persistence.writers[this.table.options.persistenceWriterFunc]){
this.writeFunc = Persistence.writers[this.table.options.persistenceWriterFunc];
}else{
console.warn("Persistence Write Error - invalid reader set", this.table.options.persistenceWriterFunc);
}
}
}else{
if(Persistence.writers[this.mode]){
this.writeFunc = Persistence.writers[this.mode];
}else{
console.warn("Persistence Write Error - invalid writer set", this.mode);
}
}
//set storage tag
this.id = "tabulator-" + (id || (this.table.element.getAttribute("id") || ""));
this.config = {
sort:this.table.options.persistence === true || this.table.options.persistence.sort,
filter:this.table.options.persistence === true || this.table.options.persistence.filter,
group:this.table.options.persistence === true || this.table.options.persistence.group,
page:this.table.options.persistence === true || this.table.options.persistence.page,
columns:this.table.options.persistence === true ? ["title", "width", "visible"] : this.table.options.persistence.columns,
};
//load pagination data if needed
if(this.config.page){
retrievedData = this.retrieveData("page");
if(retrievedData){
if(typeof retrievedData.paginationSize !== "undefined" && (this.config.page === true || this.config.page.size)){
this.table.options.paginationSize = retrievedData.paginationSize;
}
if(typeof retrievedData.paginationInitialPage !== "undefined" && (this.config.page === true || this.config.page.page)){
this.table.options.paginationInitialPage = retrievedData.paginationInitialPage;
}
}
}
//load group data if needed
if(this.config.group){
retrievedData = this.retrieveData("group");
if(retrievedData){
if(typeof retrievedData.groupBy !== "undefined" && (this.config.group === true || this.config.group.groupBy)){
this.table.options.groupBy = retrievedData.groupBy;
}
if(typeof retrievedData.groupStartOpen !== "undefined" && (this.config.group === true || this.config.group.groupStartOpen)){
this.table.options.groupStartOpen = retrievedData.groupStartOpen;
}
if(typeof retrievedData.groupHeader !== "undefined" && (this.config.group === true || this.config.group.groupHeader)){
this.table.options.groupHeader = retrievedData.groupHeader;
}
}
}
if(this.config.columns){
this.table.options.columns = this.load("columns", this.table.options.columns);
this.subscribe("column-init", this.initializeColumn.bind(this));
this.subscribe("column-show", this.save.bind(this, "columns"));
this.subscribe("column-hide", this.save.bind(this, "columns"));
this.subscribe("column-moved", this.save.bind(this, "columns"));
}
this.subscribe("table-built", this.tableBuilt.bind(this), 0);
this.subscribe("table-redraw", this.tableRedraw.bind(this));
this.subscribe("filter-changed", this.eventSave.bind(this, "filter"));
this.subscribe("sort-changed", this.eventSave.bind(this, "sort"));
this.subscribe("group-changed", this.eventSave.bind(this, "group"));
this.subscribe("page-changed", this.eventSave.bind(this, "page"));
this.subscribe("column-resized", this.eventSave.bind(this, "columns"));
this.subscribe("layout-refreshed", this.eventSave.bind(this, "columns"));
}
this.registerTableFunction("getColumnLayout", this.getColumnLayout.bind(this));
this.registerTableFunction("setColumnLayout", this.setColumnLayout.bind(this));
}
eventSave(type){
if(this.config[type]){
this.save(type);
}
}
tableBuilt(){
var sorters, filters;
if(this.config.sort){
sorters = this.load("sort");
if(!sorters === false){
this.table.options.initialSort = sorters;
}
}
if(this.config.filter){
filters = this.load("filter");
if(!filters === false){
this.table.options.initialFilter = filters;
}
}
}
tableRedraw(force){
if(force && this.config.columns){
this.save("columns");
}
}
///////////////////////////////////
///////// Table Functions /////////
///////////////////////////////////
getColumnLayout(){
return this.parseColumns(this.table.columnManager.getColumns());
}
setColumnLayout(layout){
this.table.columnManager.setColumns(this.mergeDefinition(this.table.options.columns, layout));
return true;
}
///////////////////////////////////
///////// Internal Logic //////////
///////////////////////////////////
initializeColumn(column){
var def, keys;
if(this.config.columns){
this.defWatcherBlock = true;
def = column.getDefinition();
keys = this.config.columns === true ? Object.keys(def) : this.config.columns;
keys.forEach((key)=>{
var props = Object.getOwnPropertyDescriptor(def, key);
var value = def[key];
if(props){
Object.defineProperty(def, key, {
set: function(newValue){
value = newValue;
if(!this.defWatcherBlock){
this.save("columns");
}
if(props.set){
props.set(newValue);
}
},
get:function(){
if(props.get){
props.get();
}
return value;
}
});
}
});
this.defWatcherBlock = false;
}
}
//load saved definitions
load(type, current){
var data = this.retrieveData(type);
if(current){
data = data ? this.mergeDefinition(current, data) : current;
}
return data;
}
//retrieve data from memory
retrieveData(type){
return this.readFunc ? this.readFunc(this.id, type) : false;
}
//merge old and new column definitions
mergeDefinition(oldCols, newCols){
var output = [];
newCols = newCols || [];
newCols.forEach((column, to) => {
var from = this._findColumn(oldCols, column),
keys;
if(from){
if(this.config.columns === true || this.config.columns == undefined){
keys = Object.keys(from);
keys.push("width");
}else{
keys = this.config.columns;
}
keys.forEach((key)=>{
if(key !== "columns" && typeof column[key] !== "undefined"){
from[key] = column[key];
}
});
if(from.columns){
from.columns = this.mergeDefinition(from.columns, column.columns);
}
output.push(from);
}
});
oldCols.forEach((column, i) => {
var from = this._findColumn(newCols, column);
if (!from) {
if(output.length>i){
output.splice(i, 0, column);
}else{
output.push(column);
}
}
});
return output;
}
//find matching columns
_findColumn(columns, subject){
var type = subject.columns ? "group" : (subject.field ? "field" : "object");
return columns.find(function(col){
switch(type){
case "group":
return col.title === subject.title && col.columns.length === subject.columns.length;
case "field":
return col.field === subject.field;
case "object":
return col === subject;
}
});
}
//save data
save(type){
var data = {};
switch(type){
case "columns":
data = this.parseColumns(this.table.columnManager.getColumns());
break;
case "filter":
data = this.table.modules.filter.getFilters();
break;
case "sort":
data = this.validateSorters(this.table.modules.sort.getSort());
break;
case "group":
data = this.getGroupConfig();
break;
case "page":
data = this.getPageConfig();
break;
}
if(this.writeFunc){
this.writeFunc(this.id, type, data);
}
}
//ensure sorters contain no function data
validateSorters(data){
data.forEach(function(item){
item.column = item.field;
delete item.field;
});
return data;
}
getGroupConfig(){
var data = {};
if(this.config.group){
if(this.config.group === true || this.config.group.groupBy){
data.groupBy = this.table.options.groupBy;
}
if(this.config.group === true || this.config.group.groupStartOpen){
data.groupStartOpen = this.table.options.groupStartOpen;
}
if(this.config.group === true || this.config.group.groupHeader){
data.groupHeader = this.table.options.groupHeader;
}
}
return data;
}
getPageConfig(){
var data = {};
if(this.config.page){
if(this.config.page === true || this.config.page.size){
data.paginationSize = this.table.modules.page.getPageSize();
}
if(this.config.page === true || this.config.page.page){
data.paginationInitialPage = this.table.modules.page.getPage();
}
}
return data;
}
//parse columns for data to store
parseColumns(columns){
var definitions = [],
excludedKeys = ["headerContextMenu", "headerMenu", "contextMenu", "clickMenu"];
columns.forEach((column) => {
var defStore = {},
colDef = column.getDefinition(),
keys;
if(column.isGroup){
defStore.title = colDef.title;
defStore.columns = this.parseColumns(column.getColumns());
}else{
defStore.field = column.getField();
if(this.config.columns === true || this.config.columns == undefined){
keys = Object.keys(colDef);
keys.push("width");
keys.push("visible");
}else{
keys = this.config.columns;
}
keys.forEach((key)=>{
switch(key){
case "width":
defStore.width = column.getWidth();
break;
case "visible":
defStore.visible = column.visible;
break;
default:
if(typeof colDef[key] !== "function" && excludedKeys.indexOf(key) === -1){
defStore[key] = colDef[key];
}
}
});
}
definitions.push(defStore);
});
return definitions;
}
}
Persistence.moduleName = "persistence";
Persistence.moduleInitOrder = -10;
//load defaults
Persistence.readers = defaultReaders;
Persistence.writers = defaultWriters;
export default Persistence;