otsdaq_utilities  v2_05_02_indev
responsive_layout.js
1 var ResponsiveLayout = function(table){
2  this.table = table; //hold Tabulator object
3  this.columns = [];
4  this.hiddenColumns = [];
5  this.mode = "";
6  this.index = 0;
7  this.collapseFormatter = [];
8  this.collapseStartOpen = true;
9  this.collapseHandleColumn = false;
10 };
11 
12 //generate resposive columns list
13 ResponsiveLayout.prototype.initialize = function(){
14  var self = this,
15  columns = [];
16 
17  this.mode = this.table.options.responsiveLayout;
18  this.collapseFormatter = this.table.options.responsiveLayoutCollapseFormatter || this.formatCollapsedData;
19  this.collapseStartOpen = this.table.options.responsiveLayoutCollapseStartOpen;
20  this.hiddenColumns = [];
21 
22  //detemine level of responsivity for each column
23  this.table.columnManager.columnsByIndex.forEach(function(column, i){
24  if(column.modules.responsive){
25  if(column.modules.responsive.order && column.modules.responsive.visible){
26  column.modules.responsive.index = i;
27  columns.push(column);
28 
29  if(!column.visible && self.mode === "collapse"){
30  self.hiddenColumns.push(column);
31  }
32  }
33  }
34  });
35 
36  //sort list by responsivity
37  columns = columns.reverse();
38  columns = columns.sort(function(a, b){
39  var diff = b.modules.responsive.order - a.modules.responsive.order;
40  return diff || (b.modules.responsive.index - a.modules.responsive.index);
41  });
42 
43  this.columns = columns;
44 
45  if(this.mode === "collapse"){
46  this.generateCollapsedContent();
47  }
48 
49  //assign collapse column
50  for (let col of this.table.columnManager.columnsByIndex){
51  if(col.definition.formatter == "responsiveCollapse"){
52  this.collapseHandleColumn = col;
53  break;
54  }
55  }
56 
57  if(this.collapseHandleColumn){
58  if(this.hiddenColumns.length){
59  this.collapseHandleColumn.show();
60  }else{
61  this.collapseHandleColumn.hide();
62  }
63  }
64 };
65 
66 //define layout information
67 ResponsiveLayout.prototype.initializeColumn = function(column){
68  var def = column.getDefinition();
69 
70  column.modules.responsive = {order: typeof def.responsive === "undefined" ? 1 : def.responsive, visible:def.visible === false ? false : true};
71 };
72 
73 ResponsiveLayout.prototype.initializeRow = function(row){
74  var el;
75 
76  if(row.type !== "calc"){
77  el = document.createElement("div");
78  el.classList.add("tabulator-responsive-collapse");
79 
80  row.modules.responsiveLayout = {
81  element:el,
82  open:this.collapseStartOpen,
83  };
84 
85  if(!this.collapseStartOpen){
86  el.style.display = 'none';
87  }
88  }
89 };
90 
91 ResponsiveLayout.prototype.layoutRow = function(row){
92  var rowEl = row.getElement();
93 
94  if(row.modules.responsiveLayout){
95  rowEl.appendChild(row.modules.responsiveLayout.element);
96  this.generateCollapsedRowContent(row);
97  }
98 };
99 
100 //update column visibility
101 ResponsiveLayout.prototype.updateColumnVisibility = function(column, visible){
102  var index;
103  if(column.modules.responsive){
104  column.modules.responsive.visible = visible;
105  this.initialize();
106  }
107 };
108 
109 ResponsiveLayout.prototype.hideColumn = function(column){
110  var colCount = this.hiddenColumns.length;
111 
112  column.hide(false, true);
113 
114  if(this.mode === "collapse"){
115  this.hiddenColumns.unshift(column);
116  this.generateCollapsedContent();
117 
118  if(this.collapseHandleColumn && !colCount){
119  this.collapseHandleColumn.show();
120  }
121  }
122 };
123 
124 ResponsiveLayout.prototype.showColumn = function(column){
125  var index;
126 
127  column.show(false, true);
128  //set column width to prevent calculation loops on uninitialized columns
129  column.setWidth(column.getWidth());
130 
131  if(this.mode === "collapse"){
132  index = this.hiddenColumns.indexOf(column);
133 
134  if(index > -1){
135  this.hiddenColumns.splice(index, 1);
136  }
137 
138  this.generateCollapsedContent();
139 
140  if(this.collapseHandleColumn && !this.hiddenColumns.length){
141  this.collapseHandleColumn.hide();
142  }
143  }
144 };
145 
146 //redraw columns to fit space
147 ResponsiveLayout.prototype.update = function(){
148  var self = this,
149  working = true;
150 
151  while(working){
152 
153  let width = self.table.modules.layout.getMode() == "fitColumns" ? self.table.columnManager.getFlexBaseWidth() : self.table.columnManager.getWidth();
154 
155  let diff = (self.table.options.headerVisible ? self.table.columnManager.element.clientWidth : self.table.element.clientWidth) - width;
156 
157  if(diff < 0){
158  //table is too wide
159  let column = self.columns[self.index];
160 
161  if(column){
162  self.hideColumn(column);
163  self.index ++;
164  }else{
165  working = false;
166  }
167 
168  }else{
169 
170  //table has spare space
171  let column = self.columns[self.index -1];
172 
173  if(column){
174  if(diff > 0){
175  if(diff >= column.getWidth()){
176  self.showColumn(column);
177  self.index --;
178  }else{
179  working = false;
180  }
181  }else{
182  working = false;
183  }
184  }else{
185  working = false;
186  }
187  }
188 
189  if(!self.table.rowManager.activeRowsCount){
190  self.table.rowManager.renderEmptyScroll();
191  }
192  }
193 };
194 
195 ResponsiveLayout.prototype.generateCollapsedContent = function(){
196  var self = this,
197  rows = this.table.rowManager.getDisplayRows();
198 
199  rows.forEach(function(row){
200  self.generateCollapsedRowContent(row);
201  });
202 };
203 
204 ResponsiveLayout.prototype.generateCollapsedRowContent = function(row){
205  var el, contents;
206 
207  if(row.modules.responsiveLayout){
208  el = row.modules.responsiveLayout.element;
209 
210  while(el.firstChild) el.removeChild(el.firstChild);
211 
212  contents = this.collapseFormatter(this.generateCollapsedRowData(row));
213  if(contents){
214  el.appendChild(contents);
215  }
216  }
217 };
218 
219 ResponsiveLayout.prototype.generateCollapsedRowData = function(row){
220  var self = this,
221  data = row.getData(),
222  output = [],
223  mockCellComponent;
224 
225  this.hiddenColumns.forEach(function(column){
226  var value = column.getFieldValue(data);
227 
228  if(column.definition.title && column.field){
229  if(column.modules.format && self.table.options.responsiveLayoutCollapseUseFormatters){
230 
231  mockCellComponent = {
232  value:false,
233  data:{},
234  getValue:function(){
235  return value;
236  },
237  getData:function(){
238  return data;
239  },
240  getElement:function(){
241  return document.createElement("div");
242  },
243  getRow:function(){
244  return row.getComponent();
245  },
246  getColumn:function(){
247  return column.getComponent();
248  },
249  };
250 
251  output.push({
252  title: column.definition.title,
253  value: column.modules.format.formatter.call(self.table.modules.format, mockCellComponent, column.modules.format.params)
254  });
255  }else{
256  output.push({
257  title: column.definition.title,
258  value: value
259  });
260  }
261  }
262  });
263 
264  return output;
265 };
266 
267 ResponsiveLayout.prototype.formatCollapsedData = function(data){
268  var list = document.createElement("table"),
269  listContents = "";
270 
271  data.forEach(function(item){
272  var div = document.createElement("div");
273 
274  if(item.value instanceof Node){
275  div.appendChild(item.value);
276  item.value = div.innerHTML;
277  }
278 
279  listContents += "<tr><td><strong>" + item.title + "</strong></td><td>" + item.value + "</td></tr>";
280  });
281 
282  list.innerHTML = listContents;
283 
284  return Object.keys(data).length ? list : "";
285 };
286 
287 Tabulator.prototype.registerModule("responsiveLayout", ResponsiveLayout);