otsdaq_utilities  v2_05_02_indev
layout.js
1 var Layout = function(table){
2  this.table = table;
3  this.mode = null;
4 };
5 
6 //initialize layout system
7 Layout.prototype.initialize = function(layout){
8 
9  if(this.modes[layout]){
10  this.mode = layout;
11  }else{
12  console.warn("Layout Error - invalid mode set, defaulting to 'fitData' : " + layout);
13  this.mode = 'fitData';
14  }
15 
16  this.table.element.setAttribute("tabulator-layout", this.mode);
17 };
18 
19 Layout.prototype.getMode = function(){
20  return this.mode;
21 };
22 
23 //trigger table layout
24 Layout.prototype.layout = function(){
25  this.modes[this.mode].call(this, this.table.columnManager.columnsByIndex);
26 };
27 
28 //layout render functions
29 Layout.prototype.modes = {
30 
31  //resize columns to fit data the contain
32  "fitData": function(columns){
33  columns.forEach(function(column){
34  column.reinitializeWidth();
35  });
36 
37  if(this.table.options.responsiveLayout && this.table.modExists("responsiveLayout", true)){
38  this.table.modules.responsiveLayout.update();
39  }
40  },
41 
42  //resize columns to fit data the contain and stretch row to fill table
43  "fitDataFill": function(columns){
44  columns.forEach(function(column){
45  column.reinitializeWidth();
46  });
47 
48  if(this.table.options.responsiveLayout && this.table.modExists("responsiveLayout", true)){
49  this.table.modules.responsiveLayout.update();
50  }
51  },
52 
53  //resize columns to fit data the contain and stretch last column to fill table
54  "fitDataStretch": function(columns){
55  var colsWidth = 0,
56  tableWidth = this.table.rowManager.element.clientWidth,
57  gap = 0,
58  lastCol = false;
59 
60  columns.forEach((column, i) => {
61  if(!column.widthFixed){
62  column.reinitializeWidth();
63  }
64 
65  if(this.table.options.responsiveLayout ? column.modules.responsive.visible : column.visible){
66  lastCol = column;
67  }
68 
69  if(column.visible){
70  colsWidth += column.getWidth();
71  }
72  });
73 
74  if(lastCol){
75  gap = tableWidth - colsWidth + lastCol.getWidth();
76 
77  if(this.table.options.responsiveLayout && this.table.modExists("responsiveLayout", true)){
78  lastCol.setWidth(0);
79  this.table.modules.responsiveLayout.update();
80  }
81 
82  if(gap > 0){
83  lastCol.setWidth(gap);
84  }else{
85  lastCol.reinitializeWidth();
86  }
87  }else{
88  if(this.table.options.responsiveLayout && this.table.modExists("responsiveLayout", true)){
89  this.table.modules.responsiveLayout.update();
90  }
91  }
92  },
93 
94  //resize columns to fit
95  "fitColumns": function(columns){
96  var self = this;
97 
98  var totalWidth = self.table.element.clientWidth; //table element width
99  var fixedWidth = 0; //total width of columns with a defined width
100  var flexWidth = 0; //total width available to flexible columns
101  var flexGrowUnits = 0; //total number of widthGrow blocks accross all columns
102  var flexColWidth = 0; //desired width of flexible columns
103  var flexColumns = []; //array of flexible width columns
104  var fixedShrinkColumns = []; //array of fixed width columns that can shrink
105  var flexShrinkUnits = 0; //total number of widthShrink blocks accross all columns
106  var overflowWidth = 0; //horizontal overflow width
107  var gapFill=0; //number of pixels to be added to final column to close and half pixel gaps
108 
109  function calcWidth(width){
110  var colWidth;
111 
112  if(typeof(width) == "string"){
113  if(width.indexOf("%") > -1){
114  colWidth = (totalWidth / 100) * parseInt(width);
115  }else{
116  colWidth = parseInt(width);
117  }
118  }else{
119  colWidth = width;
120  }
121 
122  return colWidth;
123  }
124 
125  //ensure columns resize to take up the correct amount of space
126  function scaleColumns(columns, freeSpace, colWidth, shrinkCols){
127 
128  var oversizeCols = [],
129  oversizeSpace = 0,
130  remainingSpace = 0,
131  nextColWidth = 0,
132  gap = 0,
133  changeUnits = 0,
134  undersizeCols = [];
135 
136  function calcGrow(col){
137  return (colWidth * (col.column.definition.widthGrow || 1));
138  }
139 
140  function calcShrink(col){
141  return (calcWidth(col.width) - (colWidth * (col.column.definition.widthShrink || 0)))
142  }
143 
144  columns.forEach(function(col, i){
145  var width = shrinkCols ? calcShrink(col) : calcGrow(col);
146  if(col.column.minWidth >= width){
147  oversizeCols.push(col);
148  }else{
149  undersizeCols.push(col);
150  changeUnits += shrinkCols ? (col.column.definition.widthShrink || 1) : (col.column.definition.widthGrow || 1);
151  }
152  });
153 
154  if(oversizeCols.length){
155  oversizeCols.forEach(function(col){
156  oversizeSpace += shrinkCols ? col.width - col.column.minWidth : col.column.minWidth;
157  col.width = col.column.minWidth;
158  });
159 
160  remainingSpace = freeSpace - oversizeSpace;
161 
162  nextColWidth = changeUnits ? Math.floor(remainingSpace/changeUnits) : remainingSpace;
163 
164  gap = remainingSpace - (nextColWidth * changeUnits);
165 
166  gap += scaleColumns(undersizeCols, remainingSpace, nextColWidth, shrinkCols);
167  }else{
168  gap = changeUnits ? freeSpace - (Math.floor(freeSpace/changeUnits) * changeUnits) : freeSpace;
169 
170  undersizeCols.forEach(function(column){
171  column.width = shrinkCols ? calcShrink(column) : calcGrow(column);
172  });
173  }
174 
175  return gap;
176  }
177 
178 
179  if(this.table.options.responsiveLayout && this.table.modExists("responsiveLayout", true)){
180  this.table.modules.responsiveLayout.update();
181  }
182 
183  //adjust for vertical scrollbar if present
184  if(this.table.rowManager.element.scrollHeight > this.table.rowManager.element.clientHeight){
185  totalWidth -= this.table.rowManager.element.offsetWidth - this.table.rowManager.element.clientWidth;
186  }
187 
188  columns.forEach(function(column){
189  var width, minWidth, colWidth;
190 
191  if(column.visible){
192 
193  width = column.definition.width;
194  minWidth = parseInt(column.minWidth);
195 
196  if(width){
197 
198  colWidth = calcWidth(width);
199 
200  fixedWidth += colWidth > minWidth ? colWidth : minWidth;
201 
202  if(column.definition.widthShrink){
203  fixedShrinkColumns.push({
204  column:column,
205  width:colWidth > minWidth ? colWidth : minWidth
206  });
207  flexShrinkUnits += column.definition.widthShrink;
208  }
209 
210  }else{
211  flexColumns.push({
212  column:column,
213  width:0,
214  });
215  flexGrowUnits += column.definition.widthGrow || 1;
216  }
217  }
218  });
219 
220 
221  //calculate available space
222  flexWidth = totalWidth - fixedWidth;
223 
224  //calculate correct column size
225  flexColWidth = Math.floor(flexWidth / flexGrowUnits)
226 
227  //generate column widths
228  var gapFill = scaleColumns(flexColumns, flexWidth, flexColWidth, false);
229 
230  //increase width of last column to account for rounding errors
231  if(flexColumns.length && gapFill > 0){
232  flexColumns[flexColumns.length-1].width += + gapFill;
233  }
234 
235  //caculate space for columns to be shrunk into
236  flexColumns.forEach(function(col){
237  flexWidth -= col.width;
238  })
239 
240  overflowWidth = Math.abs(gapFill) + flexWidth;
241 
242 
243  //shrink oversize columns if there is no available space
244  if(overflowWidth > 0 && flexShrinkUnits){
245  gapFill = scaleColumns(fixedShrinkColumns, overflowWidth, Math.floor(overflowWidth / flexShrinkUnits), true);
246  }
247 
248  //decrease width of last column to account for rounding errors
249  if(fixedShrinkColumns.length){
250  fixedShrinkColumns[fixedShrinkColumns.length-1].width -= gapFill;
251  }
252 
253 
254  flexColumns.forEach(function(col){
255  col.column.setWidth(col.width);
256  });
257 
258  fixedShrinkColumns.forEach(function(col){
259  col.column.setWidth(col.width);
260  });
261 
262  },
263 };
264 
265 
266 Tabulator.prototype.registerModule("layout", Layout);