otsdaq_utilities  v2_05_02_indev
reactive_data.js
1 var ReactiveData = function(table){
2  this.table = table; //hold Tabulator object
3  this.data = false;
4  this.blocked = false; //block reactivity while performing update
5  this.origFuncs = {}; // hold original data array functions to allow replacement after data is done with
6  this.currentVersion = 0;
7 };
8 
9 ReactiveData.prototype.watchData = function(data){
10  var self = this,
11  pushFunc, version;
12 
13  this.currentVersion ++;
14 
15  version = this.currentVersion;
16 
17  self.unwatchData();
18 
19  self.data = data;
20 
21  //override array push function
22  self.origFuncs.push = data.push;
23 
24  Object.defineProperty(self.data, "push", {
25  enumerable: false,
26  configurable: true,
27  value: function () {
28  var args = Array.from(arguments);
29 
30  if(!self.blocked && version === self.currentVersion){
31  args.forEach(function (arg){
32  self.table.rowManager.addRowActual(arg, false);
33  });
34  }
35 
36  return self.origFuncs.push.apply(data, arguments);
37  }
38  });
39 
40  //override array unshift function
41  self.origFuncs.unshift = data.unshift;
42 
43  Object.defineProperty(self.data, "unshift", {
44  enumerable: false,
45  configurable: true,
46  value: function () {
47  var args = Array.from(arguments);
48 
49  if(!self.blocked && version === self.currentVersion){
50  args.forEach(function (arg){
51  self.table.rowManager.addRowActual(arg, true);
52  });
53  }
54 
55  return self.origFuncs.unshift.apply(data, arguments);
56  }
57  });
58 
59 
60  //override array shift function
61  self.origFuncs.shift = data.shift;
62 
63  Object.defineProperty(self.data, "shift", {
64  enumerable: false,
65  configurable: true,
66  value: function () {
67  var row;
68 
69  if(!self.blocked && version === self.currentVersion){
70  if(self.data.length){
71  row = self.table.rowManager.getRowFromDataObject(self.data[0]);
72 
73  if(row){
74  row.deleteActual();
75  }
76  }
77  }
78 
79  return self.origFuncs.shift.call(data);
80  }
81  });
82 
83  //override array pop function
84  self.origFuncs.pop = data.pop;
85 
86  Object.defineProperty(self.data, "pop", {
87  enumerable: false,
88  configurable: true,
89  value: function () {
90  var row;
91  if(!self.blocked && version === self.currentVersion){
92  if(self.data.length){
93  row = self.table.rowManager.getRowFromDataObject(self.data[self.data.length - 1]);
94 
95  if(row){
96  row.deleteActual();
97  }
98  }
99  }
100  return self.origFuncs.pop.call(data);
101  }
102  });
103 
104 
105  //override array splice function
106  self.origFuncs.splice = data.splice;
107 
108  Object.defineProperty(self.data, "splice", {
109  enumerable: false,
110  configurable: true,
111  value: function () {
112  var args = Array.from(arguments),
113  start = args[0] < 0 ? data.length + args[0] : args[0],
114  end = args[1],
115  newRows = args[2] ? args.slice(2) : false,
116  startRow;
117 
118  if(!self.blocked && version === self.currentVersion){
119 
120  //add new rows
121  if(newRows){
122  startRow = data[start] ? self.table.rowManager.getRowFromDataObject(data[start]) : false;
123 
124  if(startRow){
125  newRows.forEach(function(rowData){
126  self.table.rowManager.addRowActual(rowData, true, startRow, true);
127  });
128  }else{
129  newRows = newRows.slice().reverse();
130 
131  newRows.forEach(function(rowData){
132  self.table.rowManager.addRowActual(rowData, true, false, true);
133  });
134  }
135  }
136 
137  //delete removed rows
138  if(end !== 0){
139  var oldRows = data.slice(start, typeof args[1] === "undefined" ? args[1] : start + end);
140 
141  oldRows.forEach(function(rowData, i){
142  var row = self.table.rowManager.getRowFromDataObject(rowData);
143 
144  if(row){
145  row.deleteActual(i !== oldRows.length - 1);
146  }
147  });
148  }
149 
150  if(newRows || end !== 0){
151  self.table.rowManager.reRenderInPosition();
152  }
153  }
154 
155  return self.origFuncs.splice.apply(data, arguments);
156  }
157  });
158 };
159 
160 ReactiveData.prototype.unwatchData = function(){
161  if(this.data !== false){
162  for(var key in this.origFuncs){
163  Object.defineProperty(this.data, key, {
164  enumerable: true,
165  configurable:true,
166  writable:true,
167  value: this.origFuncs.key,
168  });
169  }
170  }
171 };
172 
173 ReactiveData.prototype.watchRow = function(row){
174  var self = this,
175  data = row.getData();
176 
177  this.blocked = true;
178 
179  for(var key in data){
180  this.watchKey(row, data, key);
181  }
182 
183  this.blocked = false;
184 };
185 
186 ReactiveData.prototype.watchKey = function(row, data, key){
187  var self = this,
188  props = Object.getOwnPropertyDescriptor(data, key),
189  value = data[key],
190  version = this.currentVersion;
191 
192  Object.defineProperty(data, key, {
193  set: function(newValue){
194  value = newValue;
195  if(!self.blocked && version === self.currentVersion){
196  var update = {};
197  update[key] = newValue;
198  row.updateData(update);
199  }
200 
201  if(props.set){
202  props.set(newValue);
203  }
204  },
205  get:function(){
206 
207  if(props.get){
208  props.get();
209  }
210 
211  return value;
212  }
213  });
214 };
215 
216 ReactiveData.prototype.unwatchRow = function(row){
217  var data = row.getData();
218 
219  for(var key in data){
220  Object.defineProperty(data, key, {
221  value:data[key],
222  });
223  }
224 };
225 
226 ReactiveData.prototype.block = function(){
227  this.blocked = true;
228 };
229 
230 ReactiveData.prototype.unblock = function(){
231  this.blocked = false;
232 };
233 
234 Tabulator.prototype.registerModule("reactiveData", ReactiveData);
235 
236 
237