otsdaq_utilities  v2_05_02_indev
column.js
1 
2 //public column object
3 var ColumnComponent = function (column){
4  this._column = column;
5  this.type = "ColumnComponent";
6 };
7 
8 ColumnComponent.prototype.getElement = function(){
9  return this._column.getElement();
10 };
11 
12 ColumnComponent.prototype.getDefinition = function(){
13  return this._column.getDefinition();
14 };
15 
16 ColumnComponent.prototype.getField = function(){
17  return this._column.getField();
18 };
19 
20 ColumnComponent.prototype.getCells = function(){
21  var cells = [];
22 
23  this._column.cells.forEach(function(cell){
24  cells.push(cell.getComponent());
25  });
26 
27  return cells;
28 };
29 
30 ColumnComponent.prototype.getVisibility = function(){
31  return this._column.visible;
32 };
33 
34 ColumnComponent.prototype.show = function(){
35  if(this._column.isGroup){
36  this._column.columns.forEach(function(column){
37  column.show();
38  });
39  }else{
40  this._column.show();
41  }
42 };
43 
44 ColumnComponent.prototype.hide = function(){
45  if(this._column.isGroup){
46  this._column.columns.forEach(function(column){
47  column.hide();
48  });
49  }else{
50  this._column.hide();
51  }
52 };
53 
54 ColumnComponent.prototype.toggle = function(){
55  if(this._column.visible){
56  this.hide();
57  }else{
58  this.show();
59  }
60 };
61 
62 ColumnComponent.prototype.delete = function(){
63  return this._column.delete();
64 };
65 
66 ColumnComponent.prototype.getSubColumns = function(){
67  var output = [];
68 
69  if(this._column.columns.length){
70  this._column.columns.forEach(function(column){
71  output.push(column.getComponent());
72  });
73  }
74 
75  return output;
76 };
77 
78 ColumnComponent.prototype.getParentColumn = function(){
79  return this._column.parent instanceof Column ? this._column.parent.getComponent() : false;
80 };
81 
82 
83 ColumnComponent.prototype._getSelf = function(){
84  return this._column;
85 };
86 
87 ColumnComponent.prototype.scrollTo = function(){
88  return this._column.table.columnManager.scrollToColumn(this._column);
89 };
90 
91 ColumnComponent.prototype.getTable = function(){
92  return this._column.table;
93 };
94 
95 ColumnComponent.prototype.headerFilterFocus = function(){
96  if(this._column.table.modExists("filter", true)){
97  this._column.table.modules.filter.setHeaderFilterFocus(this._column);
98  }
99 };
100 
101 ColumnComponent.prototype.reloadHeaderFilter = function(){
102  if(this._column.table.modExists("filter", true)){
103  this._column.table.modules.filter.reloadHeaderFilter(this._column);
104  }
105 };
106 
107 ColumnComponent.prototype.setHeaderFilterValue = function(value){
108  if(this._column.table.modExists("filter", true)){
109  this._column.table.modules.filter.setHeaderFilterValue(this._column, value);
110  }
111 };
112 
113 ColumnComponent.prototype.move = function(to, after){
114  var toColumn = this._column.table.columnManager.findColumn(to);
115 
116  if(toColumn){
117  this._column.table.columnManager.moveColumn(this._column, toColumn, after)
118  }else{
119  console.warn("Move Error - No matching column found:", toColumn);
120  }
121 };
122 
123 ColumnComponent.prototype.getNextColumn = function(){
124  var nextCol = this._column.nextColumn();
125 
126  return nextCol ? nextCol.getComponent() : false;
127 };
128 
129 ColumnComponent.prototype.getPrevColumn = function(){
130  var prevCol = this._column.prevColumn();
131 
132  return prevCol ? prevCol.getComponent() : false;
133 };
134 
135 ColumnComponent.prototype.updateDefinition = function(updates){
136  return this._column.updateDefinition(updates);
137 };
138 
139 
140 
141 var Column = function(def, parent){
142  var self = this;
143 
144  this.table = parent.table;
145  this.definition = def; //column definition
146  this.parent = parent; //hold parent object
147  this.type = "column"; //type of element
148  this.columns = []; //child columns
149  this.cells = []; //cells bound to this column
150  this.element = this.createElement(); //column header element
151  this.contentElement = false;
152  this.groupElement = this.createGroupElement(); //column group holder element
153  this.isGroup = false;
154  this.tooltip = false; //hold column tooltip
155  this.hozAlign = ""; //horizontal text alignment
156 
157  //multi dimensional filed handling
158  this.field ="";
159  this.fieldStructure = "";
160  this.getFieldValue = "";
161  this.setFieldValue = "";
162 
163  this.titleFormatterRendered = false;
164 
165  this.setField(this.definition.field);
166 
167  if(this.table.options.invalidOptionWarnings){
168  this.checkDefinition();
169  }
170 
171  this.modules = {}; //hold module variables;
172 
173  this.cellEvents = {
174  cellClick:false,
175  cellDblClick:false,
176  cellContext:false,
177  cellTap:false,
178  cellDblTap:false,
179  cellTapHold:false,
180  cellMouseEnter:false,
181  cellMouseLeave:false,
182  cellMouseOver:false,
183  cellMouseOut:false,
184  cellMouseMove:false,
185  };
186 
187  this.width = null; //column width
188  this.widthStyled = ""; //column width prestyled to improve render efficiency
189  this.minWidth = null; //column minimum width
190  this.minWidthStyled = ""; //column minimum prestyled to improve render efficiency
191  this.widthFixed = false; //user has specified a width for this column
192 
193  this.visible = true; //default visible state
194 
195  this._mapDepricatedFunctionality();
196 
197  //initialize column
198  if(def.columns){
199 
200  this.isGroup = true;
201 
202  def.columns.forEach(function(def, i){
203  var newCol = new Column(def, self);
204  self.attachColumn(newCol);
205  });
206 
207  self.checkColumnVisibility();
208  }else{
209  parent.registerColumnField(this);
210  }
211 
212  if(def.rowHandle && this.table.options.movableRows !== false && this.table.modExists("moveRow")){
213  this.table.modules.moveRow.setHandle(true);
214  }
215 
216  this._buildHeader();
217 
218  this.bindModuleColumns();
219 };
220 
221 Column.prototype.createElement = function (){
222  var el = document.createElement("div");
223 
224  el.classList.add("tabulator-col");
225  el.setAttribute("role", "columnheader");
226  el.setAttribute("aria-sort", "none");
227 
228  return el;
229 };
230 
231 Column.prototype.createGroupElement = function (){
232  var el = document.createElement("div");
233 
234  el.classList.add("tabulator-col-group-cols");
235 
236  return el;
237 };
238 
239 Column.prototype.checkDefinition = function(){
240  Object.keys(this.definition).forEach((key) => {
241  if(this.defaultOptionList.indexOf(key) === -1){
242  console.warn("Invalid column definition option in '" + (this.field || this.definition.title) + "' column:", key)
243  }
244  });
245 };
246 
247 Column.prototype.setField = function(field){
248  this.field = field;
249  this.fieldStructure = field ? (this.table.options.nestedFieldSeparator ? field.split(this.table.options.nestedFieldSeparator) : [field]) : [];
250  this.getFieldValue = this.fieldStructure.length > 1 ? this._getNestedData : this._getFlatData;
251  this.setFieldValue = this.fieldStructure.length > 1 ? this._setNesteData : this._setFlatData;
252 };
253 
254 //register column position with column manager
255 Column.prototype.registerColumnPosition = function(column){
256  this.parent.registerColumnPosition(column);
257 };
258 
259 //register column position with column manager
260 Column.prototype.registerColumnField = function(column){
261  this.parent.registerColumnField(column);
262 };
263 
264 //trigger position registration
265 Column.prototype.reRegisterPosition = function(){
266  if(this.isGroup){
267  this.columns.forEach(function(column){
268  column.reRegisterPosition();
269  });
270  }else{
271  this.registerColumnPosition(this);
272  }
273 };
274 
275 Column.prototype._mapDepricatedFunctionality = function(){
276  if(typeof this.definition.hideInHtml !== "undefined"){
277  this.definition.htmlOutput = !this.definition.hideInHtml;
278  console.warn("hideInHtml column definition property is deprecated, you should now use htmlOutput")
279  }
280 };
281 
282 Column.prototype.setTooltip = function(){
283  var self = this,
284  def = self.definition;
285 
286  //set header tooltips
287  var tooltip = def.headerTooltip || def.tooltip === false ? def.headerTooltip : self.table.options.tooltipsHeader;
288 
289  if(tooltip){
290  if(tooltip === true){
291  if(def.field){
292  self.table.modules.localize.bind("columns|" + def.field, function(value){
293  self.element.setAttribute("title", value || def.title);
294  });
295  }else{
296  self.element.setAttribute("title", def.title);
297  }
298 
299  }else{
300  if(typeof(tooltip) == "function"){
301  tooltip = tooltip(self.getComponent());
302 
303  if(tooltip === false){
304  tooltip = "";
305  }
306  }
307 
308  self.element.setAttribute("title", tooltip);
309  }
310 
311  }else{
312  self.element.setAttribute("title", "");
313  }
314 };
315 
316 //build header element
317 Column.prototype._buildHeader = function(){
318  var self = this,
319  def = self.definition;
320 
321  while(self.element.firstChild) self.element.removeChild(self.element.firstChild);
322 
323  if(def.headerVertical){
324  self.element.classList.add("tabulator-col-vertical");
325 
326  if(def.headerVertical === "flip"){
327  self.element.classList.add("tabulator-col-vertical-flip");
328  }
329  }
330 
331  self.contentElement = self._bindEvents();
332 
333  self.contentElement = self._buildColumnHeaderContent();
334 
335  self.element.appendChild(self.contentElement);
336 
337  if(self.isGroup){
338  self._buildGroupHeader();
339  }else{
340  self._buildColumnHeader();
341  }
342 
343  self.setTooltip();
344 
345  //set resizable handles
346  if(self.table.options.resizableColumns && self.table.modExists("resizeColumns")){
347  self.table.modules.resizeColumns.initializeColumn("header", self, self.element);
348  }
349 
350  //set resizable handles
351  if(def.headerFilter && self.table.modExists("filter") && self.table.modExists("edit")){
352  if(typeof def.headerFilterPlaceholder !== "undefined" && def.field){
353  self.table.modules.localize.setHeaderFilterColumnPlaceholder(def.field, def.headerFilterPlaceholder);
354  }
355 
356  self.table.modules.filter.initializeColumn(self);
357  }
358 
359 
360  //set resizable handles
361  if(self.table.modExists("frozenColumns")){
362  self.table.modules.frozenColumns.initializeColumn(self);
363  }
364 
365  //set movable column
366  if(self.table.options.movableColumns && !self.isGroup && self.table.modExists("moveColumn")){
367  self.table.modules.moveColumn.initializeColumn(self);
368  }
369 
370  //set calcs column
371  if((def.topCalc || def.bottomCalc) && self.table.modExists("columnCalcs")){
372  self.table.modules.columnCalcs.initializeColumn(self);
373  }
374 
375  //handle persistence
376  if(self.table.modExists("persistence") && self.table.modules.persistence.config.columns){
377  self.table.modules.persistence.initializeColumn(self);
378  }
379 
380 
381  //update header tooltip on mouse enter
382  self.element.addEventListener("mouseenter", function(e){
383  self.setTooltip();
384  });
385 };
386 
387 Column.prototype._bindEvents = function(){
388 
389  var self = this,
390  def = self.definition,
391  dblTap, tapHold, tap;
392 
393  //setup header click event bindings
394  if(typeof(def.headerClick) == "function"){
395  self.element.addEventListener("click", function(e){def.headerClick(e, self.getComponent());});
396  }
397 
398  if(typeof(def.headerDblClick) == "function"){
399  self.element.addEventListener("dblclick", function(e){def.headerDblClick(e, self.getComponent());});
400  }
401 
402  if(typeof(def.headerContext) == "function"){
403  self.element.addEventListener("contextmenu", function(e){def.headerContext(e, self.getComponent());});
404  }
405 
406  //setup header tap event bindings
407  if(typeof(def.headerTap) == "function"){
408  tap = false;
409 
410  self.element.addEventListener("touchstart", function(e){
411  tap = true;
412  }, {passive: true});
413 
414  self.element.addEventListener("touchend", function(e){
415  if(tap){
416  def.headerTap(e, self.getComponent());
417  }
418 
419  tap = false;
420  });
421  }
422 
423  if(typeof(def.headerDblTap) == "function"){
424  dblTap = null;
425 
426  self.element.addEventListener("touchend", function(e){
427 
428  if(dblTap){
429  clearTimeout(dblTap);
430  dblTap = null;
431 
432  def.headerDblTap(e, self.getComponent());
433  }else{
434 
435  dblTap = setTimeout(function(){
436  clearTimeout(dblTap);
437  dblTap = null;
438  }, 300);
439  }
440 
441  });
442  }
443 
444  if(typeof(def.headerTapHold) == "function"){
445  tapHold = null;
446 
447  self.element.addEventListener("touchstart", function(e){
448  clearTimeout(tapHold);
449 
450  tapHold = setTimeout(function(){
451  clearTimeout(tapHold);
452  tapHold = null;
453  tap = false;
454  def.headerTapHold(e, self.getComponent());
455  }, 1000);
456 
457  }, {passive: true});
458 
459  self.element.addEventListener("touchend", function(e){
460  clearTimeout(tapHold);
461  tapHold = null;
462  });
463  }
464 
465  //store column cell click event bindings
466  if(typeof(def.cellClick) == "function"){
467  self.cellEvents.cellClick = def.cellClick;
468  }
469 
470  if(typeof(def.cellDblClick) == "function"){
471  self.cellEvents.cellDblClick = def.cellDblClick;
472  }
473 
474  if(typeof(def.cellContext) == "function"){
475  self.cellEvents.cellContext = def.cellContext;
476  }
477 
478  //store column mouse event bindings
479  if(typeof(def.cellMouseEnter) == "function"){
480  self.cellEvents.cellMouseEnter = def.cellMouseEnter;
481  }
482 
483  if(typeof(def.cellMouseLeave) == "function"){
484  self.cellEvents.cellMouseLeave = def.cellMouseLeave;
485  }
486 
487  if(typeof(def.cellMouseOver) == "function"){
488  self.cellEvents.cellMouseOver = def.cellMouseOver;
489  }
490 
491  if(typeof(def.cellMouseOut) == "function"){
492  self.cellEvents.cellMouseOut = def.cellMouseOut;
493  }
494 
495  if(typeof(def.cellMouseMove) == "function"){
496  self.cellEvents.cellMouseMove = def.cellMouseMove;
497  }
498 
499  //setup column cell tap event bindings
500  if(typeof(def.cellTap) == "function"){
501  self.cellEvents.cellTap = def.cellTap;
502  }
503 
504  if(typeof(def.cellDblTap) == "function"){
505  self.cellEvents.cellDblTap = def.cellDblTap;
506  }
507 
508  if(typeof(def.cellTapHold) == "function"){
509  self.cellEvents.cellTapHold = def.cellTapHold;
510  }
511 
512  //setup column cell edit callbacks
513  if(typeof(def.cellEdited) == "function"){
514  self.cellEvents.cellEdited = def.cellEdited;
515  }
516 
517  if(typeof(def.cellEditing) == "function"){
518  self.cellEvents.cellEditing = def.cellEditing;
519  }
520 
521  if(typeof(def.cellEditCancelled) == "function"){
522  self.cellEvents.cellEditCancelled = def.cellEditCancelled;
523  }
524 };
525 
526 //build header element for header
527 Column.prototype._buildColumnHeader = function(){
528  var self = this,
529  def = self.definition,
530  table = self.table,
531  sortable;
532 
533  //set column sorter
534  if(table.modExists("sort")){
535  table.modules.sort.initializeColumn(self, self.contentElement);
536  }
537 
538  //set column formatter
539  if(table.modExists("format")){
540  table.modules.format.initializeColumn(self);
541  }
542 
543  //set column editor
544  if(typeof def.editor != "undefined" && table.modExists("edit")){
545  table.modules.edit.initializeColumn(self);
546  }
547 
548  //set colum validator
549  if(typeof def.validator != "undefined" && table.modExists("validate")){
550  table.modules.validate.initializeColumn(self);
551  }
552 
553 
554  //set column mutator
555  if(table.modExists("mutator")){
556  table.modules.mutator.initializeColumn(self);
557  }
558 
559  //set column accessor
560  if(table.modExists("accessor")){
561  table.modules.accessor.initializeColumn(self);
562  }
563 
564  //set respoviveLayout
565  if(typeof table.options.responsiveLayout && table.modExists("responsiveLayout")){
566  table.modules.responsiveLayout.initializeColumn(self);
567  }
568 
569  //set column visibility
570  if(typeof def.visible != "undefined"){
571  if(def.visible){
572  self.show(true);
573  }else{
574  self.hide(true);
575  }
576  }
577 
578  //asign additional css classes to column header
579  if(def.cssClass){
580  var classeNames = def.cssClass.split(" ");
581  classeNames.forEach(function(className) {
582  self.element.classList.add(className)
583  });
584  }
585 
586  if(def.field){
587  this.element.setAttribute("tabulator-field", def.field);
588  }
589 
590  //set min width if present
591  self.setMinWidth(typeof def.minWidth == "undefined" ? self.table.options.columnMinWidth : parseInt(def.minWidth));
592 
593  self.reinitializeWidth();
594 
595  //set tooltip if present
596  self.tooltip = self.definition.tooltip || self.definition.tooltip === false ? self.definition.tooltip : self.table.options.tooltips;
597 
598  //set orizontal text alignment
599  self.hozAlign = typeof(self.definition.align) == "undefined" ? "" : self.definition.align;
600 };
601 
602 Column.prototype._buildColumnHeaderContent = function(){
603  var self = this,
604  def = self.definition,
605  table = self.table;
606 
607  var contentElement = document.createElement("div");
608  contentElement.classList.add("tabulator-col-content");
609 
610  contentElement.appendChild(self._buildColumnHeaderTitle());
611 
612  return contentElement;
613 };
614 
615 //build title element of column
616 Column.prototype._buildColumnHeaderTitle = function(){
617  var self = this,
618  def = self.definition,
619  table = self.table,
620  title;
621 
622  var titleHolderElement = document.createElement("div");
623  titleHolderElement.classList.add("tabulator-col-title");
624 
625  if(def.editableTitle){
626  var titleElement = document.createElement("input");
627  titleElement.classList.add("tabulator-title-editor");
628 
629  titleElement.addEventListener("click", function(e){
630  e.stopPropagation();
631  titleElement.focus();
632  });
633 
634  titleElement.addEventListener("change", function(){
635  def.title = titleElement.value;
636  table.options.columnTitleChanged.call(self.table, self.getComponent());
637  });
638 
639  titleHolderElement.appendChild(titleElement);
640 
641  if(def.field){
642  table.modules.localize.bind("columns|" + def.field, function(text){
643  titleElement.value = text || (def.title || " ");
644  });
645  }else{
646  titleElement.value = def.title || " ";
647  }
648 
649  }else{
650  if(def.field){
651  table.modules.localize.bind("columns|" + def.field, function(text){
652  self._formatColumnHeaderTitle(titleHolderElement, text || (def.title || " "));
653  });
654  }else{
655  self._formatColumnHeaderTitle(titleHolderElement, def.title || " ");
656  }
657  }
658 
659  return titleHolderElement;
660 };
661 
662 Column.prototype._formatColumnHeaderTitle = function(el, title){
663  var formatter, contents, params, mockCell, onRendered;
664 
665  if(this.definition.titleFormatter && this.table.modExists("format")){
666 
667  formatter = this.table.modules.format.getFormatter(this.definition.titleFormatter);
668 
669  onRendered = (callback) => {
670  this.titleFormatterRendered = callback;
671  };
672 
673  mockCell = {
674  getValue:function(){
675  return title;
676  },
677  getElement:function(){
678  return el;
679  }
680  };
681 
682  params = this.definition.titleFormatterParams || {};
683 
684  params = typeof params === "function" ? params() : params;
685 
686  contents = formatter.call(this.table.modules.format, mockCell, params, onRendered);
687 
688  switch(typeof contents){
689  case "object":
690  if(contents instanceof Node){
691  el.appendChild(contents);
692  }else{
693  el.innerHTML = "";
694  console.warn("Format Error - Title formatter has returned a type of object, the only valid formatter object return is an instance of Node, the formatter returned:", contents);
695  }
696  break;
697  case "undefined":
698  case "null":
699  el.innerHTML = "";
700  break;
701  default:
702  el.innerHTML = contents;
703  }
704  }else{
705  el.innerHTML = title;
706  }
707 };
708 
709 
710 //build header element for column group
711 Column.prototype._buildGroupHeader = function(){
712  this.element.classList.add("tabulator-col-group");
713  this.element.setAttribute("role", "columngroup");
714  this.element.setAttribute("aria-title", this.definition.title);
715 
716  //asign additional css classes to column header
717  if(this.definition.cssClass){
718  var classeNames = this.definition.cssClass.split(" ");
719  classeNames.forEach((className) => {
720  this.element.classList.add(className);
721  });
722  }
723 
724  this.element.appendChild(this.groupElement);
725 };
726 
727 //flat field lookup
728 Column.prototype._getFlatData = function(data){
729  return data[this.field];
730 };
731 
732 //nested field lookup
733 Column.prototype._getNestedData = function(data){
734  var dataObj = data,
735  structure = this.fieldStructure,
736  length = structure.length,
737  output;
738 
739  for(let i = 0; i < length; i++){
740 
741  dataObj = dataObj[structure[i]];
742 
743  output = dataObj;
744 
745  if(!dataObj){
746  break;
747  }
748  }
749 
750  return output;
751 };
752 
753 //flat field set
754 Column.prototype._setFlatData = function(data, value){
755  if(this.field){
756  data[this.field] = value;
757  }
758 };
759 
760 //nested field set
761 Column.prototype._setNesteData = function(data, value){
762  var dataObj = data,
763  structure = this.fieldStructure,
764  length = structure.length;
765 
766  for(let i = 0; i < length; i++){
767 
768  if(i == length -1){
769  dataObj[structure[i]] = value;
770  }else{
771  if(!dataObj[structure[i]]){
772  dataObj[structure[i]] = {};
773  }
774 
775  dataObj = dataObj[structure[i]];
776  }
777  }
778 };
779 
780 
781 //attach column to this group
782 Column.prototype.attachColumn = function(column){
783  var self = this;
784 
785  if(self.groupElement){
786  self.columns.push(column);
787  self.groupElement.appendChild(column.getElement());
788  }else{
789  console.warn("Column Warning - Column being attached to another column instead of column group");
790  }
791 };
792 
793 //vertically align header in column
794 Column.prototype.verticalAlign = function(alignment, height){
795 
796  //calculate height of column header and group holder element
797  var parentHeight = this.parent.isGroup ? this.parent.getGroupElement().clientHeight : (height || this.parent.getHeadersElement().clientHeight);
798  // var parentHeight = this.parent.isGroup ? this.parent.getGroupElement().clientHeight : this.parent.getHeadersElement().clientHeight;
799 
800  this.element.style.height = parentHeight + "px";
801 
802  if(this.isGroup){
803  this.groupElement.style.minHeight = (parentHeight - this.contentElement.offsetHeight) + "px";
804  }
805 
806  //vertically align cell contents
807  if(!this.isGroup && alignment !== "top"){
808  if(alignment === "bottom"){
809  this.element.style.paddingTop = (this.element.clientHeight - this.contentElement.offsetHeight) + "px";
810  }else{
811  this.element.style.paddingTop = ((this.element.clientHeight - this.contentElement.offsetHeight) / 2) + "px";
812  }
813  }
814 
815  this.columns.forEach(function(column){
816  column.verticalAlign(alignment);
817  });
818 };
819 
820 //clear vertical alignmenet
821 Column.prototype.clearVerticalAlign = function(){
822  this.element.style.paddingTop = "";
823  this.element.style.height = "";
824  this.element.style.minHeight = "";
825  this.groupElement.style.minHeight = "";
826 
827  this.columns.forEach(function(column){
828  column.clearVerticalAlign();
829  });
830 };
831 
832 Column.prototype.bindModuleColumns = function (){
833  //check if rownum formatter is being used on a column
834  if(this.definition.formatter == "rownum"){
835  this.table.rowManager.rowNumColumn = this;
836  }
837 };
838 
839 
841 
842 //return column header element
843 Column.prototype.getElement = function(){
844  return this.element;
845 };
846 
847 //return colunm group element
848 Column.prototype.getGroupElement = function(){
849  return this.groupElement;
850 };
851 
852 //return field name
853 Column.prototype.getField = function(){
854  return this.field;
855 };
856 
857 //return the first column in a group
858 Column.prototype.getFirstColumn = function(){
859  if(!this.isGroup){
860  return this;
861  }else{
862  if(this.columns.length){
863  return this.columns[0].getFirstColumn();
864  }else{
865  return false;
866  }
867  }
868 };
869 
870 //return the last column in a group
871 Column.prototype.getLastColumn = function(){
872  if(!this.isGroup){
873  return this;
874  }else{
875  if(this.columns.length){
876  return this.columns[this.columns.length -1].getLastColumn();
877  }else{
878  return false;
879  }
880  }
881 };
882 
883 //return all columns in a group
884 Column.prototype.getColumns = function(){
885  return this.columns;
886 };
887 
888 //return all columns in a group
889 Column.prototype.getCells = function(){
890  return this.cells;
891 };
892 
893 //retreive the top column in a group of columns
894 Column.prototype.getTopColumn = function(){
895  if(this.parent.isGroup){
896  return this.parent.getTopColumn();
897  }else{
898  return this;
899  }
900 };
901 
902 //return column definition object
903 Column.prototype.getDefinition = function(updateBranches){
904  var colDefs = [];
905 
906  if(this.isGroup && updateBranches){
907  this.columns.forEach(function(column){
908  colDefs.push(column.getDefinition(true));
909  });
910 
911  this.definition.columns = colDefs;
912  }
913 
914  return this.definition;
915 };
916 
918 
919 Column.prototype.checkColumnVisibility = function(){
920  var visible = false;
921 
922  this.columns.forEach(function(column){
923  if(column.visible){
924  visible = true;
925  }
926  });
927 
928 
929 
930  if(visible){
931  this.show();
932  this.parent.table.options.columnVisibilityChanged.call(this.table, this.getComponent(), false);
933  }else{
934  this.hide();
935  }
936 
937 };
938 
939 //show column
940 Column.prototype.show = function(silent, responsiveToggle){
941  if(!this.visible){
942  this.visible = true;
943 
944  this.element.style.display = "";
945 
946  if(this.parent.isGroup){
947  this.parent.checkColumnVisibility();
948  }
949 
950  this.cells.forEach(function(cell){
951  cell.show();
952  });
953 
954  if(!this.isGroup && this.width === null){
955  this.reinitializeWidth();
956  }
957 
958  this.table.columnManager._verticalAlignHeaders();
959 
960  if(this.table.options.persistence && this.table.modExists("persistence", true) && this.table.modules.persistence.config.columns){
961  this.table.modules.persistence.save("columns");
962  }
963 
964  if(!responsiveToggle && this.table.options.responsiveLayout && this.table.modExists("responsiveLayout", true)){
965  this.table.modules.responsiveLayout.updateColumnVisibility(this, this.visible);
966  }
967 
968  if(!silent){
969  this.table.options.columnVisibilityChanged.call(this.table, this.getComponent(), true);
970  }
971 
972  if(this.parent.isGroup){
973  this.parent.matchChildWidths();
974  }
975  }
976 };
977 
978 //hide column
979 Column.prototype.hide = function(silent, responsiveToggle){
980  if(this.visible){
981  this.visible = false;
982 
983  this.element.style.display = "none";
984 
985  this.table.columnManager._verticalAlignHeaders();
986 
987  if(this.parent.isGroup){
988  this.parent.checkColumnVisibility();
989  }
990 
991  this.cells.forEach(function(cell){
992  cell.hide();
993  });
994 
995  if(this.table.options.persistence && this.table.modExists("persistence", true) && this.table.modules.persistence.config.columns){
996  this.table.modules.persistence.save("columns");
997  }
998 
999  if(!responsiveToggle && this.table.options.responsiveLayout && this.table.modExists("responsiveLayout", true)){
1000  this.table.modules.responsiveLayout.updateColumnVisibility(this, this.visible);
1001  }
1002 
1003  if(!silent){
1004  this.table.options.columnVisibilityChanged.call(this.table, this.getComponent(), false);
1005  }
1006 
1007  if(this.parent.isGroup){
1008  this.parent.matchChildWidths();
1009  }
1010  }
1011 };
1012 
1013 Column.prototype.matchChildWidths = function(){
1014  var childWidth = 0;
1015 
1016  if(this.contentElement && this.columns.length){
1017  this.columns.forEach(function(column){
1018  if(column.visible){
1019  childWidth += column.getWidth();
1020  }
1021  });
1022 
1023  this.contentElement.style.maxWidth = (childWidth - 1) + "px";
1024  }
1025 };
1026 
1027 Column.prototype.setWidth = function(width){
1028  this.widthFixed = true;
1029  this.setWidthActual(width);
1030 };
1031 
1032 Column.prototype.setWidthActual = function(width){
1033  if(isNaN(width)){
1034  width = Math.floor((this.table.element.clientWidth/100) * parseInt(width));
1035  }
1036 
1037  width = Math.max(this.minWidth, width);
1038 
1039  this.width = width;
1040  this.widthStyled = width ? width + "px" : "";
1041 
1042  this.element.style.width = this.widthStyled;
1043 
1044  if(!this.isGroup){
1045  this.cells.forEach(function(cell){
1046  cell.setWidth();
1047  });
1048  }
1049 
1050  if(this.parent.isGroup){
1051  this.parent.matchChildWidths();
1052  }
1053 
1054  //set resizable handles
1055  if(this.table.modExists("frozenColumns")){
1056  this.table.modules.frozenColumns.layout();
1057  }
1058 };
1059 
1060 
1061 Column.prototype.checkCellHeights = function(){
1062  var rows = [];
1063 
1064  this.cells.forEach(function(cell){
1065  if(cell.row.heightInitialized){
1066  if(cell.row.getElement().offsetParent !== null){
1067  rows.push(cell.row);
1068  cell.row.clearCellHeight();
1069  }else{
1070  cell.row.heightInitialized = false;
1071  }
1072  }
1073  });
1074 
1075  rows.forEach(function(row){
1076  row.calcHeight();
1077  });
1078 
1079  rows.forEach(function(row){
1080  row.setCellHeight();
1081  });
1082 };
1083 
1084 Column.prototype.getWidth = function(){
1085  // return this.element.offsetWidth;
1086  return this.width;
1087 };
1088 
1089 Column.prototype.getHeight = function(){
1090  return this.element.offsetHeight;
1091 };
1092 
1093 Column.prototype.setMinWidth = function(minWidth){
1094  this.minWidth = minWidth;
1095  this.minWidthStyled = minWidth ? minWidth + "px" : "";
1096 
1097  this.element.style.minWidth = this.minWidthStyled;
1098 
1099  this.cells.forEach(function(cell){
1100  cell.setMinWidth();
1101  });
1102 };
1103 
1104 Column.prototype.delete = function(){
1105  return new Promise((resolve, reject) => {
1106 
1107  if(this.isGroup){
1108  this.columns.forEach(function(column){
1109  column.delete();
1110  });
1111  }
1112 
1113  var cellCount = this.cells.length;
1114 
1115  for(let i = 0; i < cellCount; i++){
1116  this.cells[0].delete();
1117  }
1118 
1119  this.element.parentNode.removeChild(this.element);
1120 
1121  this.table.columnManager.deregisterColumn(this);
1122 
1123  resolve();
1124  });
1125 };
1126 
1127 Column.prototype.columnRendered = function(){
1128  if(this.titleFormatterRendered){
1129  this.titleFormatterRendered();
1130  }
1131 };
1132 
1134 
1135 //generate cell for this column
1136 Column.prototype.generateCell = function(row){
1137  var self = this;
1138 
1139  var cell = new Cell(self, row);
1140 
1141  this.cells.push(cell);
1142 
1143  return cell;
1144 };
1145 
1146 Column.prototype.nextColumn = function(){
1147  var index = this.table.columnManager.findColumnIndex(this);
1148  return index > -1 ? this._nextVisibleColumn(index + 1) : false;
1149 };
1150 
1151 Column.prototype._nextVisibleColumn = function(index){
1152  var column = this.table.columnManager.getColumnByIndex(index);
1153  return !column || column.visible ? column : this._nextVisibleColumn(index + 1);
1154 };
1155 
1156 Column.prototype.prevColumn = function(){
1157  var index = this.table.columnManager.findColumnIndex(this);
1158  return index > -1 ? this._prevVisibleColumn(index - 1) : false;
1159 };
1160 
1161 Column.prototype._prevVisibleColumn = function(index){
1162  var column = this.table.columnManager.getColumnByIndex(index);
1163  return !column || column.visible ? column : this._prevVisibleColumn(index - 1);
1164 };
1165 
1166 Column.prototype.reinitializeWidth = function(force){
1167  this.widthFixed = false;
1168 
1169  //set width if present
1170  if(typeof this.definition.width !== "undefined" && !force){
1171  this.setWidth(this.definition.width);
1172  }
1173 
1174  //hide header filters to prevent them altering column width
1175  if(this.table.modExists("filter")){
1176  this.table.modules.filter.hideHeaderFilterElements();
1177  }
1178 
1179  this.fitToData();
1180 
1181  //show header filters again after layout is complete
1182  if(this.table.modExists("filter")){
1183  this.table.modules.filter.showHeaderFilterElements();
1184  }
1185 };
1186 
1187 //set column width to maximum cell width
1188 Column.prototype.fitToData = function(){
1189  var self = this;
1190 
1191  if(!this.widthFixed){
1192  this.element.style.width = "";
1193 
1194  self.cells.forEach(function(cell){
1195  cell.clearWidth();
1196  });
1197  }
1198 
1199  var maxWidth = this.element.offsetWidth;
1200 
1201  if(!self.width || !this.widthFixed){
1202  self.cells.forEach(function(cell){
1203  var width = cell.getWidth();
1204 
1205  if(width > maxWidth){
1206  maxWidth = width;
1207  }
1208  });
1209 
1210  if(maxWidth){
1211  self.setWidthActual(maxWidth + 1);
1212  }
1213 
1214  }
1215 };
1216 
1217 Column.prototype.updateDefinition = function(updates){
1218  return new Promise((resolve, reject) => {
1219  var definition;
1220 
1221  if(!this.isGroup){
1222  definition = Object.assign({}, this.getDefinition());
1223  definition = Object.assign(definition, updates);
1224 
1225  this.table.columnManager.addColumn(definition, false, this)
1226  .then((column) => {
1227 
1228  if(definition.field == this.field){
1229  this.field = false; //cleair field name to prevent deletion of duplicate column from arrays
1230  }
1231 
1232  this.delete()
1233  .then(() => {
1234  resolve(column.getComponent());
1235  }).catch((err) => {
1236  reject(err);
1237  });
1238 
1239  }).catch((err) => {
1240  reject(err);
1241  });
1242  }else{
1243  console.warn("Column Update Error - The updateDefintion function is only available on columns, not column groups");
1244  reject("Column Update Error - The updateDefintion function is only available on columns, not column groups");
1245  }
1246  });
1247 };
1248 
1249 
1250 Column.prototype.deleteCell = function(cell){
1251  var index = this.cells.indexOf(cell);
1252 
1253  if(index > -1){
1254  this.cells.splice(index, 1);
1255  }
1256 };
1257 
1258 
1259 Column.prototype.defaultOptionList = [
1260 "title",
1261 "field",
1262 "columns",
1263 "visible",
1264 "align",
1265 "width",
1266 "minWidth",
1267 "widthGrow",
1268 "widthShrink",
1269 "resizable",
1270 "frozen",
1271 "responsive",
1272 "tooltip",
1273 "cssClass",
1274 "rowHandle",
1275 "hideInHtml",
1276 "print",
1277 "htmlOutput",
1278 "sorter",
1279 "sorterParams",
1280 "formatter",
1281 "formatterParams",
1282 "variableHeight",
1283 "editable",
1284 "editor",
1285 "editorParams",
1286 "validator",
1287 "mutator",
1288 "mutatorParams",
1289 "mutatorData",
1290 "mutatorDataParams",
1291 "mutatorEdit",
1292 "mutatorEditParams",
1293 "mutatorClipboard",
1294 "mutatorClipboardParams",
1295 "accessor",
1296 "accessorParams",
1297 "accessorData",
1298 "accessorDataParams",
1299 "accessorDownload",
1300 "accessorDownloadParams",
1301 "accessorClipboard",
1302 "accessorClipboardParams",
1303 "clipboard",
1304 "download",
1305 "downloadTitle",
1306 "topCalc",
1307 "topCalcParams",
1308 "topCalcFormatter",
1309 "topCalcFormatterParams",
1310 "bottomCalc",
1311 "bottomCalcParams",
1312 "bottomCalcFormatter",
1313 "bottomCalcFormatterParams",
1314 "cellClick",
1315 "cellDblClick",
1316 "cellContext",
1317 "cellTap",
1318 "cellDblTap",
1319 "cellTapHold",
1320 "cellMouseEnter",
1321 "cellMouseLeave",
1322 "cellMouseOver",
1323 "cellMouseOut",
1324 "cellMouseMove",
1325 "cellEditing",
1326 "cellEdited",
1327 "cellEditCancelled",
1328 "headerSort",
1329 "headerSortStartingDir",
1330 "headerSortTristate",
1331 "headerClick",
1332 "headerDblClick",
1333 "headerContext",
1334 "headerTap",
1335 "headerDblTap",
1336 "headerTapHold",
1337 "headerTooltip",
1338 "headerVertical",
1339 "editableTitle",
1340 "titleFormatter",
1341 "titleFormatterParams",
1342 "headerFilter",
1343 "headerFilterPlaceholder",
1344 "headerFilterParams",
1345 "headerFilterEmptyCheck",
1346 "headerFilterFunc",
1347 "headerFilterFuncParams",
1348 "headerFilterLiveFilter",
1349 "print",
1350 ];
1351 
1353 
1355 Column.prototype.getComponent = function(){
1356  return new ColumnComponent(this);
1357 };