otsdaq_utilities  v2_05_02_indev
persistence.js
1 var Persistence = function(table){
2  this.table = table; //hold Tabulator object
3  this.mode = "";
4  this.id = "";
5  // this.persistProps = ["field", "width", "visible"];
6  this.defWatcherBlock = false;
7  this.config = {};
8  this.readFunc = false;
9  this.writeFunc = false;
10 };
11 
12 // Test for whether localStorage is available for use.
13 Persistence.prototype.localStorageTest = function() {
14  var testKey = "_tabulator_test";
15 
16  try {
17  window.localStorage.setItem( testKey, testKey);
18  window.localStorage.removeItem( testKey );
19  return true;
20  } catch(e) {
21  return false;
22  }
23 };
24 
25 //setup parameters
26 Persistence.prototype.initialize = function(){
27  //determine persistent layout storage type
28 
29  var mode = this.table.options.persistenceMode,
30  id = this.table.options.persistenceID,
31  retreivedData;
32 
33  this.mode = mode !== true ? mode : (this.localStorageTest() ? "local" : "cookie");
34 
35  if(this.table.options.persistenceReaderFunc){
36  if(typeof this.table.options.persistenceReaderFunc === "function"){
37  this.readFunc = this.table.options.persistenceReaderFunc;
38  }else{
39  if(this.readers[this.table.options.persistenceReaderFunc]){
40  this.readFunc = this.readers[this.table.options.persistenceReaderFunc];
41  }else{
42  console.warn("Persistence Read Error - invalid reader set", this.table.options.persistenceReaderFunc);
43  }
44  }
45  }else{
46  if(this.readers[this.mode]){
47  this.readFunc = this.readers[this.mode];
48  }else{
49  console.warn("Persistence Read Error - invalid reader set", this.mode);
50  }
51  }
52 
53  if(this.table.options.persistenceWriterFunc){
54  if(typeof this.table.options.persistenceWriterFunc === "function"){
55  this.writeFunc = this.table.options.persistenceWriterFunc;
56  }else{
57  if(this.readers[this.table.options.persistenceWriterFunc]){
58  this.writeFunc = this.readers[this.table.options.persistenceWriterFunc];
59  }else{
60  console.warn("Persistence Write Error - invalid reader set", this.table.options.persistenceWriterFunc);
61  }
62  }
63  }else{
64  if(this.writers[this.mode]){
65  this.writeFunc = this.writers[this.mode];
66  }else{
67  console.warn("Persistence Write Error - invalid writer set", this.mode);
68  }
69  }
70 
71  //set storage tag
72  this.id = "tabulator-" + (id || (this.table.element.getAttribute("id") || ""));
73 
74  this.config = {
75  sort:this.table.options.persistence === true || this.table.options.persistence.sort,
76  filter:this.table.options.persistence === true || this.table.options.persistence.filter,
77  group:this.table.options.persistence === true || this.table.options.persistence.group,
78  page:this.table.options.persistence === true || this.table.options.persistence.page,
79  columns:this.table.options.persistence === true ? ["title", "width", "visible"] : this.table.options.persistence.columns,
80  };
81 
82  //load pagination data if needed
83  if(this.config.page){
84  retreivedData = this.retreiveData("page");
85 
86  if(retreivedData){
87  if(typeof retreivedData.paginationSize !== "undefined" && (this.config.page === true || this.config.page.size)){
88  this.table.options.paginationSize = retreivedData.paginationSize;
89  }
90 
91  if(typeof retreivedData.paginationInitialPage !== "undefined" && (this.config.page === true || this.config.page.page)){
92  this.table.options.paginationInitialPage = retreivedData.paginationInitialPage;
93  }
94  }
95  }
96 
97  //load group data if needed
98  if(this.config.group){
99  retreivedData = this.retreiveData("group");
100 
101  if(retreivedData){
102  if(typeof retreivedData.groupBy !== "undefined" && (this.config.group === true || this.config.group.groupBy)){
103  this.table.options.groupBy = retreivedData.groupBy;
104  }
105  if(typeof retreivedData.groupStartOpen !== "undefined" && (this.config.group === true || this.config.group.groupStartOpen)){
106  this.table.options.groupStartOpen = retreivedData.groupStartOpen;
107  }
108  if(typeof retreivedData.groupHeader !== "undefined" && (this.config.group === true || this.config.group.groupHeader)){
109  this.table.options.groupHeader = retreivedData.groupHeader;
110  }
111  }
112  }
113 };
114 
115 
116 Persistence.prototype.initializeColumn = function(column){
117  var self = this,
118  def, keys;
119 
120  if(this.config.columns){
121  this.defWatcherBlock = true;
122 
123  def = column.getDefinition();
124 
125  keys = this.config.columns === true ? Object.keys(def) : this.config.columns;
126 
127  keys.forEach((key)=>{
128  var props = Object.getOwnPropertyDescriptor(def, key);
129  var value = def[key];
130  if(props){
131  Object.defineProperty(def, key, {
132  set: function(newValue){
133  value = newValue;
134 
135  if(!self.defWatcherBlock){
136  self.save("columns");
137  }
138 
139  if(props.set){
140  props.set(newValue);
141  }
142  },
143  get:function(){
144  if(props.get){
145  props.get();
146  }
147  return value;
148  }
149  });
150  }
151  });
152 
153  this.defWatcherBlock = false;
154  }
155 
156 };
157 
158 //load saved definitions
159 Persistence.prototype.load = function(type, current){
160  var data = this.retreiveData(type);
161 
162  if(current){
163  data = data ? this.mergeDefinition(current, data) : current;
164  }
165 
166  return data;
167 };
168 
169 //retreive data from memory
170 Persistence.prototype.retreiveData = function(type){
171  return this.readFunc ? this.readFunc(this.id, type) : false;
172 };
173 
174 //merge old and new column definitions
175 Persistence.prototype.mergeDefinition = function(oldCols, newCols){
176  var self = this,
177  output = [];
178 
179  // oldCols = oldCols || [];
180  newCols = newCols || [];
181 
182  newCols.forEach(function(column, to){
183 
184  var from = self._findColumn(oldCols, column),
185  keys;
186 
187  if(from){
188 
189  if(self.config.columns === true || self.config.columns == undefined){
190  keys = Object.keys(from);
191  keys.push("width");
192  }else{
193  keys = self.config.columns;
194  }
195 
196  keys.forEach((key)=>{
197  if(typeof column[key] !== "undefined"){
198  from[key] = column[key];
199  }
200  });
201 
202  if(from.columns){
203  from.columns = self.mergeDefinition(from.columns, column.columns);
204  }
205 
206 
207  output.push(from);
208  }
209 
210  });
211 
212  oldCols.forEach(function (column, i) {
213  var from = self._findColumn(newCols, column);
214  if (!from) {
215  if(output.length>i){
216  output.splice(i, 0, column);
217  }else{
218  output.push(column);
219  }
220  }
221  });
222 
223  return output;
224 };
225 
226 //find matching columns
227 Persistence.prototype._findColumn = function(columns, subject){
228  var type = subject.columns ? "group" : (subject.field ? "field" : "object");
229 
230  return columns.find(function(col){
231  switch(type){
232  case "group":
233  return col.title === subject.title && col.columns.length === subject.columns.length;
234  break;
235 
236  case "field":
237  return col.field === subject.field;
238  break;
239 
240  case "object":
241  return col === subject;
242  break;
243  }
244  });
245 };
246 
247 //save data
248 Persistence.prototype.save = function(type){
249  var data = {};
250 
251 
252  switch(type){
253  case "columns":
254  data = this.parseColumns(this.table.columnManager.getColumns())
255  break;
256 
257  case "filter":
258  data = this.table.modules.filter.getFilters();
259  break;
260 
261  case "sort":
262  data = this.validateSorters(this.table.modules.sort.getSort());
263  break;
264 
265  case "group":
266  data = this.getGroupConfig();
267  break;
268 
269  case "page":
270  data = this.getPageConfig();
271  break;
272  }
273 
274  if(this.writeFunc){
275  this.writeFunc(this.id, type, data);
276  }
277 
278 };
279 
280 //ensure sorters contain no function data
281 Persistence.prototype.validateSorters = function(data){
282  data.forEach(function(item){
283  item.column = item.field;
284  delete item.field;
285  });
286 
287  return data;
288 };
289 
290 Persistence.prototype.getGroupConfig = function(){
291  if(this.config.group){
292  if(this.config.group === true || this.config.group.groupBy){
293  data.groupBy = this.table.options.groupBy;
294  }
295 
296  if(this.config.group === true || this.config.group.groupStartOpen){
297  data.groupStartOpen = this.table.options.groupStartOpen;
298  }
299 
300  if(this.config.group === true || this.config.group.groupHeader){
301  data.groupHeader = this.table.options.groupHeader;
302  }
303  }
304 
305  return data;
306 };
307 
308 Persistence.prototype.getPageConfig = function(){
309  var data = {};
310 
311  if(this.config.page){
312  if(this.config.page === true || this.config.page.size){
313  data.paginationSize = this.table.modules.page.getPageSize();
314  }
315 
316  if(this.config.page === true || this.config.page.page){
317  data.paginationInitialPage = this.table.modules.page.getPage();
318  }
319  }
320 
321  return data;
322 };
323 
324 
325 //parse columns for data to store
326 Persistence.prototype.parseColumns = function(columns){
327  var self = this,
328  definitions = [];
329 
330  columns.forEach(function(column){
331  var defStore = {},
332  colDef = column.getDefinition(),
333  keys;
334 
335  if(column.isGroup){
336  defStore.title = colDef.title;
337  defStore.columns = self.parseColumns(column.getColumns());
338  }else{
339  defStore.field = column.getField();
340 
341  if(self.config.columns === true || self.config.columns == undefined){
342  keys = Object.keys(colDef);
343  keys.push("width");
344  }else{
345  keys = self.config.columns;
346  }
347 
348  keys.forEach((key)=>{
349 
350  switch(key){
351  case "width":
352  defStore.width = column.getWidth();
353  break;
354  case "visible":
355  defStore.visible = column.visible;
356  break;
357 
358  default:
359  defStore[key] = colDef[key];
360  }
361 
362  });
363  }
364 
365  definitions.push(defStore);
366  });
367 
368  return definitions;
369 };
370 
371 // read peristence information from storage
372 Persistence.prototype.readers = {
373  local:function(id, type){
374  var data = localStorage.getItem(id + "-" + type);
375 
376  return data ? JSON.parse(data) : false;
377  },
378  cookie:function(id, type){
379  var cookie = document.cookie,
380  key = id + "-" + type,
381  cookiePos = cookie.indexOf(key + "="),
382  end;
383 
384  //if cookie exists, decode and load column data into tabulator
385  if(cookiePos > -1){
386  cookie = cookie.substr(cookiePos);
387 
388  end = cookie.indexOf(";");
389 
390  if(end > -1){
391  cookie = cookie.substr(0, end);
392  }
393 
394  data = cookie.replace(key + "=", "");
395  }
396 
397  return data ? JSON.parse(data) : false;
398  }
399 };
400 
401 //write persistence information to storage
402 Persistence.prototype.writers = {
403  local:function(id, type, data){
404  localStorage.setItem(id + "-" + type, JSON.stringify(data));
405  },
406  cookie:function(id, type, data){
407  var expireDate = new Date();
408 
409  expireDate.setDate(expireDate.getDate() + 10000);
410 
411  document.cookie = id + "_" + type + "=" + JSON.stringify(data) + "; expires=" + expireDate.toUTCString();
412  }
413 };
414 
415 
416 Tabulator.prototype.registerModule("persistence", Persistence);