orgchart 5.0.0 → 6.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.
Files changed (76) hide show
  1. package/.github/workflows/publish.yml +32 -0
  2. package/README.md +172 -93
  3. package/README.zh-cn.md +163 -74
  4. package/README.zh-tw.md +163 -74
  5. package/bower.json +6 -9
  6. package/demo/10000-nodes.html +139 -0
  7. package/demo/ajax-datasource.html +46 -45
  8. package/demo/bottom2top.html +12 -9
  9. package/demo/center-on-selected-node.html +21 -17
  10. package/demo/color-coded.html +12 -9
  11. package/demo/css/style.css +28 -0
  12. package/demo/custom-icons.html +12 -9
  13. package/demo/custom-template.html +12 -9
  14. package/demo/data-prop-compact.html +11 -8
  15. package/demo/data-prop-hybrid.html +79 -50
  16. package/demo/default-collapsed.html +12 -9
  17. package/demo/drag-drop-hybrid-chart.html +17 -14
  18. package/demo/drag-drop.html +21 -16
  19. package/demo/edit-chart.html +148 -94
  20. package/demo/edit-hybrid-chart.html +178 -135
  21. package/demo/expand-to-given-depth.html +30 -22
  22. package/demo/export-chart-pdf.html +12 -9
  23. package/demo/export-chart-with-pictures.html +19 -12
  24. package/demo/export-chart.html +12 -9
  25. package/demo/family-tree.html +14 -11
  26. package/demo/familytree-custom-properties.html +108 -0
  27. package/demo/filter-node.html +104 -57
  28. package/demo/get-hierarchy.html +17 -12
  29. package/demo/get-related-nodes.html +27 -17
  30. package/demo/index.html +5 -2
  31. package/demo/integrate-map.html +32 -27
  32. package/demo/left2right.html +12 -9
  33. package/demo/level-offset.html +16 -15
  34. package/demo/link-node.html +12 -9
  35. package/demo/local-datasource.html +11 -8
  36. package/demo/minimap.html +224 -0
  37. package/demo/nodes-of-different-widths.html +11 -8
  38. package/demo/ondemand-loading-data.html +88 -91
  39. package/demo/option-createNode.html +28 -17
  40. package/demo/pan-zoom.html +20 -11
  41. package/demo/reload-data.html +17 -14
  42. package/demo/report-path.html +59 -29
  43. package/demo/responsive-design.html +14 -11
  44. package/demo/right2left.html +12 -9
  45. package/demo/toggle-sibs-resp.html +12 -9
  46. package/demo/ul-datasource.html +11 -8
  47. package/demo/vertical-level.html +12 -9
  48. package/dist/css/{jquery.orgchart.css → orgchart.css} +143 -80
  49. package/dist/css/orgchart.min.css +1 -0
  50. package/dist/js/orgchart.js +4101 -0
  51. package/dist/js/orgchart.min.js +2 -0
  52. package/dist/js/orgchart.min.js.map +1 -0
  53. package/gulpfile.js +37 -26
  54. package/package.json +32 -32
  55. package/src/css/{jquery.orgchart.css → orgchart.css} +143 -80
  56. package/src/js/orgchart.js +4101 -0
  57. package/test/cypress/e2e/demo-interactions.cy.js +91 -0
  58. package/test/cypress/e2e/demo-rendering.cy.js +100 -0
  59. package/test/cypress/e2e/drag-drop-hybrid-chart.cy.js +22 -0
  60. package/test/cypress/e2e/edit-chart.cy.js +20 -0
  61. package/test/cypress/e2e/level-offset.cy.js +21 -0
  62. package/test/cypress/e2e/minimap.cy.js +66 -0
  63. package/test/cypress/e2e/pan-zoom.cy.js +165 -0
  64. package/test/cypress/e2e/report-path.cy.js +20 -0
  65. package/test/cypress/e2e/vertical-vevel.cy.js +5 -3
  66. package/test/e2e/local-datasource/test.js +1 -1
  67. package/test/integration/init-tests.js +168 -62
  68. package/test/integration/tests.js +1034 -56
  69. package/test/unit/lifecycle-builders-export.tests.js +1426 -0
  70. package/test/unit/minimap.tests.js +210 -0
  71. package/test/unit/tests.js +2372 -252
  72. package/dist/css/jquery.orgchart.min.css +0 -1
  73. package/dist/js/jquery.orgchart.js +0 -1741
  74. package/dist/js/jquery.orgchart.min.js +0 -5
  75. package/dist/js/jquery.orgchart.min.js.map +0 -1
  76. package/src/js/jquery.orgchart.js +0 -1741
@@ -1,24 +1,39 @@
1
- var chai = require('chai');
2
- var sinon = require('sinon');
3
- var sinonChai = require('sinon-chai');
4
- var should = chai.should();
1
+ const chai = require('chai');
2
+ const sinon = require('sinon');
3
+ const sinonChai = require('sinon-chai').default;
4
+ const should = chai.should();
5
5
  chai.use(sinonChai);
6
6
  require('jsdom-global')();
7
- var $ = require('jquery');
8
- require('../../src/js/jquery.orgchart');
7
+ const OrgChart = require('../../src/js/orgchart');
8
+
9
+ function query(selector, root) {
10
+ return (root || document).querySelector(selector);
11
+ }
12
+
13
+ function queryAll(selector, root) {
14
+ return Array.from((root || document).querySelectorAll(selector));
15
+ }
16
+
17
+ function createElementFromHtml(html) {
18
+ const template = document.createElement('template');
19
+
20
+ template.innerHTML = html.trim();
21
+ return template.content.firstElementChild;
22
+ }
9
23
 
10
24
  describe('orgchart -- integration tests', function () {
11
- document.body.innerHTML = '<div id="chart-container"></div>';
12
- var $container = $('#chart-container'),
13
- ds = {
25
+ let container;
26
+
27
+ const ds = {
14
28
  'id': 'n1',
15
29
  'name': 'Lao Lao',
16
30
  'children': [
17
31
  { 'id': 'n2', 'name': 'Bo Miao' },
18
32
  { 'id': 'n3', 'name': 'Su Miao' }
19
33
  ]
20
- },
21
- fragment = '<div class="orgchart"><ul class="nodes"><li class="hierarchy">' +
34
+ };
35
+
36
+ const fragment = '<div class="orgchart"><ul class="nodes"><li class="hierarchy">' +
22
37
  '<div id="n1" class="node"><div class="title"><i class="oci oci-menu parentNodeSymbol">' +
23
38
  '</i>Lao Lao</div><i class="edge verticalEdge bottomEdge oci"></i></div><ul class="nodes">' +
24
39
  '<li class="hierarchy"><div id="n2" data-parent="n1" class="node">' +
@@ -27,23 +42,30 @@ describe('orgchart -- integration tests', function () {
27
42
  '</i></div></li><li class="hierarchy"><div id="n3" data-parent="n1" class="node">' +
28
43
  '<div class="title">Su Miao</div><i class="edge verticalEdge topEdge oci"></i>' +
29
44
  '<i class="edge horizontalEdge rightEdge oci"></i><i class="edge horizontalEdge leftEdge oci">' +
30
- '</i></div></li></ul></li></ul></div>',
31
- oc = {};
32
-
45
+ '</i></div></li></ul></li></ul></div>';
46
+
47
+ let oc = {};
48
+
49
+ beforeEach(function () {
50
+ document.body.innerHTML = '<div id="chart-container"></div>';
51
+ container = document.getElementById('chart-container');
52
+ });
53
+
33
54
  afterEach(function () {
34
- $container.empty();
55
+ container.innerHTML = '';
35
56
  });
36
57
 
37
58
  describe('init()', function () {
38
59
  it('initialize chart with json datasource', function () {
39
- oc = $container.orgchart({
60
+ oc = new OrgChart({
61
+ chartContainer: '#chart-container',
40
62
  'data': ds
41
63
  });
42
- $container.html().should.equal(fragment);
64
+ container.innerHTML.should.equal(fragment);
43
65
  });
44
66
 
45
67
  it('initialize chart with <ul> datasource', function () {
46
- var $ul = $(
68
+ const ulElement = createElementFromHtml(
47
69
  '<ul id="ul-data">' +
48
70
  '<li data-id="n1">Lao Lao' +
49
71
  '<ul>' +
@@ -53,39 +75,42 @@ describe('orgchart -- integration tests', function () {
53
75
  '</li>' +
54
76
  '</ul>'
55
77
  );
56
- $('body').append($ul);
57
- oc = $container.orgchart({
58
- 'data': $('#ul-data')
78
+ document.body.appendChild(ulElement);
79
+ oc = new OrgChart({
80
+ chartContainer: '#chart-container',
81
+ 'data': ulElement
59
82
  });
60
- $container.html().should.equal(fragment);
61
- $ul.remove();
83
+ container.innerHTML.should.equal(fragment);
84
+ ulElement.remove();
62
85
  });
63
86
 
64
87
  it('initialize chart with the given visible level', function () {
65
- oc = $container.orgchart({
88
+ oc = new OrgChart({
89
+ chartContainer: '#chart-container',
66
90
  'data': ds,
67
91
  'visibleLevel': 1
68
92
  });
69
- oc.$chart.find('.hierarchy:first').is('.hidden').should.be.false;
70
- oc.$chart.find('.nodes').eq(1).is('.hidden').should.be.true;
71
- oc.$chart.find('.node.slide-up').should.lengthOf(2);
93
+ query('.hierarchy', oc.chart).classList.contains('hidden').should.be.false;
94
+ queryAll('.nodes', oc.chart)[1].classList.contains('hidden').should.be.true;
95
+ queryAll('.node.slide-up', oc.chart).should.lengthOf(2);
72
96
  });
73
97
 
74
98
  it('initialize chart with the given vertical level', function () {
75
- var fragment = '<li class="hierarchy"><div id="n1" class="node"><div class="title">' +
99
+ const fragment = '<li class="hierarchy"><div id="n1" class="node"><div class="title">' +
76
100
  '<i class="oci oci-menu parentNodeSymbol"></i>Lao Lao</div><i class="edge verticalEdge bottomEdge oci">' +
77
101
  '</i></div><ul class="nodes vertical"><li class="hierarchy"><div id="n2" data-parent="n1" class="node">' +
78
102
  '<div class="title">Bo Miao</div></div></li><li class="hierarchy"><div id="n3" data-parent="n1" class="node">' +
79
103
  '<div class="title">Su Miao</div></div></li></ul></li>';
80
- oc = $container.orgchart({
104
+ oc = new OrgChart({
105
+ chartContainer: '#chart-container',
81
106
  'data': ds,
82
107
  'verticalLevel': 2
83
108
  });
84
- oc.$chart.find('.nodes:first').html().should.equal(fragment);
109
+ query('.nodes', oc.chart).innerHTML.should.equal(fragment);
85
110
  });
86
111
 
87
112
  context('initialize chart with various combinations of "visibleLevel" and "verticalLevel" ', function () {
88
- var ds = {
113
+ const ds = {
89
114
  'name': 'Lao Lao',
90
115
  'children': [
91
116
  { 'name': 'Bo Miao'
@@ -100,7 +125,7 @@ describe('orgchart -- integration tests', function () {
100
125
  };
101
126
 
102
127
  it('verticalLevel=2 and visibleLevel=1', function () {
103
- var fragment = '<div class="orgchart"><ul class="nodes"><li class="hierarchy">' +
128
+ const fragment = '<div class="orgchart"><ul class="nodes"><li class="hierarchy">' +
104
129
  '<div class="node"><div class="title"><i class="oci oci-menu parentNodeSymbol">' +
105
130
  '</i>Lao Lao</div><i class="edge verticalEdge bottomEdge oci"></i></div>' +
106
131
  '<ul class="nodes hidden vertical"><li class="hierarchy"><div class="node slide-up">' +
@@ -110,16 +135,17 @@ describe('orgchart -- integration tests', function () {
110
135
  '<li class="hierarchy"><div class="node slide-up"><div class="title">Tie Hua</div>' +
111
136
  '</div></li><li class="hierarchy"><div class="node slide-up">' +
112
137
  '<div class="title">Hei Hei</div></div></li></ul></li></ul></li></ul></div>';
113
- oc = $container.orgchart({
138
+ oc = new OrgChart({
139
+ chartContainer: '#chart-container',
114
140
  'data': ds,
115
141
  'verticalLevel': 2,
116
142
  'visibleLevel': 1
117
143
  });
118
- $container.html().should.equal(fragment);
144
+ container.innerHTML.should.equal(fragment);
119
145
  });
120
146
 
121
147
  it('verticalLevel=2 and visibleLevel=2', function () {
122
- var fragment = '<div class="orgchart"><ul class="nodes"><li class="hierarchy">' +
148
+ const fragment = '<div class="orgchart"><ul class="nodes"><li class="hierarchy">' +
123
149
  '<div class="node"><div class="title"><i class="oci oci-menu parentNodeSymbol"></i>Lao Lao</div>' +
124
150
  '<i class="edge verticalEdge bottomEdge oci"></i></div><ul class="nodes vertical">' +
125
151
  '<li class="hierarchy"><div class="node"><div class="title">Bo Miao</div></div></li>' +
@@ -128,16 +154,17 @@ describe('orgchart -- integration tests', function () {
128
154
  '<li class="hierarchy"><div class="node slide-up"><div class="title">Tie Hua</div></div>' +
129
155
  '</li><li class="hierarchy"><div class="node slide-up"><div class="title">Hei Hei</div>' +
130
156
  '</div></li></ul></li></ul></li></ul></div>';
131
- oc = $container.orgchart({
157
+ oc = new OrgChart({
158
+ chartContainer: '#chart-container',
132
159
  'data': ds,
133
160
  'verticalLevel': 2,
134
161
  'visibleLevel': 2
135
162
  });
136
- $container.html().should.equal(fragment);
163
+ container.innerHTML.should.equal(fragment);
137
164
  });
138
165
 
139
166
  it('verticalLevel=2 and visibleLevel=3', function () {
140
- var fragment = '<div class="orgchart"><ul class="nodes"><li class="hierarchy">' +
167
+ const fragment = '<div class="orgchart"><ul class="nodes"><li class="hierarchy">' +
141
168
  '<div class="node"><div class="title"><i class="oci oci-menu parentNodeSymbol"></i>Lao Lao</div>' +
142
169
  '<i class="edge verticalEdge bottomEdge oci"></i></div><ul class="nodes vertical">' +
143
170
  '<li class="hierarchy"><div class="node"><div class="title">Bo Miao</div></div></li>' +
@@ -146,81 +173,160 @@ describe('orgchart -- integration tests', function () {
146
173
  '<li class="hierarchy"><div class="node"><div class="title">Tie Hua</div></div>' +
147
174
  '</li><li class="hierarchy"><div class="node"><div class="title">Hei Hei</div></div>' +
148
175
  '</li></ul></li></ul></li></ul></div>';
149
- oc = $container.orgchart({
176
+ oc = new OrgChart({
177
+ chartContainer: '#chart-container',
150
178
  'data': ds,
151
179
  'verticalLevel': 2,
152
180
  'visibleLevel': 3
153
181
  });
154
- $container.html().should.equal(fragment);
182
+ container.innerHTML.should.equal(fragment);
155
183
  });
156
184
  });
157
185
 
158
186
  it('initCompleted should be invoked immediately after construting one node', function () {
159
- var spy = sinon.spy();
160
- oc = $container.orgchart({
187
+ const spy = sinon.spy();
188
+ oc = new OrgChart({
189
+ chartContainer: '#chart-container',
161
190
  'data': ds,
162
191
  'createNode': spy
163
192
  });
164
193
  spy.should.have.been.callCount(3);
165
- spy.should.have.been.calledWithMatch($('#n1'),{ 'id': 'n1', 'name': 'Lao Lao' });
166
- spy.should.have.been.calledWithMatch($('#n2'),{ 'id': 'n2', 'name': 'Bo Miao' });
167
- spy.should.have.been.calledWithMatch($('#n3'),{ 'id': 'n3', 'name': 'Su Miao' });
194
+ spy.getCall(0).args[0].id.should.equal('n1');
195
+ spy.getCall(0).args[1].id.should.equal('n1');
196
+ spy.getCall(1).args[0].id.should.equal('n2');
197
+ spy.getCall(1).args[1].id.should.equal('n2');
198
+ spy.getCall(2).args[0].id.should.equal('n3');
199
+ spy.getCall(2).args[1].id.should.equal('n3');
168
200
  // spy.should.always.have.been.calledOn(oc);
169
201
  });
170
202
 
203
+ it('renders custom data fields and invokes createNode after the node markup is built', function () {
204
+ const createNode = sinon.spy(function (nodeElement, data) {
205
+ nodeElement.setAttribute('data-role', data.role);
206
+ });
207
+
208
+ oc = new OrgChart({
209
+ chartContainer: '#chart-container',
210
+ data: {
211
+ key: 'n1',
212
+ label: 'Director',
213
+ role: 'Operations',
214
+ children: [{ key: 'n2', label: 'Engineer', role: 'Platform' }]
215
+ },
216
+ nodeId: 'key',
217
+ nodeTitle: 'label',
218
+ nodeContent: 'role',
219
+ createNode: createNode
220
+ });
221
+
222
+ query('#n1 .title', oc.chart).textContent.should.equal('Director');
223
+ query('#n1 .content', oc.chart).textContent.should.equal('Operations');
224
+ query('#n2', oc.chart).getAttribute('data-role').should.equal('Platform');
225
+ createNode.should.have.been.calledTwice;
226
+ createNode.firstCall.args[0].querySelector('.title').textContent.should.equal('Director');
227
+ });
228
+
229
+ it('renders custom node templates instead of the default title and content markup', function () {
230
+ oc = new OrgChart({
231
+ chartContainer: '#chart-container',
232
+ data: ds,
233
+ nodeTemplate: function (data) {
234
+ return '<section class="employee-card" data-name="' + data.name + '">' + data.name + '</section>';
235
+ }
236
+ });
237
+
238
+ query('#n1 .employee-card', oc.chart).getAttribute('data-name').should.equal('Lao Lao');
239
+ query('#n2 .employee-card', oc.chart).textContent.should.equal('Bo Miao');
240
+ should.not.exist(query('#n1 > .title', oc.chart));
241
+ });
242
+
243
+ it('dispatches init.orgchart after initCompleted receives the rendered chart', function (done) {
244
+ const initCompleted = sinon.spy(function (chartElement) {
245
+ chartElement.addEventListener('init.orgchart', function () {
246
+ initCompleted.should.have.been.calledOnce;
247
+ initCompleted.firstCall.args[0].should.equal(chartElement);
248
+ done();
249
+ }, { once: true });
250
+ });
251
+
252
+ oc = new OrgChart({
253
+ chartContainer: '#chart-container',
254
+ data: ds,
255
+ initCompleted: initCompleted
256
+ });
257
+ });
258
+
171
259
  it('initialize chart with default className', function () {
172
- oc = $container.orgchart({
260
+ oc = new OrgChart({
261
+ chartContainer: '#chart-container',
173
262
  'data': ds,
174
263
  'chartClass': 'demo'
175
264
  });
176
- oc.$chart.is('.demo').should.be.true;
265
+ oc.chart.classList.contains('demo').should.be.true;
177
266
  });
178
267
 
179
268
  it('initialize chart with export button', function () {
180
- oc = $container.orgchart({
269
+ oc = new OrgChart({
270
+ chartContainer: '#chart-container',
181
271
  'data': ds,
182
272
  'exportButton': true
183
273
  });
184
- $('.oc-export-btn').prop('outerHTML').should.equal('<button class="oc-export-btn">Export</button>');
274
+ query('.oc-export-btn').outerHTML.should.equal('<button class="oc-export-btn">Export</button>');
185
275
  });
186
276
 
187
277
  it('initialize chart with "bottom to top" direction', function () {
188
- oc = $container.orgchart({
278
+ oc = new OrgChart({
279
+ chartContainer: '#chart-container',
189
280
  'data': ds,
190
281
  'direction': 'b2t'
191
282
  });
192
- oc.$chart.is('.b2t').should.be.true;
283
+ oc.chart.classList.contains('b2t').should.be.true;
284
+ });
285
+
286
+ it('applies horizontal direction classes', function () {
287
+ oc = new OrgChart({
288
+ chartContainer: '#chart-container',
289
+ data: ds,
290
+ direction: 'l2r'
291
+ });
292
+ oc.chart.classList.contains('l2r').should.be.true;
293
+
294
+ oc.init({ direction: 'r2l' });
295
+ oc.chart.classList.contains('r2l').should.be.true;
296
+ oc.chart.classList.contains('l2r').should.be.false;
193
297
  });
194
298
 
195
299
  it('reinitialize chart with drggable feature', function () {
196
- oc = $container.orgchart({
300
+ oc = new OrgChart({
301
+ chartContainer: '#chart-container',
197
302
  'data': ds
198
303
  });
199
- var spy = sinon.spy(oc, 'bindDragDrop');
304
+ const spy = sinon.spy(oc, 'bindDragDrop');
200
305
  oc.init({ 'draggable': true });
201
306
  spy.should.have.been.callCount(3);
202
- spy.should.have.been.calledWith($('#n1'));
203
- spy.should.have.been.calledWithMatch($('#n2'));
204
- spy.should.have.been.calledWithMatch($('#n3'));
307
+ spy.getCall(0).args[0].id.should.equal('n1');
308
+ spy.getCall(1).args[0].id.should.equal('n2');
309
+ spy.getCall(2).args[0].id.should.equal('n3');
205
310
  });
206
311
 
207
312
  it('reinitialize chart with pan feature', function () {
208
- oc = $container.orgchart({
313
+ oc = new OrgChart({
314
+ chartContainer: '#chart-container',
209
315
  'data': ds
210
316
  });
211
- var spy = sinon.spy(oc, 'bindPan');
317
+ const spy = sinon.spy(oc, 'bindPan');
212
318
  oc.init({ 'pan': true });
213
319
  spy.should.have.been.callCount(1);
214
320
  });
215
321
 
216
322
  it('reinitialize chart with zoom feature', function () {
217
- oc = $container.orgchart({
323
+ oc = new OrgChart({
324
+ chartContainer: '#chart-container',
218
325
  'data': ds
219
326
  });
220
- var spy = sinon.spy(oc, 'bindZoom');
327
+ const spy = sinon.spy(oc, 'bindZoom');
221
328
  oc.init({ 'zoom': true });
222
329
  spy.should.have.been.callCount(1);
223
330
  });
224
331
  });
225
-
226
- });
332
+ });