1 var DataTree =
function(table){
5 this.collapseEl = null;
8 this.elementField =
false;
10 this.startOpen =
function(){};
12 this.displayIndex = 0;
15 DataTree.prototype.initialize =
function(){
17 firstCol = this.table.columnManager.getFirstVisibileColumn(),
18 options = this.table.options;
20 this.field = options.dataTreeChildField;
21 this.indent = options.dataTreeChildIndent;
22 this.elementField = options.dataTreeElementColumn || (firstCol ? firstCol.field :
false);
24 if(options.dataTreeBranchElement){
26 if(options.dataTreeBranchElement ===
true){
27 this.branchEl = document.createElement(
"div");
28 this.branchEl.classList.add(
"tabulator-data-tree-branch");
30 if(typeof options.dataTreeBranchElement ===
"string"){
31 dummyEl = document.createElement(
"div");
32 dummyEl.innerHTML = options.dataTreeBranchElement;
33 this.branchEl = dummyEl.firstChild;
35 this.branchEl = options.dataTreeBranchElement;
40 if(options.dataTreeCollapseElement){
41 if(typeof options.dataTreeCollapseElement ===
"string"){
42 dummyEl = document.createElement(
"div");
43 dummyEl.innerHTML = options.dataTreeCollapseElement;
44 this.collapseEl = dummyEl.firstChild;
46 this.collapseEl = options.dataTreeCollapseElement;
49 this.collapseEl = document.createElement(
"div");
50 this.collapseEl.classList.add(
"tabulator-data-tree-control");
51 this.collapseEl.tabIndex = 0;
52 this.collapseEl.innerHTML =
"<div class='tabulator-data-tree-control-collapse'></div>";
55 if(options.dataTreeExpandElement){
56 if(typeof options.dataTreeExpandElement ===
"string"){
57 dummyEl = document.createElement(
"div");
58 dummyEl.innerHTML = options.dataTreeExpandElement;
59 this.expandEl = dummyEl.firstChild;
61 this.expandEl = options.dataTreeExpandElement;
64 this.expandEl = document.createElement(
"div");
65 this.expandEl.classList.add(
"tabulator-data-tree-control");
66 this.expandEl.tabIndex = 0;
67 this.expandEl.innerHTML =
"<div class='tabulator-data-tree-control-expand'></div>";
71 switch(typeof options.dataTreeStartExpanded){
73 this.startOpen =
function(row, index){
74 return options.dataTreeStartExpanded;
79 this.startOpen = options.dataTreeStartExpanded;
83 this.startOpen =
function(row, index){
84 return options.dataTreeStartExpanded[index];
90 DataTree.prototype.initializeRow =
function(row){
91 var childArray = row.getData()[this.field];
92 var isArray = Array.isArray(childArray);
94 var children = isArray || (!isArray && typeof childArray ===
"object" && childArray !== null) ;
96 row.modules.dataTree = {
98 open:children ? this.startOpen(row.getComponent(), 0) :
false,
107 DataTree.prototype.layoutRow =
function(row){
108 var cell = this.elementField ? row.getCell(this.elementField) : row.getCells()[0],
109 el = cell.getElement(),
110 config = row.modules.dataTree;
113 config.branchEl.parentNode.removeChild(config.branchEl);
116 this.generateControlElement(row, el);
118 row.element.classList.add(
"tabulator-tree-level-" + config.index);
122 config.branchEl = this.branchEl.cloneNode(
true);
123 el.insertBefore(config.branchEl, el.firstChild);
124 config.branchEl.style.marginLeft = (((config.branchEl.offsetWidth + config.branchEl.style.marginRight) * (config.index - 1)) + (config.index *
this.indent)) +
"px";
126 el.style.paddingLeft = parseInt(window.getComputedStyle(el, null).getPropertyValue(
'padding-left')) + (config.index *
this.indent) +
"px";
131 DataTree.prototype.generateControlElement =
function(row, el){
132 var config = row.modules.dataTree,
133 el = el || row.getCells()[0].getElement(),
134 oldControl = config.controlEl;
136 if(config.children !==
false){
139 config.controlEl = this.collapseEl.cloneNode(
true);
140 config.controlEl.addEventListener(
"click", (e) => {
142 this.collapseRow(row);
145 config.controlEl = this.expandEl.cloneNode(
true);
146 config.controlEl.addEventListener(
"click", (e) => {
152 config.controlEl.addEventListener(
"mousedown", (e) => {
156 if(oldControl && oldControl.parentNode === el){
157 oldControl.parentNode.replaceChild(config.controlEl,oldControl);
159 el.insertBefore(config.controlEl, el.firstChild);
164 DataTree.prototype.setDisplayIndex =
function (index) {
165 this.displayIndex = index;
168 DataTree.prototype.getDisplayIndex =
function () {
169 return this.displayIndex;
172 DataTree.prototype.getRows =
function(rows){
175 rows.forEach((row, i) => {
176 var config, children;
180 if(row instanceof Row){
182 config = row.modules.dataTree.children;
184 if(!config.index && config.children !==
false){
185 children = this.getChildren(row);
187 children.forEach((child) => {
198 DataTree.prototype.getChildren =
function(row){
199 var config = row.modules.dataTree,
203 if(config.children !==
false && config.open){
204 if(!Array.isArray(config.children)){
205 config.children = this.generateChildren(row);
208 if(this.table.modExists(
"filter")){
209 children = this.table.modules.filter.filter(config.children);
211 children = config.children;
214 if(this.table.modExists(
"sort")){
215 this.table.modules.sort.sort(children);
218 children.forEach((child) => {
221 var subChildren = this.getChildren(child);
223 subChildren.forEach((sub) => {
233 DataTree.prototype.generateChildren =
function(row){
236 var childArray = row.getData()[this.field];
238 if(!Array.isArray(childArray)){
239 childArray = [childArray];
242 childArray.forEach((childData) => {
243 var childRow =
new Row(childData || {}, this.table.rowManager);
244 childRow.modules.dataTree.index = row.modules.dataTree.index + 1;
245 childRow.modules.dataTree.parent = row;
246 if(childRow.modules.dataTree.children){
247 childRow.modules.dataTree.open = this.startOpen(childRow.getComponent(), childRow.modules.dataTree.index);
249 children.push(childRow);
257 DataTree.prototype.expandRow =
function(row, silent){
258 var config = row.modules.dataTree;
260 if(config.children !==
false){
265 this.table.rowManager.refreshActiveData(
"tree",
false,
true);
267 this.table.options.dataTreeRowExpanded(row.getComponent(), row.modules.dataTree.index);
271 DataTree.prototype.collapseRow =
function(row){
272 var config = row.modules.dataTree;
274 if(config.children !==
false){
279 this.table.rowManager.refreshActiveData(
"tree",
false,
true);
281 this.table.options.dataTreeRowCollapsed(row.getComponent(), row.modules.dataTree.index);
285 DataTree.prototype.toggleRow =
function(row){
286 var config = row.modules.dataTree;
288 if(config.children !==
false){
290 this.collapseRow(row);
297 DataTree.prototype.getTreeParent =
function(row){
298 return row.modules.dataTree.parent ? row.modules.dataTree.parent.getComponent() :
false;
301 DataTree.prototype.getTreeChildren =
function(row){
302 var config = row.modules.dataTree,
307 if(!Array.isArray(config.children)){
308 config.children = this.generateChildren(row);
311 config.children.forEach((childRow) => {
312 if(childRow instanceof Row){
313 output.push(childRow.getComponent());
322 DataTree.prototype.checkForRestyle =
function(cell){
323 if(!cell.row.cells.indexOf(cell)){
324 if(cell.row.modules.dataTree.children !==
false){
325 cell.row.reinitialize();
330 DataTree.prototype.getChildField =
function(){
334 DataTree.prototype.redrawNeeded =
function(data){
335 return (this.field ? typeof data[this.field] !==
"undefined" :
false) || (this.elementField ? typeof data[this.elementField] !==
"undefined" :
false);
338 Tabulator.prototype.registerModule(
"dataTree", DataTree);