orgchart 5.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 +35 -0
- package/README.md +214 -123
- package/README.zh-cn.md +232 -100
- package/README.zh-tw.md +232 -100
- package/bower.json +6 -9
- package/demo/10000-nodes.html +139 -0
- package/demo/ajax-datasource.html +46 -45
- package/demo/bottom2top.html +12 -9
- package/demo/center-on-selected-node.html +21 -17
- package/demo/color-coded.html +12 -9
- package/demo/css/style.css +28 -0
- package/demo/custom-icons.html +12 -9
- package/demo/custom-template.html +12 -9
- package/demo/data-prop-compact.html +11 -8
- package/demo/data-prop-hybrid.html +79 -50
- package/demo/default-collapsed.html +12 -9
- package/demo/drag-drop-hybrid-chart.html +17 -14
- package/demo/drag-drop.html +21 -16
- package/demo/edit-chart.html +144 -94
- package/demo/edit-hybrid-chart.html +177 -135
- package/demo/expand-to-given-depth.html +30 -22
- package/demo/export-chart-pdf.html +12 -9
- package/demo/export-chart-with-pictures.html +19 -12
- package/demo/export-chart.html +12 -9
- package/demo/family-tree.html +14 -11
- package/demo/familytree-custom-properties.html +108 -0
- package/demo/filter-node.html +104 -57
- package/demo/get-hierarchy.html +17 -12
- package/demo/get-related-nodes.html +27 -17
- package/demo/index.html +10 -3
- package/demo/integrate-map.html +32 -27
- package/demo/left2right.html +12 -9
- package/demo/level-offset.html +16 -15
- package/demo/link-node.html +12 -9
- package/demo/local-datasource.html +11 -8
- package/demo/minimap.html +224 -0
- package/demo/nodes-of-different-widths.html +11 -8
- package/demo/ondemand-loading-data.html +166 -112
- package/demo/option-createNode.html +28 -17
- 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/demo/pan-zoom.html +20 -11
- package/demo/reload-data.html +17 -14
- package/demo/report-path.html +59 -29
- package/demo/responsive-design.html +14 -11
- package/demo/right2left.html +12 -9
- package/demo/toggle-sibs-resp.html +12 -9
- package/demo/ul-datasource.html +11 -8
- package/demo/vertical-level.html +12 -9
- package/dist/css/{jquery.orgchart.css → orgchart.css} +154 -80
- package/dist/css/orgchart.min.css +1 -0
- package/dist/js/orgchart.js +4474 -0
- package/dist/js/orgchart.min.js +2 -0
- package/dist/js/orgchart.min.js.map +1 -0
- package/gulpfile.js +42 -27
- package/package.json +33 -32
- package/src/css/{jquery.orgchart.css → orgchart.css} +154 -80
- package/src/js/orgchart.js +4474 -0
- 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 +91 -0
- package/test/cypress/e2e/demo-rendering.cy.js +161 -0
- package/test/cypress/e2e/drag-drop-hybrid-chart.cy.js +23 -0
- package/test/cypress/e2e/edit-chart.cy.js +20 -0
- package/test/cypress/e2e/level-offset.cy.js +21 -0
- package/test/cypress/e2e/local-datasource.cy.js +16 -16
- package/test/cypress/e2e/minimap.cy.js +66 -0
- package/test/cypress/e2e/ondemand-loading-data.cy.js +34 -10
- package/test/cypress/e2e/pan-zoom.cy.js +165 -0
- package/test/cypress/e2e/report-path.cy.js +20 -0
- package/test/cypress/e2e/toggle-sibs-resp.cy.js +4 -4
- package/test/cypress/e2e/vertical-vevel.cy.js +7 -5
- package/test/e2e/local-datasource/test.js +1 -1
- package/test/integration/init-tests.js +192 -99
- package/test/integration/tests.js +1043 -57
- package/test/unit/lifecycle-builders-export.tests.js +1487 -0
- package/test/unit/minimap.tests.js +210 -0
- package/test/unit/tests.js +2372 -253
- package/dist/css/jquery.orgchart.min.css +0 -1
- package/dist/js/jquery.orgchart.js +0 -1741
- package/dist/js/jquery.orgchart.min.js +0 -5
- package/dist/js/jquery.orgchart.min.js.map +0 -1
- package/src/js/jquery.orgchart.js +0 -1741
|
@@ -5,6 +5,70 @@ describe('Pan & Zoom', () => {
|
|
|
5
5
|
});
|
|
6
6
|
|
|
7
7
|
const chart = '.orgchart';
|
|
8
|
+
const chartContainer = '#chart-container';
|
|
9
|
+
const pinchAnchorTolerance = 5;
|
|
10
|
+
const dispatchTouchEvent = (win, target, type, touches) => {
|
|
11
|
+
const touchLikePoints = touches.map((touch, index) => ({
|
|
12
|
+
identifier: index,
|
|
13
|
+
target,
|
|
14
|
+
clientX: touch.clientX,
|
|
15
|
+
clientY: touch.clientY,
|
|
16
|
+
pageX: touch.clientX,
|
|
17
|
+
pageY: touch.clientY,
|
|
18
|
+
screenX: touch.clientX,
|
|
19
|
+
screenY: touch.clientY
|
|
20
|
+
}));
|
|
21
|
+
const touchEvent = new win.Event(type, {
|
|
22
|
+
bubbles: true,
|
|
23
|
+
cancelable: true
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
Object.defineProperty(touchEvent, 'touches', {
|
|
27
|
+
value: type === 'touchend' ? [] : touchLikePoints,
|
|
28
|
+
configurable: true
|
|
29
|
+
});
|
|
30
|
+
Object.defineProperty(touchEvent, 'targetTouches', {
|
|
31
|
+
value: type === 'touchend' ? [] : touchLikePoints,
|
|
32
|
+
configurable: true
|
|
33
|
+
});
|
|
34
|
+
Object.defineProperty(touchEvent, 'changedTouches', {
|
|
35
|
+
value: touchLikePoints,
|
|
36
|
+
configurable: true
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
target.dispatchEvent(touchEvent);
|
|
40
|
+
};
|
|
41
|
+
const parseMatrixScale = (transformValue) => {
|
|
42
|
+
const matrixMatch = /matrix\(([^)]+)\)/.exec(transformValue || '');
|
|
43
|
+
|
|
44
|
+
if (!matrixMatch) {
|
|
45
|
+
return 1;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return Number.parseFloat(matrixMatch[1].split(',')[0]);
|
|
49
|
+
};
|
|
50
|
+
const pinchAtPoint = (win, target, center, startGap, endGap) => {
|
|
51
|
+
const initialTouches = [
|
|
52
|
+
{ clientX: center.x - (startGap / 2), clientY: center.y },
|
|
53
|
+
{ clientX: center.x + (startGap / 2), clientY: center.y }
|
|
54
|
+
];
|
|
55
|
+
const movedTouches = [
|
|
56
|
+
{ clientX: center.x - (endGap / 2), clientY: center.y },
|
|
57
|
+
{ clientX: center.x + (endGap / 2), clientY: center.y }
|
|
58
|
+
];
|
|
59
|
+
|
|
60
|
+
dispatchTouchEvent(win, target, 'touchstart', initialTouches);
|
|
61
|
+
dispatchTouchEvent(win, win.document, 'touchmove', movedTouches);
|
|
62
|
+
dispatchTouchEvent(win, win.document, 'touchend', movedTouches);
|
|
63
|
+
};
|
|
64
|
+
const getNodeCenter = ($node) => {
|
|
65
|
+
const rect = $node[0].getBoundingClientRect();
|
|
66
|
+
|
|
67
|
+
return {
|
|
68
|
+
x: rect.left + (rect.width / 2),
|
|
69
|
+
y: rect.top + (rect.height / 2)
|
|
70
|
+
};
|
|
71
|
+
};
|
|
8
72
|
|
|
9
73
|
it('drag the chart to the top', () => {
|
|
10
74
|
cy.get(chart)
|
|
@@ -38,4 +102,105 @@ describe('Pan & Zoom', () => {
|
|
|
38
102
|
.should('have.css', 'transform', 'matrix(1, 0, 0, 1, 100, 0)');
|
|
39
103
|
});
|
|
40
104
|
|
|
105
|
+
it('zooms around the node under the mouse pointer', () => {
|
|
106
|
+
cy.contains('.node .title', 'Lao Lao')
|
|
107
|
+
.closest('.node')
|
|
108
|
+
.then(($node) => {
|
|
109
|
+
const beforeCenter = getNodeCenter($node);
|
|
110
|
+
|
|
111
|
+
cy.get(chartContainer).then(($container) => {
|
|
112
|
+
const wheelEvent = new $container[0].ownerDocument.defaultView.WheelEvent('wheel', {
|
|
113
|
+
deltaY: -1,
|
|
114
|
+
clientX: beforeCenter.x,
|
|
115
|
+
clientY: beforeCenter.y,
|
|
116
|
+
bubbles: true,
|
|
117
|
+
cancelable: true
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
$container[0].dispatchEvent(wheelEvent);
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
cy.contains('.node .title', 'Lao Lao')
|
|
124
|
+
.closest('.node')
|
|
125
|
+
.then(($zoomedNode) => {
|
|
126
|
+
const afterCenter = getNodeCenter($zoomedNode);
|
|
127
|
+
|
|
128
|
+
expect(Math.abs(afterCenter.x - beforeCenter.x)).to.be.lessThan(1);
|
|
129
|
+
expect(Math.abs(afterCenter.y - beforeCenter.y)).to.be.lessThan(1);
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
it('ignores wheel zoom when the pointer is outside the chart container bounds', () => {
|
|
135
|
+
cy.get(chart).invoke('css', 'transform').then((beforeTransform) => {
|
|
136
|
+
cy.get(chartContainer).then(($container) => {
|
|
137
|
+
const rect = $container[0].getBoundingClientRect();
|
|
138
|
+
|
|
139
|
+
cy.get(chartContainer).trigger('wheel', {
|
|
140
|
+
eventConstructor: 'WheelEvent',
|
|
141
|
+
deltaY: -1,
|
|
142
|
+
clientX: rect.left - 5,
|
|
143
|
+
clientY: rect.top + 10,
|
|
144
|
+
bubbles: true,
|
|
145
|
+
cancelable: true
|
|
146
|
+
});
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
cy.get(chart).should('have.css', 'transform', beforeTransform);
|
|
150
|
+
});
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
it('zooms in on touch pinch out', () => {
|
|
154
|
+
cy.window().then((win) => {
|
|
155
|
+
const chartContainerElement = win.document.querySelector(chartContainer);
|
|
156
|
+
|
|
157
|
+
pinchAtPoint(win, chartContainerElement, { x: 160, y: 160 }, 40, 80);
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
cy.get(chart)
|
|
161
|
+
.invoke('css', 'transform')
|
|
162
|
+
.then((transformValue) => {
|
|
163
|
+
expect(parseMatrixScale(transformValue)).to.be.greaterThan(1);
|
|
164
|
+
});
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
it('zooms out on touch pinch in', () => {
|
|
168
|
+
cy.window().then((win) => {
|
|
169
|
+
const chartContainerElement = win.document.querySelector(chartContainer);
|
|
170
|
+
|
|
171
|
+
pinchAtPoint(win, chartContainerElement, { x: 160, y: 160 }, 80, 40);
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
cy.get(chart)
|
|
175
|
+
.invoke('css', 'transform')
|
|
176
|
+
.then((transformValue) => {
|
|
177
|
+
expect(parseMatrixScale(transformValue)).to.be.lessThan(1);
|
|
178
|
+
});
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
it('keeps the pinch midpoint inside the same node during touch pinch', () => {
|
|
182
|
+
cy.contains('.node .title', 'Lao Lao')
|
|
183
|
+
.closest('.node')
|
|
184
|
+
.then(($node) => {
|
|
185
|
+
const beforeCenter = getNodeCenter($node);
|
|
186
|
+
|
|
187
|
+
cy.window().then((win) => {
|
|
188
|
+
const chartContainerElement = win.document.querySelector(chartContainer);
|
|
189
|
+
|
|
190
|
+
pinchAtPoint(win, chartContainerElement, beforeCenter, 40, 80);
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
cy.contains('.node .title', 'Lao Lao')
|
|
194
|
+
.closest('.node')
|
|
195
|
+
.then(($zoomedNode) => {
|
|
196
|
+
const rect = $zoomedNode[0].getBoundingClientRect();
|
|
197
|
+
|
|
198
|
+
expect(beforeCenter.x).to.be.greaterThan(rect.left - pinchAnchorTolerance);
|
|
199
|
+
expect(beforeCenter.x).to.be.lessThan(rect.right + pinchAnchorTolerance);
|
|
200
|
+
expect(beforeCenter.y).to.be.greaterThan(rect.top - pinchAnchorTolerance);
|
|
201
|
+
expect(beforeCenter.y).to.be.lessThan(rect.bottom + pinchAnchorTolerance);
|
|
202
|
+
});
|
|
203
|
+
});
|
|
204
|
+
});
|
|
205
|
+
|
|
41
206
|
});
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
describe('Report Path', () => {
|
|
2
|
+
|
|
3
|
+
const danDan = '.node:contains("Dan Dan")';
|
|
4
|
+
const selectedNode = '#selected-node';
|
|
5
|
+
const reportButton = '#btn-report-path';
|
|
6
|
+
|
|
7
|
+
beforeEach(() => {
|
|
8
|
+
cy.visit('demo/report-path.html');
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
it('keeps the chosen node selected after drawing its management path', () => {
|
|
12
|
+
cy.get(danDan).click();
|
|
13
|
+
cy.get(selectedNode).should('have.value', 'Dan Dan');
|
|
14
|
+
|
|
15
|
+
cy.get(reportButton).click().should('be.disabled');
|
|
16
|
+
cy.get(danDan).should('have.class', 'focused');
|
|
17
|
+
cy.get(selectedNode).should('have.value', 'Dan Dan');
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
});
|
|
@@ -13,19 +13,19 @@ describe('Toggle sibling nodes respectively', () => {
|
|
|
13
13
|
});
|
|
14
14
|
|
|
15
15
|
it('toggle the left side sibling nodes of sumiao', () => {
|
|
16
|
-
cy.get(sumiao).find('.leftEdge').click();
|
|
16
|
+
cy.get(sumiao).trigger('mouseenter').find('.leftEdge').click();
|
|
17
17
|
cy.get(bomiao).get(renwu).get(lixin).should('not.be.visible');
|
|
18
18
|
|
|
19
|
-
cy.get(sumiao).find('.leftEdge').click();
|
|
19
|
+
cy.get(sumiao).trigger('mouseenter').find('.leftEdge').click();
|
|
20
20
|
cy.get(bomiao).should('be.visible');
|
|
21
21
|
cy.get(renwu).get(lixin).should('not.be.visible');
|
|
22
22
|
});
|
|
23
23
|
|
|
24
24
|
it('toggle the right side sibling nodes of sumiao', () => {
|
|
25
|
-
cy.get(sumiao).find('.rightEdge').click();
|
|
25
|
+
cy.get(sumiao).trigger('mouseenter').find('.rightEdge').click();
|
|
26
26
|
cy.get(hongmiao).get(xingan).get(yidian).should('not.be.visible');
|
|
27
27
|
|
|
28
|
-
cy.get(sumiao).find('.rightEdge').click();
|
|
28
|
+
cy.get(sumiao).trigger('mouseenter').find('.rightEdge').click();
|
|
29
29
|
cy.get(hongmiao).should('be.visible');
|
|
30
30
|
cy.get(xingan).get(yidian).should('not.be.visible');
|
|
31
31
|
});
|
|
@@ -15,22 +15,24 @@ describe('Hybrid(horizontal + vertical) Chart', () => {
|
|
|
15
15
|
const wudan = '.node:contains("Wu Dan")';
|
|
16
16
|
|
|
17
17
|
it('toggle the vertical nodes', () => {
|
|
18
|
-
cy.get(dandan).find('.toggleBtn').click();
|
|
18
|
+
cy.get(dandan).trigger('mouseenter').find('.toggleBtn').click({ force: true });
|
|
19
|
+
cy.get(dandan).find('.toggleBtn').should('have.class', 'oci-minus-square');
|
|
19
20
|
cy.get(erdan).get(sandan).should('be.visible');
|
|
20
21
|
cy.get(sidan).get(wudan).should('not.be.visible');
|
|
21
22
|
|
|
22
|
-
cy.get(heihei).find('.toggleBtn').click();
|
|
23
|
+
cy.get(heihei).trigger('mouseenter').find('.toggleBtn').click({ force: true });
|
|
24
|
+
cy.get(heihei).find('.toggleBtn').should('have.class', 'oci-plus-square');
|
|
23
25
|
cy.get(pangpang).get(dandan).get(erdan).get(sandan).should('not.be.visible');
|
|
24
26
|
|
|
25
|
-
cy.get(heihei).find('.toggleBtn').click();
|
|
27
|
+
cy.get(heihei).trigger('mouseenter').find('.toggleBtn').click({ force: true });
|
|
26
28
|
cy.get(pangpang).get(dandan).should('be.visible');
|
|
27
29
|
});
|
|
28
30
|
|
|
29
31
|
it('toggle the vertical nodes by cicking horizontal nodes', () => {
|
|
30
|
-
cy.get(sumiao).find('.bottomEdge').click();
|
|
32
|
+
cy.get(sumiao).trigger('mouseenter').find('.bottomEdge').click();
|
|
31
33
|
cy.get(tiehua).get(heihei).get(pangpang).get(dandan).should('be.visible');
|
|
32
34
|
|
|
33
|
-
cy.get(sumiao).find('.bottomEdge').click();
|
|
35
|
+
cy.get(sumiao).trigger('mouseenter').find('.bottomEdge').click();
|
|
34
36
|
cy.get(tiehua).get(heihei).should('be.visible');
|
|
35
37
|
cy.get(pangpang).get(dandan).should('not.be.visible');
|
|
36
38
|
});
|
|
@@ -100,7 +100,7 @@ test('horizontalEdge of heihei node works well', async t => {
|
|
|
100
100
|
await t
|
|
101
101
|
.hover(heihei)
|
|
102
102
|
.click(heihei.find('.topEdge'))
|
|
103
|
-
/* take into account the transition settings in
|
|
103
|
+
/* take into account the transition settings in orgchart.css
|
|
104
104
|
* .orgchart .node {
|
|
105
105
|
* transition: transform 0.3s, opacity 0.3s;
|
|
106
106
|
* }
|