orgchart 6.0.0 → 7.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/publish.yml +11 -8
- package/README.md +47 -35
- package/README.zh-cn.md +73 -30
- package/README.zh-tw.md +73 -30
- package/demo/edit-chart.html +0 -4
- package/demo/edit-hybrid-chart.html +3 -4
- package/demo/index.html +5 -1
- package/demo/ondemand-loading-data.html +137 -80
- package/demo/options-compact-drag.html +82 -0
- package/demo/options-export-navigation.html +76 -0
- package/demo/options-horizontal-template.html +80 -0
- package/demo/options-hybrid-navigation.html +71 -0
- package/dist/css/orgchart.css +12 -1
- package/dist/css/orgchart.min.css +1 -1
- package/dist/js/orgchart.js +896 -523
- package/dist/js/orgchart.min.js +1 -1
- package/dist/js/orgchart.min.js.map +1 -1
- package/gulpfile.js +5 -1
- package/package.json +2 -1
- package/src/css/orgchart.css +12 -1
- package/src/js/orgchart.js +896 -523
- package/test/compatibility/README.md +123 -0
- package/test/compatibility/browser.tests.js +1279 -0
- package/test/compatibility/options.tests.js +628 -0
- package/test/cypress/e2e/demo-interactions.cy.js +3 -3
- package/test/cypress/e2e/demo-rendering.cy.js +62 -1
- package/test/cypress/e2e/drag-drop-hybrid-chart.cy.js +2 -1
- package/test/cypress/e2e/local-datasource.cy.js +16 -16
- package/test/cypress/e2e/ondemand-loading-data.cy.js +34 -10
- package/test/cypress/e2e/toggle-sibs-resp.cy.js +4 -4
- package/test/cypress/e2e/vertical-vevel.cy.js +5 -5
- package/test/integration/init-tests.js +30 -43
- package/test/integration/tests.js +21 -13
- package/test/unit/lifecycle-builders-export.tests.js +179 -118
- package/test/unit/tests.js +33 -34
package/src/js/orgchart.js
CHANGED
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
}
|
|
19
19
|
}(function (window, document, undefined) {
|
|
20
20
|
const elementDataStore = new WeakMap();
|
|
21
|
+
const nodeLayoutStore = new WeakMap();
|
|
21
22
|
const getWindow = () => (typeof globalThis !== 'undefined' && globalThis.window ? globalThis.window : window);
|
|
22
23
|
const getDocument = () => {
|
|
23
24
|
const currentWindow = getWindow();
|
|
@@ -41,10 +42,128 @@
|
|
|
41
42
|
return normalizeInput(input, context || getDocument());
|
|
42
43
|
}
|
|
43
44
|
|
|
45
|
+
function getChildNodesContainer(nodeElement) {
|
|
46
|
+
const nodeData = getState(nodeElement, 'sourceData');
|
|
47
|
+
const containers = Array.from(nodeElement.parentElement ? nodeElement.parentElement.children : []).filter(function (element) {
|
|
48
|
+
return element.classList.contains('nodes');
|
|
49
|
+
});
|
|
50
|
+
const ownedContainer = containers.find(function (container) {
|
|
51
|
+
return nodeData && getState(container, 'parentData') === nodeData;
|
|
52
|
+
});
|
|
53
|
+
if (ownedContainer) {
|
|
54
|
+
return ownedContainer;
|
|
55
|
+
}
|
|
56
|
+
if (containers.some(function (container) { return !!getState(container, 'parentData'); })) {
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
const nextElement = nodeElement.nextElementSibling;
|
|
60
|
+
if (nextElement && nextElement.classList.contains('nodes')) {
|
|
61
|
+
return nextElement;
|
|
62
|
+
}
|
|
63
|
+
if (nodeElement.parentElement && nodeElement.parentElement.classList.contains('hierarchy')) {
|
|
64
|
+
return Array.from(nodeElement.parentElement.children).find(function (element) {
|
|
65
|
+
return element.classList.contains('nodes');
|
|
66
|
+
}) || null;
|
|
67
|
+
}
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
|
|
44
71
|
function mergeObjects() {
|
|
45
72
|
return Object.assign.apply(Object, [{}].concat(Array.from(arguments)));
|
|
46
73
|
}
|
|
47
74
|
|
|
75
|
+
function mergeChartOptions(defaults) {
|
|
76
|
+
const options = mergeObjects({}, defaults);
|
|
77
|
+
options.icons = mergeObjects({}, defaults.icons);
|
|
78
|
+
Array.from(arguments).slice(1).forEach(function (overrides) {
|
|
79
|
+
if (!overrides) {
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
Object.assign(options, overrides, { icons: mergeObjects({}, options.icons, overrides.icons) });
|
|
83
|
+
if (Object.prototype.hasOwnProperty.call(overrides, 'drag')
|
|
84
|
+
&& !Object.prototype.hasOwnProperty.call(overrides, 'draggable')) {
|
|
85
|
+
options.draggable = overrides.drag;
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
options.visibleLevel = options.visibleLevel === true ? defaults.visibleLevel
|
|
89
|
+
: options.visibleLevel === false ? 1 : Number(options.visibleLevel);
|
|
90
|
+
if (!Number.isInteger(options.visibleLevel) || options.visibleLevel < 0) {
|
|
91
|
+
throw new RangeError('visibleLevel must be a nonnegative integer or boolean');
|
|
92
|
+
}
|
|
93
|
+
options.zoomoutLimit = Number(options.zoomoutLimit);
|
|
94
|
+
options.zoominLimit = Number(options.zoominLimit);
|
|
95
|
+
if (!Number.isFinite(options.zoomoutLimit) || !Number.isFinite(options.zoominLimit)
|
|
96
|
+
|| options.zoomoutLimit <= 0 || options.zoominLimit < options.zoomoutLimit) {
|
|
97
|
+
throw new RangeError('zoom limits must be positive and zoomoutLimit must not exceed zoominLimit');
|
|
98
|
+
}
|
|
99
|
+
if (!['t2b', 'b2t', 'l2r', 'r2l'].includes(options.direction)) {
|
|
100
|
+
throw new RangeError('direction must be t2b, b2t, l2r, or r2l');
|
|
101
|
+
}
|
|
102
|
+
return options;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function prepareNodeData(data, resetLayout) {
|
|
106
|
+
if (Array.isArray(data)) {
|
|
107
|
+
data.forEach(function (item) {
|
|
108
|
+
prepareNodeData(item, resetLayout);
|
|
109
|
+
});
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
if (!isPlainObject(data)) {
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
const layoutKeys = ['compact', 'associatedCompact', 'vertical', 'level', 'parentId'];
|
|
116
|
+
let layout = nodeLayoutStore.get(data);
|
|
117
|
+
if (!layout) {
|
|
118
|
+
layout = {};
|
|
119
|
+
layoutKeys.forEach(function (key) {
|
|
120
|
+
if (Object.prototype.hasOwnProperty.call(data, key)) {
|
|
121
|
+
layout[key] = data[key];
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
nodeLayoutStore.set(data, layout);
|
|
125
|
+
}
|
|
126
|
+
if (resetLayout) {
|
|
127
|
+
delete layout.level;
|
|
128
|
+
delete layout.parentId;
|
|
129
|
+
}
|
|
130
|
+
layoutKeys.forEach(function (key) {
|
|
131
|
+
if (Object.prototype.hasOwnProperty.call(layout, key)) {
|
|
132
|
+
data[key] = layout[key];
|
|
133
|
+
} else {
|
|
134
|
+
delete data[key];
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
(data.children || []).forEach(function (child) {
|
|
138
|
+
prepareNodeData(child, resetLayout);
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function usesCompactLayout(data, options, level) {
|
|
143
|
+
return !!data.compact && !data.hybrid && !data.vertical
|
|
144
|
+
&& !(options.verticalLevel && level + 1 >= options.verticalLevel);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function findDataLocation(datasource, target) {
|
|
148
|
+
let location = null;
|
|
149
|
+
const visit = function (data, parent, list, index, outerList, outerIndex) {
|
|
150
|
+
if (location) {
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
if (Array.isArray(data)) {
|
|
154
|
+
data.forEach(function (item, itemIndex) {
|
|
155
|
+
visit(item, parent, data, itemIndex, list, index);
|
|
156
|
+
});
|
|
157
|
+
} else if (data === target) {
|
|
158
|
+
location = { parent: parent, list: list, index: index, outerList: outerList, outerIndex: outerIndex };
|
|
159
|
+
} else if (data && data.children) {
|
|
160
|
+
visit(data.children, data, null, null, null, null);
|
|
161
|
+
}
|
|
162
|
+
};
|
|
163
|
+
visit(datasource, null, null, null, null, null);
|
|
164
|
+
return location;
|
|
165
|
+
}
|
|
166
|
+
|
|
48
167
|
function forEachValue(collection, callback) {
|
|
49
168
|
if (Array.isArray(collection) || isNodeList(collection)) {
|
|
50
169
|
for (let index = 0; index < collection.length; index += 1) {
|
|
@@ -116,8 +235,16 @@
|
|
|
116
235
|
if (!element || element.nodeType !== 1) {
|
|
117
236
|
return false;
|
|
118
237
|
}
|
|
119
|
-
|
|
120
|
-
|
|
238
|
+
let currentElement = element;
|
|
239
|
+
while (currentElement && currentElement.nodeType === 1) {
|
|
240
|
+
const style = getWindow().getComputedStyle(currentElement);
|
|
241
|
+
if (currentElement.classList.contains('hidden') || style.display === 'none'
|
|
242
|
+
|| style.visibility === 'hidden' || style.visibility === 'collapse' || style.opacity === '0') {
|
|
243
|
+
return false;
|
|
244
|
+
}
|
|
245
|
+
currentElement = currentElement.parentElement;
|
|
246
|
+
}
|
|
247
|
+
return true;
|
|
121
248
|
}
|
|
122
249
|
|
|
123
250
|
function matchesSelector(element, selector) {
|
|
@@ -344,7 +471,7 @@
|
|
|
344
471
|
|
|
345
472
|
function getChartTransform(chartElement) {
|
|
346
473
|
let currentTransform;
|
|
347
|
-
let matrixValues;
|
|
474
|
+
let matrixValues = [1, 0, 0, 1, 0, 0];
|
|
348
475
|
let currentScale = 1;
|
|
349
476
|
let currentTranslateX = 0;
|
|
350
477
|
let currentTranslateY = 0;
|
|
@@ -353,7 +480,8 @@
|
|
|
353
480
|
return {
|
|
354
481
|
scale: currentScale,
|
|
355
482
|
translateX: currentTranslateX,
|
|
356
|
-
translateY: currentTranslateY
|
|
483
|
+
translateY: currentTranslateY,
|
|
484
|
+
matrix: matrixValues
|
|
357
485
|
};
|
|
358
486
|
}
|
|
359
487
|
|
|
@@ -363,14 +491,14 @@
|
|
|
363
491
|
matrixValues = currentTransform.slice(9, -1).split(',').map(function (value) {
|
|
364
492
|
return getWindow().parseFloat(value.trim());
|
|
365
493
|
});
|
|
366
|
-
currentScale = Math.
|
|
494
|
+
currentScale = Math.hypot(matrixValues[0], matrixValues[1], matrixValues[2]) || 1;
|
|
367
495
|
currentTranslateX = matrixValues[12] || 0;
|
|
368
496
|
currentTranslateY = matrixValues[13] || 0;
|
|
369
497
|
} else if (currentTransform.indexOf('matrix(') === 0) {
|
|
370
498
|
matrixValues = currentTransform.slice(7, -1).split(',').map(function (value) {
|
|
371
499
|
return getWindow().parseFloat(value.trim());
|
|
372
500
|
});
|
|
373
|
-
currentScale = Math.
|
|
501
|
+
currentScale = Math.hypot(matrixValues[0], matrixValues[1]) || 1;
|
|
374
502
|
currentTranslateX = matrixValues[4] || 0;
|
|
375
503
|
currentTranslateY = matrixValues[5] || 0;
|
|
376
504
|
} else if (currentTransform.indexOf('scale3d(') === 0) {
|
|
@@ -378,21 +506,82 @@
|
|
|
378
506
|
return getWindow().parseFloat(value.trim());
|
|
379
507
|
});
|
|
380
508
|
currentScale = Math.abs(matrixValues[0]) || 1;
|
|
509
|
+
matrixValues = [matrixValues[0], 0, 0, 0, 0, matrixValues[1], 0, 0, 0, 0, matrixValues[2], 0, 0, 0, 0, 1];
|
|
381
510
|
} else if (currentTransform.indexOf('scale(') === 0) {
|
|
382
511
|
matrixValues = currentTransform.slice(6, -1).split(',').map(function (value) {
|
|
383
512
|
return getWindow().parseFloat(value.trim());
|
|
384
513
|
});
|
|
385
514
|
currentScale = Math.abs(matrixValues[0]) || 1;
|
|
515
|
+
matrixValues = [matrixValues[0], 0, 0, matrixValues[1] === undefined ? matrixValues[0] : matrixValues[1], 0, 0];
|
|
386
516
|
}
|
|
387
517
|
}
|
|
388
518
|
|
|
389
519
|
return {
|
|
390
520
|
scale: currentScale,
|
|
391
521
|
translateX: currentTranslateX,
|
|
392
|
-
translateY: currentTranslateY
|
|
522
|
+
translateY: currentTranslateY,
|
|
523
|
+
matrix: matrixValues
|
|
393
524
|
};
|
|
394
525
|
}
|
|
395
526
|
|
|
527
|
+
function applyChartTransform(chartElement, chartTransform, scale, translateX, translateY) {
|
|
528
|
+
const matrixValues = chartTransform.matrix.slice();
|
|
529
|
+
const scaleRatio = scale / chartTransform.scale;
|
|
530
|
+
const is3d = matrixValues.length === 16;
|
|
531
|
+
const linearIndexes = is3d ? [0, 1, 2, 4, 5, 6, 8, 9, 10] : [0, 1, 2, 3];
|
|
532
|
+
|
|
533
|
+
linearIndexes.forEach(function (index) {
|
|
534
|
+
matrixValues[index] *= scaleRatio;
|
|
535
|
+
});
|
|
536
|
+
matrixValues[is3d ? 12 : 4] = translateX;
|
|
537
|
+
matrixValues[is3d ? 13 : 5] = translateY;
|
|
538
|
+
chartElement.style.transformOrigin = '0 0';
|
|
539
|
+
chartElement.style.transform = (is3d ? 'matrix3d(' : 'matrix(') + matrixValues.join(', ') + ')';
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
function rebuildFromData(orgChart, expandedData, updatedDatasource) {
|
|
543
|
+
const chartElement = orgChart.chart;
|
|
544
|
+
const datasource = updatedDatasource || getState(chartElement, 'datasource') || orgChart.options.data;
|
|
545
|
+
const expansionStates = new Map();
|
|
546
|
+
const transform = chartElement.style.transform;
|
|
547
|
+
const transformOrigin = chartElement.style.transformOrigin;
|
|
548
|
+
Array.from(chartElement.querySelectorAll('.node')).forEach(function (nodeElement) {
|
|
549
|
+
expansionStates.set(getState(nodeElement, 'sourceData'), {
|
|
550
|
+
visible: isVisibleElement(nodeElement),
|
|
551
|
+
expanded: nodeElement.classList.contains('compact')
|
|
552
|
+
? nodeElement.classList.contains('looseMode')
|
|
553
|
+
: orgChart.getNodeState(nodeElement, 'children').visible
|
|
554
|
+
});
|
|
555
|
+
});
|
|
556
|
+
prepareNodeData(datasource, true);
|
|
557
|
+
orgChart.init({ data: datasource });
|
|
558
|
+
orgChart.chart.style.transform = transform;
|
|
559
|
+
orgChart.chart.style.transformOrigin = transformOrigin;
|
|
560
|
+
Array.from(orgChart.chart.querySelectorAll('.node')).forEach(function (nodeElement) {
|
|
561
|
+
const nodeData = getState(nodeElement, 'sourceData');
|
|
562
|
+
const state = expansionStates.get(nodeData);
|
|
563
|
+
const expanded = nodeData === expandedData || (state && state.expanded);
|
|
564
|
+
if (state && state.visible) {
|
|
565
|
+
nodeElement.classList.remove('slide-up');
|
|
566
|
+
}
|
|
567
|
+
if (nodeElement.classList.contains('compact')) {
|
|
568
|
+
if (expanded && orgChart.getChildren(nodeElement).length) {
|
|
569
|
+
orgChart.backToLooseHandler({ compactNode: nodeElement });
|
|
570
|
+
}
|
|
571
|
+
} else {
|
|
572
|
+
const childContainer = getChildNodesContainer(nodeElement);
|
|
573
|
+
if (childContainer && (state || nodeData === expandedData)) {
|
|
574
|
+
childContainer.classList.toggle('hidden', !expanded);
|
|
575
|
+
nodeElement.closest('.hierarchy').classList.toggle('isChildrenCollapsed', !expanded);
|
|
576
|
+
if (expanded) {
|
|
577
|
+
orgChart.getChildren(nodeElement).forEach(function (child) { child.classList.remove('slide-up'); });
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
});
|
|
582
|
+
orgChart.updateMinimap(true);
|
|
583
|
+
}
|
|
584
|
+
|
|
396
585
|
const OrgChart = function (elem, opts) {
|
|
397
586
|
if (!(this instanceof OrgChart)) {
|
|
398
587
|
return new OrgChart(elem, opts);
|
|
@@ -405,6 +594,7 @@
|
|
|
405
594
|
this.opts = opts || {};
|
|
406
595
|
}
|
|
407
596
|
this.chart = null;
|
|
597
|
+
this.exportButtonElement = null;
|
|
408
598
|
this.defaultOptions = {
|
|
409
599
|
'icons': {
|
|
410
600
|
'theme': 'oci',
|
|
@@ -454,7 +644,9 @@
|
|
|
454
644
|
OrgChart.prototype = {
|
|
455
645
|
//
|
|
456
646
|
init: function (opts) {
|
|
457
|
-
|
|
647
|
+
const options = mergeChartOptions(this.defaultOptions, this.opts, opts);
|
|
648
|
+
this.opts = options;
|
|
649
|
+
this.options = options;
|
|
458
650
|
// build the org-chart
|
|
459
651
|
const chartContainerElement = this.chartContainer;
|
|
460
652
|
let chartElement;
|
|
@@ -464,6 +656,13 @@
|
|
|
464
656
|
|
|
465
657
|
this.detachMinimap();
|
|
466
658
|
if (this.chart) {
|
|
659
|
+
const initObserver = getState(this.chart, 'initMutationObserver');
|
|
660
|
+
if (initObserver) {
|
|
661
|
+
initObserver.disconnect();
|
|
662
|
+
}
|
|
663
|
+
this.panEndHandler({ chart: this.chart });
|
|
664
|
+
this.unbindPan();
|
|
665
|
+
this.unbindZoom();
|
|
467
666
|
this.chart.remove();
|
|
468
667
|
}
|
|
469
668
|
const data = this.options.data;
|
|
@@ -479,12 +678,21 @@
|
|
|
479
678
|
Array.from(chartElement.querySelectorAll('.node.focused')).forEach(function (focusedNodeEl) {
|
|
480
679
|
focusedNodeEl.classList.remove('focused');
|
|
481
680
|
});
|
|
681
|
+
const activeElement = getDocument().activeElement;
|
|
682
|
+
if (activeElement && chartElement.contains(activeElement) && activeElement.closest('.node')) {
|
|
683
|
+
activeElement.blur();
|
|
684
|
+
}
|
|
482
685
|
}
|
|
483
686
|
});
|
|
484
687
|
if (typeof getWindow().MutationObserver !== 'undefined') {
|
|
485
688
|
this.triggerInitEvent();
|
|
486
689
|
}
|
|
487
690
|
const isListElementData = isElement(data) && data.tagName === 'UL';
|
|
691
|
+
const datasource = isListElementData ? this.buildJsonDS(data.firstElementChild) : data;
|
|
692
|
+
prepareNodeData(datasource);
|
|
693
|
+
setState(chartElement, 'datasource', datasource);
|
|
694
|
+
this.options.data = datasource;
|
|
695
|
+
this.opts.data = datasource;
|
|
488
696
|
rootNodesContainerElement = getDocument().createElement('ul');
|
|
489
697
|
rootNodesContainerElement.className = 'nodes';
|
|
490
698
|
chartElement.appendChild(rootNodesContainerElement);
|
|
@@ -498,23 +706,22 @@
|
|
|
498
706
|
rootElement = rootHierarchyElement;
|
|
499
707
|
}
|
|
500
708
|
|
|
501
|
-
|
|
502
|
-
this.buildHierarchy(rootElement, this.buildJsonDS(data.firstElementChild));
|
|
503
|
-
} else { // local json datasource
|
|
504
|
-
if (data.relationship) {
|
|
505
|
-
this.buildHierarchy(rootElement, data);
|
|
506
|
-
} else {
|
|
507
|
-
this.buildHierarchy(rootElement, Array.isArray(data) ? data : this.attachRel(data, '00'));
|
|
508
|
-
}
|
|
509
|
-
}
|
|
709
|
+
this.buildHierarchy(rootElement, datasource);
|
|
510
710
|
|
|
511
711
|
if (chartContainerElement) {
|
|
512
712
|
chartContainerElement.appendChild(chartElement);
|
|
513
713
|
}
|
|
514
714
|
|
|
515
715
|
// append the export button
|
|
516
|
-
if (this.options.exportButton
|
|
517
|
-
this.
|
|
716
|
+
if (this.options.exportButton) {
|
|
717
|
+
if (!this.exportButtonElement || !this.exportButtonElement.parentElement) {
|
|
718
|
+
this.attachExportButton();
|
|
719
|
+
} else {
|
|
720
|
+
this.exportButtonElement.textContent = this.options.exportButtonName;
|
|
721
|
+
}
|
|
722
|
+
} else if (this.exportButtonElement) {
|
|
723
|
+
this.exportButtonElement.remove();
|
|
724
|
+
this.exportButtonElement = null;
|
|
518
725
|
}
|
|
519
726
|
|
|
520
727
|
if (this.options.pan) {
|
|
@@ -556,26 +763,30 @@
|
|
|
556
763
|
//
|
|
557
764
|
triggerInitEvent: function () {
|
|
558
765
|
const orgChart = this;
|
|
766
|
+
const chartElement = this.chart;
|
|
767
|
+
const options = this.options;
|
|
559
768
|
const MutationObserverCtor = getWindow().MutationObserver;
|
|
560
769
|
const mo = new MutationObserverCtor(function (mutations) {
|
|
561
770
|
mo.disconnect();
|
|
771
|
+
setState(chartElement, 'initMutationObserver', null);
|
|
562
772
|
initTime:
|
|
563
773
|
for (let i = 0; i < mutations.length; i++) {
|
|
564
774
|
for (let j = 0; j < mutations[i].addedNodes.length; j++) {
|
|
565
|
-
if (mutations[i].addedNodes[j]
|
|
775
|
+
if (mutations[i].addedNodes[j] === chartElement) {
|
|
566
776
|
orgChart.handleCompactNodes();
|
|
567
|
-
if (!
|
|
777
|
+
if (!chartElement.isConnected) {
|
|
568
778
|
break initTime;
|
|
569
779
|
}
|
|
570
|
-
if (
|
|
571
|
-
|
|
780
|
+
if (options.initCompleted && typeof options.initCompleted === 'function') {
|
|
781
|
+
options.initCompleted(chartElement);
|
|
572
782
|
}
|
|
573
|
-
|
|
783
|
+
chartElement.dispatchEvent(createTriggeredEvent('init.orgchart'));
|
|
574
784
|
break initTime;
|
|
575
785
|
}
|
|
576
786
|
}
|
|
577
787
|
}
|
|
578
788
|
});
|
|
789
|
+
setState(chartElement, 'initMutationObserver', mo);
|
|
579
790
|
mo.observe(this.chartContainer, { childList: true });
|
|
580
791
|
},
|
|
581
792
|
triggerShowEvent: function (targetEl, rel) {
|
|
@@ -601,72 +812,53 @@
|
|
|
601
812
|
exportButtonElement = getDocument().createElement('button');
|
|
602
813
|
exportButtonElement.className = 'oc-export-btn';
|
|
603
814
|
exportButtonElement.textContent = this.options.exportButtonName;
|
|
815
|
+
setState(exportButtonElement, 'orgChart', this);
|
|
604
816
|
exportButtonElement.addEventListener('click', function (event) {
|
|
605
817
|
event.preventDefault();
|
|
606
818
|
orgChart.export();
|
|
607
819
|
});
|
|
820
|
+
this.exportButtonElement = exportButtonElement;
|
|
608
821
|
chartContainerElement.insertAdjacentElement('afterend', exportButtonElement);
|
|
609
822
|
},
|
|
610
823
|
setOptions: function (opts, val) {
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
824
|
+
const overrides = typeof opts === 'string' ? { [opts]: val } : opts;
|
|
825
|
+
if (!overrides || typeof overrides !== 'object') {
|
|
826
|
+
return this;
|
|
827
|
+
}
|
|
828
|
+
const options = mergeChartOptions(this.defaultOptions, this.opts, this.options, overrides);
|
|
829
|
+
const needsRebuild = Object.keys(overrides).some(function (key) {
|
|
830
|
+
return !['pan', 'zoom', 'minimap', 'zoominLimit', 'zoomoutLimit', 'exportScale', 'exportFilename', 'exportFileextension'].includes(key);
|
|
831
|
+
});
|
|
832
|
+
if (needsRebuild) {
|
|
833
|
+
return this.init(options);
|
|
834
|
+
}
|
|
835
|
+
this.opts = options;
|
|
836
|
+
this.options = options;
|
|
837
|
+
if (this.chart) {
|
|
838
|
+
setState(this.chart, 'options', options);
|
|
839
|
+
}
|
|
840
|
+
if (Object.prototype.hasOwnProperty.call(overrides, 'pan')) {
|
|
841
|
+
if (options.pan) {
|
|
842
|
+
this.bindPan();
|
|
843
|
+
} else {
|
|
844
|
+
this.panEndHandler({ chart: this.chart });
|
|
845
|
+
this.unbindPan();
|
|
625
846
|
}
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
this.attachMinimap();
|
|
633
|
-
} else {
|
|
634
|
-
this.detachMinimap();
|
|
635
|
-
}
|
|
847
|
+
}
|
|
848
|
+
if (Object.prototype.hasOwnProperty.call(overrides, 'zoom')) {
|
|
849
|
+
if (options.zoom) {
|
|
850
|
+
this.bindZoom();
|
|
851
|
+
} else {
|
|
852
|
+
this.unbindZoom();
|
|
636
853
|
}
|
|
637
854
|
}
|
|
638
|
-
if (
|
|
639
|
-
if (
|
|
640
|
-
this.
|
|
855
|
+
if (Object.prototype.hasOwnProperty.call(overrides, 'minimap')) {
|
|
856
|
+
if (options.minimap) {
|
|
857
|
+
this.attachMinimap();
|
|
641
858
|
} else {
|
|
642
|
-
|
|
643
|
-
if (opts.pan) {
|
|
644
|
-
this.bindPan();
|
|
645
|
-
} else {
|
|
646
|
-
this.unbindPan();
|
|
647
|
-
}
|
|
648
|
-
}
|
|
649
|
-
if (typeof opts.zoom !== 'undefined') {
|
|
650
|
-
if (opts.zoom) {
|
|
651
|
-
this.bindZoom();
|
|
652
|
-
} else {
|
|
653
|
-
this.unbindZoom();
|
|
654
|
-
}
|
|
655
|
-
}
|
|
656
|
-
if (typeof opts.minimap !== 'undefined') {
|
|
657
|
-
this.options = mergeObjects({}, this.options || {}, { minimap: opts.minimap });
|
|
658
|
-
if (this.chart) {
|
|
659
|
-
setState(this.chart, 'options', this.options);
|
|
660
|
-
}
|
|
661
|
-
if (opts.minimap) {
|
|
662
|
-
this.attachMinimap();
|
|
663
|
-
} else {
|
|
664
|
-
this.detachMinimap();
|
|
665
|
-
}
|
|
666
|
-
}
|
|
859
|
+
this.detachMinimap();
|
|
667
860
|
}
|
|
668
861
|
}
|
|
669
|
-
|
|
670
862
|
return this;
|
|
671
863
|
},
|
|
672
864
|
attachMinimap: function () {
|
|
@@ -679,7 +871,9 @@
|
|
|
679
871
|
let minimapViewportElement;
|
|
680
872
|
let minimapWheelBoundHandler;
|
|
681
873
|
let minimapPointerDownBoundHandler;
|
|
874
|
+
let minimapViewportChangeBoundHandler;
|
|
682
875
|
let minimapMutationObserver;
|
|
876
|
+
let minimapResizeObserver;
|
|
683
877
|
|
|
684
878
|
if (!chartContainerElement || !chartElement) {
|
|
685
879
|
return;
|
|
@@ -712,21 +906,53 @@
|
|
|
712
906
|
minimapPointerDownBoundHandler = function (event) {
|
|
713
907
|
orgChart.minimapStartHandler(event);
|
|
714
908
|
};
|
|
909
|
+
minimapViewportChangeBoundHandler = function () {
|
|
910
|
+
orgChart.updateMinimap();
|
|
911
|
+
};
|
|
715
912
|
|
|
716
|
-
minimapElement.addEventListener('wheel', minimapWheelBoundHandler);
|
|
913
|
+
minimapElement.addEventListener('wheel', minimapWheelBoundHandler, { passive: false });
|
|
717
914
|
minimapViewportElement.addEventListener('mousedown', minimapPointerDownBoundHandler);
|
|
915
|
+
chartContainerElement.addEventListener('scroll', minimapViewportChangeBoundHandler);
|
|
916
|
+
getWindow().addEventListener('resize', minimapViewportChangeBoundHandler);
|
|
718
917
|
|
|
719
918
|
if (typeof getWindow().MutationObserver !== 'undefined') {
|
|
720
|
-
minimapMutationObserver = new (getWindow().MutationObserver)(function () {
|
|
721
|
-
|
|
919
|
+
minimapMutationObserver = new (getWindow().MutationObserver)(function (mutations) {
|
|
920
|
+
const controlsSelector = '.edge, .toggleBtn, .backToCompactSymbol, .backToLooseSymbol';
|
|
921
|
+
const needsRefresh = mutations.some(function (mutation) {
|
|
922
|
+
if (mutation.type === 'childList') {
|
|
923
|
+
return Array.from(mutation.addedNodes).concat(Array.from(mutation.removedNodes)).some(function (node) {
|
|
924
|
+
return node.nodeType !== 1 || !node.matches(controlsSelector);
|
|
925
|
+
});
|
|
926
|
+
}
|
|
927
|
+
if (mutation.target.matches(controlsSelector)) {
|
|
928
|
+
return false;
|
|
929
|
+
}
|
|
930
|
+
const layoutClasses = function (value) {
|
|
931
|
+
return (value || '').split(/\s+/).filter(function (className) {
|
|
932
|
+
return className && className !== 'controls-active' && className !== 'focused';
|
|
933
|
+
}).sort().join(' ');
|
|
934
|
+
};
|
|
935
|
+
return layoutClasses(mutation.oldValue) !== layoutClasses(mutation.target.className);
|
|
936
|
+
});
|
|
937
|
+
if (needsRefresh) {
|
|
938
|
+
orgChart.updateMinimap(true);
|
|
939
|
+
}
|
|
722
940
|
});
|
|
723
941
|
minimapMutationObserver.observe(chartElement, {
|
|
724
942
|
childList: true,
|
|
725
943
|
subtree: true,
|
|
726
944
|
attributes: true,
|
|
945
|
+
attributeOldValue: true,
|
|
727
946
|
attributeFilter: ['class']
|
|
728
947
|
});
|
|
729
948
|
}
|
|
949
|
+
if (typeof getWindow().ResizeObserver !== 'undefined') {
|
|
950
|
+
minimapResizeObserver = new (getWindow().ResizeObserver)(function () {
|
|
951
|
+
orgChart.updateMinimap(true);
|
|
952
|
+
});
|
|
953
|
+
minimapResizeObserver.observe(chartContainerElement);
|
|
954
|
+
minimapResizeObserver.observe(chartElement);
|
|
955
|
+
}
|
|
730
956
|
|
|
731
957
|
setState(chartElement, 'minimapElement', minimapElement);
|
|
732
958
|
setState(chartElement, 'minimapStageElement', minimapStageElement);
|
|
@@ -734,7 +960,9 @@
|
|
|
734
960
|
setState(chartElement, 'minimapViewportElement', minimapViewportElement);
|
|
735
961
|
setState(chartElement, 'minimapWheelBoundHandler', minimapWheelBoundHandler);
|
|
736
962
|
setState(chartElement, 'minimapPointerDownBoundHandler', minimapPointerDownBoundHandler);
|
|
963
|
+
setState(chartElement, 'minimapViewportChangeBoundHandler', minimapViewportChangeBoundHandler);
|
|
737
964
|
setState(chartElement, 'minimapMutationObserver', minimapMutationObserver || null);
|
|
965
|
+
setState(chartElement, 'minimapResizeObserver', minimapResizeObserver || null);
|
|
738
966
|
|
|
739
967
|
this.updateMinimap(true);
|
|
740
968
|
},
|
|
@@ -748,6 +976,8 @@
|
|
|
748
976
|
let minimapMoveBoundHandler;
|
|
749
977
|
let minimapEndBoundHandler;
|
|
750
978
|
let minimapMutationObserver;
|
|
979
|
+
let minimapViewportChangeBoundHandler;
|
|
980
|
+
let minimapResizeObserver;
|
|
751
981
|
|
|
752
982
|
if (chartElement) {
|
|
753
983
|
minimapElement = getState(chartElement, 'minimapElement');
|
|
@@ -757,6 +987,8 @@
|
|
|
757
987
|
minimapMoveBoundHandler = getState(chartElement, 'minimapMoveBoundHandler');
|
|
758
988
|
minimapEndBoundHandler = getState(chartElement, 'minimapEndBoundHandler');
|
|
759
989
|
minimapMutationObserver = getState(chartElement, 'minimapMutationObserver');
|
|
990
|
+
minimapViewportChangeBoundHandler = getState(chartElement, 'minimapViewportChangeBoundHandler');
|
|
991
|
+
minimapResizeObserver = getState(chartElement, 'minimapResizeObserver');
|
|
760
992
|
|
|
761
993
|
if (minimapElement && minimapWheelBoundHandler) {
|
|
762
994
|
minimapElement.removeEventListener('wheel', minimapWheelBoundHandler);
|
|
@@ -773,6 +1005,13 @@
|
|
|
773
1005
|
if (minimapMutationObserver) {
|
|
774
1006
|
minimapMutationObserver.disconnect();
|
|
775
1007
|
}
|
|
1008
|
+
if (minimapViewportChangeBoundHandler) {
|
|
1009
|
+
chartContainerElement.removeEventListener('scroll', minimapViewportChangeBoundHandler);
|
|
1010
|
+
getWindow().removeEventListener('resize', minimapViewportChangeBoundHandler);
|
|
1011
|
+
}
|
|
1012
|
+
if (minimapResizeObserver) {
|
|
1013
|
+
minimapResizeObserver.disconnect();
|
|
1014
|
+
}
|
|
776
1015
|
if (minimapElement && minimapElement.parentElement) {
|
|
777
1016
|
minimapElement.remove();
|
|
778
1017
|
}
|
|
@@ -787,6 +1026,8 @@
|
|
|
787
1026
|
'minimapMoveBoundHandler',
|
|
788
1027
|
'minimapEndBoundHandler',
|
|
789
1028
|
'minimapMutationObserver',
|
|
1029
|
+
'minimapViewportChangeBoundHandler',
|
|
1030
|
+
'minimapResizeObserver',
|
|
790
1031
|
'minimapDragState',
|
|
791
1032
|
'minimapScale',
|
|
792
1033
|
'minimapOffsetX',
|
|
@@ -813,6 +1054,9 @@
|
|
|
813
1054
|
if (typeof event.preventDefault === 'function') {
|
|
814
1055
|
event.preventDefault();
|
|
815
1056
|
}
|
|
1057
|
+
if (typeof event.stopPropagation === 'function') {
|
|
1058
|
+
event.stopPropagation();
|
|
1059
|
+
}
|
|
816
1060
|
|
|
817
1061
|
this.setChartScale(this.chart, 1 + (event.deltaY > 0 ? -0.2 : 0.2), {
|
|
818
1062
|
x: chartContainerElement.getBoundingClientRect().left + (chartContainerElement.clientWidth / 2),
|
|
@@ -897,8 +1141,7 @@
|
|
|
897
1141
|
let localViewportHeight;
|
|
898
1142
|
let localLeft;
|
|
899
1143
|
let localTop;
|
|
900
|
-
let
|
|
901
|
-
let baseTop;
|
|
1144
|
+
let transformedRect;
|
|
902
1145
|
|
|
903
1146
|
if (!chartElement || !chartContainerElement || !minimapStageElement || !minimapScale || !chartRect || !containerRect) {
|
|
904
1147
|
return;
|
|
@@ -908,13 +1151,11 @@
|
|
|
908
1151
|
localViewportHeight = viewportHeight / minimapScale;
|
|
909
1152
|
localLeft = clampValue((stageLeft - minimapOffsetX) / minimapScale, 0, Math.max(minimapContentWidth - localViewportWidth, 0));
|
|
910
1153
|
localTop = clampValue((stageTop - minimapOffsetY) / minimapScale, 0, Math.max(minimapContentHeight - localViewportHeight, 0));
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
+ (containerRect.left - baseLeft - (localLeft * chartTransform.scale)) + ', '
|
|
917
|
-
+ (containerRect.top - baseTop - (localTop * chartTransform.scale)) + ')';
|
|
1154
|
+
applyChartTransform(chartElement, chartTransform, chartTransform.scale, chartTransform.translateX, chartTransform.translateY);
|
|
1155
|
+
transformedRect = chartElement.getBoundingClientRect();
|
|
1156
|
+
applyChartTransform(chartElement, chartTransform, chartTransform.scale,
|
|
1157
|
+
chartTransform.translateX + containerRect.left - (localLeft * chartTransform.scale) - transformedRect.left,
|
|
1158
|
+
chartTransform.translateY + containerRect.top - (localTop * chartTransform.scale) - transformedRect.top);
|
|
918
1159
|
this.updateMinimap();
|
|
919
1160
|
},
|
|
920
1161
|
updateMinimap: function (forceRefresh) {
|
|
@@ -953,6 +1194,8 @@
|
|
|
953
1194
|
minimapScale = Math.min(stageWidth / Math.max(contentWidth, 1), stageHeight / Math.max(contentHeight, 1));
|
|
954
1195
|
minimapOffsetX = (stageWidth - (contentWidth * minimapScale)) / 2;
|
|
955
1196
|
minimapOffsetY = (stageHeight - (contentHeight * minimapScale)) / 2;
|
|
1197
|
+
const minimapElement = getState(chartElement, 'minimapElement');
|
|
1198
|
+
minimapElement.style.transform = 'translate(' + chartContainerElement.scrollLeft + 'px, ' + chartContainerElement.scrollTop + 'px)';
|
|
956
1199
|
|
|
957
1200
|
minimapContentElement.style.width = contentWidth + 'px';
|
|
958
1201
|
minimapContentElement.style.height = contentHeight + 'px';
|
|
@@ -1005,11 +1248,11 @@
|
|
|
1005
1248
|
if (lastTf !== 'none') {
|
|
1006
1249
|
const temp = lastTf.split(',');
|
|
1007
1250
|
if (lastTf.indexOf('3d') === -1) {
|
|
1008
|
-
lastX =
|
|
1009
|
-
lastY =
|
|
1251
|
+
lastX = parseFloat(temp[4]) || 0;
|
|
1252
|
+
lastY = parseFloat(temp[5]) || 0;
|
|
1010
1253
|
} else {
|
|
1011
|
-
lastX =
|
|
1012
|
-
lastY =
|
|
1254
|
+
lastX = parseFloat(temp[12]) || 0;
|
|
1255
|
+
lastY = parseFloat(temp[13]) || 0;
|
|
1013
1256
|
}
|
|
1014
1257
|
}
|
|
1015
1258
|
let startX = 0;
|
|
@@ -1065,8 +1308,8 @@
|
|
|
1065
1308
|
matrix[13] = ' ' + newY;
|
|
1066
1309
|
}
|
|
1067
1310
|
chartElement.style.transform = matrix.join(',');
|
|
1068
|
-
orgChart.updateMinimap();
|
|
1069
1311
|
}
|
|
1312
|
+
orgChart.updateMinimap();
|
|
1070
1313
|
};
|
|
1071
1314
|
|
|
1072
1315
|
setState(chartElement, 'panMoveHandler', panMoveHandler);
|
|
@@ -1203,6 +1446,7 @@
|
|
|
1203
1446
|
dist = orgChart.getPinchDist(nativeEvent);
|
|
1204
1447
|
pinchCenter = orgChart.getPinchCenter(nativeEvent);
|
|
1205
1448
|
setState(chartElement, 'pinchDistStart', dist);
|
|
1449
|
+
setState(chartElement, 'pinchDistEnd', dist);
|
|
1206
1450
|
setState(chartElement, 'pinchCenterStart', pinchCenter);
|
|
1207
1451
|
setState(chartElement, 'pinchCenterEnd', pinchCenter);
|
|
1208
1452
|
}
|
|
@@ -1214,7 +1458,7 @@
|
|
|
1214
1458
|
let dist;
|
|
1215
1459
|
let pinchCenter;
|
|
1216
1460
|
|
|
1217
|
-
if(chartElement && getState(chartElement, 'pinching')) {
|
|
1461
|
+
if(chartElement && getState(chartElement, 'pinching') && nativeEvent.touches && nativeEvent.touches.length === 2) {
|
|
1218
1462
|
dist = orgChart.getPinchDist(nativeEvent);
|
|
1219
1463
|
pinchCenter = orgChart.getPinchCenter(nativeEvent);
|
|
1220
1464
|
setState(chartElement, 'pinchDistEnd', dist);
|
|
@@ -1340,16 +1584,9 @@
|
|
|
1340
1584
|
const chartContainerElement = this.chartContainer;
|
|
1341
1585
|
let opts;
|
|
1342
1586
|
let chartRect;
|
|
1343
|
-
let
|
|
1344
|
-
let
|
|
1345
|
-
let currentTranslateY = 0;
|
|
1587
|
+
let chartTransform;
|
|
1588
|
+
let transformedRect;
|
|
1346
1589
|
let targetScale = 1;
|
|
1347
|
-
let anchorX;
|
|
1348
|
-
let anchorY;
|
|
1349
|
-
let localAnchorX;
|
|
1350
|
-
let localAnchorY;
|
|
1351
|
-
let baseLeft;
|
|
1352
|
-
let baseTop;
|
|
1353
1590
|
let containerRect;
|
|
1354
1591
|
let targetTranslateX;
|
|
1355
1592
|
let targetTranslateY;
|
|
@@ -1359,17 +1596,18 @@
|
|
|
1359
1596
|
}
|
|
1360
1597
|
|
|
1361
1598
|
opts = getState(chartElement, 'options');
|
|
1362
|
-
|
|
1363
|
-
currentTranslateX = getChartTransform(chartElement).translateX;
|
|
1364
|
-
currentTranslateY = getChartTransform(chartElement).translateY;
|
|
1599
|
+
chartTransform = getChartTransform(chartElement);
|
|
1365
1600
|
|
|
1366
|
-
|
|
1367
|
-
|
|
1601
|
+
if (!Number.isFinite(newScale) || newScale <= 0) {
|
|
1602
|
+
return;
|
|
1603
|
+
}
|
|
1604
|
+
targetScale = clampValue(chartTransform.scale * newScale, opts.zoomoutLimit, opts.zoominLimit);
|
|
1605
|
+
if (targetScale === chartTransform.scale) {
|
|
1368
1606
|
return;
|
|
1369
1607
|
}
|
|
1370
1608
|
|
|
1371
|
-
targetTranslateX =
|
|
1372
|
-
targetTranslateY =
|
|
1609
|
+
targetTranslateX = chartTransform.translateX;
|
|
1610
|
+
targetTranslateY = chartTransform.translateY;
|
|
1373
1611
|
chartRect = typeof chartElement.getBoundingClientRect === 'function'
|
|
1374
1612
|
? chartElement.getBoundingClientRect()
|
|
1375
1613
|
: null;
|
|
@@ -1380,19 +1618,15 @@
|
|
|
1380
1618
|
y: containerRect.top + (containerRect.height / 2)
|
|
1381
1619
|
};
|
|
1382
1620
|
}
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
baseTop = chartRect.top - currentTranslateY;
|
|
1390
|
-
targetTranslateX = anchorX - baseLeft - (localAnchorX * targetScale);
|
|
1391
|
-
targetTranslateY = anchorY - baseTop - (localAnchorY * targetScale);
|
|
1621
|
+
applyChartTransform(chartElement, chartTransform, targetScale, targetTranslateX, targetTranslateY);
|
|
1622
|
+
if (zoomAnchor && chartRect && typeof zoomAnchor.x === 'number' && typeof zoomAnchor.y === 'number' && chartTransform.scale !== 0) {
|
|
1623
|
+
const scaleRatio = targetScale / chartTransform.scale;
|
|
1624
|
+
transformedRect = chartElement.getBoundingClientRect();
|
|
1625
|
+
targetTranslateX += zoomAnchor.x + ((chartRect.left - zoomAnchor.x) * scaleRatio) - transformedRect.left;
|
|
1626
|
+
targetTranslateY += zoomAnchor.y + ((chartRect.top - zoomAnchor.y) * scaleRatio) - transformedRect.top;
|
|
1392
1627
|
}
|
|
1393
1628
|
|
|
1394
|
-
chartElement
|
|
1395
|
-
chartElement.style.transform = 'matrix(' + targetScale + ', 0, 0, ' + targetScale + ', ' + targetTranslateX + ', ' + targetTranslateY + ')';
|
|
1629
|
+
applyChartTransform(chartElement, chartTransform, targetScale, targetTranslateX, targetTranslateY);
|
|
1396
1630
|
this.updateMinimap();
|
|
1397
1631
|
},
|
|
1398
1632
|
//
|
|
@@ -1411,12 +1645,7 @@
|
|
|
1411
1645
|
}) || null;
|
|
1412
1646
|
|
|
1413
1647
|
jsonNodeData = {
|
|
1414
|
-
'name': ((liElement.childNodes && liElement.childNodes[0]) ? liElement.childNodes[0].textContent : '').trim()
|
|
1415
|
-
'relationship': (liElement.parentElement && liElement.parentElement.parentElement && liElement.parentElement.parentElement.tagName === 'LI' ? '1' : '0')
|
|
1416
|
-
+ (liElement.parentElement ? Array.from(liElement.parentElement.children).filter(function (siblingEl) {
|
|
1417
|
-
return siblingEl !== liElement && siblingEl.tagName === 'LI';
|
|
1418
|
-
}).length ? 1 : 0 : 0)
|
|
1419
|
-
+ (childListElement ? 1 : 0)
|
|
1648
|
+
'name': ((liElement.childNodes && liElement.childNodes[0]) ? liElement.childNodes[0].textContent : '').trim()
|
|
1420
1649
|
};
|
|
1421
1650
|
forEachValue(getDatasetSnapshot(liElement), function(key, value) {
|
|
1422
1651
|
jsonNodeData[key] = value;
|
|
@@ -1435,33 +1664,10 @@
|
|
|
1435
1664
|
|
|
1436
1665
|
return jsonNodeData;
|
|
1437
1666
|
},
|
|
1438
|
-
// process datasource and add necessary information
|
|
1439
|
-
attachRel: function (data, flags) {
|
|
1440
|
-
const orgChart = this;
|
|
1441
|
-
data.relationship = flags + (data.children && data.children.length > 0 ? 1 : 0);
|
|
1442
|
-
if (this.options?.compact?.constructor === Function && this.options.compact(data)) {
|
|
1443
|
-
data.compact = true;
|
|
1444
|
-
}
|
|
1445
|
-
if (data.children) {
|
|
1446
|
-
data.children.forEach(function(item) {
|
|
1447
|
-
if (data.hybrid || data.vertical) { // identify all the descendant nodes except the root node of hybrid structure
|
|
1448
|
-
item.vertical = true;
|
|
1449
|
-
} else if (data.compact && item.children) { // identify all the compact ancestor nodes
|
|
1450
|
-
item.compact = true;
|
|
1451
|
-
} else if (data.compact && !item.children) { // identify all the compact descendant nodes
|
|
1452
|
-
item.associatedCompact = true;
|
|
1453
|
-
}
|
|
1454
|
-
orgChart.attachRel(item, '1' + (data.children.length > 1 ? 1 : 0));
|
|
1455
|
-
});
|
|
1456
|
-
}
|
|
1457
|
-
return data;
|
|
1458
|
-
},
|
|
1459
|
-
//
|
|
1460
1667
|
loopChart: function (chartEl, includeNodeData) {
|
|
1461
1668
|
const orgChart = this;
|
|
1462
1669
|
const chartElement = getElement(chartEl);
|
|
1463
1670
|
let nodeElement;
|
|
1464
|
-
let childNodesContainerElement;
|
|
1465
1671
|
let hierarchyNodeData;
|
|
1466
1672
|
|
|
1467
1673
|
includeNodeData = (includeNodeData !== null && includeNodeData !== undefined) ? includeNodeData : false;
|
|
@@ -1470,11 +1676,13 @@
|
|
|
1470
1676
|
return {};
|
|
1471
1677
|
}
|
|
1472
1678
|
|
|
1473
|
-
nodeElement = chartElement.classList && chartElement.classList.contains('
|
|
1474
|
-
?
|
|
1679
|
+
nodeElement = chartElement.classList && chartElement.classList.contains('node')
|
|
1680
|
+
? chartElement
|
|
1681
|
+
: chartElement.classList && chartElement.classList.contains('hierarchy')
|
|
1682
|
+
? Array.from(chartElement.children || []).find(function (childEl) {
|
|
1475
1683
|
return childEl.classList && childEl.classList.contains('node');
|
|
1476
1684
|
})
|
|
1477
|
-
|
|
1685
|
+
: chartElement.querySelector('.node');
|
|
1478
1686
|
if (!nodeElement) {
|
|
1479
1687
|
return {};
|
|
1480
1688
|
}
|
|
@@ -1485,18 +1693,10 @@
|
|
|
1485
1693
|
hierarchyNodeData[key] = value;
|
|
1486
1694
|
});
|
|
1487
1695
|
}
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
Array.from(childNodesContainerElement.children).forEach(function (childEl) {
|
|
1493
|
-
if (!childEl.classList || !childEl.classList.contains('hierarchy')) {
|
|
1494
|
-
return;
|
|
1495
|
-
}
|
|
1496
|
-
if (!hierarchyNodeData.children) {
|
|
1497
|
-
hierarchyNodeData.children = [];
|
|
1498
|
-
}
|
|
1499
|
-
hierarchyNodeData.children.push(orgChart.loopChart(childEl, includeNodeData));
|
|
1696
|
+
const childNodeElements = this.getChildren(nodeElement);
|
|
1697
|
+
if (childNodeElements.length) {
|
|
1698
|
+
hierarchyNodeData.children = childNodeElements.map(function (childNodeElement) {
|
|
1699
|
+
return orgChart.loopChart(childNodeElement, includeNodeData);
|
|
1500
1700
|
});
|
|
1501
1701
|
}
|
|
1502
1702
|
|
|
@@ -1520,95 +1720,61 @@
|
|
|
1520
1720
|
}
|
|
1521
1721
|
}
|
|
1522
1722
|
}
|
|
1723
|
+
const datasource = getState(chartElement, 'datasource');
|
|
1724
|
+
if (Array.isArray(datasource)) {
|
|
1725
|
+
const exportFamily = function (groups) {
|
|
1726
|
+
return groups.map(function (group) {
|
|
1727
|
+
return group.map(function (data) {
|
|
1728
|
+
const node = nodeElements.find(function (element) { return getState(element, 'sourceData') === data; });
|
|
1729
|
+
const result = includeNodeData ? mergeObjects({}, getState(node, 'nodeData')) : {};
|
|
1730
|
+
result.id = node.id;
|
|
1731
|
+
if (data.children && data.children.length) {
|
|
1732
|
+
result.children = Array.isArray(data.children[0]) ? exportFamily(data.children)
|
|
1733
|
+
: data.children.map(function (childData) {
|
|
1734
|
+
const childNode = nodeElements.find(function (element) { return getState(element, 'sourceData') === childData; });
|
|
1735
|
+
return this.loopChart(childNode, includeNodeData);
|
|
1736
|
+
}, this);
|
|
1737
|
+
}
|
|
1738
|
+
return result;
|
|
1739
|
+
}, this);
|
|
1740
|
+
}, this);
|
|
1741
|
+
}.bind(this);
|
|
1742
|
+
return exportFamily(datasource);
|
|
1743
|
+
}
|
|
1523
1744
|
return this.loopChart(chartElement, includeNodeData);
|
|
1524
1745
|
},
|
|
1525
1746
|
// detect the exist/display state of related node
|
|
1526
1747
|
getNodeState: function (nodeEl, relation) {
|
|
1527
1748
|
const nodeElement = getElement(nodeEl);
|
|
1528
|
-
let relatedElement;
|
|
1529
|
-
let isVerticalNode;
|
|
1530
|
-
let siblingElements;
|
|
1531
1749
|
|
|
1532
1750
|
if (!nodeElement || !nodeElement.classList || !nodeElement.classList.contains('node')) {
|
|
1533
1751
|
return { 'exist': false, 'visible': false };
|
|
1534
1752
|
}
|
|
1535
1753
|
|
|
1536
1754
|
relation = relation || 'self';
|
|
1537
|
-
isVerticalNode = !!nodeElement.closest('vertical');
|
|
1538
|
-
|
|
1539
1755
|
if (relation === 'parent') {
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
relatedElement = relatedElement ? relatedElement.parentElement && relatedElement.parentElement.closest('ul') : null;
|
|
1543
|
-
if (!relatedElement) {
|
|
1544
|
-
relatedElement = nodeElement.closest('.nodes');
|
|
1545
|
-
if (!relatedElement) {
|
|
1546
|
-
relatedElement = nodeElement.closest('.vertical');
|
|
1547
|
-
relatedElement = relatedElement && relatedElement.parentElement ? relatedElement.parentElement.firstElementChild : null;
|
|
1548
|
-
}
|
|
1549
|
-
}
|
|
1550
|
-
} else {
|
|
1551
|
-
relatedElement = nodeElement.closest('.nodes');
|
|
1552
|
-
relatedElement = relatedElement ? relatedElement.previousElementSibling : null;
|
|
1553
|
-
}
|
|
1554
|
-
|
|
1555
|
-
if (relatedElement) {
|
|
1556
|
-
if (relatedElement.classList.contains('hidden')
|
|
1557
|
-
|| (relatedElement.closest('.nodes') && relatedElement.closest('.nodes').classList.contains('hidden'))
|
|
1558
|
-
|| (relatedElement.closest('.vertical') && relatedElement.closest('.vertical').classList.contains('hidden'))) {
|
|
1559
|
-
return { 'exist': true, 'visible': false };
|
|
1560
|
-
}
|
|
1561
|
-
return { 'exist': true, 'visible': true };
|
|
1562
|
-
}
|
|
1756
|
+
const parentElement = this.getParent(nodeElement);
|
|
1757
|
+
return { exist: !!parentElement, visible: !!parentElement && this.getNodeState(parentElement).visible };
|
|
1563
1758
|
} else if (relation === 'children') {
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
:
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
if (relatedElement) {
|
|
1573
|
-
if (!relatedElement.classList.contains('hidden')) {
|
|
1574
|
-
return { 'exist': true, 'visible': true };
|
|
1575
|
-
}
|
|
1576
|
-
return { 'exist': true, 'visible': false };
|
|
1577
|
-
}
|
|
1759
|
+
const childElements = this.getChildren(nodeElement);
|
|
1760
|
+
const childContainer = getChildNodesContainer(nodeElement);
|
|
1761
|
+
return {
|
|
1762
|
+
exist: childElements.length > 0 || !!childContainer,
|
|
1763
|
+
visible: childElements.length > 0
|
|
1764
|
+
? childElements.some(function (childElement) { return this.getNodeState(childElement).visible; }, this)
|
|
1765
|
+
: !!childContainer && !childContainer.closest('.hidden') && this.getNodeState(nodeElement).visible
|
|
1766
|
+
};
|
|
1578
1767
|
} else if (relation === 'siblings') {
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
siblingElements
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
}
|
|
1585
|
-
siblingElements = nodeElement.parentElement && nodeElement.parentElement.parentElement
|
|
1586
|
-
? Array.from(nodeElement.parentElement.parentElement.children).filter(function (childEl) {
|
|
1587
|
-
return childEl !== nodeElement.parentElement;
|
|
1588
|
-
})
|
|
1589
|
-
: [];
|
|
1590
|
-
relatedElement = siblingElements[0] || null;
|
|
1591
|
-
}
|
|
1592
|
-
|
|
1593
|
-
if (relatedElement && (!isVerticalNode || siblingElements.length > 1)) {
|
|
1594
|
-
if (!siblingElements.some(function (siblingEl) { return siblingEl.classList.contains('hidden'); })
|
|
1595
|
-
&& !siblingElements.some(function (siblingEl) { return siblingEl.parentElement && siblingEl.parentElement.classList.contains('hidden'); })
|
|
1596
|
-
&& (!isVerticalNode || !relatedElement.closest('.vertical') || !relatedElement.closest('.vertical').classList.contains('hidden'))) {
|
|
1597
|
-
return { 'exist': true, 'visible': true };
|
|
1598
|
-
}
|
|
1599
|
-
return { 'exist': true, 'visible': false };
|
|
1600
|
-
}
|
|
1601
|
-
} else {
|
|
1602
|
-
if (!((nodeElement.closest('.nodes') && nodeElement.closest('.nodes').classList.contains('hidden')) ||
|
|
1603
|
-
(nodeElement.closest('.hierarchy') && nodeElement.closest('.hierarchy').classList.contains('hidden')) ||
|
|
1604
|
-
(nodeElement.closest('.vertical') && ((nodeElement.closest('.nodes') && nodeElement.closest('.nodes').classList.contains('hidden')) || nodeElement.closest('.vertical').classList.contains('hidden')))
|
|
1605
|
-
)) {
|
|
1606
|
-
return { 'exist': true, 'visible': true };
|
|
1607
|
-
}
|
|
1608
|
-
return { 'exist': true, 'visible': false };
|
|
1768
|
+
const siblingElements = this.getSiblings(nodeElement);
|
|
1769
|
+
return {
|
|
1770
|
+
exist: siblingElements.length > 0,
|
|
1771
|
+
visible: siblingElements.length > 0
|
|
1772
|
+
&& siblingElements.every(function (siblingElement) { return this.getNodeState(siblingElement).visible; }, this)
|
|
1773
|
+
};
|
|
1609
1774
|
}
|
|
1610
|
-
|
|
1611
|
-
|
|
1775
|
+
const collapsedCompactAncestor = nodeElement.parentElement
|
|
1776
|
+
? nodeElement.parentElement.closest('.node.compact:not(.looseMode)') : null;
|
|
1777
|
+
return { exist: true, visible: !nodeElement.closest('.hidden') && !collapsedCompactAncestor };
|
|
1612
1778
|
},
|
|
1613
1779
|
getParent: function (nodeEl) {
|
|
1614
1780
|
return this.getRelatedNodes(nodeEl, 'parent');
|
|
@@ -1631,12 +1797,25 @@
|
|
|
1631
1797
|
}
|
|
1632
1798
|
|
|
1633
1799
|
if (relation === 'parent') {
|
|
1800
|
+
if (nodeElement.parentElement && nodeElement.parentElement.classList.contains('node')) {
|
|
1801
|
+
return nodeElement.parentElement;
|
|
1802
|
+
}
|
|
1634
1803
|
nodesContainerEl = nodeElement.closest('.nodes');
|
|
1804
|
+
const parentData = nodesContainerEl ? getState(nodesContainerEl, 'parentData') : null;
|
|
1805
|
+
if (parentData) {
|
|
1806
|
+
return Array.from(nodeElement.closest('.orgchart').querySelectorAll('.node')).find(function (element) {
|
|
1807
|
+
return getState(element, 'sourceData') === parentData;
|
|
1808
|
+
}) || null;
|
|
1809
|
+
}
|
|
1635
1810
|
return nodesContainerEl ? nodesContainerEl.previousElementSibling : null;
|
|
1636
1811
|
} else if (relation === 'children') {
|
|
1637
|
-
|
|
1638
|
-
return
|
|
1812
|
+
const nestedNodeElements = Array.from(nodeElement.children).filter(function (childElement) {
|
|
1813
|
+
return childElement.classList.contains('node');
|
|
1639
1814
|
});
|
|
1815
|
+
if (nestedNodeElements.length) {
|
|
1816
|
+
return nestedNodeElements;
|
|
1817
|
+
}
|
|
1818
|
+
childNodesContainerElement = getChildNodesContainer(nodeElement);
|
|
1640
1819
|
|
|
1641
1820
|
if (!childNodesContainerElement) {
|
|
1642
1821
|
return [];
|
|
@@ -1644,20 +1823,27 @@
|
|
|
1644
1823
|
|
|
1645
1824
|
return Array.from(childNodesContainerElement.children).filter(function (childEl) {
|
|
1646
1825
|
return childEl.classList && childEl.classList.contains('hierarchy');
|
|
1647
|
-
}).
|
|
1648
|
-
return childHierarchyEl.
|
|
1649
|
-
})
|
|
1826
|
+
}).flatMap(function (childHierarchyEl) {
|
|
1827
|
+
return Array.from(childHierarchyEl.children).filter(function (element) { return element.classList.contains('node'); });
|
|
1828
|
+
});
|
|
1650
1829
|
} else if (relation === 'siblings') {
|
|
1830
|
+
if (nodeElement.parentElement && nodeElement.parentElement.classList.contains('node')) {
|
|
1831
|
+
return Array.from(nodeElement.parentElement.children).filter(function (siblingElement) {
|
|
1832
|
+
return siblingElement !== nodeElement && siblingElement.classList.contains('node');
|
|
1833
|
+
});
|
|
1834
|
+
}
|
|
1651
1835
|
hierarchyEl = nodeElement.closest('.hierarchy');
|
|
1652
1836
|
if (!hierarchyEl || !hierarchyEl.parentElement) {
|
|
1653
1837
|
return [];
|
|
1654
1838
|
}
|
|
1655
1839
|
|
|
1656
1840
|
return Array.from(hierarchyEl.parentElement.children).filter(function (siblingEl) {
|
|
1657
|
-
return siblingEl
|
|
1658
|
-
}).
|
|
1659
|
-
return
|
|
1660
|
-
|
|
1841
|
+
return siblingEl.classList.contains('hierarchy');
|
|
1842
|
+
}).flatMap(function (siblingHierarchyEl) {
|
|
1843
|
+
return Array.from(siblingHierarchyEl.children).filter(function (element) {
|
|
1844
|
+
return element !== nodeElement && element.classList.contains('node');
|
|
1845
|
+
});
|
|
1846
|
+
});
|
|
1661
1847
|
}
|
|
1662
1848
|
|
|
1663
1849
|
return [];
|
|
@@ -1820,9 +2006,7 @@
|
|
|
1820
2006
|
}
|
|
1821
2007
|
|
|
1822
2008
|
hierarchyElement = nodeElement.closest('.hierarchy');
|
|
1823
|
-
lowerLevelElement =
|
|
1824
|
-
return childEl !== nodeElement && childEl.classList && childEl.classList.contains('nodes');
|
|
1825
|
-
}) || null;
|
|
2009
|
+
lowerLevelElement = getChildNodesContainer(nodeElement);
|
|
1826
2010
|
|
|
1827
2011
|
if (!lowerLevelElement) {
|
|
1828
2012
|
return;
|
|
@@ -1898,9 +2082,7 @@
|
|
|
1898
2082
|
}
|
|
1899
2083
|
|
|
1900
2084
|
hierarchyElement = nodeElement.closest('.hierarchy');
|
|
1901
|
-
levelsElement =
|
|
1902
|
-
return childEl !== nodeElement && childEl.classList && childEl.classList.contains('nodes');
|
|
1903
|
-
}) || null;
|
|
2085
|
+
levelsElement = getChildNodesContainer(nodeElement);
|
|
1904
2086
|
|
|
1905
2087
|
if (!levelsElement) {
|
|
1906
2088
|
return;
|
|
@@ -1915,11 +2097,7 @@
|
|
|
1915
2097
|
? Array.from(levelsElement.querySelectorAll('.node')).filter(function (visibleNodeEl, index) {
|
|
1916
2098
|
return this.isVisibleNode(index, visibleNodeEl);
|
|
1917
2099
|
}, this)
|
|
1918
|
-
:
|
|
1919
|
-
return childEl.classList && childEl.classList.contains('hierarchy');
|
|
1920
|
-
}).map(function (childHierarchyEl) {
|
|
1921
|
-
return childHierarchyEl.querySelector('.node');
|
|
1922
|
-
}).filter(function (visibleNodeEl, index) {
|
|
2100
|
+
: this.getChildren(nodeElement).filter(function (visibleNodeEl, index) {
|
|
1923
2101
|
return this.isVisibleNode(index, visibleNodeEl);
|
|
1924
2102
|
}, this);
|
|
1925
2103
|
if (!isVerticalDesc) {
|
|
@@ -2266,18 +2444,22 @@
|
|
|
2266
2444
|
edgeElement.classList.add('hidden');
|
|
2267
2445
|
nodeElement = edgeElement.parentElement;
|
|
2268
2446
|
if (nodeElement) {
|
|
2447
|
+
setState(nodeElement, 'loadingEdge', edgeElement);
|
|
2269
2448
|
nodeElement.insertAdjacentHTML('beforeend', `<i class="${this.options.icons.theme} ${this.options.icons.spinner} spinner"></i>`);
|
|
2270
2449
|
spinnerElement = Array.from(nodeElement.children || []).find(function (childEl) {
|
|
2271
2450
|
return childEl.classList && childEl.classList.contains('spinner');
|
|
2272
2451
|
}) || null;
|
|
2273
2452
|
Array.from(nodeElement.children || []).forEach(function (childEl) {
|
|
2274
2453
|
if (childEl !== spinnerElement) {
|
|
2454
|
+
setState(childEl, 'loadingOriginalOpacity', childEl.style.opacity);
|
|
2275
2455
|
childEl.style.opacity = 0.2;
|
|
2276
2456
|
}
|
|
2277
2457
|
});
|
|
2278
2458
|
}
|
|
2279
2459
|
setState(chartElement, 'inAjax', true);
|
|
2280
|
-
Array.from(getDocument().querySelectorAll('.oc-export-btn')).
|
|
2460
|
+
Array.from(getDocument().querySelectorAll('.oc-export-btn')).filter(function (exportButtonEl) {
|
|
2461
|
+
return !getState(exportButtonEl, 'orgChart') || getState(exportButtonEl, 'orgChart') === this;
|
|
2462
|
+
}, this).forEach(function (exportButtonEl) {
|
|
2281
2463
|
exportButtonEl.disabled = true;
|
|
2282
2464
|
});
|
|
2283
2465
|
return true;
|
|
@@ -2299,32 +2481,132 @@
|
|
|
2299
2481
|
spinnerEl.remove();
|
|
2300
2482
|
});
|
|
2301
2483
|
Array.from(nodeElement.children || []).forEach(function (childEl) {
|
|
2302
|
-
childEl.
|
|
2484
|
+
childEl.style.opacity = getState(childEl, 'loadingOriginalOpacity') || '';
|
|
2485
|
+
if (!childEl.style.cssText) {
|
|
2486
|
+
childEl.removeAttribute('style');
|
|
2487
|
+
}
|
|
2303
2488
|
});
|
|
2489
|
+
setState(nodeElement, 'loadingEdge', null);
|
|
2490
|
+
if (this.isInAction(nodeElement)) {
|
|
2491
|
+
this.nodeEnterLeaveHandler({ type: 'mouseenter', node: nodeElement });
|
|
2492
|
+
} else {
|
|
2493
|
+
this.removeNodeControls(nodeElement);
|
|
2494
|
+
}
|
|
2304
2495
|
}
|
|
2305
2496
|
setState(chartElement, 'inAjax', false);
|
|
2306
|
-
Array.from(getDocument().querySelectorAll('.oc-export-btn')).
|
|
2497
|
+
Array.from(getDocument().querySelectorAll('.oc-export-btn')).filter(function (exportButtonEl) {
|
|
2498
|
+
return !getState(exportButtonEl, 'orgChart') || getState(exportButtonEl, 'orgChart') === this;
|
|
2499
|
+
}, this).forEach(function (exportButtonEl) {
|
|
2307
2500
|
exportButtonEl.disabled = false;
|
|
2308
2501
|
});
|
|
2309
2502
|
},
|
|
2310
2503
|
// whether the cursor is hovering over the node
|
|
2311
2504
|
isInAction: function (nodeEl) {
|
|
2312
2505
|
const nodeElement = getElement(nodeEl);
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2506
|
+
return !!nodeElement && nodeElement.classList.contains('controls-active');
|
|
2507
|
+
},
|
|
2508
|
+
renderNodeControls: function (nodeEl) {
|
|
2509
|
+
const nodeElement = getElement(nodeEl);
|
|
2510
|
+
if (!nodeElement || !this.isInAction(nodeElement) || getState(nodeElement, 'loadingEdge')
|
|
2511
|
+
|| getState(nodeElement, 'updatingControls')) {
|
|
2512
|
+
return;
|
|
2513
|
+
}
|
|
2514
|
+
const data = getState(nodeElement, 'sourceData') || {};
|
|
2515
|
+
const opts = this.options;
|
|
2516
|
+
const icons = opts.icons;
|
|
2517
|
+
const hasChildren = this.getNodeState(nodeElement, 'children').exist;
|
|
2518
|
+
const isVertical = data.vertical || (opts.verticalLevel && data.level >= opts.verticalLevel)
|
|
2519
|
+
|| !!nodeElement.closest('.nodes.vertical');
|
|
2520
|
+
const controls = [];
|
|
2521
|
+
if (isVertical) {
|
|
2522
|
+
if (hasChildren) {
|
|
2523
|
+
controls.push(`<i class="toggleBtn ${icons.theme}"></i>`);
|
|
2524
|
+
}
|
|
2525
|
+
} else if (data.hybrid) {
|
|
2526
|
+
if (hasChildren) {
|
|
2527
|
+
controls.push(`<i class="edge verticalEdge bottomEdge ${icons.theme}"></i>`);
|
|
2528
|
+
}
|
|
2529
|
+
} else if (usesCompactLayout(data, opts, data.level)) {
|
|
2530
|
+
if (hasChildren) {
|
|
2531
|
+
const isLoose = nodeElement.classList.contains('looseMode');
|
|
2532
|
+
controls.push(`<i class="${icons.theme} ${icons.backToCompact} backToCompactSymbol${isLoose ? '' : ' hidden'}"></i>`);
|
|
2533
|
+
controls.push(`<i class="${icons.theme} ${icons.backToLoose} backToLooseSymbol${isLoose ? ' hidden' : ''}"></i>`);
|
|
2534
|
+
}
|
|
2535
|
+
} else if (!data.associatedCompact) {
|
|
2536
|
+
if (this.getNodeState(nodeElement, 'parent').exist) {
|
|
2537
|
+
controls.push(`<i class="edge verticalEdge topEdge ${icons.theme}"></i>`);
|
|
2538
|
+
}
|
|
2539
|
+
if (this.getNodeState(nodeElement, 'siblings').exist) {
|
|
2540
|
+
controls.push(`<i class="edge horizontalEdge rightEdge ${icons.theme}"></i>`);
|
|
2541
|
+
controls.push(`<i class="edge horizontalEdge leftEdge ${icons.theme}"></i>`);
|
|
2542
|
+
}
|
|
2543
|
+
if (hasChildren) {
|
|
2544
|
+
controls.push(`<i class="edge verticalEdge bottomEdge ${icons.theme}"></i>`);
|
|
2545
|
+
}
|
|
2546
|
+
}
|
|
2547
|
+
const controlClasses = ['topEdge', 'bottomEdge', 'leftEdge', 'rightEdge', 'toggleBtn', 'backToCompactSymbol', 'backToLooseSymbol'];
|
|
2548
|
+
const newControls = createNodesFromHtml(controls.join(''));
|
|
2549
|
+
const desiredClasses = newControls.map(function (control) {
|
|
2550
|
+
return controlClasses.find(function (className) { return control.classList.contains(className); });
|
|
2327
2551
|
});
|
|
2552
|
+
setState(nodeElement, 'updatingControls', true);
|
|
2553
|
+
try {
|
|
2554
|
+
Array.from(nodeElement.children).filter(function (child) {
|
|
2555
|
+
return controlClasses.some(function (className) { return child.classList.contains(className); })
|
|
2556
|
+
&& !desiredClasses.some(function (className) { return child.classList.contains(className); });
|
|
2557
|
+
}).forEach(function (control) { control.remove(); });
|
|
2558
|
+
newControls.forEach(function (control, index) {
|
|
2559
|
+
const existingControl = nodeElement.querySelector(':scope > .' + desiredClasses[index]);
|
|
2560
|
+
const label = desiredClasses[index] === 'topEdge' ? 'Toggle parent nodes'
|
|
2561
|
+
: desiredClasses[index] === 'leftEdge' || desiredClasses[index] === 'rightEdge' ? 'Toggle sibling nodes'
|
|
2562
|
+
: desiredClasses[index] === 'backToCompactSymbol' ? 'Use compact layout'
|
|
2563
|
+
: desiredClasses[index] === 'backToLooseSymbol' ? 'Expand compact layout' : 'Toggle child nodes';
|
|
2564
|
+
if (existingControl) {
|
|
2565
|
+
existingControl.className = control.className;
|
|
2566
|
+
} else {
|
|
2567
|
+
control.tabIndex = 0;
|
|
2568
|
+
control.setAttribute('role', 'button');
|
|
2569
|
+
control.setAttribute('aria-label', label);
|
|
2570
|
+
control.title = label;
|
|
2571
|
+
nodeElement.appendChild(control);
|
|
2572
|
+
}
|
|
2573
|
+
});
|
|
2574
|
+
} finally {
|
|
2575
|
+
setState(nodeElement, 'updatingControls', false);
|
|
2576
|
+
}
|
|
2577
|
+
},
|
|
2578
|
+
removeNodeControls: function (nodeEl) {
|
|
2579
|
+
const nodeElement = getElement(nodeEl);
|
|
2580
|
+
if (!nodeElement || getState(nodeElement, 'updatingControls')) {
|
|
2581
|
+
return;
|
|
2582
|
+
}
|
|
2583
|
+
setState(nodeElement, 'updatingControls', true);
|
|
2584
|
+
try {
|
|
2585
|
+
Array.from(nodeElement.children).filter(function (child) {
|
|
2586
|
+
return child.matches('.edge, .toggleBtn, .backToCompactSymbol, .backToLooseSymbol')
|
|
2587
|
+
&& child !== getState(nodeElement, 'loadingEdge');
|
|
2588
|
+
}).forEach(function (control) { control.remove(); });
|
|
2589
|
+
} finally {
|
|
2590
|
+
setState(nodeElement, 'updatingControls', false);
|
|
2591
|
+
}
|
|
2592
|
+
},
|
|
2593
|
+
refreshNodeControls: function (nodeEl) {
|
|
2594
|
+
const nodeElement = getElement(nodeEl);
|
|
2595
|
+
if (nodeElement) {
|
|
2596
|
+
const titleElement = nodeElement.querySelector(':scope > .title');
|
|
2597
|
+
const symbol = titleElement ? titleElement.querySelector('.parentNodeSymbol') : null;
|
|
2598
|
+
const hasChildren = this.getNodeState(nodeElement, 'children').exist;
|
|
2599
|
+
if (titleElement && hasChildren && !symbol) {
|
|
2600
|
+
titleElement.insertAdjacentHTML('afterbegin', `<i class="${this.options.icons.theme} ${this.options.icons.parentNode} parentNodeSymbol"></i>`);
|
|
2601
|
+
} else if (!hasChildren && symbol) {
|
|
2602
|
+
symbol.remove();
|
|
2603
|
+
}
|
|
2604
|
+
}
|
|
2605
|
+
if (this.chart) {
|
|
2606
|
+
Array.from(this.chart.querySelectorAll('.node.controls-active')).forEach(function (activeNode) {
|
|
2607
|
+
this.nodeEnterLeaveHandler({ type: 'mouseenter', node: activeNode });
|
|
2608
|
+
}, this);
|
|
2609
|
+
}
|
|
2328
2610
|
},
|
|
2329
2611
|
//
|
|
2330
2612
|
switchVerticalArrow: function (arrowEl) {
|
|
@@ -2402,61 +2684,42 @@
|
|
|
2402
2684
|
const nativeEvent = event.originalEvent || event;
|
|
2403
2685
|
const eventType = nativeEvent.type;
|
|
2404
2686
|
const nodeElement = event.node || nativeEvent.currentTarget;
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
return childEl.classList && childEl.classList.contains('rightEdge');
|
|
2415
|
-
}) || null;
|
|
2416
|
-
const bottomEdgeElement = childElements.find(function (childEl) {
|
|
2417
|
-
return childEl.classList && childEl.classList.contains('bottomEdge');
|
|
2418
|
-
}) || null;
|
|
2419
|
-
const leftEdgeElement = childElements.find(function (childEl) {
|
|
2420
|
-
return childEl.classList && childEl.classList.contains('leftEdge');
|
|
2421
|
-
}) || null;
|
|
2422
|
-
let isExpanded = false;
|
|
2423
|
-
if (isVerticalNode) {
|
|
2424
|
-
if (eventType === 'mouseenter') {
|
|
2425
|
-
if (toggleBtnElement) {
|
|
2426
|
-
isExpanded = this.getNodeState(nodeElement, 'children').visible;
|
|
2427
|
-
toggleBtnElement.classList.toggle(this.options.icons.collapsed, !isExpanded);
|
|
2428
|
-
toggleBtnElement.classList.toggle(this.options.icons.expanded, isExpanded);
|
|
2429
|
-
}
|
|
2430
|
-
} else if (toggleBtnElement) {
|
|
2431
|
-
toggleBtnElement.classList.remove(this.options.icons.collapsed, this.options.icons.expanded);
|
|
2432
|
-
}
|
|
2433
|
-
} else {
|
|
2434
|
-
if (eventType === 'mouseenter') {
|
|
2435
|
-
if (topEdgeElement) {
|
|
2436
|
-
isExpanded = this.getNodeState(nodeElement, 'parent').visible;
|
|
2437
|
-
topEdgeElement.classList.toggle(this.options.icons.expandToUp, !isExpanded);
|
|
2438
|
-
topEdgeElement.classList.toggle(this.options.icons.collapseToDown, isExpanded);
|
|
2439
|
-
}
|
|
2440
|
-
if (bottomEdgeElement) {
|
|
2441
|
-
isExpanded = this.getNodeState(nodeElement, 'children').visible;
|
|
2442
|
-
bottomEdgeElement.classList.toggle(this.options.icons.collapseToDown, !isExpanded);
|
|
2443
|
-
bottomEdgeElement.classList.toggle(this.options.icons.expandToUp, isExpanded);
|
|
2444
|
-
}
|
|
2445
|
-
if (leftEdgeElement || rightEdgeElement) {
|
|
2446
|
-
this.switchHorizontalArrow(nodeElement);
|
|
2447
|
-
}
|
|
2448
|
-
} else {
|
|
2449
|
-
childElements.forEach(function (childEl) {
|
|
2450
|
-
if (childEl.classList && childEl.classList.contains('edge')) {
|
|
2451
|
-
childEl.classList.remove(
|
|
2452
|
-
this.options.icons.expandToUp,
|
|
2453
|
-
this.options.icons.collapseToDown,
|
|
2454
|
-
this.options.icons.collapseToLeft,
|
|
2455
|
-
this.options.icons.expandToRight
|
|
2456
|
-
);
|
|
2457
|
-
}
|
|
2458
|
-
}, this);
|
|
2687
|
+
if (!nodeElement || getState(nodeElement, 'updatingControls')) {
|
|
2688
|
+
return;
|
|
2689
|
+
}
|
|
2690
|
+
if (eventType === 'mouseleave' || eventType === 'focusout') {
|
|
2691
|
+
const activeElement = getDocument().activeElement;
|
|
2692
|
+
if ((eventType === 'mouseleave' && activeElement && activeElement.closest('.node') === nodeElement)
|
|
2693
|
+
|| (eventType === 'focusout' && ((nativeEvent.relatedTarget && nodeElement.contains(nativeEvent.relatedTarget))
|
|
2694
|
+
|| nodeElement.matches(':hover')))) {
|
|
2695
|
+
return;
|
|
2459
2696
|
}
|
|
2697
|
+
nodeElement.classList.remove('controls-active');
|
|
2698
|
+
this.removeNodeControls(nodeElement);
|
|
2699
|
+
return;
|
|
2700
|
+
}
|
|
2701
|
+
nodeElement.classList.add('controls-active');
|
|
2702
|
+
this.renderNodeControls(nodeElement);
|
|
2703
|
+
const toggle = nodeElement.querySelector(':scope > .toggleBtn');
|
|
2704
|
+
const topEdge = nodeElement.querySelector(':scope > .topEdge');
|
|
2705
|
+
const bottomEdge = nodeElement.querySelector(':scope > .bottomEdge');
|
|
2706
|
+
if (toggle) {
|
|
2707
|
+
const expanded = this.getNodeState(nodeElement, 'children').visible;
|
|
2708
|
+
toggle.classList.toggle(this.options.icons.collapsed, !expanded);
|
|
2709
|
+
toggle.classList.toggle(this.options.icons.expanded, expanded);
|
|
2710
|
+
}
|
|
2711
|
+
if (topEdge) {
|
|
2712
|
+
const expanded = this.getNodeState(nodeElement, 'parent').visible;
|
|
2713
|
+
topEdge.classList.toggle(this.options.icons.expandToUp, !expanded);
|
|
2714
|
+
topEdge.classList.toggle(this.options.icons.collapseToDown, expanded);
|
|
2715
|
+
}
|
|
2716
|
+
if (bottomEdge) {
|
|
2717
|
+
const expanded = this.getNodeState(nodeElement, 'children').visible;
|
|
2718
|
+
bottomEdge.classList.toggle(this.options.icons.collapseToDown, !expanded);
|
|
2719
|
+
bottomEdge.classList.toggle(this.options.icons.expandToUp, expanded);
|
|
2720
|
+
}
|
|
2721
|
+
if (nodeElement.querySelector(':scope > .horizontalEdge')) {
|
|
2722
|
+
this.switchHorizontalArrow(nodeElement);
|
|
2460
2723
|
}
|
|
2461
2724
|
},
|
|
2462
2725
|
//
|
|
@@ -2468,11 +2731,18 @@
|
|
|
2468
2731
|
if (!chartElement || !nodeElement || !nodeElement.classList) {
|
|
2469
2732
|
return;
|
|
2470
2733
|
}
|
|
2734
|
+
if (nativeEvent.target && nativeEvent.target.closest && nativeEvent.target.closest('.node') !== nodeElement) {
|
|
2735
|
+
return;
|
|
2736
|
+
}
|
|
2471
2737
|
|
|
2472
2738
|
Array.from(chartElement.querySelectorAll('.focused')).forEach(function (focusedEl) {
|
|
2473
2739
|
focusedEl.classList.remove('focused');
|
|
2474
2740
|
});
|
|
2475
2741
|
nodeElement.classList.add('focused');
|
|
2742
|
+
if (!this.isInAction(nodeElement)) {
|
|
2743
|
+
nodeElement.focus({ preventScroll: true });
|
|
2744
|
+
this.nodeEnterLeaveHandler({ type: 'mouseenter', node: nodeElement });
|
|
2745
|
+
}
|
|
2476
2746
|
},
|
|
2477
2747
|
addAncestors: function (data, parentId) {
|
|
2478
2748
|
const rootHierarchyElement = this.chart ? this.chart.querySelector(':scope > .nodes > .hierarchy') : null;
|
|
@@ -2502,6 +2772,7 @@
|
|
|
2502
2772
|
if (targetSiblingsContainerElement && targetSiblingsContainerElement !== ancestorWrapperElement.parentElement) {
|
|
2503
2773
|
targetSiblingsContainerElement.appendChild(ancestorWrapperElement);
|
|
2504
2774
|
}
|
|
2775
|
+
this.refreshNodeControls(targetParentNodeElement);
|
|
2505
2776
|
},
|
|
2506
2777
|
addDescendants:function (data, parentEl) {
|
|
2507
2778
|
const orgChart = this;
|
|
@@ -2511,6 +2782,10 @@
|
|
|
2511
2782
|
if (!parentElement || !parentElement.parentElement) {
|
|
2512
2783
|
return;
|
|
2513
2784
|
}
|
|
2785
|
+
if (getState(parentElement, 'sourceData')) {
|
|
2786
|
+
this.addChildren(parentElement, data);
|
|
2787
|
+
return;
|
|
2788
|
+
}
|
|
2514
2789
|
|
|
2515
2790
|
descendantsElement = getDocument().createElement('ul');
|
|
2516
2791
|
descendantsElement.className = 'nodes';
|
|
@@ -2526,8 +2801,9 @@
|
|
|
2526
2801
|
//
|
|
2527
2802
|
HideFirstParentEnd: function (event) {
|
|
2528
2803
|
const nativeEvent = event.originalEvent || event;
|
|
2529
|
-
const
|
|
2530
|
-
const nodeElement =
|
|
2804
|
+
const previousEdge = getElement(event.topEdge || nativeEvent.topEdge);
|
|
2805
|
+
const nodeElement = getElement(event.node || nativeEvent.node) || (previousEdge ? previousEdge.parentElement : null);
|
|
2806
|
+
const topEdgeElement = nodeElement ? nodeElement.querySelector(':scope > .topEdge') : null;
|
|
2531
2807
|
|
|
2532
2808
|
if (this.isInAction(nodeElement)) {
|
|
2533
2809
|
this.switchVerticalArrow(topEdgeElement);
|
|
@@ -2553,7 +2829,7 @@
|
|
|
2553
2829
|
this.hideParent(nodeElement);
|
|
2554
2830
|
if (parentEl) {
|
|
2555
2831
|
parentEl.addEventListener('transitionend', function (transitionEvent) {
|
|
2556
|
-
transitionEvent.
|
|
2832
|
+
transitionEvent.node = nodeElement;
|
|
2557
2833
|
orgChart.HideFirstParentEnd(transitionEvent);
|
|
2558
2834
|
}, { once: true });
|
|
2559
2835
|
}
|
|
@@ -2572,16 +2848,8 @@
|
|
|
2572
2848
|
let childNodesContainerElement;
|
|
2573
2849
|
let childNodeElements;
|
|
2574
2850
|
if (childrenState.exist) {
|
|
2575
|
-
childNodesContainerElement =
|
|
2576
|
-
|
|
2577
|
-
}) || null;
|
|
2578
|
-
childNodeElements = childNodesContainerElement
|
|
2579
|
-
? Array.from(childNodesContainerElement.children).filter(function (childEl) {
|
|
2580
|
-
return childEl.classList && childEl.classList.contains('hierarchy');
|
|
2581
|
-
}).map(function (childHierarchyEl) {
|
|
2582
|
-
return childHierarchyEl.querySelector('.node');
|
|
2583
|
-
}).filter(Boolean)
|
|
2584
|
-
: [];
|
|
2851
|
+
childNodesContainerElement = getChildNodesContainer(nodeElement);
|
|
2852
|
+
childNodeElements = childNodesContainerElement ? this.getChildren(nodeElement) : [];
|
|
2585
2853
|
if (childNodeElements.some(function (childNodeEl) { return childNodeEl.classList.contains('sliding'); })) { return; }
|
|
2586
2854
|
// hide the descendant nodes of the specified node
|
|
2587
2855
|
if (childrenState.visible) {
|
|
@@ -2658,7 +2926,13 @@
|
|
|
2658
2926
|
}
|
|
2659
2927
|
|
|
2660
2928
|
compactNodeEl.classList.remove('looseMode');
|
|
2661
|
-
|
|
2929
|
+
const familyContainer = getChildNodesContainer(compactNodeEl);
|
|
2930
|
+
if (familyContainer && familyContainer.classList.contains('compact-family')) {
|
|
2931
|
+
familyContainer.classList.add('hidden');
|
|
2932
|
+
}
|
|
2933
|
+
nestedLooseModeElements = Array.from(compactNodeEl.querySelectorAll('.looseMode')).concat(
|
|
2934
|
+
familyContainer ? Array.from(familyContainer.querySelectorAll('.looseMode')) : []
|
|
2935
|
+
);
|
|
2662
2936
|
nestedLooseModeElements.forEach(function (nestedLooseModeEl) {
|
|
2663
2937
|
const nestedBackToCompactSymbolElement = Array.from(nestedLooseModeEl.children || []).find(function (childEl) {
|
|
2664
2938
|
return childEl.classList && childEl.classList.contains('backToCompactSymbol');
|
|
@@ -2668,6 +2942,10 @@
|
|
|
2668
2942
|
}) || null;
|
|
2669
2943
|
|
|
2670
2944
|
nestedLooseModeEl.classList.remove('looseMode');
|
|
2945
|
+
const nestedContainer = getChildNodesContainer(nestedLooseModeEl);
|
|
2946
|
+
if (nestedContainer && nestedContainer.classList.contains('compact-family')) {
|
|
2947
|
+
nestedContainer.classList.add('hidden');
|
|
2948
|
+
}
|
|
2671
2949
|
if (nestedBackToCompactSymbolElement) {
|
|
2672
2950
|
nestedBackToCompactSymbolElement.classList.add('hidden');
|
|
2673
2951
|
}
|
|
@@ -2701,6 +2979,13 @@
|
|
|
2701
2979
|
}
|
|
2702
2980
|
|
|
2703
2981
|
compactNodeEl.classList.add('looseMode');
|
|
2982
|
+
const familyContainer = getChildNodesContainer(compactNodeEl);
|
|
2983
|
+
if (familyContainer && familyContainer.classList.contains('compact-family')) {
|
|
2984
|
+
familyContainer.classList.remove('hidden');
|
|
2985
|
+
}
|
|
2986
|
+
this.getChildren(compactNodeEl).forEach(function (childElement) {
|
|
2987
|
+
childElement.classList.remove('slide-up');
|
|
2988
|
+
});
|
|
2704
2989
|
backToLooseSymbolElement = Array.from(compactNodeEl.children || []).find(function (childEl) {
|
|
2705
2990
|
return childEl.classList && childEl.classList.contains('backToLooseSymbol');
|
|
2706
2991
|
}) || null;
|
|
@@ -2804,8 +3089,6 @@
|
|
|
2804
3089
|
const origEvent = nativeEvent;
|
|
2805
3090
|
const isFirefox = /firefox/.test(getWindow().navigator.userAgent.toLowerCase());
|
|
2806
3091
|
let sourceRect;
|
|
2807
|
-
let transformValue;
|
|
2808
|
-
let transformValues;
|
|
2809
3092
|
let isVerticalChartDirection;
|
|
2810
3093
|
let scaleFactor;
|
|
2811
3094
|
let ghostNodeEl, nodeCoverEl;
|
|
@@ -2831,10 +3114,8 @@
|
|
|
2831
3114
|
}
|
|
2832
3115
|
|
|
2833
3116
|
sourceRect = sourceNodeEl.getBoundingClientRect();
|
|
2834
|
-
transformValue = chartElement.style.transform || getWindow().getComputedStyle(chartElement).transform || 'none';
|
|
2835
|
-
transformValues = transformValue.split(',');
|
|
2836
3117
|
isVerticalChartDirection = opts.direction === 't2b' || opts.direction === 'b2t';
|
|
2837
|
-
scaleFactor =
|
|
3118
|
+
scaleFactor = getChartTransform(chartElement).scale;
|
|
2838
3119
|
ghostNodeEl.setAttribute('width', isVerticalChartDirection ? sourceRect.width : sourceRect.height);
|
|
2839
3120
|
ghostNodeEl.setAttribute('height', isVerticalChartDirection ? sourceRect.height : sourceRect.width);
|
|
2840
3121
|
nodeCoverEl.setAttribute('x',5 * scaleFactor);
|
|
@@ -2878,12 +3159,10 @@
|
|
|
2878
3159
|
return 0;
|
|
2879
3160
|
}
|
|
2880
3161
|
|
|
2881
|
-
currentElement = nodeElement
|
|
3162
|
+
currentElement = nodeElement;
|
|
2882
3163
|
while (currentElement) {
|
|
2883
|
-
|
|
2884
|
-
|
|
2885
|
-
}
|
|
2886
|
-
currentElement = currentElement.parentElement;
|
|
3164
|
+
levelCount += 1;
|
|
3165
|
+
currentElement = this.getParent(currentElement);
|
|
2887
3166
|
}
|
|
2888
3167
|
|
|
2889
3168
|
return levelCount;
|
|
@@ -2955,15 +3234,18 @@
|
|
|
2955
3234
|
? draggedNodeEl.closest('[draggable]')
|
|
2956
3235
|
: null;
|
|
2957
3236
|
draggingNode = !!(draggableHostEl && draggableHostEl.classList && draggableHostEl.classList.contains('node'));
|
|
2958
|
-
draggedParentNodeEl =
|
|
2959
|
-
|
|
2960
|
-
|
|
2961
|
-
|
|
2962
|
-
|
|
2963
|
-
|
|
3237
|
+
draggedParentNodeEl = this.getParent(draggedNodeEl);
|
|
3238
|
+
draggedSubtreeNodeEls = [];
|
|
3239
|
+
const pendingNodes = draggingNode ? [draggedNodeEl.closest('.node')] : [];
|
|
3240
|
+
while (pendingNodes.length) {
|
|
3241
|
+
const currentNode = pendingNodes.pop();
|
|
3242
|
+
draggedSubtreeNodeEls.push(currentNode);
|
|
3243
|
+
Array.prototype.push.apply(pendingNodes, this.getChildren(currentNode));
|
|
3244
|
+
}
|
|
2964
3245
|
excludedNodeEls = new Set(draggedSubtreeNodeEls);
|
|
2965
3246
|
setState(chartElement, 'dragged', draggedNodeEl);
|
|
2966
3247
|
Array.from(chartElement.querySelectorAll('.node')).forEach(function (node) {
|
|
3248
|
+
node.classList.remove('allowedDrop');
|
|
2967
3249
|
if (!draggingNode || !excludedNodeEls.has(node)) {
|
|
2968
3250
|
if (opts.dropCriteria) {
|
|
2969
3251
|
if (opts.dropCriteria(draggedNodeEl, draggedParentNodeEl, node)) {
|
|
@@ -3052,7 +3334,7 @@
|
|
|
3052
3334
|
return;
|
|
3053
3335
|
}
|
|
3054
3336
|
|
|
3055
|
-
draggedParentNodeEl =
|
|
3337
|
+
draggedParentNodeEl = this.getParent(draggedEl);
|
|
3056
3338
|
const dropEvent = createEventLike('nodedrop.orgchart');
|
|
3057
3339
|
if (chartElement) {
|
|
3058
3340
|
const triggeredDropEvent = createTriggeredEvent(dropEvent, {
|
|
@@ -3068,23 +3350,66 @@
|
|
|
3068
3350
|
if (dropEvent.isDefaultPrevented()) {
|
|
3069
3351
|
return;
|
|
3070
3352
|
}
|
|
3353
|
+
const sourceData = getState(draggedEl, 'sourceData');
|
|
3354
|
+
const parentData = draggedParentNodeEl ? getState(draggedParentNodeEl, 'sourceData') : null;
|
|
3355
|
+
const targetData = getState(dropZoneEl, 'sourceData');
|
|
3356
|
+
const datasource = getState(chartElement, 'datasource') || chartOptions.data;
|
|
3357
|
+
const sourceLocation = sourceData ? findDataLocation(datasource, sourceData) : null;
|
|
3358
|
+
if (sourceData && targetData && findDataLocation(sourceData, targetData)) {
|
|
3359
|
+
return;
|
|
3360
|
+
}
|
|
3361
|
+
const needsRebuild = Array.isArray(datasource) || this.options.compact || chartOptions.verticalLevel
|
|
3362
|
+
|| chartElement.querySelector('.node.compact, .nodes.vertical');
|
|
3363
|
+
if (needsRebuild && sourceLocation && sourceLocation.list && targetData) {
|
|
3364
|
+
sourceLocation.list.splice(sourceLocation.index, 1);
|
|
3365
|
+
if (!sourceLocation.list.length && sourceLocation.outerList) {
|
|
3366
|
+
sourceLocation.outerList.splice(sourceLocation.outerIndex, 1);
|
|
3367
|
+
}
|
|
3368
|
+
if (sourceLocation.parent && sourceLocation.parent.children && !sourceLocation.parent.children.length) {
|
|
3369
|
+
delete sourceLocation.parent.children;
|
|
3370
|
+
}
|
|
3371
|
+
const isGrouped = Array.isArray(datasource) || (targetData.children && Array.isArray(targetData.children[0]));
|
|
3372
|
+
if (!targetData.children) {
|
|
3373
|
+
targetData.children = [];
|
|
3374
|
+
}
|
|
3375
|
+
targetData.children.push(isGrouped ? [sourceData] : sourceData);
|
|
3376
|
+
rebuildFromData(this, targetData);
|
|
3377
|
+
return;
|
|
3378
|
+
}
|
|
3071
3379
|
// special process for hybrid chart
|
|
3072
|
-
const datasource = chartOptions.data;
|
|
3073
3380
|
const dataDigger = new JSONDigger(datasource, chartOptions.nodeId, 'children');
|
|
3074
3381
|
const hybridNodeData = dataDigger.findOneNode({ 'hybrid': true });
|
|
3075
3382
|
if (chartOptions.verticalLevel > 1 || hybridNodeData) {
|
|
3076
|
-
const
|
|
3383
|
+
const draggedNodeId = getState(draggedEl, 'nodeData')[chartOptions.nodeId];
|
|
3384
|
+
const dropNodeId = getState(dropZoneEl, 'nodeData')[chartOptions.nodeId];
|
|
3385
|
+
const draggedNodeData = dataDigger.findNodeById(draggedNodeId);
|
|
3386
|
+
const dropNodeData = dataDigger.findNodeById(dropNodeId);
|
|
3387
|
+
if (!draggedNodeData || !dropNodeData) {
|
|
3388
|
+
return;
|
|
3389
|
+
}
|
|
3077
3390
|
const draggedNodeCopy = Object.assign({}, draggedNodeData);
|
|
3078
|
-
dataDigger.removeNode(
|
|
3079
|
-
const dropNodeData = dataDigger.findNodeById(getState(dropZoneEl, 'nodeData').id);
|
|
3391
|
+
dataDigger.removeNode(draggedNodeId);
|
|
3080
3392
|
if (dropNodeData.children) {
|
|
3081
3393
|
dropNodeData.children.push(draggedNodeCopy);
|
|
3082
3394
|
} else {
|
|
3083
3395
|
dropNodeData.children = [draggedNodeCopy];
|
|
3084
3396
|
}
|
|
3085
|
-
orgChart.attachRel(datasource, '00');
|
|
3086
3397
|
orgChart.init({ 'data': datasource });
|
|
3087
3398
|
} else {
|
|
3399
|
+
if (sourceData && parentData && targetData && parentData.children
|
|
3400
|
+
&& parentData.children.indexOf(sourceData) !== -1) {
|
|
3401
|
+
parentData.children.splice(parentData.children.indexOf(sourceData), 1);
|
|
3402
|
+
if (!parentData.children.length) {
|
|
3403
|
+
delete parentData.children;
|
|
3404
|
+
}
|
|
3405
|
+
if (!targetData.children) {
|
|
3406
|
+
targetData.children = [];
|
|
3407
|
+
}
|
|
3408
|
+
targetData.children.push(sourceData);
|
|
3409
|
+
sourceData.parentId = targetData[chartOptions.nodeId];
|
|
3410
|
+
getState(draggedEl, 'nodeData').parentId = sourceData.parentId;
|
|
3411
|
+
draggedEl.setAttribute('data-parent', sourceData.parentId);
|
|
3412
|
+
}
|
|
3088
3413
|
// The folowing code snippets are used to process horizontal chart
|
|
3089
3414
|
draggedHierarchyEl = draggedEl.closest('.hierarchy');
|
|
3090
3415
|
dropChildrenContainerEl = Array.from(dropZoneEl.parentElement ? dropZoneEl.parentElement.children : []).find(function (childEl) {
|
|
@@ -3092,33 +3417,11 @@
|
|
|
3092
3417
|
}) || null;
|
|
3093
3418
|
// firstly, deal with the hierarchy of drop zone
|
|
3094
3419
|
if (!dropChildrenContainerEl) { // if the drop zone is a leaf node
|
|
3095
|
-
dropZoneEl.insertAdjacentHTML('beforeend', `<i class="edge verticalEdge bottomEdge ${this.options.icons.theme}"></i>`);
|
|
3096
3420
|
dropZoneEl.insertAdjacentHTML('afterend', '<ul class="nodes"></ul>');
|
|
3097
3421
|
dropChildrenContainerEl = dropZoneEl.nextElementSibling;
|
|
3098
|
-
Array.from(draggedEl.querySelectorAll('.horizontalEdge')).forEach(function (edgeEl) {
|
|
3099
|
-
edgeEl.remove();
|
|
3100
|
-
});
|
|
3101
3422
|
dropChildrenContainerEl.appendChild(draggedHierarchyEl);
|
|
3102
|
-
const titleEl = Array.from(dropZoneEl.children || []).find(function (childEl) {
|
|
3103
|
-
return childEl.classList && childEl.classList.contains('title');
|
|
3104
|
-
}) || null;
|
|
3105
|
-
if (titleEl) {
|
|
3106
|
-
titleEl.insertAdjacentHTML('afterbegin', `<i class="${this.options.icons.theme} ${chartOptions.icons.parentNode} parentNodeSymbol"></i>`);
|
|
3107
|
-
}
|
|
3108
3423
|
} else {
|
|
3109
|
-
const horizontalEdges = `<i class="edge horizontalEdge rightEdge ${this.options.icons.theme}"></i><i class="edge horizontalEdge leftEdge ${this.options.icons.theme}"></i>`;
|
|
3110
|
-
if (!draggedEl.querySelector('.horizontalEdge')) {
|
|
3111
|
-
draggedEl.insertAdjacentHTML('beforeend', horizontalEdges);
|
|
3112
|
-
}
|
|
3113
3424
|
dropChildrenContainerEl.appendChild(draggedHierarchyEl);
|
|
3114
|
-
const dropSiblingNodeEls = Array.from(dropChildrenContainerEl.children || []).filter(function (childEl) {
|
|
3115
|
-
return childEl !== draggedHierarchyEl && childEl.classList && childEl.classList.contains('hierarchy');
|
|
3116
|
-
}).map(function (siblingHierarchyEl) {
|
|
3117
|
-
return siblingHierarchyEl.querySelector('.node');
|
|
3118
|
-
}).filter(Boolean);
|
|
3119
|
-
if (dropSiblingNodeEls.length === 1) {
|
|
3120
|
-
dropSiblingNodeEls[0].insertAdjacentHTML('beforeend', horizontalEdges);
|
|
3121
|
-
}
|
|
3122
3425
|
}
|
|
3123
3426
|
// secondly, deal with the hierarchy of dragged node
|
|
3124
3427
|
draggedParentChildrenContainerEl = Array.from(draggedParentNodeEl && draggedParentNodeEl.parentElement ? draggedParentNodeEl.parentElement.children : []).find(function (childEl) {
|
|
@@ -3129,21 +3432,20 @@
|
|
|
3129
3432
|
return childEl.classList && childEl.classList.contains('hierarchy');
|
|
3130
3433
|
})
|
|
3131
3434
|
: [];
|
|
3132
|
-
if (remainingHierarchyEls.length ===
|
|
3133
|
-
const remainingNodeEl = remainingHierarchyEls[0].querySelector('.node');
|
|
3134
|
-
if (remainingNodeEl) {
|
|
3135
|
-
Array.from(remainingNodeEl.querySelectorAll('.horizontalEdge')).forEach(function (edgeEl) {
|
|
3136
|
-
edgeEl.remove();
|
|
3137
|
-
});
|
|
3138
|
-
}
|
|
3139
|
-
} else if (remainingHierarchyEls.length === 0) {
|
|
3140
|
-
Array.from(draggedParentNodeEl.querySelectorAll('.bottomEdge, .parentNodeSymbol')).forEach(function (edgeEl) {
|
|
3141
|
-
edgeEl.remove();
|
|
3142
|
-
});
|
|
3435
|
+
if (remainingHierarchyEls.length === 0) {
|
|
3143
3436
|
if (draggedParentChildrenContainerEl) {
|
|
3144
3437
|
draggedParentChildrenContainerEl.remove();
|
|
3145
3438
|
}
|
|
3146
3439
|
}
|
|
3440
|
+
dropChildrenContainerEl.classList.remove('hidden');
|
|
3441
|
+
dropZoneEl.closest('.hierarchy').classList.remove('isChildrenCollapsed');
|
|
3442
|
+
this.getChildren(dropZoneEl).forEach(function (childNode) {
|
|
3443
|
+
childNode.classList.remove('slide-up', 'sliding');
|
|
3444
|
+
childNode.closest('.hierarchy').classList.remove('isCollapsedDescendant');
|
|
3445
|
+
});
|
|
3446
|
+
this.refreshNodeControls(draggedParentNodeEl);
|
|
3447
|
+
this.refreshNodeControls(dropZoneEl);
|
|
3448
|
+
this.updateMinimap(true);
|
|
3147
3449
|
}
|
|
3148
3450
|
},
|
|
3149
3451
|
//
|
|
@@ -3334,19 +3636,33 @@
|
|
|
3334
3636
|
return;
|
|
3335
3637
|
}
|
|
3336
3638
|
|
|
3337
|
-
|
|
3338
|
-
|
|
3339
|
-
|
|
3340
|
-
|
|
3341
|
-
|
|
3342
|
-
|
|
3343
|
-
|
|
3639
|
+
const orgChart = this;
|
|
3640
|
+
const handlers = {
|
|
3641
|
+
dragstart: this.dragstartHandler,
|
|
3642
|
+
dragover: this.dragoverHandler,
|
|
3643
|
+
dragend: this.dragendHandler,
|
|
3644
|
+
drop: this.dropHandler,
|
|
3645
|
+
touchstart: this.touchstartHandler,
|
|
3646
|
+
touchmove: this.touchmoveHandler,
|
|
3647
|
+
touchend: this.touchendHandler
|
|
3648
|
+
};
|
|
3649
|
+
Object.keys(handlers).forEach(function (eventType) {
|
|
3650
|
+
nodeElement.addEventListener(eventType, function (event) {
|
|
3651
|
+
if (!event.target.closest || event.target.closest('.node') === nodeElement) {
|
|
3652
|
+
handlers[eventType].call(orgChart, event);
|
|
3653
|
+
}
|
|
3654
|
+
}, { passive: false });
|
|
3655
|
+
});
|
|
3344
3656
|
},
|
|
3345
3657
|
// create node
|
|
3346
3658
|
createNode: function (data) {
|
|
3347
3659
|
const opts = this.options;
|
|
3348
3660
|
const level = data.level;
|
|
3349
|
-
|
|
3661
|
+
if ((opts.compact === true && data.children && data.children.length)
|
|
3662
|
+
|| (typeof opts.compact === 'function' && opts.compact(data))) {
|
|
3663
|
+
data.compact = true;
|
|
3664
|
+
}
|
|
3665
|
+
const isCompactLayout = usesCompactLayout(data, opts, level);
|
|
3350
3666
|
const nodeClassName = [
|
|
3351
3667
|
'node',
|
|
3352
3668
|
data.className || '',
|
|
@@ -3356,7 +3672,7 @@
|
|
|
3356
3672
|
const titleMarkupParts = [];
|
|
3357
3673
|
const contentMarkupParts = [];
|
|
3358
3674
|
const nodeMarkupParts = [];
|
|
3359
|
-
const shouldAddParentSymbol =
|
|
3675
|
+
const shouldAddParentSymbol = !!(data.children && data.children.length);
|
|
3360
3676
|
|
|
3361
3677
|
if (data.children && data[opts.nodeId]) {
|
|
3362
3678
|
forEachValue(data.children, function (index, child) {
|
|
@@ -3379,32 +3695,6 @@
|
|
|
3379
3695
|
nodeMarkupParts.push(contentMarkupParts.join(''));
|
|
3380
3696
|
}
|
|
3381
3697
|
|
|
3382
|
-
if ((opts.verticalLevel && level >= opts.verticalLevel) || data.vertical) {
|
|
3383
|
-
if (shouldAddParentSymbol) {
|
|
3384
|
-
nodeMarkupParts.push(`<i class="toggleBtn ${opts.icons.theme}"></i>`);
|
|
3385
|
-
}
|
|
3386
|
-
} else if (data.hybrid) {
|
|
3387
|
-
if (shouldAddParentSymbol) {
|
|
3388
|
-
nodeMarkupParts.push(`<i class="edge verticalEdge bottomEdge ${opts.icons.theme}"></i>`);
|
|
3389
|
-
}
|
|
3390
|
-
} else if (data.compact) {
|
|
3391
|
-
if (shouldAddParentSymbol) {
|
|
3392
|
-
nodeMarkupParts.push(`<i class="${opts.icons.theme} ${opts.icons.backToCompact} backToCompactSymbol hidden"></i>`);
|
|
3393
|
-
nodeMarkupParts.push(`<i class="${opts.icons.theme} ${opts.icons.backToLoose} backToLooseSymbol"></i>`);
|
|
3394
|
-
}
|
|
3395
|
-
} else if (!data.associatedCompact) {
|
|
3396
|
-
if (Number(flags.substr(0, 1))) {
|
|
3397
|
-
nodeMarkupParts.push(`<i class="edge verticalEdge topEdge ${opts.icons.theme}"></i>`);
|
|
3398
|
-
}
|
|
3399
|
-
if (Number(flags.substr(1, 1))) {
|
|
3400
|
-
nodeMarkupParts.push(`<i class="edge horizontalEdge rightEdge ${opts.icons.theme}"></i>`);
|
|
3401
|
-
nodeMarkupParts.push(`<i class="edge horizontalEdge leftEdge ${opts.icons.theme}"></i>`);
|
|
3402
|
-
}
|
|
3403
|
-
if (shouldAddParentSymbol) {
|
|
3404
|
-
nodeMarkupParts.push(`<i class="edge verticalEdge bottomEdge ${opts.icons.theme}"></i>`);
|
|
3405
|
-
}
|
|
3406
|
-
}
|
|
3407
|
-
|
|
3408
3698
|
// construct the content of node
|
|
3409
3699
|
const nodeElement = getDocument().createElement('div');
|
|
3410
3700
|
const routeNodeClick = function (selector, handler) {
|
|
@@ -3431,19 +3721,38 @@
|
|
|
3431
3721
|
nodeElement.setAttribute('data-parent', data.parentId);
|
|
3432
3722
|
}
|
|
3433
3723
|
nodeElement.className = nodeClassName;
|
|
3724
|
+
nodeElement.tabIndex = 0;
|
|
3434
3725
|
nodeElement.insertAdjacentHTML('beforeend', nodeMarkupParts.join(''));
|
|
3435
3726
|
//
|
|
3436
3727
|
const storedNodeData = mergeObjects({}, data);
|
|
3437
3728
|
delete storedNodeData.children;
|
|
3438
3729
|
setState(nodeElement, 'nodeData', storedNodeData);
|
|
3730
|
+
setState(nodeElement, 'sourceData', data);
|
|
3439
3731
|
nodeElement.__ocNodeData = storedNodeData;
|
|
3440
|
-
if (
|
|
3441
|
-
nodeElement.style.gridTemplateColumns = `repeat(${Math.floor(Math.sqrt(data.children.length + 1))}, auto)`;
|
|
3732
|
+
if (isCompactLayout && nodeElement && nodeElement.style) {
|
|
3733
|
+
nodeElement.style.gridTemplateColumns = `repeat(${Math.floor(Math.sqrt((data.children || []).length + 1))}, auto)`;
|
|
3442
3734
|
}
|
|
3443
3735
|
|
|
3444
3736
|
nodeElement.addEventListener('mouseenter', this.nodeEnterLeaveHandler.bind(this));
|
|
3445
3737
|
nodeElement.addEventListener('mouseleave', this.nodeEnterLeaveHandler.bind(this));
|
|
3738
|
+
nodeElement.addEventListener('focusin', function (event) {
|
|
3739
|
+
if (event.target.closest('.node') === nodeElement) {
|
|
3740
|
+
this.nodeEnterLeaveHandler(event);
|
|
3741
|
+
}
|
|
3742
|
+
}.bind(this));
|
|
3743
|
+
nodeElement.addEventListener('focusout', function (event) {
|
|
3744
|
+
if (event.target.closest('.node') === nodeElement) {
|
|
3745
|
+
this.nodeEnterLeaveHandler(event);
|
|
3746
|
+
}
|
|
3747
|
+
}.bind(this));
|
|
3446
3748
|
nodeElement.addEventListener('click', this.nodeClickHandler.bind(this));
|
|
3749
|
+
nodeElement.addEventListener('keydown', function (event) {
|
|
3750
|
+
const control = event.target.closest('.edge, .toggleBtn, .backToCompactSymbol, .backToLooseSymbol');
|
|
3751
|
+
if (control && control.parentElement === nodeElement && (event.key === 'Enter' || event.key === ' ')) {
|
|
3752
|
+
event.preventDefault();
|
|
3753
|
+
control.click();
|
|
3754
|
+
}
|
|
3755
|
+
});
|
|
3447
3756
|
routeNodeClick('.topEdge', this.topEdgeClickHandler);
|
|
3448
3757
|
routeNodeClick('.bottomEdge', this.bottomEdgeClickHandler);
|
|
3449
3758
|
routeNodeClick('.leftEdge, .rightEdge', this.hEdgeClickHandler);
|
|
@@ -3471,16 +3780,27 @@
|
|
|
3471
3780
|
const hierarchyElement = getElement(hierarchyEl);
|
|
3472
3781
|
const nodeElement = getElement(nodeEl);
|
|
3473
3782
|
const isHidden = level + 1 > opts.visibleLevel || (data.collapsed !== undefined && data.collapsed);
|
|
3783
|
+
const isCompactLayout = usesCompactLayout(data, opts, level);
|
|
3474
3784
|
let nodesLayerElement;
|
|
3475
3785
|
|
|
3476
3786
|
if (!hierarchyElement) {
|
|
3477
3787
|
return;
|
|
3478
3788
|
}
|
|
3479
3789
|
|
|
3480
|
-
|
|
3790
|
+
data.children.flat().forEach(function (child) {
|
|
3791
|
+
if (data.hybrid || data.vertical) {
|
|
3792
|
+
child.vertical = true;
|
|
3793
|
+
} else if (data.compact && child.children) {
|
|
3794
|
+
child.compact = true;
|
|
3795
|
+
} else if (data.compact) {
|
|
3796
|
+
child.associatedCompact = true;
|
|
3797
|
+
}
|
|
3798
|
+
});
|
|
3799
|
+
|
|
3800
|
+
if ((opts.verticalLevel && (level + 1) >= opts.verticalLevel) || data.hybrid || data.vertical) {
|
|
3481
3801
|
nodesLayerElement = getDocument().createElement('ul');
|
|
3482
3802
|
nodesLayerElement.className = 'nodes';
|
|
3483
|
-
if (isHidden
|
|
3803
|
+
if (isHidden) {
|
|
3484
3804
|
nodesLayerElement.classList.add('hidden');
|
|
3485
3805
|
}
|
|
3486
3806
|
if (((opts.verticalLevel && level + 1 === opts.verticalLevel) || data.hybrid)
|
|
@@ -3488,10 +3808,16 @@
|
|
|
3488
3808
|
nodesLayerElement.classList.add('vertical');
|
|
3489
3809
|
}
|
|
3490
3810
|
hierarchyElement.appendChild(nodesLayerElement);
|
|
3491
|
-
} else if (
|
|
3811
|
+
} else if (isCompactLayout) {
|
|
3492
3812
|
if (nodeElement && nodeElement.classList) {
|
|
3493
3813
|
nodeElement.classList.add('compact');
|
|
3494
3814
|
}
|
|
3815
|
+
if (Array.isArray(data.children[0])) {
|
|
3816
|
+
nodesLayerElement = getDocument().createElement('ul');
|
|
3817
|
+
nodesLayerElement.className = 'nodes compact-family hidden';
|
|
3818
|
+
nodesLayerElement.style.setProperty('--compact-columns', Math.ceil(Math.sqrt(data.children.length)));
|
|
3819
|
+
hierarchyElement.appendChild(nodesLayerElement);
|
|
3820
|
+
}
|
|
3495
3821
|
} else {
|
|
3496
3822
|
nodesLayerElement = getDocument().createElement('ul');
|
|
3497
3823
|
nodesLayerElement.className = isHidden ? 'nodes hidden' : 'nodes';
|
|
@@ -3500,16 +3826,20 @@
|
|
|
3500
3826
|
}
|
|
3501
3827
|
hierarchyElement.appendChild(nodesLayerElement);
|
|
3502
3828
|
}
|
|
3829
|
+
if (nodesLayerElement) {
|
|
3830
|
+
const parentNode = nodeElement || hierarchyElement.querySelector(':scope > .node');
|
|
3831
|
+
setState(nodesLayerElement, 'parentData', parentNode ? getState(parentNode, 'sourceData') || data : data);
|
|
3832
|
+
}
|
|
3503
3833
|
// recurse through children nodes
|
|
3504
3834
|
if (Array.isArray(data.children[0])) {
|
|
3505
3835
|
forEachValue(data.children, function() {
|
|
3506
|
-
this.level = level + 1;
|
|
3836
|
+
forEachValue(this, function () { this.level = level + 1; });
|
|
3507
3837
|
});
|
|
3508
3838
|
this.buildHierarchy(nodesLayerElement, data.children); // 构造子一层的夫妻组合(每个组合可能有多妻多夫情况)
|
|
3509
3839
|
} else {
|
|
3510
3840
|
forEachValue(data.children, function () {
|
|
3511
3841
|
this.level = level + 1;
|
|
3512
|
-
if (
|
|
3842
|
+
if (isCompactLayout) {
|
|
3513
3843
|
orgChart.buildHierarchy(nodeElement, this);
|
|
3514
3844
|
} else {
|
|
3515
3845
|
const nodeCellElement = getDocument().createElement('li');
|
|
@@ -3533,8 +3863,8 @@
|
|
|
3533
3863
|
return;
|
|
3534
3864
|
}
|
|
3535
3865
|
|
|
3536
|
-
if (data.level || data[0]?.level) {
|
|
3537
|
-
level = data.level;
|
|
3866
|
+
if (data.level || data[0]?.level || data[0]?.[0]?.level) {
|
|
3867
|
+
level = data.level || data[0]?.level || data[0]?.[0]?.level;
|
|
3538
3868
|
} else {
|
|
3539
3869
|
let currentAncestorElement = hierarchyElement.parentElement;
|
|
3540
3870
|
|
|
@@ -3545,6 +3875,7 @@
|
|
|
3545
3875
|
currentAncestorElement = currentAncestorElement.parentElement;
|
|
3546
3876
|
}
|
|
3547
3877
|
if (Array.isArray(data) && Array.isArray(data[0])) {
|
|
3878
|
+
level = Math.max(level, 1);
|
|
3548
3879
|
forEachValue(data, function () {
|
|
3549
3880
|
forEachValue(this, function () {
|
|
3550
3881
|
this.level = level;
|
|
@@ -3566,7 +3897,7 @@
|
|
|
3566
3897
|
// if there are only two persons in a marriage, two single nodes will appear in a hierarchy
|
|
3567
3898
|
if (familyNodes.length === 2 && i === 1) {
|
|
3568
3899
|
spouseNodeElement = Array.from(hierarchyElement.querySelectorAll('.node')).find(function (candidateNodeEl) {
|
|
3569
|
-
return candidateNodeEl
|
|
3900
|
+
return getState(candidateNodeEl, 'sourceData') === familyNodes[0];
|
|
3570
3901
|
}) || null;
|
|
3571
3902
|
if (spouseNodeElement && spouseNodeElement.parentElement) {
|
|
3572
3903
|
spouseNodeElement.after(nodeElement);
|
|
@@ -3600,7 +3931,7 @@
|
|
|
3600
3931
|
});
|
|
3601
3932
|
});
|
|
3602
3933
|
} else {
|
|
3603
|
-
if (Object.keys(data).
|
|
3934
|
+
if (Object.keys(data).some(function (key) { return key !== 'children' && key !== 'level'; })) {
|
|
3604
3935
|
nodeElement = this.createNode(data);
|
|
3605
3936
|
hierarchyElement.appendChild(nodeElement);
|
|
3606
3937
|
}
|
|
@@ -3639,35 +3970,26 @@
|
|
|
3639
3970
|
// exposed method
|
|
3640
3971
|
addChildren: function (nodeEl, data) {
|
|
3641
3972
|
const nodeElement = getElement(nodeEl);
|
|
3642
|
-
let titleElement;
|
|
3643
|
-
let bottomEdgeElement;
|
|
3644
3973
|
|
|
3645
3974
|
if (!nodeElement) {
|
|
3646
3975
|
return;
|
|
3647
3976
|
}
|
|
3648
|
-
|
|
3649
|
-
|
|
3650
|
-
|
|
3651
|
-
|
|
3652
|
-
|
|
3653
|
-
|
|
3654
|
-
if (titleElement) {
|
|
3655
|
-
titleElement.insertAdjacentHTML('afterbegin', `<i class="${this.options.icons.theme} ${this.options.icons.parentNode} parentNodeSymbol"></i>`);
|
|
3977
|
+
const nodeData = getState(nodeElement, 'sourceData');
|
|
3978
|
+
if (nodeData) {
|
|
3979
|
+
const datasource = getState(this.chart, 'datasource');
|
|
3980
|
+
const isGrouped = Array.isArray(datasource) || (nodeData.children && Array.isArray(nodeData.children[0]));
|
|
3981
|
+
if (!nodeData.children) {
|
|
3982
|
+
nodeData.children = [];
|
|
3656
3983
|
}
|
|
3657
|
-
|
|
3658
|
-
|
|
3659
|
-
|
|
3660
|
-
|
|
3984
|
+
Array.prototype.push.apply(nodeData.children, isGrouped ? data.map(function (item) { return Array.isArray(item) ? item : [item]; }) : data);
|
|
3985
|
+
if (isGrouped || this.chart.querySelector('.node.compact') || this.options.compact) {
|
|
3986
|
+
rebuildFromData(this, nodeData);
|
|
3987
|
+
return;
|
|
3661
3988
|
}
|
|
3662
|
-
} else if (!nodeElement.querySelector(':scope > .bottomEdge')) {
|
|
3663
|
-
nodeElement.insertAdjacentHTML('beforeend', `<i class="edge verticalEdge bottomEdge ${this.options.icons.theme}"></i>`);
|
|
3664
|
-
}
|
|
3665
|
-
if (this.isInAction(nodeElement)) {
|
|
3666
|
-
bottomEdgeElement = Array.from(nodeElement.children || []).find(function (childEl) {
|
|
3667
|
-
return childEl.classList && childEl.classList.contains('bottomEdge');
|
|
3668
|
-
}) || null;
|
|
3669
|
-
this.switchVerticalArrow(bottomEdgeElement);
|
|
3670
3989
|
}
|
|
3990
|
+
|
|
3991
|
+
this.buildChildNode(nodeElement.closest('.hierarchy'), data);
|
|
3992
|
+
this.refreshNodeControls(nodeElement);
|
|
3671
3993
|
},
|
|
3672
3994
|
// build the parent node of specific node
|
|
3673
3995
|
buildParentNode: function (currentRootEl, data) {
|
|
@@ -3683,7 +4005,6 @@
|
|
|
3683
4005
|
return;
|
|
3684
4006
|
}
|
|
3685
4007
|
|
|
3686
|
-
data.relationship = data.relationship || '001';
|
|
3687
4008
|
currentRootListElement = currentRootElement.closest('ul');
|
|
3688
4009
|
currentRootHierarchyElement = currentRootElement.closest('.hierarchy');
|
|
3689
4010
|
parentHierarchyElement = currentRootListElement ? currentRootListElement.closest('.hierarchy') : null;
|
|
@@ -3714,28 +4035,51 @@
|
|
|
3714
4035
|
// exposed method
|
|
3715
4036
|
addParent: function (currentRootEl, data) {
|
|
3716
4037
|
const currentRootElement = getElement(currentRootEl);
|
|
3717
|
-
let titleElement;
|
|
3718
|
-
let topEdgeElement;
|
|
3719
4038
|
|
|
3720
4039
|
if (!currentRootElement) {
|
|
3721
4040
|
return;
|
|
3722
4041
|
}
|
|
4042
|
+
const currentData = getState(currentRootElement, 'sourceData');
|
|
4043
|
+
const datasource = getState(this.chart, 'datasource');
|
|
4044
|
+
if (currentData && (Array.isArray(datasource) || this.chart.querySelector('.node.compact') || this.options.compact)) {
|
|
4045
|
+
const parentElement = this.getParent(currentRootElement);
|
|
4046
|
+
const parentData = parentElement ? getState(parentElement, 'sourceData') : null;
|
|
4047
|
+
const newParentData = mergeObjects({}, data, { children: Array.isArray(datasource) ? [[currentData]] : [currentData] });
|
|
4048
|
+
const location = findDataLocation(datasource, currentData);
|
|
4049
|
+
if (Array.isArray(datasource) && location && location.list) {
|
|
4050
|
+
location.list.splice(location.index, 1, newParentData);
|
|
4051
|
+
rebuildFromData(this, newParentData);
|
|
4052
|
+
return;
|
|
4053
|
+
}
|
|
4054
|
+
if (parentData && parentData.children) {
|
|
4055
|
+
const index = parentData.children.indexOf(currentData);
|
|
4056
|
+
if (index === -1) {
|
|
4057
|
+
return;
|
|
4058
|
+
}
|
|
4059
|
+
parentData.children.splice(index, 1, newParentData);
|
|
4060
|
+
rebuildFromData(this, newParentData);
|
|
4061
|
+
} else {
|
|
4062
|
+
rebuildFromData(this, newParentData, newParentData);
|
|
4063
|
+
}
|
|
4064
|
+
return;
|
|
4065
|
+
}
|
|
3723
4066
|
|
|
4067
|
+
const currentLocation = currentData ? findDataLocation(datasource, currentData) : null;
|
|
3724
4068
|
this.buildParentNode(currentRootElement, data);
|
|
3725
|
-
if (
|
|
3726
|
-
|
|
3727
|
-
|
|
3728
|
-
|
|
3729
|
-
|
|
3730
|
-
|
|
4069
|
+
if (currentData) {
|
|
4070
|
+
data.children = [currentData];
|
|
4071
|
+
if (currentLocation && currentLocation.list) {
|
|
4072
|
+
currentLocation.list.splice(currentLocation.index, 1, data);
|
|
4073
|
+
} else {
|
|
4074
|
+
setState(this.chart, 'datasource', data);
|
|
4075
|
+
this.options.data = data;
|
|
4076
|
+
this.opts.data = data;
|
|
3731
4077
|
}
|
|
4078
|
+
currentData.parentId = data[this.options.nodeId];
|
|
4079
|
+
getState(currentRootElement, 'nodeData').parentId = currentData.parentId;
|
|
4080
|
+
currentRootElement.setAttribute('data-parent', currentData.parentId);
|
|
3732
4081
|
}
|
|
3733
|
-
|
|
3734
|
-
topEdgeElement = Array.from(currentRootElement.children || []).find(function (childEl) {
|
|
3735
|
-
return childEl.classList && childEl.classList.contains('topEdge');
|
|
3736
|
-
}) || null;
|
|
3737
|
-
this.switchVerticalArrow(topEdgeElement);
|
|
3738
|
-
}
|
|
4082
|
+
this.refreshNodeControls(this.getParent(currentRootElement));
|
|
3739
4083
|
},
|
|
3740
4084
|
// build the sibling nodes of specific node
|
|
3741
4085
|
buildSiblingNode: function (nodeChartEl, data) {
|
|
@@ -3836,49 +4180,88 @@
|
|
|
3836
4180
|
addSiblings: function (nodeEl, data) {
|
|
3837
4181
|
const nodeElement = getElement(nodeEl);
|
|
3838
4182
|
let nodesContainerElement;
|
|
3839
|
-
let topEdgeElement;
|
|
3840
4183
|
|
|
3841
4184
|
if (!nodeElement) {
|
|
3842
4185
|
return;
|
|
3843
4186
|
}
|
|
4187
|
+
const nodeData = getState(nodeElement, 'sourceData');
|
|
4188
|
+
const datasource = getState(this.chart, 'datasource');
|
|
4189
|
+
if (nodeData && (Array.isArray(datasource) || this.chart.querySelector('.node.compact') || this.options.compact)) {
|
|
4190
|
+
const parentElement = this.getParent(nodeElement);
|
|
4191
|
+
const parentData = parentElement ? getState(parentElement, 'sourceData') : null;
|
|
4192
|
+
const newSiblings = Array.isArray(data) ? data : data.children;
|
|
4193
|
+
if (parentData && parentData.children) {
|
|
4194
|
+
const siblings = Array.isArray(datasource) ? (newSiblings || []).map(function (item) { return Array.isArray(item) ? item : [item]; }) : newSiblings || [];
|
|
4195
|
+
Array.prototype.push.apply(parentData.children, siblings);
|
|
4196
|
+
rebuildFromData(this, parentData);
|
|
4197
|
+
} else if (Array.isArray(datasource) && Array.isArray(data)) {
|
|
4198
|
+
Array.prototype.push.apply(datasource, data.map(function (item) { return Array.isArray(item) ? item : [item]; }));
|
|
4199
|
+
rebuildFromData(this);
|
|
4200
|
+
} else if (!Array.isArray(data)) {
|
|
4201
|
+
const children = (newSiblings || []).slice();
|
|
4202
|
+
const insertPosition = Math.floor((children.length + 1) / 2 - 1) + 1;
|
|
4203
|
+
children.splice(Math.max(insertPosition, 0), 0, nodeData);
|
|
4204
|
+
const newParentData = mergeObjects({}, data, { children: children });
|
|
4205
|
+
rebuildFromData(this, newParentData, newParentData);
|
|
4206
|
+
}
|
|
4207
|
+
return;
|
|
4208
|
+
}
|
|
3844
4209
|
|
|
4210
|
+
const oldParent = this.getParent(nodeElement);
|
|
4211
|
+
const oldParentData = oldParent ? getState(oldParent, 'sourceData') : null;
|
|
3845
4212
|
this.buildSiblingNode(nodeElement.closest('.hierarchy'), data);
|
|
4213
|
+
if (nodeData && oldParentData && oldParentData.children && Array.isArray(data)) {
|
|
4214
|
+
Array.prototype.push.apply(oldParentData.children, data);
|
|
4215
|
+
} else if (nodeData && !oldParentData && !Array.isArray(data) && data.children) {
|
|
4216
|
+
const insertPosition = Math.floor((data.children.length + 1) / 2 - 1) + 1;
|
|
4217
|
+
data.children.splice(Math.max(insertPosition, 0), 0, nodeData);
|
|
4218
|
+
setState(this.chart, 'datasource', data);
|
|
4219
|
+
this.options.data = data;
|
|
4220
|
+
this.opts.data = data;
|
|
4221
|
+
}
|
|
3846
4222
|
nodesContainerElement = nodeElement.closest('.nodes');
|
|
3847
4223
|
if (nodesContainerElement) {
|
|
3848
4224
|
setState(nodesContainerElement, 'siblingsLoaded', true);
|
|
3849
4225
|
}
|
|
3850
|
-
|
|
3851
|
-
return childEl.classList && childEl.classList.contains('leftEdge');
|
|
3852
|
-
})) {
|
|
3853
|
-
topEdgeElement = Array.from(nodeElement.children || []).find(function (childEl) {
|
|
3854
|
-
return childEl.classList && childEl.classList.contains('topEdge');
|
|
3855
|
-
}) || null;
|
|
3856
|
-
if (topEdgeElement) {
|
|
3857
|
-
topEdgeElement.insertAdjacentHTML('afterend', `<i class="edge horizontalEdge rightEdge ${this.options.icons.theme}"></i><i class="edge horizontalEdge leftEdge ${this.options.icons.theme}"></i>`);
|
|
3858
|
-
}
|
|
3859
|
-
}
|
|
3860
|
-
if (this.isInAction(nodeElement)) {
|
|
3861
|
-
this.switchHorizontalArrow(nodeElement);
|
|
3862
|
-
topEdgeElement = Array.from(nodeElement.children || []).find(function (childEl) {
|
|
3863
|
-
return childEl.classList && childEl.classList.contains('topEdge');
|
|
3864
|
-
}) || null;
|
|
3865
|
-
if (topEdgeElement && topEdgeElement.classList) {
|
|
3866
|
-
topEdgeElement.classList.remove(this.options.icons.expandToUp);
|
|
3867
|
-
topEdgeElement.classList.add(this.options.icons.collapseToDown);
|
|
3868
|
-
}
|
|
3869
|
-
}
|
|
4226
|
+
this.refreshNodeControls(this.getParent(nodeElement));
|
|
3870
4227
|
},
|
|
3871
4228
|
// remove node and its descendent nodes
|
|
3872
4229
|
removeNodes: function (nodeEl) {
|
|
3873
4230
|
const nodeElement = getElement(nodeEl);
|
|
3874
4231
|
let hierarchyElement;
|
|
3875
4232
|
let wrapperElement;
|
|
3876
|
-
let remainingNodeElement;
|
|
3877
|
-
let parentNodeElement;
|
|
3878
4233
|
|
|
3879
4234
|
if (!nodeElement) {
|
|
3880
4235
|
return;
|
|
3881
4236
|
}
|
|
4237
|
+
const parentElement = this.getParent(nodeElement);
|
|
4238
|
+
const parentData = parentElement ? getState(parentElement, 'sourceData') : null;
|
|
4239
|
+
const nodeData = getState(nodeElement, 'sourceData');
|
|
4240
|
+
const datasource = getState(this.chart, 'datasource');
|
|
4241
|
+
if (Array.isArray(datasource) && nodeData) {
|
|
4242
|
+
const location = findDataLocation(datasource, nodeData);
|
|
4243
|
+
if (location && location.list) {
|
|
4244
|
+
location.list.splice(location.index, 1);
|
|
4245
|
+
if (!location.list.length && location.outerList) {
|
|
4246
|
+
location.outerList.splice(location.outerIndex, 1);
|
|
4247
|
+
}
|
|
4248
|
+
if (location.parent && location.parent.children && !location.parent.children.length) {
|
|
4249
|
+
delete location.parent.children;
|
|
4250
|
+
}
|
|
4251
|
+
rebuildFromData(this);
|
|
4252
|
+
return;
|
|
4253
|
+
}
|
|
4254
|
+
}
|
|
4255
|
+
if (parentData && parentData.children && parentData.children.indexOf(nodeData) !== -1) {
|
|
4256
|
+
parentData.children.splice(parentData.children.indexOf(nodeData), 1);
|
|
4257
|
+
if (!parentData.children.length) {
|
|
4258
|
+
delete parentData.children;
|
|
4259
|
+
}
|
|
4260
|
+
if (this.chart.querySelector('.node.compact') || this.options.compact) {
|
|
4261
|
+
rebuildFromData(this);
|
|
4262
|
+
return;
|
|
4263
|
+
}
|
|
4264
|
+
}
|
|
3882
4265
|
|
|
3883
4266
|
hierarchyElement = nodeElement.closest('.hierarchy');
|
|
3884
4267
|
wrapperElement = hierarchyElement ? hierarchyElement.parentElement : null;
|
|
@@ -3890,23 +4273,10 @@
|
|
|
3890
4273
|
if (wrapperElement.parentElement && wrapperElement.parentElement.classList && wrapperElement.parentElement.classList.contains('hierarchy')) {
|
|
3891
4274
|
if (this.getNodeState(nodeElement, 'siblings').exist) {
|
|
3892
4275
|
hierarchyElement.remove();
|
|
3893
|
-
if (wrapperElement.children.length === 1) {
|
|
3894
|
-
remainingNodeElement = wrapperElement.querySelector('.node');
|
|
3895
|
-
if (remainingNodeElement) {
|
|
3896
|
-
Array.from(remainingNodeElement.querySelectorAll('.horizontalEdge')).forEach(function (edgeEl) {
|
|
3897
|
-
edgeEl.remove();
|
|
3898
|
-
});
|
|
3899
|
-
}
|
|
3900
|
-
}
|
|
3901
4276
|
} else {
|
|
3902
|
-
parentNodeElement = wrapperElement.parentElement.querySelector(':scope > .node');
|
|
3903
|
-
if (parentNodeElement) {
|
|
3904
|
-
Array.from(parentNodeElement.querySelectorAll('.bottomEdge, .parentNodeSymbol')).forEach(function (edgeEl) {
|
|
3905
|
-
edgeEl.remove();
|
|
3906
|
-
});
|
|
3907
|
-
}
|
|
3908
4277
|
wrapperElement.remove();
|
|
3909
4278
|
}
|
|
4279
|
+
this.refreshNodeControls(parentElement);
|
|
3910
4280
|
} else { // if $node is root node
|
|
3911
4281
|
const chartElement = wrapperElement.closest('.orgchart');
|
|
3912
4282
|
if (chartElement) {
|
|
@@ -3998,7 +4368,6 @@
|
|
|
3998
4368
|
const isEdge = navigatorObject.appName === 'Microsoft Internet Explorer' || (navigatorObject.appName === 'Netscape' && navigatorObject.appVersion.indexOf('Edge') > -1);
|
|
3999
4369
|
const chartContainerElement = this.chartContainer;
|
|
4000
4370
|
let downloadButtonClassName;
|
|
4001
|
-
let downloadSelector;
|
|
4002
4371
|
let downloadAnchorElement;
|
|
4003
4372
|
|
|
4004
4373
|
if (!chartContainerElement) {
|
|
@@ -4009,8 +4378,12 @@
|
|
|
4009
4378
|
getWindow().navigator.msSaveBlob(canvas.msToBlob(), exportFilename + '.png');
|
|
4010
4379
|
} else {
|
|
4011
4380
|
downloadButtonClassName = 'download-btn' + (this.options.chartClass !== '' ? ' ' + this.options.chartClass : '');
|
|
4012
|
-
|
|
4013
|
-
downloadAnchorElement = chartContainerElement.
|
|
4381
|
+
const chartClassNames = this.options.chartClass.split(/\s+/).filter(Boolean);
|
|
4382
|
+
downloadAnchorElement = Array.from(chartContainerElement.querySelectorAll('a.download-btn')).find(function (anchorElement) {
|
|
4383
|
+
return chartClassNames.every(function (className) {
|
|
4384
|
+
return anchorElement.classList.contains(className);
|
|
4385
|
+
});
|
|
4386
|
+
});
|
|
4014
4387
|
|
|
4015
4388
|
if (!downloadAnchorElement) {
|
|
4016
4389
|
downloadAnchorElement = getDocument().createElement('a');
|