orgchart 4.0.1 → 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 (77) hide show
  1. package/.github/workflows/publish.yml +32 -0
  2. package/README.md +205 -89
  3. package/README.zh-cn.md +221 -68
  4. package/README.zh-tw.md +221 -68
  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 +100 -0
  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 +7 -4
  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 +31 -20
  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} +210 -78
  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} +210 -78
  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/demo/multiple-layers.html +0 -128
  73. package/dist/css/jquery.orgchart.min.css +0 -1
  74. package/dist/js/jquery.orgchart.js +0 -1686
  75. package/dist/js/jquery.orgchart.min.js +0 -5
  76. package/dist/js/jquery.orgchart.min.js.map +0 -1
  77. package/src/js/jquery.orgchart.js +0 -1686
@@ -2,9 +2,9 @@
2
2
  <html lang="en">
3
3
  <head>
4
4
  <meta charset="utf-8">
5
- <title>Organization Chart Plugin</title>
5
+ <title>OrgChart Edit Chart Demo</title>
6
6
  <link rel="icon" href="img/logo.png">
7
- <link rel="stylesheet" href="css/jquery.orgchart.css">
7
+ <link rel="stylesheet" href="css/orgchart.css">
8
8
  <link rel="stylesheet" href="css/style.css">
9
9
  <style type="text/css">
10
10
  #chart-container { height: 500px; }
@@ -33,6 +33,10 @@
33
33
  </style>
34
34
  </head>
35
35
  <body>
36
+ <section class="demo-notes">
37
+ <h1>Edit Chart Demo</h1>
38
+ <p>This demo uses the edit panel to add parent, child, and sibling nodes, delete nodes, and reset the chart state.</p>
39
+ </section>
36
40
  <div id="chart-container"></div>
37
41
  <div id="edit-panel">
38
42
  <span id="chart-state-panel" class="radio-panel">
@@ -56,13 +60,19 @@
56
60
  <button type="button" id="btn-delete-nodes">Delete</button>
57
61
  <button type="button" id="btn-reset">Reset</button>
58
62
  </div>
59
- <script type="text/javascript" src="js/jquery.min.js"></script>
60
63
  <script type="text/javascript" src="js/html2canvas.min.js"></script>
61
- <script type="text/javascript" src="js/jquery.orgchart.js"></script>
64
+ <script type="text/javascript" src="js/orgchart.js"></script>
62
65
  <script type="text/javascript">
63
- $(function() {
66
+ document.addEventListener('DOMContentLoaded', () => {
64
67
 
65
- var datascource = {
68
+ const chartContainer = document.getElementById('chart-container');
69
+ const selectedNodeInput = document.getElementById('selected-node');
70
+ const editPanel = document.getElementById('edit-panel');
71
+ const newNodeList = document.getElementById('new-nodelist');
72
+ const nodeTypePanel = document.getElementById('node-type-panel');
73
+ let selectedNode = null;
74
+
75
+ const datasource = {
66
76
  'name': 'Ball game',
67
77
  'children': [
68
78
  { 'name': 'Football' },
@@ -71,146 +81,190 @@
71
81
  ]
72
82
  };
73
83
 
74
- var getId = function() {
75
- return (new Date().getTime()) * 1000 + Math.floor(Math.random() * 1001);
84
+ const getId = () => (Date.now() * 1000) + Math.floor(Math.random() * 1001);
85
+ const getRootNode = () => chartContainer.querySelector('.orgchart .node');
86
+ const getCheckedNodeType = () => document.querySelector('input[name="node-type"]:checked');
87
+ const getCheckedChartState = () => document.querySelector('input[name="chart-state"]:checked');
88
+ const getNewNodeValues = () => Array.from(newNodeList.querySelectorAll('.new-node'))
89
+ .map((input) => input.value.trim())
90
+ .filter(Boolean);
91
+ const clearSelection = () => {
92
+ selectedNode = null;
93
+ selectedNodeInput.value = '';
76
94
  };
77
-
78
- var oc = $('#chart-container').orgchart({
79
- 'data' : datascource,
80
- 'createNode': function($node, data) {
81
- $node[0].id = getId();
95
+ const syncChartEditState = () => {
96
+ const isEditMode = getCheckedChartState()?.value === 'edit';
97
+ const chartElement = chartContainer.querySelector('.orgchart');
98
+ if (!chartElement) {
99
+ return;
82
100
  }
83
- });
101
+ chartElement.classList.toggle('edit-state', isEditMode);
102
+ };
84
103
 
85
- oc.$chartContainer.on('click', '.node', function() {
86
- var $this = $(this);
87
- $('#selected-node').val($this.find('.title').text()).data('node', $this);
104
+ let oc = new OrgChart({
105
+ chartContainer: '#chart-container',
106
+ 'data' : datasource,
107
+ 'createNode': function(node) {
108
+ node.id = getId();
109
+ }
88
110
  });
89
111
 
90
- oc.$chartContainer.on('click', '.orgchart', function(event) {
91
- if (!$(event.target).closest('.node').length) {
92
- $('#selected-node').val('');
112
+ chartContainer.addEventListener('click', (event) => {
113
+ const clickedNode = event.target.closest('.node');
114
+ if (clickedNode && chartContainer.contains(clickedNode)) {
115
+ selectedNode = clickedNode;
116
+ const titleElement = clickedNode.querySelector('.title');
117
+ selectedNodeInput.value = titleElement ? titleElement.textContent.trim() : '';
118
+ return;
119
+ }
120
+ if (event.target.closest('.orgchart')) {
121
+ clearSelection();
93
122
  }
94
123
  });
95
124
 
96
- $('input[name="chart-state"]').on('click', function() {
97
- $('.orgchart').toggleClass('edit-state', this.value !== 'view');
98
- $('#edit-panel').toggleClass('edit-state', this.value === 'view');
99
- if ($(this).val() === 'edit') {
100
- $('.orgchart').find('.hidden').removeClass('hidden')
101
- .end().find('.hierarchy').removeClass('isCollapsedDescendant isChildrenCollapsed isSiblingsCollapsed isCollapsedSibling')
102
- .find('.node').removeClass('slide-up slide-down slide-right slide-left');
103
- } else {
104
- $('#btn-reset').trigger('click');
105
- }
125
+ document.querySelectorAll('input[name="chart-state"]').forEach((radio) => {
126
+ radio.addEventListener('click', () => {
127
+ const isEditMode = radio.value === 'edit';
128
+ const chartElement = chartContainer.querySelector('.orgchart');
129
+ if (chartElement) {
130
+ chartElement.classList.toggle('edit-state', isEditMode);
131
+ }
132
+ editPanel.classList.toggle('edit-state', !isEditMode);
133
+ if (isEditMode) {
134
+ const orgchart = chartContainer.querySelector('.orgchart');
135
+ if (orgchart) {
136
+ orgchart.querySelectorAll('.hidden').forEach((element) => element.classList.remove('hidden'));
137
+ orgchart.querySelectorAll('.hierarchy').forEach((element) => {
138
+ element.classList.remove('isCollapsedDescendant', 'isChildrenCollapsed', 'isSiblingsCollapsed', 'isCollapsedSibling');
139
+ });
140
+ orgchart.querySelectorAll('.node').forEach((element) => {
141
+ element.classList.remove('slide-up', 'slide-down', 'slide-right', 'slide-left');
142
+ });
143
+ }
144
+ } else {
145
+ document.getElementById('btn-reset').click();
146
+ }
147
+ });
106
148
  });
107
149
 
108
- $('input[name="node-type"]').on('click', function() {
109
- var $this = $(this);
110
- if ($this.val() === 'parent') {
111
- $('#edit-panel').addClass('edit-parent-node');
112
- $('#new-nodelist').children(':gt(0)').remove();
113
- } else {
114
- $('#edit-panel').removeClass('edit-parent-node');
115
- }
150
+ document.querySelectorAll('input[name="node-type"]').forEach((radio) => {
151
+ radio.addEventListener('click', () => {
152
+ if (radio.value === 'parent') {
153
+ editPanel.classList.add('edit-parent-node');
154
+ Array.from(newNodeList.children).slice(1).forEach((item) => item.remove());
155
+ } else {
156
+ editPanel.classList.remove('edit-parent-node');
157
+ }
158
+ });
116
159
  });
117
160
 
118
- $('#btn-add-input').on('click', function() {
119
- $('#new-nodelist').append('<li><input type="text" class="new-node"></li>');
161
+ document.getElementById('btn-add-input').addEventListener('click', () => {
162
+ const item = document.createElement('li');
163
+ item.innerHTML = '<input type="text" class="new-node">';
164
+ newNodeList.appendChild(item);
120
165
  });
121
166
 
122
- $('#btn-remove-input').on('click', function() {
123
- var inputs = $('#new-nodelist').children('li');
124
- if (inputs.length > 1) {
125
- inputs.last().remove();
167
+ document.getElementById('btn-remove-input').addEventListener('click', () => {
168
+ if (newNodeList.children.length > 1) {
169
+ newNodeList.lastElementChild.remove();
126
170
  }
127
171
  });
128
172
 
129
- $('#btn-add-nodes').on('click', function() {
130
- var $chartContainer = $('#chart-container');
131
- var nodeVals = [];
132
- $('#new-nodelist').find('.new-node').each(function(index, item) {
133
- var validVal = item.value.trim();
134
- if (validVal.length) {
135
- nodeVals.push(validVal);
136
- }
137
- });
138
- var $node = $('#selected-node').data('node');
173
+ document.getElementById('btn-add-nodes').addEventListener('click', () => {
174
+ const nodeVals = getNewNodeValues();
175
+ const nodeType = getCheckedNodeType();
176
+ const rootNode = getRootNode();
139
177
  if (!nodeVals.length) {
140
178
  alert('Please input value for new node');
141
179
  return;
142
180
  }
143
- var nodeType = $('input[name="node-type"]:checked');
144
- if (!nodeType.length) {
181
+ if (!nodeType) {
145
182
  alert('Please select a node type');
146
183
  return;
147
184
  }
148
- if (nodeType.val() !== 'parent' && !$('.orgchart').length) {
185
+ if (nodeType.value !== 'parent' && !chartContainer.querySelector('.orgchart')) {
149
186
  alert('Please creat the root node firstly when you want to build up the orgchart from the scratch');
150
187
  return;
151
188
  }
152
- if (nodeType.val() !== 'parent' && !$node) {
189
+ if (nodeType.value !== 'parent' && !selectedNode) {
153
190
  alert('Please select one node in orgchart');
154
191
  return;
155
192
  }
156
- if (nodeType.val() === 'parent') {
157
- if (!$chartContainer.children('.orgchart').length) {// if the original chart has been deleted
158
- oc = $chartContainer.orgchart({
193
+ if (nodeType.value === 'parent') {
194
+ if (!chartContainer.querySelector('.orgchart')) {
195
+ oc = new OrgChart({
196
+ chartContainer: '#chart-container',
159
197
  'data' : { 'name': nodeVals[0] },
160
198
  'chartClass': 'edit-state',
161
199
  'exportButton': true,
162
200
  'exportFilename': 'SportsChart',
163
- 'createNode': function($node, data) {
164
- $node[0].id = getId();
201
+ 'createNode': function(node) {
202
+ node.id = getId();
165
203
  }
166
204
  });
205
+ syncChartEditState();
167
206
  } else {
168
- oc.addParent($chartContainer.find('.node:first'), { 'name': nodeVals[0], 'id': getId() });
207
+ oc.addParent(selectedNode || rootNode, { 'name': nodeVals[0], 'id': getId() });
169
208
  }
170
- } else if (nodeType.val() === 'siblings') {
171
- if ($node[0].id === oc.$chart.find('.node:first')[0].id) {
209
+ return;
210
+ }
211
+ if (nodeType.value === 'siblings') {
212
+ if (selectedNode.id === rootNode.id) {
172
213
  alert('You are not allowed to directly add sibling nodes to root node');
173
214
  return;
174
215
  }
175
- oc.addSiblings($node, nodeVals.map(function (item) {
176
- return { 'name': item, 'relationship': '110', 'id': getId() };
177
- }));
216
+ oc.addSiblings(selectedNode, nodeVals.map((item) => ({
217
+ 'name': item,
218
+ 'relationship': '110',
219
+ 'id': getId()
220
+ })));
221
+ return;
222
+ }
223
+
224
+ const childLevel = selectedNode.nextElementSibling;
225
+ if (!childLevel || !childLevel.classList.contains('nodes')) {
226
+ const relationship = nodeVals.length > 1 ? '110' : '100';
227
+ oc.addChildren(selectedNode, nodeVals.map((item) => ({
228
+ 'name': item,
229
+ 'relationship': relationship,
230
+ 'id': getId()
231
+ })));
178
232
  } else {
179
- if (!$node.siblings('.nodes').length) {
180
- var rel = nodeVals.length > 1 ? '110' : '100';
181
- oc.addChildren($node, nodeVals.map(function (item) {
182
- return { 'name': item, 'relationship': rel, 'id': getId() };
183
- }));
184
- } else {
185
- oc.addSiblings($node.siblings('.nodes').find('.node:first'), nodeVals.map(function (item) {
186
- return { 'name': item, 'relationship': '110', 'id': getId() };
187
- }));
188
- }
233
+ oc.addSiblings(childLevel.querySelector('.node'), nodeVals.map((item) => ({
234
+ 'name': item,
235
+ 'relationship': '110',
236
+ 'id': getId()
237
+ })));
189
238
  }
190
239
  });
191
240
 
192
- $('#btn-delete-nodes').on('click', function() {
193
- var $node = $('#selected-node').data('node');
194
- if (!$node) {
241
+ document.getElementById('btn-delete-nodes').addEventListener('click', () => {
242
+ const rootNode = getRootNode();
243
+ if (!selectedNode) {
195
244
  alert('Please select one node in orgchart');
196
245
  return;
197
- } else if ($node[0] === $('.orgchart').find('.node:first')[0]) {
198
- if (!window.confirm('Are you sure you want to delete the whole chart?')) {
199
- return;
200
- }
201
246
  }
202
- oc.removeNodes($node);
203
- $('#selected-node').val('').data('node', null);
247
+ if (rootNode && selectedNode === rootNode && !window.confirm('Are you sure you want to delete the whole chart?')) {
248
+ return;
249
+ }
250
+ oc.removeNodes(selectedNode);
251
+ clearSelection();
204
252
  });
205
253
 
206
- $('#btn-reset').on('click', function() {
207
- $('.orgchart').find('.focused').removeClass('focused');
208
- $('#selected-node').val('');
209
- $('#new-nodelist').find('input:first').val('').parent().siblings().remove();
210
- $('#node-type-panel').find('input').prop('checked', false);
254
+ document.getElementById('btn-reset').addEventListener('click', () => {
255
+ chartContainer.querySelectorAll('.focused').forEach((element) => element.classList.remove('focused'));
256
+ clearSelection();
257
+ const inputs = newNodeList.querySelectorAll('input');
258
+ if (inputs.length) {
259
+ inputs[0].value = '';
260
+ }
261
+ Array.from(newNodeList.children).slice(1).forEach((item) => item.remove());
262
+ nodeTypePanel.querySelectorAll('input').forEach((input) => {
263
+ input.checked = false;
264
+ });
211
265
  });
212
266
 
213
- });
267
+ });
214
268
  </script>
215
269
  </body>
216
270
  </html>