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
@@ -2,20 +2,22 @@
2
2
  <html lang="en">
3
3
  <head>
4
4
  <meta charset="utf-8">
5
- <title>Organization Chart Plugin</title>
5
+ <title>OrgChart Level Offset 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
  </head>
10
10
  <body>
11
+ <section class="demo-notes">
12
+ <h1>Level Offset Demo</h1>
13
+ <p>This demo offsets selected nodes to specific levels so branches can intentionally break the default depth alignment.</p>
14
+ </section>
11
15
  <div id="chart-container"></div>
12
-
13
- <script type="text/javascript" src="js/jquery.min.js"></script>
14
- <script type="text/javascript" src="js/jquery.orgchart.js"></script>
16
+ <script type="text/javascript" src="js/orgchart.js"></script>
15
17
  <script type="text/javascript">
16
- $(function() {
18
+ document.addEventListener('DOMContentLoaded', () => {
17
19
 
18
- var datasource = {
20
+ const datasource = {
19
21
  'name': 'Lao Lao',
20
22
  'title': 'general manager',
21
23
  'children': [
@@ -35,18 +37,17 @@
35
37
  ]
36
38
  };
37
39
 
38
- $('#chart-container').orgchart({
40
+ const oc = new OrgChart({
41
+ chartContainer: '#chart-container',
39
42
  'data' : datasource,
40
43
  'nodeContent': 'title',
41
44
  'createNode': function(node, data) {
42
45
  if (data.levelOffset) {
43
- node.css({
44
- 'margin-top': (data.levelOffset * 70) + 'px',
45
- '--top': (-11 - data.levelOffset * 70) + 'px',
46
- '--height': (9 + data.levelOffset * 70) + 'px',
47
- '--top-cross-point': (-13 - data.levelOffset * 70) + 'px',
48
- '--height-cross-point': (11 + data.levelOffset * 70) + 'px'
49
- });
46
+ node.style.marginTop = (data.levelOffset * 70) + 'px';
47
+ node.style.setProperty('--top', (-11 - data.levelOffset * 70) + 'px');
48
+ node.style.setProperty('--height', (9 + data.levelOffset * 70) + 'px');
49
+ node.style.setProperty('--top-cross-point', (-13 - data.levelOffset * 70) + 'px');
50
+ node.style.setProperty('--height-cross-point', (11 + data.levelOffset * 70) + 'px');
50
51
  }
51
52
  }
52
53
  });
@@ -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 Link Node 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
  .orgchart .linkNode {
@@ -25,14 +25,16 @@
25
25
  </style>
26
26
  </head>
27
27
  <body>
28
+ <section class="demo-notes">
29
+ <h1>Link Node Demo</h1>
30
+ <p>This demo inserts connector-style intermediary nodes to visualize indirect relationships inside the hierarchy.</p>
31
+ </section>
28
32
  <div id="chart-container"></div>
29
-
30
- <script type="text/javascript" src="js/jquery.min.js"></script>
31
- <script type="text/javascript" src="js/jquery.orgchart.js"></script>
33
+ <script type="text/javascript" src="js/orgchart.js"></script>
32
34
  <script type="text/javascript">
33
- $(function() {
35
+ document.addEventListener('DOMContentLoaded', () => {
34
36
 
35
- var datascource = {
37
+ const datasource = {
36
38
  'name': 'Lao Lao',
37
39
  'title': 'general manager',
38
40
  'children': [
@@ -59,8 +61,9 @@
59
61
  ]
60
62
  };
61
63
 
62
- $('#chart-container').orgchart({
63
- 'data' : datascource,
64
+ const oc = new OrgChart({
65
+ chartContainer: '#chart-container',
66
+ 'data' : datasource,
64
67
  'nodeContent': 'title'
65
68
  });
66
69
 
@@ -2,20 +2,22 @@
2
2
  <html lang="en">
3
3
  <head>
4
4
  <meta charset="utf-8">
5
- <title>Organization Chart Plugin</title>
5
+ <title>OrgChart Local Datasource 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
  </head>
10
10
  <body>
11
+ <section class="demo-notes">
12
+ <h1>Local Datasource Demo</h1>
13
+ <p>This demo builds the chart directly from a local JSON datasource embedded in the page.</p>
14
+ </section>
11
15
  <div id="chart-container"></div>
12
-
13
- <script type="text/javascript" src="js/jquery.min.js"></script>
14
- <script type="text/javascript" src="js/jquery.orgchart.js"></script>
16
+ <script type="text/javascript" src="js/orgchart.js"></script>
15
17
  <script type="text/javascript">
16
- $(function() {
18
+ document.addEventListener('DOMContentLoaded', () => {
17
19
 
18
- var datasource = {
20
+ const datasource = {
19
21
  'name': 'Lao Lao',
20
22
  'title': 'general manager',
21
23
  'children': [
@@ -35,7 +37,8 @@
35
37
  ]
36
38
  };
37
39
 
38
- $('#chart-container').orgchart({
40
+ const oc = new OrgChart({
41
+ chartContainer: '#chart-container',
39
42
  'data' : datasource,
40
43
  'nodeContent': 'title'
41
44
  });
@@ -0,0 +1,224 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <title>OrgChart Minimap Demo</title>
6
+ <link rel="icon" href="img/logo.png">
7
+ <link rel="stylesheet" href="css/orgchart.css">
8
+ <link rel="stylesheet" href="css/style.css">
9
+ <style type="text/css">
10
+ body {
11
+ padding: 0.5rem;
12
+ }
13
+ #chart-container {
14
+ height: 520px;
15
+ }
16
+ .orgchart {
17
+ background: white;
18
+ }
19
+ </style>
20
+ </head>
21
+ <body>
22
+ <section class="demo-notes">
23
+ <h1>Minimap Demo</h1>
24
+ <p>This demo enables the new <code>minimap</code> option and renders a live overview in the bottom-right corner of the chart container.</p>
25
+ <p>Drag the main chart to pan, use the mouse wheel or touch pinch to zoom, then check that the minimap viewport follows the visible area.</p>
26
+ <p>Drag the blue viewport rectangle inside the minimap to move the main chart. You can also zoom from inside the minimap with the mouse wheel.</p>
27
+ </section>
28
+ <div id="chart-container"></div>
29
+ <script type="text/javascript" src="js/orgchart.js"></script>
30
+ <script type="text/javascript">
31
+ document.addEventListener('DOMContentLoaded', () => {
32
+
33
+ const datasource = {
34
+ 'name': 'Lao Lao',
35
+ 'title': 'general manager',
36
+ 'children': [
37
+ {
38
+ 'name': 'Bo Miao',
39
+ 'title': 'department manager',
40
+ 'children': [
41
+ { 'name': 'Ling', 'title': 'senior engineer' },
42
+ { 'name': 'Qing', 'title': 'product designer' },
43
+ { 'name': 'Yao', 'title': 'quality engineer' }
44
+ ]
45
+ },
46
+ {
47
+ 'name': 'Su Miao',
48
+ 'title': 'department manager',
49
+ 'children': [
50
+ {
51
+ 'name': 'Tie Hua',
52
+ 'title': 'senior engineer',
53
+ 'children': [
54
+ {
55
+ 'name': 'Pang Pang',
56
+ 'title': 'engineer',
57
+ 'children': [
58
+ {
59
+ 'name': 'Ke Xin',
60
+ 'title': 'staff engineer',
61
+ 'children': [
62
+ {
63
+ 'name': 'Iris Sun',
64
+ 'title': 'technical lead',
65
+ 'children': [
66
+ {
67
+ 'name': 'Nina Wu',
68
+ 'title': 'platform engineer',
69
+ 'children': [
70
+ {
71
+ 'name': 'Ethan Lin',
72
+ 'title': 'principal engineer',
73
+ 'children': [
74
+ {
75
+ 'name': 'Mila Tan',
76
+ 'title': 'engineering manager',
77
+ 'children': [
78
+ {
79
+ 'name': 'Sophie He',
80
+ 'title': 'senior platform engineer',
81
+ 'children': [
82
+ {
83
+ 'name': 'Leo Fang',
84
+ 'title': 'platform architect',
85
+ 'children': [
86
+ {
87
+ 'name': 'Grace Qian',
88
+ 'title': 'director of engineering',
89
+ 'children': [
90
+ {
91
+ 'name': 'Victor Shen',
92
+ 'title': 'vp of infrastructure',
93
+ 'children': [
94
+ {
95
+ 'name': 'Hazel Zhou',
96
+ 'title': 'cto advisor',
97
+ 'children': [
98
+ {
99
+ 'name': 'Ryan Luo',
100
+ 'title': 'chief architect',
101
+ 'children': [
102
+ {
103
+ 'name': 'Ava Meng',
104
+ 'title': 'distinguished engineer',
105
+ 'children': [
106
+ {
107
+ 'name': 'Noah Yao',
108
+ 'title': 'innovation fellow',
109
+ 'children': [
110
+ {
111
+ 'name': 'Ella Jin',
112
+ 'title': 'research director',
113
+ 'children': [
114
+ {
115
+ 'name': 'Caleb Xu',
116
+ 'title': 'systems strategist',
117
+ 'children': [
118
+ {
119
+ 'name': 'Ruby Dai',
120
+ 'title': 'transformation lead',
121
+ 'children': [
122
+ {
123
+ 'name': 'Simon Pei',
124
+ 'title': 'program executive',
125
+ 'children': [
126
+ { 'name': 'Tina Mo', 'title': 'senior advisor' }
127
+ ]
128
+ }
129
+ ]
130
+ }
131
+ ]
132
+ }
133
+ ]
134
+ }
135
+ ]
136
+ }
137
+ ]
138
+ }
139
+ ]
140
+ }
141
+ ]
142
+ }
143
+ ]
144
+ }
145
+ ]
146
+ }
147
+ ]
148
+ }
149
+ ]
150
+ }
151
+ ]
152
+ }
153
+ ]
154
+ }
155
+ ]
156
+ },
157
+ { 'name': 'Owen Gu', 'title': 'site reliability engineer' }
158
+ ]
159
+ }
160
+ ]
161
+ }
162
+ ]
163
+ },
164
+ { 'name': 'Xiang Xiang', 'title': 'UE engineer' },
165
+ { 'name': 'Dan Dan', 'title': 'QA engineer' }
166
+ ]
167
+ },
168
+ {
169
+ 'name': 'Hei Hei',
170
+ 'title': 'senior engineer',
171
+ 'children': [
172
+ { 'name': 'Jia Jia', 'title': 'engineer' },
173
+ { 'name': 'Ming Ming', 'title': 'DevOps engineer' }
174
+ ]
175
+ }
176
+ ]
177
+ },
178
+ {
179
+ 'name': 'Hong Miao',
180
+ 'title': 'department manager',
181
+ 'children': [
182
+ { 'name': 'Fei Fei', 'title': 'product manager' },
183
+ { 'name': 'A Hui', 'title': 'data analyst' },
184
+ { 'name': 'Xiao Yu', 'title': 'support lead' }
185
+ ]
186
+ },
187
+ {
188
+ 'name': 'Yu Wei',
189
+ 'title': 'department manager',
190
+ 'children': [
191
+ { 'name': 'Lin Lin', 'title': 'solution architect' },
192
+ { 'name': 'Qiao Qiao', 'title': 'technical writer' },
193
+ { 'name': 'Ran Ran', 'title': 'operations specialist' }
194
+ ]
195
+ },
196
+ {
197
+ 'name': 'Chun Miao',
198
+ 'title': 'department manager',
199
+ 'children': [
200
+ { 'name': 'An An', 'title': 'research engineer' },
201
+ { 'name': 'Le Le', 'title': 'frontend engineer' },
202
+ { 'name': 'Tao Tao', 'title': 'backend engineer' }
203
+ ]
204
+ }
205
+ ]
206
+ };
207
+
208
+ const oc = new OrgChart({
209
+ chartContainer: '#chart-container',
210
+ 'data': datasource,
211
+ 'nodeContent': 'title',
212
+ 'pan': true,
213
+ 'zoom': true,
214
+ 'minimap': true
215
+ });
216
+
217
+ oc.chartContainer.addEventListener('touchmove', function(event) {
218
+ event.preventDefault();
219
+ }, { passive: false });
220
+
221
+ });
222
+ </script>
223
+ </body>
224
+ </html>
@@ -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 Different Width Nodes 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
  .orgchart .node .title {
@@ -17,14 +17,16 @@
17
17
  </style>
18
18
  </head>
19
19
  <body>
20
+ <section class="demo-notes">
21
+ <h1>Different Width Nodes Demo</h1>
22
+ <p>This demo removes fixed title and content widths so node sizing follows the actual text length.</p>
23
+ </section>
20
24
  <div id="chart-container"></div>
21
-
22
- <script type="text/javascript" src="js/jquery.min.js"></script>
23
- <script type="text/javascript" src="js/jquery.orgchart.js"></script>
25
+ <script type="text/javascript" src="js/orgchart.js"></script>
24
26
  <script type="text/javascript">
25
- $(function() {
27
+ document.addEventListener('DOMContentLoaded', () => {
26
28
 
27
- var datasource = {
29
+ const datasource = {
28
30
  'name': 'Lao Lao',
29
31
  'title': 'Lorem ipsum dolor sit amet',
30
32
  'children': [
@@ -44,7 +46,8 @@
44
46
  ]
45
47
  };
46
48
 
47
- $('#chart-container').orgchart({
49
+ const oc = new OrgChart({
50
+ chartContainer: '#chart-container',
48
51
  'data' : datasource,
49
52
  'nodeContent': 'title'
50
53
  });
@@ -2,25 +2,23 @@
2
2
  <html lang="en">
3
3
  <head>
4
4
  <meta charset="utf-8">
5
- <title>Organization Chart Plugin</title>
5
+ <title>OrgChart On-Demand Loading 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
  </head>
10
10
  <body>
11
+ <section class="demo-notes">
12
+ <h1>On-Demand Loading Demo</h1>
13
+ <p>This demo loads ancestors and descendants only when users expand the corresponding branches.</p>
14
+ </section>
11
15
  <div id="chart-container"></div>
12
-
13
- <script type="text/javascript" src="js/jquery.min.js"></script>
14
- <script type="text/javascript" src="js/jquery.orgchart.js"></script>
15
- <script type="text/javascript" src="js/jquery.mockjax.min.js"></script>
16
+ <script type="text/javascript" src="js/orgchart.js"></script>
16
17
  <script type="text/javascript">
17
- $(function() {
18
+ document.addEventListener('DOMContentLoaded', () => {
18
19
 
19
- $.mockjax({
20
- url: '/orgchart/ancestors/n1',
21
- contentType: 'application/json',
22
- responseTime: 1000,
23
- responseText: {
20
+ const responseMap = {
21
+ '/orgchart/ancestors/n1': {
24
22
  'id': 'n0',
25
23
  'name': 'Lao Lao',
26
24
  'title': 'general manager', 'relationship': '001',
@@ -33,23 +31,11 @@
33
31
  { 'id': 'n15', 'name': 'Chun Miao', 'title': 'department engineer', 'relationship': '110' },
34
32
  { 'id': 'n16', 'name': 'Yu Tie', 'title': 'department engineer', 'relationship': '110' }
35
33
  ]
36
- }
37
- });
38
-
39
- $.mockjax({
40
- url: '/orgchart/descendants/n2',
41
- contentType: 'application/json',
42
- responseTime: 1000,
43
- responseText: [
34
+ },
35
+ '/orgchart/descendants/n2': [
44
36
  { 'id': 'n4', 'name': 'Xiang Xiang', 'title': 'engineer', 'relationship': '110' }
45
- ]
46
- });
47
-
48
- $.mockjax({
49
- url: '/orgchart/descendants/n3',
50
- contentType: 'application/json',
51
- responseTime: 1000,
52
- responseText: [
37
+ ],
38
+ '/orgchart/descendants/n3': [
53
39
  { 'id': 'n5', 'name': 'Pang Pang', 'title': 'engineer', 'relationship': '111',
54
40
  'children': [
55
41
  { 'id': 'n6', 'name': 'Er Dan', 'title': 'UE engineer', 'relationship': '110'}
@@ -57,9 +43,13 @@
57
43
  },
58
44
  { 'id': 'n7', 'name': 'Dan Dan', 'title': 'engineer', 'relationship': '110' }
59
45
  ]
46
+ };
47
+
48
+ const requestJson = (url) => new Promise((resolve) => {
49
+ window.setTimeout(() => resolve(responseMap[url]), 1000);
60
50
  });
61
51
 
62
- var datascource = {
52
+ const datasource = {
63
53
  'id': 'n1',
64
54
  'name': 'Su Miao',
65
55
  'title': 'department manager',
@@ -70,82 +60,89 @@
70
60
  ]
71
61
  };
72
62
 
73
- var ajaxURLs = {
74
- 'children': '/orgchart/children/',
75
- 'parent': '/orgchart/parent/',
76
- 'siblings': function(nodeData) {
77
- return '/orgchart/siblings/' + nodeData.id;
78
- },
79
- 'families': function(nodeData) {
80
- return '/orgchart/families/' + nodeData.id;
81
- }
82
- };
83
-
84
- var oc = $('#chart-container').orgchart({
85
- 'data' : datascource,
63
+ const oc = new OrgChart({
64
+ chartContainer: '#chart-container',
65
+ 'data' : datasource,
86
66
  'nodeContent': 'title',
87
67
  'nodeId': 'id'
88
68
  });
89
69
 
90
- oc.$chart.on('click', '.topEdge, .horizontalEdge', function(e) {
91
- var $chart = oc.$chart;
92
- var $topEdge = $(e.target);
93
- var $node = $topEdge.parent();
94
- var parentState = oc.getNodeState($node, 'parent');
95
- if (!parentState.exist) {
96
- if (!($chart.data('inAjax') === true)) {
97
- $topEdge.addClass('hidden');
98
- $node.append(`<i class="oci oci-spinner spinner"></i>`)
99
- $node.children().not('.spinner').css('opacity', 0.2);
100
- $chart.data('inAjax', true);
101
-
102
- $.ajax({
103
- 'url': '/orgchart/ancestors/' + $node.data('nodeData').id,
104
- 'dataType': 'json'
105
- })
106
- .done(function(data, textStatus, jqXHR) {
107
- oc.addAncestors(data, 'n0');
108
- })
109
- .always(function() {
110
- $topEdge.removeClass('hidden');
111
- $node.children('.spinner').remove();
112
- $node.children().removeAttr('style');
113
- $chart.data('inAjax', false);
70
+ const chartElement = document.getElementById('chart-container');
71
+ const getAjaxFlag = () => oc.chart.dataset.inAjax === 'true';
72
+ const setAjaxFlag = (value) => {
73
+ oc.chart.dataset.inAjax = value ? 'true' : 'false';
74
+ };
75
+ const toggleLoading = (edgeElement, isLoading) => {
76
+ const nodeElement = edgeElement.parentElement;
77
+ const spinner = nodeElement.querySelector('.spinner');
78
+ edgeElement.classList.toggle('hidden', isLoading);
79
+ if (isLoading && !spinner) {
80
+ nodeElement.insertAdjacentHTML('beforeend', '<i class="oci oci-spinner spinner"></i>');
81
+ Array.from(nodeElement.children)
82
+ .filter((child) => !child.classList.contains('spinner'))
83
+ .forEach((child) => {
84
+ child.style.opacity = '0.2';
114
85
  });
86
+ setAjaxFlag(true);
87
+ return;
88
+ }
89
+ if (!isLoading) {
90
+ const currentSpinner = nodeElement.querySelector('.spinner');
91
+ if (currentSpinner) {
92
+ currentSpinner.remove();
93
+ }
94
+ Array.from(nodeElement.children).forEach((child) => {
95
+ child.removeAttribute('style');
96
+ });
97
+ setAjaxFlag(false);
98
+ }
99
+ };
100
+
101
+ chartElement.addEventListener('click', async (event) => {
102
+ const clickableAncestor = event.target.closest('.topEdge, .horizontalEdge');
103
+ if (!clickableAncestor || !chartElement.contains(clickableAncestor)) {
104
+ return;
105
+ }
106
+ const nodeElement = clickableAncestor.parentElement;
107
+ const parentState = oc.getNodeState(nodeElement, 'parent');
108
+ if (!parentState.exist) {
109
+ if (getAjaxFlag()) {
110
+ return;
111
+ }
112
+ toggleLoading(clickableAncestor, true);
113
+ try {
114
+ const nodeData = nodeElement ? nodeElement.__ocNodeData || nodeElement.dataset : {};
115
+ const data = await requestJson('/orgchart/ancestors/' + nodeData.id);
116
+ oc.addAncestors(data, 'n0');
117
+ } finally {
118
+ toggleLoading(clickableAncestor, false);
115
119
  }
116
120
  }
117
121
  });
118
122
 
119
- oc.$chart.on('click', '.bottomEdge', function(e) {
120
- var $chart = oc.$chart;
121
- var $bottomEdge = $(e.target);
122
- var $node = $bottomEdge.parent();
123
- var childrenState = oc.getNodeState($node, 'children');
123
+ chartElement.addEventListener('click', async (event) => {
124
+ const bottomEdge = event.target.closest('.bottomEdge');
125
+ if (!bottomEdge || !chartElement.contains(bottomEdge)) {
126
+ return;
127
+ }
128
+ const nodeElement = bottomEdge.parentElement;
129
+ const childrenState = oc.getNodeState(nodeElement, 'children');
124
130
  if (!childrenState.exist) {
125
- if (!($chart.data('inAjax') === true)) {
126
- $bottomEdge.addClass('hidden');
127
- $node.append(`<i class="oci oci-spinner spinner"></i>`)
128
- $node.children().not('.spinner').css('opacity', 0.2);
129
- $chart.data('inAjax', true);
130
-
131
- $.ajax({
132
- 'url': '/orgchart/descendants/' + $node.data('nodeData').id,
133
- 'dataType': 'json'
134
- })
135
- .done(function(data, textStatus, jqXHR) {
136
- oc.addDescendants(data, $node);
137
- })
138
- .always(function() {
139
- $bottomEdge.removeClass('hidden');
140
- $node.children('.spinner').remove();
141
- $node.children().removeAttr('style');
142
- $chart.data('inAjax', false);
143
- });
131
+ if (getAjaxFlag()) {
132
+ return;
133
+ }
134
+ toggleLoading(bottomEdge, true);
135
+ try {
136
+ const nodeData = nodeElement ? nodeElement.__ocNodeData || nodeElement.dataset : {};
137
+ const data = await requestJson('/orgchart/descendants/' + nodeData.id);
138
+ oc.addDescendants(data, nodeElement);
139
+ } finally {
140
+ toggleLoading(bottomEdge, false);
144
141
  }
145
142
  }
146
143
  });
147
144
 
148
- });
145
+ });
149
146
  </script>
150
147
  </body>
151
148
  </html>