Commit edb4d5a6ec3b369a026318af28b99d3e9b42a5e3

Authored by ww
1 parent 959f9d93

chore: del dist folder

1 -/**  
2 - * Copyright (c) 2006-2012, JGraph Ltd  
3 - */  
4 -Format = function (editorUi, container) {  
5 - this.editorUi = editorUi;  
6 - this.container = container;  
7 -};  
8 -  
9 -/**  
10 - * Background color for inactive tabs.  
11 - * 没有激活的tab栏 背景色  
12 - */  
13 -Format.inactiveTabBackgroundColor = "#f1f3f4";  
14 -  
15 -/**  
16 - * Icons for markers (24x16).  
17 - */  
18 -Format.classicFilledMarkerImage = Graph.createSvgImage(  
19 - 20,  
20 - 22,  
21 - '<path transform="translate(4,2)" stroke-width="2" d="M 0 8 L 10 2 L 5 8 L 10 14 Z M 0 8 L 24 8" stroke="#404040" fill="#404040"/>',  
22 - 32,  
23 - 20,  
24 -);  
25 -Format.classicThinFilledMarkerImage = Graph.createSvgImage(  
26 - 20,  
27 - 22,  
28 - '<path transform="translate(4,2)" stroke-width="2" d="M 0 8 L 8 4 L 3 8 L 8 12 Z M 0 8 L 24 8" stroke="#404040" fill="#404040"/>',  
29 - 32,  
30 - 20,  
31 -);  
32 -Format.openFilledMarkerImage = Graph.createSvgImage(  
33 - 20,  
34 - 22,  
35 - '<path transform="translate(4,2)" stroke-width="2" d="M 8 0 L 0 8 L 8 16 M 0 8 L 24 8" stroke="#404040" fill="transparent"/>',  
36 - 32,  
37 - 20,  
38 -);  
39 -Format.openThinFilledMarkerImage = Graph.createSvgImage(  
40 - 20,  
41 - 22,  
42 - '<path transform="translate(4,2)" stroke-width="2" d="M 8 4 L 0 8 L 8 12 M 0 8 L 24 8" stroke="#404040" fill="transparent"/>',  
43 - 32,  
44 - 20,  
45 -);  
46 -Format.openAsyncFilledMarkerImage = Graph.createSvgImage(  
47 - 20,  
48 - 22,  
49 - '<path transform="translate(4,2)" stroke-width="2" d="M 8 4 L 0 8 L 24 8" stroke="#404040" fill="transparent"/>',  
50 - 32,  
51 - 20,  
52 -);  
53 -Format.blockFilledMarkerImage = Graph.createSvgImage(  
54 - 20,  
55 - 22,  
56 - '<path transform="translate(4,2)" stroke-width="2" d="M 0 8 L 8 2 L 8 14 Z M 0 8 L 24 8" stroke="#404040" fill="#404040"/>',  
57 - 32,  
58 - 20,  
59 -);  
60 -Format.blockThinFilledMarkerImage = Graph.createSvgImage(  
61 - 20,  
62 - 22,  
63 - '<path transform="translate(4,2)" stroke-width="2" d="M 0 8 L 8 4 L 8 12 Z M 0 8 L 24 8" stroke="#404040" fill="#404040"/>',  
64 - 32,  
65 - 20,  
66 -);  
67 -Format.asyncFilledMarkerImage = Graph.createSvgImage(  
68 - 20,  
69 - 22,  
70 - '<path transform="translate(4,2)" stroke-width="2" d="M 6 8 L 6 4 L 0 8 L 24 8" stroke="#404040" fill="#404040"/>',  
71 - 32,  
72 - 20,  
73 -);  
74 -Format.ovalFilledMarkerImage = Graph.createSvgImage(  
75 - 20,  
76 - 22,  
77 - '<path transform="translate(4,2)" stroke-width="2" d="M 0 8 A 5 5 0 0 1 5 3 A 5 5 0 0 1 11 8 A 5 5 0 0 1 5 13 A 5 5 0 0 1 0 8 Z M 10 8 L 24 8" stroke="#404040" fill="#404040"/>',  
78 - 32,  
79 - 20,  
80 -);  
81 -Format.diamondFilledMarkerImage = Graph.createSvgImage(  
82 - 20,  
83 - 22,  
84 - '<path transform="translate(4,2)" stroke-width="2" d="M 0 8 L 6 2 L 12 8 L 6 14 Z M 0 8 L 24 8" stroke="#404040" fill="#404040"/>',  
85 - 32,  
86 - 20,  
87 -);  
88 -Format.diamondThinFilledMarkerImage = Graph.createSvgImage(  
89 - 20,  
90 - 22,  
91 - '<path transform="translate(4,2)" stroke-width="2" d="M 0 8 L 8 3 L 16 8 L 8 13 Z M 0 8 L 24 8" stroke="#404040" fill="#404040"/>',  
92 - 32,  
93 - 20,  
94 -);  
95 -Format.classicMarkerImage = Graph.createSvgImage(  
96 - 20,  
97 - 22,  
98 - '<path transform="translate(4,2)" stroke-width="2" d="M 0 8 L 10 2 L 5 8 L 10 14 Z M 5 8 L 24 8" stroke="#404040" fill="transparent"/>',  
99 - 32,  
100 - 20,  
101 -);  
102 -Format.classicThinMarkerImage = Graph.createSvgImage(  
103 - 20,  
104 - 22,  
105 - '<path transform="translate(4,2)" stroke-width="2" d="M 0 8 L 8 4 L 5 8 L 8 12 Z M 5 8 L 24 8" stroke="#404040" fill="transparent"/>',  
106 - 32,  
107 - 20,  
108 -);  
109 -Format.blockMarkerImage = Graph.createSvgImage(  
110 - 20,  
111 - 22,  
112 - '<path transform="translate(4,2)" stroke-width="2" d="M 0 8 L 8 2 L 8 14 Z M 8 8 L 24 8" stroke="#404040" fill="transparent"/>',  
113 - 32,  
114 - 20,  
115 -);  
116 -Format.blockThinMarkerImage = Graph.createSvgImage(  
117 - 20,  
118 - 22,  
119 - '<path transform="translate(4,2)" stroke-width="2" d="M 0 8 L 8 4 L 8 12 Z M 8 8 L 24 8" stroke="#404040" fill="transparent"/>',  
120 - 32,  
121 - 20,  
122 -);  
123 -Format.asyncMarkerImage = Graph.createSvgImage(  
124 - 20,  
125 - 22,  
126 - '<path transform="translate(4,2)" stroke-width="2" d="M 6 8 L 6 4 L 0 8 L 24 8" stroke="#404040" fill="transparent"/>',  
127 - 32,  
128 - 20,  
129 -);  
130 -Format.ovalMarkerImage = Graph.createSvgImage(  
131 - 20,  
132 - 22,  
133 - '<path transform="translate(4,2)" stroke-width="2" d="M 0 8 A 5 5 0 0 1 5 3 A 5 5 0 0 1 11 8 A 5 5 0 0 1 5 13 A 5 5 0 0 1 0 8 Z M 10 8 L 24 8" stroke="#404040" fill="transparent"/>',  
134 - 32,  
135 - 20,  
136 -);  
137 -Format.diamondMarkerImage = Graph.createSvgImage(  
138 - 20,  
139 - 22,  
140 - '<path transform="translate(4,2)" stroke-width="2" d="M 0 8 L 6 2 L 12 8 L 6 14 Z M 12 8 L 24 8" stroke="#404040" fill="transparent"/>',  
141 - 32,  
142 - 20,  
143 -);  
144 -Format.diamondThinMarkerImage = Graph.createSvgImage(  
145 - 20,  
146 - 22,  
147 - '<path transform="translate(4,2)" stroke-width="2" d="M 0 8 L 8 3 L 16 8 L 8 13 Z M 16 8 L 24 8" stroke="#404040" fill="transparent"/>',  
148 - 32,  
149 - 20,  
150 -);  
151 -Format.boxMarkerImage = Graph.createSvgImage(  
152 - 20,  
153 - 22,  
154 - '<path transform="translate(4,2)" stroke-width="2" d="M 0 3 L 10 3 L 10 13 L 0 13 Z M 10 8 L 24 8" stroke="#404040" fill="transparent"/>',  
155 - 32,  
156 - 20,  
157 -);  
158 -Format.halfCircleMarkerImage = Graph.createSvgImage(  
159 - 20,  
160 - 22,  
161 - '<path transform="translate(4,2)" stroke-width="2" d="M 0 3 A 5 5 0 0 1 5 8 A 5 5 0 0 1 0 13 M 5 8 L 24 8" stroke="#404040" fill="transparent"/>',  
162 - 32,  
163 - 20,  
164 -);  
165 -Format.dashMarkerImage = Graph.createSvgImage(  
166 - 20,  
167 - 22,  
168 - '<path transform="translate(4,2)" stroke-width="2" d="M 0 2 L 12 14 M 0 8 L 24 8" stroke="#404040" fill="transparent"/>',  
169 - 32,  
170 - 20,  
171 -);  
172 -Format.crossMarkerImage = Graph.createSvgImage(  
173 - 20,  
174 - 22,  
175 - '<path transform="translate(4,2)" stroke-width="2" d="M 0 2 L 12 14 M 12 2 L 0 14 M 0 8 L 24 8" stroke="#404040" fill="transparent"/>',  
176 - 32,  
177 - 20,  
178 -);  
179 -Format.circlePlusMarkerImage = Graph.createSvgImage(  
180 - 20,  
181 - 22,  
182 - '<path transform="translate(4,2)" stroke-width="2" d="M 0 8 A 6 6 0 0 1 6 2 A 6 6 0 0 1 12 8 A 6 6 0 0 1 6 14 A 6 6 0 0 1 0 8 Z M 6 2 L 6 14 M 0 8 L 24 8" stroke="#404040" fill="transparent"/>',  
183 - 32,  
184 - 20,  
185 -);  
186 -Format.circleMarkerImage = Graph.createSvgImage(  
187 - 20,  
188 - 22,  
189 - '<path transform="translate(4,2)" stroke-width="2" d="M 0 8 A 6 6 0 0 1 6 2 A 6 6 0 0 1 12 8 A 6 6 0 0 1 6 14 A 6 6 0 0 1 0 8 Z M 12 8 L 24 8" stroke="#404040" fill="transparent"/>',  
190 - 32,  
191 - 20,  
192 -);  
193 -Format.ERmandOneMarkerImage = Graph.createSvgImage(  
194 - 20,  
195 - 22,  
196 - '<path transform="translate(4,2)" stroke-width="2" d="M 6 2 L 6 14 M 9 2 L 9 14 M 0 8 L 24 8" stroke="#404040" fill="transparent"/>',  
197 - 32,  
198 - 20,  
199 -);  
200 -Format.ERmanyMarkerImage = Graph.createSvgImage(  
201 - 20,  
202 - 22,  
203 - '<path transform="translate(4,2)" stroke-width="2" d="M 0 2 L 12 8 L 0 14 M 0 8 L 24 8" stroke="#404040" fill="transparent"/>',  
204 - 32,  
205 - 20,  
206 -);  
207 -Format.ERoneToManyMarkerImage = Graph.createSvgImage(  
208 - 20,  
209 - 22,  
210 - '<path transform="translate(4,2)" stroke-width="2" d="M 0 2 L 12 8 L 0 14 M 15 2 L 15 14 M 0 8 L 24 8" stroke="#404040" fill="transparent"/>',  
211 - 32,  
212 - 20,  
213 -);  
214 -Format.ERzeroToOneMarkerImage = Graph.createSvgImage(  
215 - 20,  
216 - 22,  
217 - '<path transform="translate(4,2)" stroke-width="2" d="M 8 8 A 5 5 0 0 1 13 3 A 5 5 0 0 1 18 8 A 5 5 0 0 1 13 13 A 5 5 0 0 1 8 8 Z M 0 8 L 8 8 M 18 8 L 24 8 M 4 3 L 4 13" stroke="#404040" fill="transparent"/>',  
218 - 32,  
219 - 20,  
220 -);  
221 -Format.ERzeroToManyMarkerImage = Graph.createSvgImage(  
222 - 20,  
223 - 22,  
224 - '<path transform="translate(4,2)" stroke-width="2" d="M 8 8 A 5 5 0 0 1 13 3 A 5 5 0 0 1 18 8 A 5 5 0 0 1 13 13 A 5 5 0 0 1 8 8 Z M 0 8 L 8 8 M 18 8 L 24 8 M 0 3 L 8 8 L 0 13" stroke="#404040" fill="transparent"/>',  
225 - 32,  
226 - 20,  
227 -);  
228 -Format.EROneMarkerImage = Graph.createSvgImage(  
229 - 20,  
230 - 22,  
231 - '<path transform="translate(4,2)" stroke-width="2" d="M 5 2 L 5 14 M 0 8 L 24 8" stroke="#404040" fill="transparent"/>',  
232 - 32,  
233 - 20,  
234 -);  
235 -Format.baseDashMarkerImage = Graph.createSvgImage(  
236 - 20,  
237 - 22,  
238 - '<path transform="translate(4,2)" stroke-width="2" d="M 0 2 L 0 14 M 0 8 L 24 8" stroke="#404040" fill="transparent"/>',  
239 - 32,  
240 - 20,  
241 -);  
242 -Format.doubleBlockMarkerImage = Graph.createSvgImage(  
243 - 20,  
244 - 22,  
245 - '<path transform="translate(4,2)" stroke-width="2" d="M 0 8 L 8 2 L 8 14 Z M 8 8 L 16 2 L 16 14 Z M 16 8 L 24 8" stroke="#404040" fill="transparent"/>',  
246 - 32,  
247 - 20,  
248 -);  
249 -Format.doubleBlockFilledMarkerImage = Graph.createSvgImage(  
250 - 20,  
251 - 22,  
252 - '<path transform="translate(4,2)" stroke-width="2" d="M 0 8 L 8 2 L 8 14 Z M 8 8 L 16 2 L 16 14 Z M 16 8 L 24 8" stroke="#404040" fill="#404040"/>',  
253 - 32,  
254 - 20,  
255 -);  
256 -  
257 -/**  
258 - * Adds a style change item to the given menu.  
259 - */  
260 -Format.processMenuIcon = function (elt, transform) {  
261 - var imgs = elt.getElementsByTagName("img");  
262 -  
263 - if (imgs.length > 0) {  
264 - if (Editor.isDarkMode()) {  
265 - imgs[0].style.filter = "invert(100%)";  
266 - }  
267 -  
268 - imgs[0].className = "geIcon";  
269 - imgs[0].style.padding = "0px";  
270 - imgs[0].style.margin = "0 0 0 2px";  
271 -  
272 - if (transform != null) {  
273 - mxUtils.setPrefixedStyle(imgs[0].style, "transform", transform);  
274 - }  
275 - }  
276 -  
277 - return elt;  
278 -};  
279 -  
280 -/**  
281 - * Returns information about the current selection.  
282 - */  
283 -Format.prototype.labelIndex = 0;  
284 -  
285 -/**  
286 - * Returns information about the current selection.  
287 - * 默认选中的formatBar的tab栏索引 / 0是第一个  
288 - */  
289 -Format.prototype.diagramIndex = 0;  
290 -  
291 -/**  
292 - * Returns information about the current selection.  
293 - */  
294 -Format.prototype.currentIndex = 0;  
295 -  
296 -/**  
297 - * Returns information about the current selection.  
298 - * 是否显示关闭按钮  
299 - */  
300 -Format.prototype.showCloseButton = false;  
301 -  
302 -/**  
303 - * Adds the label menu items to the given menu and parent.  
304 - */  
305 -Format.prototype.init = function () {  
306 - var ui = this.editorUi;  
307 - var editor = ui.editor;  
308 - var graph = editor.graph;  
309 - this.update = mxUtils.bind(this, function (sender, evt) {  
310 - this.refresh();  
311 - });  
312 -  
313 - graph.getSelectionModel().addListener(mxEvent.CHANGE, this.update);  
314 - graph.getModel().addListener(mxEvent.CHANGE, this.update);  
315 - graph.addListener(mxEvent.EDITING_STARTED, this.update);  
316 - graph.addListener(mxEvent.EDITING_STOPPED, this.update);  
317 - graph.getView().addListener("unitChanged", this.update);  
318 - editor.addListener("autosaveChanged", this.update);  
319 - graph.addListener(mxEvent.ROOT, this.update);  
320 - ui.addListener("styleChanged", this.update);  
321 -  
322 - this.refresh();  
323 -};  
324 -  
325 -/**  
326 - * Adds the label menu items to the given menu and parent.  
327 - */  
328 -Format.prototype.clear = function () {  
329 - this.container.innerHTML = "";  
330 -  
331 - // Destroy existing panels  
332 - if (this.panels != null) {  
333 - for (var i = 0; i < this.panels.length; i++) {  
334 - this.panels[i].destroy();  
335 - }  
336 - }  
337 -  
338 - this.panels = [];  
339 -};  
340 -  
341 -/**  
342 - * Adds the label menu items to the given menu and parent.  
343 - */  
344 -Format.prototype.refresh = function () {  
345 - if (this.pendingRefresh != null) {  
346 - window.clearTimeout(this.pendingRefresh);  
347 - this.pendingRefresh = null;  
348 - }  
349 -  
350 - this.pendingRefresh = window.setTimeout(  
351 - mxUtils.bind(this, function () {  
352 - this.immediateRefresh();  
353 - }),  
354 - );  
355 -};  
356 -  
357 -/**  
358 - * Adds the label menu items to the given menu and parent.  
359 - */  
360 -Format.prototype.immediateRefresh = function () {  
361 - // Performance tweak: No refresh needed if not visible  
362 - if (this.container.style.width == "0px") {  
363 - return;  
364 - }  
365 -  
366 - this.clear();  
367 - var ui = this.editorUi;  
368 - var graph = ui.editor.graph;  
369 -  
370 - var div = document.createElement("div");  
371 - div.style.whiteSpace = "nowrap";  
372 - div.style.color = "rgb(112, 112, 112)";  
373 - div.style.textAlign = "left";  
374 - div.style.cursor = "default";  
375 - // div.style.display = 'flex'  
376 -  
377 - var label = document.createElement("div");  
378 - label.className = "geFormatSection";  
379 - label.style.textAlign = "center";  
380 - label.style.fontWeight = "bold";  
381 - label.style.paddingTop = "8px";  
382 - label.style.fontSize = "13px";  
383 - label.style.borderWidth = "0px 0px 1px 1px";  
384 - label.style.borderStyle = "solid";  
385 - label.style.display = "inline-block";  
386 - label.style.height = "25px";  
387 - label.style.overflow = "hidden";  
388 - label.style.width = "100%";  
389 - label.style.flex = 'auto'  
390 - this.container.appendChild(div);  
391 -  
392 - // Prevents text selection  
393 - mxEvent.addListener(  
394 - label,  
395 - mxClient.IS_POINTER ? "pointerdown" : "mousedown",  
396 - mxUtils.bind(this, function (evt) {  
397 - evt.preventDefault();  
398 - }),  
399 - );  
400 -  
401 - var ss = ui.getSelectionState();  
402 - var containsLabel = ss.containsLabel;  
403 - var currentLabel = null;  
404 - var currentPanel = null;  
405 -  
406 -  
407 - /**  
408 - * @description 验证是否有数据绑定面板  
409 - * @returns {boolean}  
410 - */  
411 - const validateHasDataSourcePanel = () => {  
412 - const ui = this.editorUi;  
413 - const ss = ui.getSelectionState();  
414 - const vertices = ss.vertices || []  
415 - const sidebarInstance = ui.sidebar  
416 - const cell = vertices[0]  
417 - if (!cell) return false  
418 - const basicAttr = sidebarInstance.enumCellBasicAttribute  
419 - const componentType = cell.getAttribute(basicAttr.COMPONENT_TYPE)  
420 - const hasPermission = sidebarInstance.getComponentPermission(componentType)  
421 - return !!hasPermission.length && hasSavePermission()  
422 - }  
423 -  
424 - var addClickHandler = mxUtils.bind(  
425 - this,  
426 - function (elt, panel, index, lastEntry) {  
427 - var clickHandler = mxUtils.bind(this, function (evt) {  
428 - if (currentLabel != elt) {  
429 - if (containsLabel) {  
430 - this.labelIndex = index;  
431 - } else if (graph.isSelectionEmpty()) {  
432 - this.diagramIndex = index;  
433 - } else {  
434 - this.currentIndex = index;  
435 - }  
436 -  
437 - if (currentLabel != null) {  
438 - currentLabel.style.backgroundColor =  
439 - Format.inactiveTabBackgroundColor;  
440 - currentLabel.style.borderBottomWidth = "1px";  
441 - }  
442 -  
443 - currentLabel = elt;  
444 - currentLabel.style.backgroundColor = "";  
445 - currentLabel.style.borderBottomWidth = "0px";  
446 -  
447 - if (currentPanel != panel) {  
448 - if (currentPanel != null) {  
449 - currentPanel.style.display = "none";  
450 - }  
451 -  
452 - currentPanel = panel;  
453 - currentPanel.style.display = "";  
454 - }  
455 - }  
456 -  
457 - if (!validateHasDataSourcePanel()) this.currentIndex = 0  
458 - });  
459 -  
460 - mxEvent.addListener(elt, "click", clickHandler);  
461 -  
462 - // Prevents text selection  
463 - mxEvent.addListener(  
464 - elt,  
465 - mxClient.IS_POINTER ? "pointerdown" : "mousedown",  
466 - mxUtils.bind(this, function (evt) {  
467 - evt.preventDefault();  
468 - }),  
469 - );  
470 -  
471 - if (  
472 - (lastEntry && currentLabel == null) ||  
473 - index ==  
474 - (containsLabel  
475 - ? this.labelIndex  
476 - : graph.isSelectionEmpty()  
477 - ? this.diagramIndex  
478 - : this.currentIndex)  
479 - ) {  
480 - // Invokes handler directly as a workaround for no click on DIV in KHTML.  
481 - clickHandler();  
482 - }  
483 - },  
484 - );  
485 -  
486 - var idx = 0;  
487 -  
488 - if (graph.isSelectionEmpty()) {  
489 - mxUtils.write(label, mxResources.get("diagram"));  
490 - label.style.borderLeftWidth = "0px";  
491 -  
492 - div.appendChild(label);  
493 - var diagramPanel = div.cloneNode(false);  
494 - this.panels.push(new DiagramFormatPanel(this, ui, diagramPanel));  
495 - this.container.appendChild(diagramPanel);  
496 -  
497 - if (Editor.styles != null) {  
498 - diagramPanel.style.display = "none";  
499 - label.style.width = this.showCloseButton ? "106px" : "50%";  
500 - label.style.cursor = "pointer";  
501 - label.style.backgroundColor = Format.inactiveTabBackgroundColor;  
502 -  
503 - var label2 = label.cloneNode(false);  
504 - label2.style.borderLeftWidth = "1px";  
505 - label2.style.borderRightWidth = "1px";  
506 - label2.style.backgroundColor = Format.inactiveTabBackgroundColor;  
507 -  
508 - addClickHandler(label, diagramPanel, idx++);  
509 -  
510 - var stylePanel = div.cloneNode(false);  
511 - stylePanel.style.display = "none";  
512 - mxUtils.write(label2, mxResources.get("style"));  
513 - div.appendChild(label2);  
514 - this.panels.push(new DiagramStylePanel(this, ui, stylePanel));  
515 - this.container.appendChild(stylePanel);  
516 -  
517 - addClickHandler(label2, stylePanel, idx++);  
518 - }  
519 -  
520 - // Adds button to hide the format panel since  
521 - // people don't seem to find the toolbar button  
522 - // and the menu item in the format menu  
523 - if (this.showCloseButton) {  
524 - var label2 = label.cloneNode(false);  
525 - label2.style.borderLeftWidth = "1px";  
526 - label2.style.borderRightWidth = "1px";  
527 - label2.style.borderBottomWidth = "1px";  
528 - label2.style.backgroundColor = Format.inactiveTabBackgroundColor;  
529 - label2.style.position = "absolute";  
530 - label2.style.right = "0px";  
531 - label2.style.top = "0px";  
532 - label2.style.width = "25px";  
533 -  
534 - var img = document.createElement("img");  
535 - img.setAttribute("border", "0");  
536 - img.setAttribute("src", Dialog.prototype.closeImage);  
537 - img.setAttribute("title", mxResources.get("hide"));  
538 - img.style.position = "absolute";  
539 - img.style.display = "block";  
540 - img.style.right = "0px";  
541 - img.style.top = "8px";  
542 - img.style.cursor = "pointer";  
543 - img.style.marginTop = "1px";  
544 - img.style.marginRight = "6px";  
545 - img.style.border = "1px solid transparent";  
546 - img.style.padding = "1px";  
547 - img.style.opacity = 0.5;  
548 - label2.appendChild(img);  
549 -  
550 - mxEvent.addListener(img, "click", function () {  
551 - ui.actions.get("formatPanel").funct();  
552 - });  
553 -  
554 - div.appendChild(label2);  
555 - }  
556 - } else if (graph.isEditing()) {  
557 - mxUtils.write(label, mxResources.get("text"));  
558 - div.appendChild(label);  
559 - this.panels.push(new TextFormatPanel(this, ui, div));  
560 - } else {  
561 - //选中图形,右侧FormatBar添加样式 TODO add other style  
562 - label.style.backgroundColor = Format.inactiveTabBackgroundColor;  
563 - label.style.borderLeftWidth = "1px";  
564 - label.style.cursor = "pointer";  
565 - label.style.width = containsLabel || ss.cells.length == 0 ? "50%" : validateHasDataSourcePanel() ? "25%" : "33.333%";  
566 - var label2 = label.cloneNode(false);  
567 - var label3 = label2.cloneNode(false);  
568 - var label4 = label3.cloneNode(false);  
569 -  
570 - // Workaround for ignored background in IE  
571 - label2.style.backgroundColor = Format.inactiveTabBackgroundColor;  
572 - label3.style.backgroundColor = Format.inactiveTabBackgroundColor;  
573 - label4.style.backgroundColor = Format.inactiveTabBackgroundColor;  
574 -  
575 - // Style  
576 - if (containsLabel) {  
577 - label2.style.borderLeftWidth = "0px";  
578 - } else {  
579 - label.style.borderLeftWidth = "0px";  
580 - mxUtils.write(label, mxResources.get("style"));  
581 - div.appendChild(label);  
582 -  
583 - var stylePanel = div.cloneNode(false);  
584 - stylePanel.style.display = "none";  
585 - this.panels.push(new StyleFormatPanel(this, ui, stylePanel));  
586 - this.container.appendChild(stylePanel);  
587 -  
588 - addClickHandler(label, stylePanel, idx++);  
589 - }  
590 -  
591 - if (validateHasDataSourcePanel()) {  
592 - // bind data  
593 - mxUtils.write(label4, "数据绑定");  
594 - div.appendChild(label4);  
595 -  
596 - var dataPanel = div.cloneNode(false);  
597 - dataPanel.style.display = "none";  
598 - this.panels.push(new DataFormatPanel(this, ui, dataPanel));  
599 - this.container.appendChild(dataPanel);  
600 - }  
601 -  
602 - // Text  
603 - mxUtils.write(label2, mxResources.get("text"));  
604 - div.appendChild(label2);  
605 -  
606 - var textPanel = div.cloneNode(false);  
607 - textPanel.style.display = "none";  
608 - this.panels.push(new TextFormatPanel(this, ui, textPanel));  
609 - this.container.appendChild(textPanel);  
610 -  
611 - // Arrange  
612 - mxUtils.write(label3, mxResources.get("arrange"));  
613 - div.appendChild(label3);  
614 -  
615 - var arrangePanel = div.cloneNode(false);  
616 - arrangePanel.style.display = "none";  
617 - this.panels.push(new ArrangePanel(this, ui, arrangePanel));  
618 - this.container.appendChild(arrangePanel);  
619 -  
620 - if (ss.cells.length > 0) {  
621 - addClickHandler(label2, textPanel, idx++);  
622 - } else {  
623 - label2.style.display = "none";  
624 - }  
625 - addClickHandler(label3, arrangePanel, idx++);  
626 - if (ss.cells.length > 0) {  
627 - addClickHandler(label4, dataPanel, idx++, true);  
628 - } else {  
629 - label4.style.display = "none";  
630 - }  
631 - }  
632 -};  
633 -  
634 -/**  
635 - * Base class for format panels.  
636 - */  
637 -BaseFormatPanel = function (format, editorUi, container) {  
638 - this.format = format;  
639 - this.editorUi = editorUi;  
640 - this.container = container;  
641 - this.listeners = [];  
642 -};  
643 -  
644 -/**  
645 - *  
646 - */  
647 -BaseFormatPanel.prototype.buttonBackgroundColor = "white";  
648 -  
649 -/**  
650 - * Install input handler.  
651 - */  
652 -BaseFormatPanel.prototype.installInputHandler = function (  
653 - input,  
654 - key,  
655 - defaultValue,  
656 - min,  
657 - max,  
658 - unit,  
659 - textEditFallback,  
660 - isFloat,  
661 -) {  
662 - unit = unit != null ? unit : "";  
663 - isFloat = isFloat != null ? isFloat : false;  
664 -  
665 - var ui = this.editorUi;  
666 - var graph = ui.editor.graph;  
667 -  
668 - min = min != null ? min : 1;  
669 - max = max != null ? max : 999;  
670 -  
671 - var selState = null;  
672 - var updating = false;  
673 -  
674 - var update = mxUtils.bind(this, function (evt) {  
675 - var value = isFloat ? parseFloat(input.value) : parseInt(input.value);  
676 -  
677 - // Special case: angle mod 360  
678 - if (!isNaN(value) && key == mxConstants.STYLE_ROTATION) {  
679 - // Workaround for decimal rounding errors in floats is to  
680 - // use integer and round all numbers to two decimal point  
681 - value = mxUtils.mod(Math.round(value * 100), 36000) / 100;  
682 - }  
683 -  
684 - value = Math.min(max, Math.max(min, isNaN(value) ? defaultValue : value));  
685 -  
686 - if (graph.cellEditor.isContentEditing() && textEditFallback) {  
687 - if (!updating) {  
688 - updating = true;  
689 -  
690 - if (selState != null) {  
691 - graph.cellEditor.restoreSelection(selState);  
692 - selState = null;  
693 - }  
694 -  
695 - textEditFallback(value);  
696 - input.value = value + unit;  
697 -  
698 - // Restore focus and selection in input  
699 - updating = false;  
700 - }  
701 - } else if (  
702 - value != mxUtils.getValue(ui.getSelectionState().style, key, defaultValue)  
703 - ) {  
704 - if (graph.isEditing()) {  
705 - graph.stopEditing(true);  
706 - }  
707 - // TODO update data ??  
708 - graph.getModel().beginUpdate();  
709 - try {  
710 - var cells = ui.getSelectionState().cells;  
711 - graph.setCellStyles(key, value, cells);  
712 -  
713 - // Handles special case for fontSize where HTML labels are parsed and updated  
714 - if (key == mxConstants.STYLE_FONTSIZE) {  
715 - graph.updateLabelElements(cells, function (elt) {  
716 - elt.style.fontSize = value + "px";  
717 - elt.removeAttribute("size");  
718 - });  
719 - }  
720 -  
721 - for (var i = 0; i < cells.length; i++) {  
722 - if (graph.model.getChildCount(cells[i]) == 0) {  
723 - graph.autoSizeCell(cells[i], false);  
724 - }  
725 - }  
726 -  
727 - ui.fireEvent(  
728 - new mxEventObject(  
729 - "styleChanged",  
730 - "keys",  
731 - [key],  
732 - "values",  
733 - [value],  
734 - "cells",  
735 - cells,  
736 - ),  
737 - );  
738 - } finally {  
739 - graph.getModel().endUpdate();  
740 - }  
741 - }  
742 -  
743 - input.value = value + unit;  
744 - mxEvent.consume(evt);  
745 - });  
746 -  
747 - if (textEditFallback && graph.cellEditor.isContentEditing()) {  
748 - // KNOWN: Arrow up/down clear selection text in quirks/IE 8  
749 - // Text size via arrow button limits to 16 in IE11. Why?  
750 - mxEvent.addListener(input, "mousedown", function () {  
751 - if (document.activeElement == graph.cellEditor.textarea) {  
752 - selState = graph.cellEditor.saveSelection();  
753 - }  
754 - });  
755 -  
756 - mxEvent.addListener(input, "touchstart", function () {  
757 - if (document.activeElement == graph.cellEditor.textarea) {  
758 - selState = graph.cellEditor.saveSelection();  
759 - }  
760 - });  
761 - }  
762 -  
763 - mxEvent.addListener(input, "change", update);  
764 - mxEvent.addListener(input, "blur", update);  
765 -  
766 - return update;  
767 -};  
768 -  
769 -/**  
770 - * Adds the given option.  
771 - */  
772 -BaseFormatPanel.prototype.createPanel = function () {  
773 - var div = document.createElement("div");  
774 - div.className = "geFormatSection";  
775 - div.style.padding = "12px 0px 12px 14px";  
776 -  
777 - return div;  
778 -};  
779 -  
780 -/**  
781 - * Adds the given option.  
782 - */  
783 -BaseFormatPanel.prototype.createTitle = function (title) {  
784 - var div = document.createElement("div");  
785 - div.style.padding = "0px 0px 6px 0px";  
786 - div.style.whiteSpace = "nowrap";  
787 - div.style.overflow = "hidden";  
788 - div.style.width = "200px";  
789 - div.style.fontWeight = "bold";  
790 - mxUtils.write(div, title);  
791 -  
792 - return div;  
793 -};  
794 -  
795 -/**  
796 - *  
797 - */  
798 -BaseFormatPanel.prototype.addAction = function (div, name) {  
799 - var action = this.editorUi.actions.get(name);  
800 - var btn = null;  
801 -  
802 - if (action != null && action.isEnabled()) {  
803 - btn = mxUtils.button(action.label, function (evt) {  
804 - action.funct(evt, evt);  
805 - });  
806 -  
807 - var short = action.shortcut != null ? " (" + action.shortcut + ")" : "";  
808 - btn.setAttribute("title", action.label + short);  
809 - btn.style.marginBottom = "2px";  
810 - btn.style.width = "210px";  
811 - div.appendChild(btn);  
812 - result = true;  
813 - }  
814 -  
815 - return btn;  
816 -};  
817 -  
818 -/**  
819 - *  
820 - */  
821 -BaseFormatPanel.prototype.addActions = function (div, names) {  
822 - var lastBr = null;  
823 - var last = null;  
824 - var count = 0;  
825 -  
826 - for (var i = 0; i < names.length; i++) {  
827 - var btn = this.addAction(div, names[i]);  
828 -  
829 - if (btn != null) {  
830 - count++;  
831 -  
832 - if (mxUtils.mod(count, 2) == 0) {  
833 - last.style.marginRight = "2px";  
834 - last.style.width = "104px";  
835 - btn.style.width = "104px";  
836 - lastBr.parentNode.removeChild(lastBr);  
837 - }  
838 -  
839 - lastBr = mxUtils.br(div);  
840 - last = btn;  
841 - }  
842 - }  
843 -  
844 - return count;  
845 -};  
846 -  
847 -/**  
848 - *  
849 - */  
850 -BaseFormatPanel.prototype.createStepper = function (  
851 - input,  
852 - update,  
853 - step,  
854 - height,  
855 - disableFocus,  
856 - defaultValue,  
857 - isFloat,  
858 -) {  
859 - step = step != null ? step : 1;  
860 - height = height != null ? height : 9;  
861 - var bigStep = 10 * step;  
862 -  
863 - var stepper = document.createElement("div");  
864 - mxUtils.setPrefixedStyle(stepper.style, "borderRadius", "3px");  
865 - stepper.style.border = "1px solid rgb(192, 192, 192)";  
866 - stepper.style.position = "absolute";  
867 -  
868 - var up = document.createElement("div");  
869 - up.style.borderBottom = "1px solid rgb(192, 192, 192)";  
870 - up.style.position = "relative";  
871 - up.style.height = height + "px";  
872 - up.style.width = "10px";  
873 - up.className = "geBtnUp";  
874 - stepper.appendChild(up);  
875 -  
876 - var down = up.cloneNode(false);  
877 - down.style.border = "none";  
878 - down.style.height = height + "px";  
879 - down.className = "geBtnDown";  
880 - stepper.appendChild(down);  
881 -  
882 - mxEvent.addGestureListeners(  
883 - down,  
884 - function (evt) {  
885 - // Stops text selection on shift+click  
886 - mxEvent.consume(evt);  
887 - },  
888 - null,  
889 - function (evt) {  
890 - if (input.value == "") {  
891 - input.value = defaultValue || "2";  
892 - }  
893 -  
894 - var val = isFloat ? parseFloat(input.value) : parseInt(input.value);  
895 -  
896 - if (!isNaN(val)) {  
897 - input.value = val - (mxEvent.isShiftDown(evt) ? bigStep : step);  
898 -  
899 - if (update != null) {  
900 - update(evt);  
901 - }  
902 - }  
903 -  
904 - mxEvent.consume(evt);  
905 - },  
906 - );  
907 -  
908 - mxEvent.addGestureListeners(  
909 - up,  
910 - function (evt) {  
911 - // Stops text selection on shift+click  
912 - mxEvent.consume(evt);  
913 - },  
914 - null,  
915 - function (evt) {  
916 - if (input.value == "") {  
917 - input.value = defaultValue || "0";  
918 - }  
919 -  
920 - var val = isFloat ? parseFloat(input.value) : parseInt(input.value);  
921 -  
922 - if (!isNaN(val)) {  
923 - input.value = val + (mxEvent.isShiftDown(evt) ? bigStep : step);  
924 -  
925 - if (update != null) {  
926 - update(evt);  
927 - }  
928 - }  
929 -  
930 - mxEvent.consume(evt);  
931 - },  
932 - );  
933 -  
934 - // Disables transfer of focus to DIV but also :active CSS  
935 - // so it's only used for fontSize where the focus should  
936 - // stay on the selected text, but not for any other input.  
937 - if (disableFocus) {  
938 - var currentSelection = null;  
939 -  
940 - mxEvent.addGestureListeners(  
941 - stepper,  
942 - function (evt) {  
943 - mxEvent.consume(evt);  
944 - },  
945 - null,  
946 - function (evt) {  
947 - // Workaround for lost current selection in page because of focus in IE  
948 - if (currentSelection != null) {  
949 - try {  
950 - currentSelection.select();  
951 - } catch (e) {  
952 - // ignore  
953 - }  
954 -  
955 - currentSelection = null;  
956 - mxEvent.consume(evt);  
957 - }  
958 - },  
959 - );  
960 - } else {  
961 - // Stops propagation on checkbox labels  
962 - mxEvent.addListener(stepper, "click", function (evt) {  
963 - mxEvent.consume(evt);  
964 - });  
965 - }  
966 -  
967 - return stepper;  
968 -};  
969 -  
970 -/**  
971 - * Adds the given option.  
972 - */  
973 -BaseFormatPanel.prototype.createOption = function (  
974 - label,  
975 - isCheckedFn,  
976 - setCheckedFn,  
977 - listener,  
978 - fn,  
979 -) {  
980 - var div = document.createElement("div");  
981 - div.style.padding = "3px 0px 3px 0px";  
982 - div.style.whiteSpace = "nowrap";  
983 - div.style.textOverflow = "ellipsis";  
984 - div.style.overflow = "hidden";  
985 - div.style.width = "200px";  
986 - div.style.height = "18px";  
987 -  
988 - var cb = document.createElement("input");  
989 - cb.setAttribute("type", "checkbox");  
990 - cb.style.margin = "1px 6px 0px 0px";  
991 - cb.style.verticalAlign = "top";  
992 - div.appendChild(cb);  
993 -  
994 - var span = document.createElement("span");  
995 - span.style.verticalAlign = "top";  
996 - span.style.userSelect = "none";  
997 - mxUtils.write(span, label);  
998 - div.appendChild(span);  
999 -  
1000 - var applying = false;  
1001 - var value = isCheckedFn();  
1002 -  
1003 - var apply = function (newValue, evt) {  
1004 - if (!applying) {  
1005 - applying = true;  
1006 -  
1007 - if (newValue) {  
1008 - cb.setAttribute("checked", "checked");  
1009 - cb.defaultChecked = true;  
1010 - cb.checked = true;  
1011 - } else {  
1012 - cb.removeAttribute("checked");  
1013 - cb.defaultChecked = false;  
1014 - cb.checked = false;  
1015 - }  
1016 -  
1017 - if (value != newValue) {  
1018 - value = newValue;  
1019 -  
1020 - // Checks if the color value needs to be updated in the model  
1021 - if (isCheckedFn() != value) {  
1022 - setCheckedFn(value, evt);  
1023 - }  
1024 - }  
1025 -  
1026 - applying = false;  
1027 - }  
1028 - };  
1029 -  
1030 - mxEvent.addListener(div, "click", function (evt) {  
1031 - if (cb.getAttribute("disabled") != "disabled") {  
1032 - // Toggles checkbox state for click on label  
1033 - var source = mxEvent.getSource(evt);  
1034 -  
1035 - if (source == div || source == span) {  
1036 - cb.checked = !cb.checked;  
1037 - }  
1038 -  
1039 - apply(cb.checked, evt);  
1040 - }  
1041 - });  
1042 -  
1043 - apply(value);  
1044 -  
1045 - if (listener != null) {  
1046 - listener.install(apply);  
1047 - this.listeners.push(listener);  
1048 - }  
1049 -  
1050 - if (fn != null) {  
1051 - fn(div);  
1052 - }  
1053 -  
1054 - return div;  
1055 -};  
1056 -  
1057 -/**  
1058 - * The string 'null' means use null in values.  
1059 - */  
1060 -BaseFormatPanel.prototype.createCellOption = function (  
1061 - label,  
1062 - key,  
1063 - defaultValue,  
1064 - enabledValue,  
1065 - disabledValue,  
1066 - fn,  
1067 - action,  
1068 - stopEditing,  
1069 - cells,  
1070 -) {  
1071 - var ui = this.editorUi;  
1072 - var editor = ui.editor;  
1073 - var graph = editor.graph;  
1074 -  
1075 - enabledValue =  
1076 - enabledValue != null ? (enabledValue == "null" ? null : enabledValue) : 1;  
1077 - disabledValue =  
1078 - disabledValue != null  
1079 - ? disabledValue == "null"  
1080 - ? null  
1081 - : disabledValue  
1082 - : 0;  
1083 -  
1084 - var style =  
1085 - cells != null ? graph.getCommonStyle(cells) : ui.getSelectionState().style;  
1086 -  
1087 - return this.createOption(  
1088 - label,  
1089 - function () {  
1090 - return mxUtils.getValue(style, key, defaultValue) != disabledValue;  
1091 - },  
1092 - function (checked) {  
1093 - if (stopEditing) {  
1094 - graph.stopEditing();  
1095 - }  
1096 -  
1097 - if (action != null) {  
1098 - action.funct();  
1099 - } else {  
1100 - graph.getModel().beginUpdate();  
1101 - try {  
1102 - var temp = cells != null ? cells : ui.getSelectionState().cells;  
1103 - var value = checked ? enabledValue : disabledValue;  
1104 - graph.setCellStyles(key, value, temp);  
1105 -  
1106 - if (fn != null) {  
1107 - fn(temp, value);  
1108 - }  
1109 -  
1110 - ui.fireEvent(  
1111 - new mxEventObject(  
1112 - "styleChanged",  
1113 - "keys",  
1114 - [key],  
1115 - "values",  
1116 - [value],  
1117 - "cells",  
1118 - temp,  
1119 - ),  
1120 - );  
1121 - } finally {  
1122 - graph.getModel().endUpdate();  
1123 - }  
1124 - }  
1125 - },  
1126 - {  
1127 - install: function (apply) {  
1128 - this.listener = function () {  
1129 - apply(mxUtils.getValue(style, key, defaultValue) != disabledValue);  
1130 - };  
1131 -  
1132 - graph.getModel().addListener(mxEvent.CHANGE, this.listener);  
1133 - },  
1134 - destroy: function () {  
1135 - graph.getModel().removeListener(this.listener);  
1136 - },  
1137 - },  
1138 - );  
1139 -};  
1140 -  
1141 -/**  
1142 - * Adds the given color option.  
1143 - */  
1144 -BaseFormatPanel.prototype.createColorOption = function (  
1145 - label,  
1146 - getColorFn,  
1147 - setColorFn,  
1148 - defaultColor,  
1149 - listener,  
1150 - callbackFn,  
1151 - hideCheckbox,  
1152 - defaultColorValue,  
1153 -) {  
1154 - var div = document.createElement("div");  
1155 - div.style.padding = "3px 0px 3px 0px";  
1156 - div.style.whiteSpace = "nowrap";  
1157 - div.style.overflow = "hidden";  
1158 - div.style.width = "200px";  
1159 - div.style.height = "18px";  
1160 -  
1161 - var cb = document.createElement("input");  
1162 - cb.setAttribute("type", "checkbox");  
1163 - cb.style.margin = "1px 6px 0px 0px";  
1164 - cb.style.verticalAlign = "top";  
1165 -  
1166 - if (!hideCheckbox) {  
1167 - div.appendChild(cb);  
1168 - }  
1169 -  
1170 - var span = document.createElement("span");  
1171 - span.style.verticalAlign = "top";  
1172 - mxUtils.write(span, label);  
1173 - div.appendChild(span);  
1174 -  
1175 - var title = "Shift+Click for Color Dropper";  
1176 - var value = getColorFn();  
1177 - var applying = false;  
1178 - var btn = null;  
1179 -  
1180 - var apply = function (color, disableUpdate, forceUpdate) {  
1181 - if (!applying) {  
1182 - var defaultValue = defaultColor == "null" ? null : defaultColor;  
1183 -  
1184 - applying = true;  
1185 - color = /(^#?[a-zA-Z0-9]*$)/.test(color) ? color : defaultValue;  
1186 - var tempColor =  
1187 - color != null && color != mxConstants.NONE ? color : defaultValue;  
1188 -  
1189 - var div = document.createElement("div");  
1190 - div.style.width = "36px";  
1191 - div.style.height = "12px";  
1192 - div.style.margin = "3px";  
1193 - div.style.border = "1px solid black";  
1194 - div.style.backgroundColor =  
1195 - tempColor == "default" ? defaultColorValue : tempColor;  
1196 - btn.innerHTML = "";  
1197 - btn.appendChild(div);  
1198 -  
1199 - if (  
1200 - color != null &&  
1201 - color != mxConstants.NONE &&  
1202 - color.length > 1 &&  
1203 - typeof color === "string"  
1204 - ) {  
1205 - var clr =  
1206 - color.charAt(0) == "#" ? color.substring(1).toUpperCase() : color;  
1207 - var name = ColorDialog.prototype.colorNames[clr];  
1208 - btn.setAttribute(  
1209 - "title",  
1210 - name != null ? name + " (" + title + ")" : title,  
1211 - );  
1212 - }  
1213 -  
1214 - if (color != null && color != mxConstants.NONE) {  
1215 - cb.setAttribute("checked", "checked");  
1216 - cb.defaultChecked = true;  
1217 - cb.checked = true;  
1218 - } else {  
1219 - cb.removeAttribute("checked");  
1220 - cb.defaultChecked = false;  
1221 - cb.checked = false;  
1222 - }  
1223 -  
1224 - btn.style.display = cb.checked || hideCheckbox ? "" : "none";  
1225 -  
1226 - if (callbackFn != null) {  
1227 - callbackFn(color == "null" ? null : color);  
1228 - }  
1229 -  
1230 - value = color;  
1231 -  
1232 - if (!disableUpdate) {  
1233 - // Checks if the color value needs to be updated in the model  
1234 - if (forceUpdate || hideCheckbox || getColorFn() != value) {  
1235 - setColorFn(value == "null" ? null : value, value);  
1236 - }  
1237 - }  
1238 -  
1239 - applying = false;  
1240 - }  
1241 - };  
1242 -  
1243 - var clrInput = document.createElement("input");  
1244 - clrInput.setAttribute("type", "color");  
1245 - clrInput.style.visibility = "hidden";  
1246 - clrInput.style.width = "0px";  
1247 - clrInput.style.height = "0px";  
1248 - clrInput.style.border = "none";  
1249 - div.appendChild(clrInput);  
1250 -  
1251 - btn = mxUtils.button(  
1252 - "",  
1253 - mxUtils.bind(this, function (evt) {  
1254 - var color = value;  
1255 -  
1256 - if (color == "default") {  
1257 - color = defaultColorValue;  
1258 - }  
1259 -  
1260 - if (mxEvent.isShiftDown(evt) && !mxClient.IS_IE && !mxClient.IS_IE11) {  
1261 - clrInput.value = color;  
1262 - clrInput.click();  
1263 -  
1264 - mxEvent.addListener(clrInput, "input", function () {  
1265 - apply(clrInput.value, null, true);  
1266 - });  
1267 - } else {  
1268 - this.editorUi.pickColor(  
1269 - color,  
1270 - function (newColor) {  
1271 - apply(newColor, null, true);  
1272 - },  
1273 - defaultColorValue,  
1274 - );  
1275 - }  
1276 -  
1277 - mxEvent.consume(evt);  
1278 - }),  
1279 - );  
1280 -  
1281 - btn.style.position = "absolute";  
1282 - btn.style.marginTop = "-3px";  
1283 - btn.style.left = "178px";  
1284 - btn.style.height = "22px";  
1285 - btn.className = "geColorBtn";  
1286 - btn.style.display = cb.checked || hideCheckbox ? "" : "none";  
1287 - div.appendChild(btn);  
1288 -  
1289 - var clr =  
1290 - value != null && typeof value === "string" && value.charAt(0) == "#"  
1291 - ? value.substring(1).toUpperCase()  
1292 - : value;  
1293 - var name = ColorDialog.prototype.colorNames[clr];  
1294 - btn.setAttribute("title", name != null ? name + " (" + title + ")" : title);  
1295 -  
1296 - mxEvent.addListener(div, "click", function (evt) {  
1297 - var source = mxEvent.getSource(evt);  
1298 -  
1299 - if (source == cb || source.nodeName != "INPUT") {  
1300 - // Toggles checkbox state for click on label  
1301 - if (source != cb) {  
1302 - cb.checked = !cb.checked;  
1303 - }  
1304 -  
1305 - // Overrides default value with current value to make it easier  
1306 - // to restore previous value if the checkbox is clicked twice  
1307 - if (  
1308 - !cb.checked &&  
1309 - value != null &&  
1310 - value != mxConstants.NONE &&  
1311 - defaultColor != mxConstants.NONE  
1312 - ) {  
1313 - defaultColor = value;  
1314 - }  
1315 -  
1316 - apply(cb.checked ? defaultColor : mxConstants.NONE);  
1317 - }  
1318 - });  
1319 -  
1320 - apply(value, true);  
1321 -  
1322 - if (listener != null) {  
1323 - listener.install(apply);  
1324 - this.listeners.push(listener);  
1325 - }  
1326 -  
1327 - return div;  
1328 -};  
1329 -  
1330 -/**  
1331 - *  
1332 - */  
1333 -BaseFormatPanel.prototype.createCellColorOption = function (  
1334 - label,  
1335 - colorKey,  
1336 - defaultColor,  
1337 - callbackFn,  
1338 - setStyleFn,  
1339 - defaultColorValue,  
1340 -) {  
1341 - var ui = this.editorUi;  
1342 - var editor = ui.editor;  
1343 - var graph = editor.graph;  
1344 -  
1345 - return this.createColorOption(  
1346 - label,  
1347 - function () {  
1348 - // Seems to be null sometimes, not sure why...  
1349 - var state = graph.view.getState(ui.getSelectionState().cells[0]);  
1350 -  
1351 - if (state != null) {  
1352 - return mxUtils.getValue(state.style, colorKey, null);  
1353 - }  
1354 -  
1355 - return null;  
1356 - },  
1357 - function (color, realValue) {  
1358 - graph.getModel().beginUpdate();  
1359 - try {  
1360 - var cells = ui.getSelectionState().cells;  
1361 - graph.setCellStyles(colorKey, color, cells);  
1362 -  
1363 - if (setStyleFn != null) {  
1364 - setStyleFn(color);  
1365 - }  
1366 -  
1367 - ui.fireEvent(  
1368 - new mxEventObject(  
1369 - "styleChanged",  
1370 - "keys",  
1371 - [colorKey],  
1372 - "values",  
1373 - [color],  
1374 - "cells",  
1375 - cells,  
1376 - ),  
1377 - );  
1378 - } finally {  
1379 - graph.getModel().endUpdate();  
1380 - }  
1381 - },  
1382 - defaultColor || mxConstants.NONE,  
1383 - {  
1384 - install: function (apply) {  
1385 - this.listener = function () {  
1386 - // Seems to be null sometimes, not sure why...  
1387 - var state = graph.view.getState(ui.getSelectionState().cells[0]);  
1388 -  
1389 - if (state != null) {  
1390 - apply(mxUtils.getValue(state.style, colorKey, null), true);  
1391 - }  
1392 - };  
1393 -  
1394 - graph.getModel().addListener(mxEvent.CHANGE, this.listener);  
1395 - },  
1396 - destroy: function () {  
1397 - graph.getModel().removeListener(this.listener);  
1398 - },  
1399 - },  
1400 - callbackFn,  
1401 - null,  
1402 - defaultColorValue,  
1403 - );  
1404 -};  
1405 -  
1406 -/**  
1407 - *  
1408 - */  
1409 -BaseFormatPanel.prototype.addArrow = function (elt, height) {  
1410 - height = height != null ? height : 10;  
1411 -  
1412 - var arrow = document.createElement("div");  
1413 - arrow.style.display = "inline-block";  
1414 - arrow.style.paddingRight = "4px";  
1415 - arrow.style.padding = "6px";  
1416 -  
1417 - var m = 10 - height;  
1418 -  
1419 - if (m == 2) {  
1420 - arrow.style.paddingTop = 6 + "px";  
1421 - } else if (m > 0) {  
1422 - arrow.style.paddingTop = 6 - m + "px";  
1423 - } else {  
1424 - arrow.style.marginTop = "-2px";  
1425 - }  
1426 -  
1427 - arrow.style.height = height + "px";  
1428 - arrow.style.borderLeft = "1px solid #a0a0a0";  
1429 -  
1430 - var img = document.createElement("img");  
1431 - img.setAttribute("border", "0");  
1432 - img.setAttribute("valign", "middle");  
1433 - img.setAttribute("src", Toolbar.prototype.dropDownImage);  
1434 - arrow.appendChild(img);  
1435 -  
1436 - var img = arrow.getElementsByTagName("img")[0];  
1437 - img.style.position = "relative";  
1438 - img.style.left = "1px";  
1439 - img.style.top = mxClient.IS_FF ? "0px" : "-4px";  
1440 - mxUtils.setOpacity(arrow, 70);  
1441 -  
1442 - var symbol = elt.getElementsByTagName("div")[0];  
1443 -  
1444 - if (symbol != null) {  
1445 - symbol.style.paddingRight = "6px";  
1446 - symbol.style.marginLeft = "4px";  
1447 - symbol.style.marginTop = "-1px";  
1448 - symbol.style.display = "inline-block";  
1449 - mxUtils.setOpacity(symbol, 60);  
1450 - }  
1451 -  
1452 - mxUtils.setOpacity(elt, 100);  
1453 - elt.style.border = "1px solid #a0a0a0";  
1454 - elt.style.backgroundColor = this.buttonBackgroundColor;  
1455 - elt.style.backgroundImage = "none";  
1456 - elt.style.width = "auto";  
1457 - elt.className += " geColorBtn";  
1458 - mxUtils.setPrefixedStyle(elt.style, "borderRadius", "3px");  
1459 -  
1460 - elt.appendChild(arrow);  
1461 -  
1462 - return symbol;  
1463 -};  
1464 -  
1465 -/**  
1466 - *  
1467 - */  
1468 -BaseFormatPanel.prototype.addUnitInput = function (  
1469 - container,  
1470 - unit,  
1471 - right,  
1472 - width,  
1473 - update,  
1474 - step,  
1475 - marginTop,  
1476 - disableFocus,  
1477 - isFloat,  
1478 -) {  
1479 - marginTop = marginTop != null ? marginTop : 0;  
1480 -  
1481 - var input = document.createElement("input");  
1482 - input.style.position = "absolute";  
1483 - input.style.textAlign = "right";  
1484 - input.style.marginTop = "-2px";  
1485 - input.style.left = 228 - right - width + "px";  
1486 - input.style.width = width + "px";  
1487 - input.style.height = "21px";  
1488 - input.style.border = "1px solid rgb(160, 160, 160)";  
1489 - input.style.borderRadius = "4px";  
1490 - input.style.boxSizing = "border-box";  
1491 -  
1492 - container.appendChild(input);  
1493 -  
1494 - var stepper = this.createStepper(  
1495 - input,  
1496 - update,  
1497 - step,  
1498 - null,  
1499 - disableFocus,  
1500 - null,  
1501 - isFloat,  
1502 - );  
1503 - stepper.style.marginTop = marginTop - 2 + "px";  
1504 - stepper.style.left = 228 - right + "px";  
1505 - container.appendChild(stepper);  
1506 -  
1507 - return input;  
1508 -};  
1509 -  
1510 -/**  
1511 - *  
1512 - */  
1513 -BaseFormatPanel.prototype.createRelativeOption = function (  
1514 - label,  
1515 - key,  
1516 - width,  
1517 - handler,  
1518 - init,  
1519 -) {  
1520 - width = width != null ? width : 52;  
1521 -  
1522 - var ui = this.editorUi;  
1523 - var graph = ui.editor.graph;  
1524 - var div = this.createPanel();  
1525 - div.style.paddingTop = "10px";  
1526 - div.style.paddingBottom = "10px";  
1527 - mxUtils.write(div, label);  
1528 - div.style.fontWeight = "bold";  
1529 -  
1530 - var update = mxUtils.bind(this, function (evt) {  
1531 - if (handler != null) {  
1532 - handler(input);  
1533 - } else {  
1534 - var value = parseInt(input.value);  
1535 - value = Math.min(100, Math.max(0, isNaN(value) ? 100 : value));  
1536 - var state = graph.view.getState(ui.getSelectionState().cells[0]);  
1537 -  
1538 - if (state != null && value != mxUtils.getValue(state.style, key, 100)) {  
1539 - // Removes entry in style (assumes 100 is default for relative values)  
1540 - if (value == 100) {  
1541 - value = null;  
1542 - }  
1543 -  
1544 - var cells = ui.getSelectionState().cells;  
1545 - graph.setCellStyles(key, value, cells);  
1546 - this.editorUi.fireEvent(  
1547 - new mxEventObject(  
1548 - "styleChanged",  
1549 - "keys",  
1550 - [key],  
1551 - "values",  
1552 - [value],  
1553 - "cells",  
1554 - cells,  
1555 - ),  
1556 - );  
1557 - }  
1558 -  
1559 - input.value = (value != null ? value : "100") + " %";  
1560 - }  
1561 -  
1562 - mxEvent.consume(evt);  
1563 - });  
1564 -  
1565 - var input = this.addUnitInput(  
1566 - div,  
1567 - "%",  
1568 - 16,  
1569 - width,  
1570 - update,  
1571 - 10,  
1572 - -15,  
1573 - handler != null,  
1574 - );  
1575 -  
1576 - if (key != null) {  
1577 - var listener = mxUtils.bind(this, function (sender, evt, force) {  
1578 - if (force || input != document.activeElement) {  
1579 - var ss = ui.getSelectionState();  
1580 - var tmp = parseInt(mxUtils.getValue(ss.style, key, 100));  
1581 - input.value = isNaN(tmp) ? "" : tmp + " %";  
1582 - }  
1583 - });  
1584 -  
1585 - mxEvent.addListener(input, "keydown", function (e) {  
1586 - if (e.keyCode == 13) {  
1587 - graph.container.focus();  
1588 - mxEvent.consume(e);  
1589 - } else if (e.keyCode == 27) {  
1590 - listener(null, null, true);  
1591 - graph.container.focus();  
1592 - mxEvent.consume(e);  
1593 - }  
1594 - });  
1595 -  
1596 - graph.getModel().addListener(mxEvent.CHANGE, listener);  
1597 - this.listeners.push({  
1598 - destroy: function () {  
1599 - graph.getModel().removeListener(listener);  
1600 - },  
1601 - });  
1602 - listener();  
1603 - }  
1604 -  
1605 - mxEvent.addListener(input, "blur", update);  
1606 - mxEvent.addListener(input, "change", update);  
1607 -  
1608 - if (init != null) {  
1609 - init(input);  
1610 - }  
1611 -  
1612 - return div;  
1613 -};  
1614 -  
1615 -/**  
1616 - *  
1617 - */  
1618 -BaseFormatPanel.prototype.addLabel = function (div, title, right, width) {  
1619 - width = width != null ? width : 61;  
1620 -  
1621 - var label = document.createElement("div");  
1622 - mxUtils.write(label, title);  
1623 - label.style.position = "absolute";  
1624 - label.style.left = 240 - right - width + "px";  
1625 - label.style.width = width + "px";  
1626 - label.style.marginTop = "6px";  
1627 - label.style.textAlign = "center";  
1628 - div.appendChild(label);  
1629 -};  
1630 -  
1631 -/**  
1632 - *  
1633 - */  
1634 -BaseFormatPanel.prototype.addKeyHandler = function (input, listener) {  
1635 - mxEvent.addListener(  
1636 - input,  
1637 - "keydown",  
1638 - mxUtils.bind(this, function (e) {  
1639 - if (e.keyCode == 13) {  
1640 - this.editorUi.editor.graph.container.focus();  
1641 - mxEvent.consume(e);  
1642 - } else if (e.keyCode == 27) {  
1643 - if (listener != null) {  
1644 - listener(null, null, true);  
1645 - }  
1646 -  
1647 - this.editorUi.editor.graph.container.focus();  
1648 - mxEvent.consume(e);  
1649 - }  
1650 - }),  
1651 - );  
1652 -};  
1653 -  
1654 -/**  
1655 - *  
1656 - */  
1657 -BaseFormatPanel.prototype.styleButtons = function (elts) {  
1658 - for (var i = 0; i < elts.length; i++) {  
1659 - mxUtils.setPrefixedStyle(elts[i].style, "borderRadius", "3px");  
1660 - mxUtils.setOpacity(elts[i], 100);  
1661 - elts[i].style.border = "1px solid #a0a0a0";  
1662 - elts[i].style.padding = "4px";  
1663 - elts[i].style.paddingTop = "3px";  
1664 - elts[i].style.paddingRight = "1px";  
1665 - elts[i].style.margin = "1px";  
1666 - elts[i].style.marginRight = "2px";  
1667 - elts[i].style.width = "24px";  
1668 - elts[i].style.height = "20px";  
1669 - elts[i].className += " geColorBtn";  
1670 - }  
1671 -};  
1672 -  
1673 -/**  
1674 - * Adds the label menu items to the given menu and parent.  
1675 - */  
1676 -BaseFormatPanel.prototype.destroy = function () {  
1677 - if (this.listeners != null) {  
1678 - for (var i = 0; i < this.listeners.length; i++) {  
1679 - this.listeners[i].destroy();  
1680 - }  
1681 -  
1682 - this.listeners = null;  
1683 - }  
1684 -};  
1685 -  
1686 -/**  
1687 - * Adds the label menu items to the given menu and parent.  
1688 - */  
1689 -ArrangePanel = function (format, editorUi, container) {  
1690 - BaseFormatPanel.call(this, format, editorUi, container);  
1691 - this.init();  
1692 -};  
1693 -  
1694 -mxUtils.extend(ArrangePanel, BaseFormatPanel);  
1695 -  
1696 -/**  
1697 - * Adds the label menu items to the given menu and parent.  
1698 - */  
1699 -ArrangePanel.prototype.init = function () {  
1700 - var ss = this.editorUi.getSelectionState();  
1701 -  
1702 - if (ss.cells.length > 0) {  
1703 - this.container.appendChild(this.addLayerOps(this.createPanel()));  
1704 -  
1705 - // Special case that adds two panels  
1706 - this.addGeometry(this.container);  
1707 - this.addEdgeGeometry(this.container);  
1708 -  
1709 - if (!ss.containsLabel || ss.edges.length == 0) {  
1710 - this.container.appendChild(this.addAngle(this.createPanel()));  
1711 - }  
1712 -  
1713 - if (!ss.containsLabel) {  
1714 - this.container.appendChild(this.addFlip(this.createPanel()));  
1715 - }  
1716 -  
1717 - this.container.appendChild(this.addAlign(this.createPanel()));  
1718 -  
1719 - if (ss.vertices.length > 1 && !ss.cell && !ss.row) {  
1720 - this.container.appendChild(this.addDistribute(this.createPanel()));  
1721 - }  
1722 -  
1723 - this.container.appendChild(this.addTable(this.createPanel()));  
1724 - this.container.appendChild(this.addGroupOps(this.createPanel()));  
1725 - }  
1726 -  
1727 - if (ss.containsLabel) {  
1728 - // Adds functions from hidden style format panel  
1729 - var span = document.createElement("div");  
1730 - span.style.width = "100%";  
1731 - span.style.marginTop = "0px";  
1732 - span.style.fontWeight = "bold";  
1733 - span.style.padding = "10px 0 0 14px";  
1734 - mxUtils.write(span, mxResources.get("style"));  
1735 - this.container.appendChild(span);  
1736 -  
1737 - new StyleFormatPanel(this.format, this.editorUi, this.container);  
1738 - }  
1739 -};  
1740 -  
1741 -/**  
1742 - *  
1743 - */  
1744 -ArrangePanel.prototype.addTable = function (div) {  
1745 - var ui = this.editorUi;  
1746 - var editor = ui.editor;  
1747 - var graph = editor.graph;  
1748 - var ss = ui.getSelectionState();  
1749 - div.style.paddingTop = "6px";  
1750 - div.style.paddingBottom = "10px";  
1751 -  
1752 - var span = document.createElement("div");  
1753 - span.style.marginTop = "0px";  
1754 - span.style.marginBottom = "6px";  
1755 - span.style.fontWeight = "bold";  
1756 - mxUtils.write(span, mxResources.get("table"));  
1757 - div.appendChild(span);  
1758 -  
1759 - var panel = document.createElement("div");  
1760 - panel.style.position = "relative";  
1761 - panel.style.paddingLeft = "0px";  
1762 - panel.style.borderWidth = "0px";  
1763 - panel.style.width = "220px";  
1764 - panel.className = "geToolbarContainer";  
1765 -  
1766 - var cell = ss.vertices[0];  
1767 -  
1768 - if (graph.getSelectionCount() > 1) {  
1769 - if (graph.isTableCell(cell)) {  
1770 - cell = graph.model.getParent(cell);  
1771 - }  
1772 -  
1773 - if (graph.isTableRow(cell)) {  
1774 - cell = graph.model.getParent(cell);  
1775 - }  
1776 - }  
1777 -  
1778 - var isTable = ss.table || ss.row || ss.cell;  
1779 - var isStack = graph.isStack(cell) || graph.isStackChild(cell);  
1780 -  
1781 - var showCols = isTable;  
1782 - var showRows = isTable;  
1783 -  
1784 - if (isStack) {  
1785 - var style = graph.isStack(cell)  
1786 - ? ss.style  
1787 - : graph.getCellStyle(graph.model.getParent(cell));  
1788 -  
1789 - showRows = style["horizontalStack"] == "0";  
1790 - showCols = !showRows;  
1791 - }  
1792 -  
1793 - var btns = [];  
1794 -  
1795 - if (showCols) {  
1796 - btns = btns.concat([  
1797 - ui.toolbar.addButton(  
1798 - "geSprite-insertcolumnbefore",  
1799 - mxResources.get("insertColumnBefore"),  
1800 - mxUtils.bind(this, function () {  
1801 - try {  
1802 - if (isStack) {  
1803 - graph.insertLane(cell, true);  
1804 - } else {  
1805 - graph.insertTableColumn(cell, true);  
1806 - }  
1807 - } catch (e) {  
1808 - ui.handleError(e);  
1809 - }  
1810 - }),  
1811 - panel,  
1812 - ),  
1813 - ui.toolbar.addButton(  
1814 - "geSprite-insertcolumnafter",  
1815 - mxResources.get("insertColumnAfter"),  
1816 - mxUtils.bind(this, function () {  
1817 - try {  
1818 - if (isStack) {  
1819 - graph.insertLane(cell, false);  
1820 - } else {  
1821 - graph.insertTableColumn(cell, false);  
1822 - }  
1823 - } catch (e) {  
1824 - ui.handleError(e);  
1825 - }  
1826 - }),  
1827 - panel,  
1828 - ),  
1829 - ui.toolbar.addButton(  
1830 - "geSprite-deletecolumn",  
1831 - mxResources.get("deleteColumn"),  
1832 - mxUtils.bind(this, function () {  
1833 - try {  
1834 - if (isStack) {  
1835 - graph.deleteLane(cell);  
1836 - } else {  
1837 - graph.deleteTableColumn(cell);  
1838 - }  
1839 - } catch (e) {  
1840 - ui.handleError(e);  
1841 - }  
1842 - }),  
1843 - panel,  
1844 - ),  
1845 - ]);  
1846 - }  
1847 -  
1848 - if (showRows) {  
1849 - btns = btns.concat([  
1850 - ui.toolbar.addButton(  
1851 - "geSprite-insertrowbefore",  
1852 - mxResources.get("insertRowBefore"),  
1853 - mxUtils.bind(this, function () {  
1854 - try {  
1855 - if (isStack) {  
1856 - graph.insertLane(cell, true);  
1857 - } else {  
1858 - graph.insertTableRow(cell, true);  
1859 - }  
1860 - } catch (e) {  
1861 - ui.handleError(e);  
1862 - }  
1863 - }),  
1864 - panel,  
1865 - ),  
1866 - ui.toolbar.addButton(  
1867 - "geSprite-insertrowafter",  
1868 - mxResources.get("insertRowAfter"),  
1869 - mxUtils.bind(this, function () {  
1870 - try {  
1871 - if (isStack) {  
1872 - graph.insertLane(cell, false);  
1873 - } else {  
1874 - graph.insertTableRow(cell, false);  
1875 - }  
1876 - } catch (e) {  
1877 - ui.handleError(e);  
1878 - }  
1879 - }),  
1880 - panel,  
1881 - ),  
1882 - ui.toolbar.addButton(  
1883 - "geSprite-deleterow",  
1884 - mxResources.get("deleteRow"),  
1885 - mxUtils.bind(this, function () {  
1886 - try {  
1887 - if (isStack) {  
1888 - graph.deleteLane(cell);  
1889 - } else {  
1890 - graph.deleteTableRow(cell);  
1891 - }  
1892 - } catch (e) {  
1893 - ui.handleError(e);  
1894 - }  
1895 - }),  
1896 - panel,  
1897 - ),  
1898 - ]);  
1899 - }  
1900 -  
1901 - if (btns.length > 0) {  
1902 - this.styleButtons(btns);  
1903 - div.appendChild(panel);  
1904 -  
1905 - if (btns.length > 3) {  
1906 - btns[2].style.marginRight = "10px";  
1907 - }  
1908 -  
1909 - var count = 0;  
1910 -  
1911 - if (ss.mergeCell != null) {  
1912 - count += this.addActions(div, ["mergeCells"]);  
1913 - } else if (ss.style["colspan"] > 1 || ss.style["rowspan"] > 1) {  
1914 - count += this.addActions(div, ["unmergeCells"]);  
1915 - }  
1916 -  
1917 - if (count > 0) {  
1918 - panel.style.paddingBottom = "2px";  
1919 - }  
1920 - } else {  
1921 - div.style.display = "none";  
1922 - }  
1923 -  
1924 - return div;  
1925 -};  
1926 -  
1927 -/**  
1928 - *  
1929 - */  
1930 -ArrangePanel.prototype.addLayerOps = function (div) {  
1931 - this.addActions(div, ["toFront", "toBack"]);  
1932 - this.addActions(div, ["bringForward", "sendBackward"]);  
1933 -  
1934 - return div;  
1935 -};  
1936 -  
1937 -/**  
1938 - *  
1939 - */  
1940 -ArrangePanel.prototype.addGroupOps = function (div) {  
1941 - var ui = this.editorUi;  
1942 - var graph = ui.editor.graph;  
1943 - var ss = ui.getSelectionState();  
1944 -  
1945 - div.style.paddingTop = "8px";  
1946 - div.style.paddingBottom = "6px";  
1947 -  
1948 - var count = 0;  
1949 -  
1950 - if (!ss.cell && !ss.row) {  
1951 - count +=  
1952 - this.addActions(div, ["group", "ungroup", "copySize", "pasteSize"]) +  
1953 - this.addActions(div, ["removeFromGroup"]);  
1954 - }  
1955 -  
1956 - var copyBtn = null;  
1957 -  
1958 - if (  
1959 - ss.cells.length == 1 &&  
1960 - ss.cells[0].value != null &&  
1961 - !isNaN(ss.cells[0].value.nodeType)  
1962 - ) {  
1963 - copyBtn = mxUtils.button(mxResources.get("copyData"), function (evt) {  
1964 - if (mxEvent.isShiftDown(evt)) {  
1965 - var result = graph.getDataForCells(graph.getSelectionCells());  
1966 -  
1967 - var dlg = new EmbedDialog(  
1968 - ui,  
1969 - JSON.stringify(result, null, 2),  
1970 - null,  
1971 - null,  
1972 - function () {  
1973 - console.log(result);  
1974 - ui.alert("Written to Console (Dev Tools)");  
1975 - },  
1976 - mxResources.get("copyData"),  
1977 - null,  
1978 - "Console",  
1979 - "data.json",  
1980 - );  
1981 - ui.showDialog(dlg.container, 450, 240, true, true);  
1982 - dlg.init();  
1983 - } else {  
1984 - ui.actions.get("copyData").funct(evt);  
1985 - }  
1986 - });  
1987 -  
1988 - copyBtn.setAttribute(  
1989 - "title",  
1990 - mxResources.get("copyData") +  
1991 - " (" +  
1992 - this.editorUi.actions.get("copyData").shortcut +  
1993 - ")" +  
1994 - " Shift+Click to Extract Data",  
1995 - );  
1996 - copyBtn.style.marginBottom = "2px";  
1997 - copyBtn.style.width = "210px";  
1998 - div.appendChild(copyBtn);  
1999 - count++;  
2000 - }  
2001 -  
2002 - var pasteBtn = null;  
2003 -  
2004 - if (ui.copiedValue != null && ss.cells.length > 0) {  
2005 - pasteBtn = mxUtils.button(mxResources.get("pasteData"), function (evt) {  
2006 - ui.actions.get("pasteData").funct(evt);  
2007 - });  
2008 -  
2009 - pasteBtn.setAttribute(  
2010 - "title",  
2011 - mxResources.get("pasteData") +  
2012 - " (" +  
2013 - this.editorUi.actions.get("pasteData").shortcut +  
2014 - ")",  
2015 - );  
2016 - pasteBtn.style.marginBottom = "2px";  
2017 - pasteBtn.style.width = "210px";  
2018 - div.appendChild(pasteBtn);  
2019 - count++;  
2020 -  
2021 - if (copyBtn != null) {  
2022 - copyBtn.style.width = "104px";  
2023 - pasteBtn.style.width = "104px";  
2024 - pasteBtn.style.marginBottom = "2px";  
2025 - copyBtn.style.marginBottom = "2px";  
2026 - copyBtn.style.marginRight = "2px";  
2027 - }  
2028 - }  
2029 -  
2030 - if (copyBtn != null || pasteBtn != null) {  
2031 - mxUtils.br(div);  
2032 - }  
2033 -  
2034 - var clearWaypoints = this.addAction(div, "clearWaypoints");  
2035 -  
2036 - if (clearWaypoints != null) {  
2037 - mxUtils.br(div);  
2038 - clearWaypoints.setAttribute(  
2039 - "title",  
2040 - mxResources.get("clearWaypoints") +  
2041 - " (" +  
2042 - this.editorUi.actions.get("clearWaypoints").shortcut +  
2043 - ")" +  
2044 - " Shift+Click to Clear Anchor Points",  
2045 - );  
2046 - count++;  
2047 - }  
2048 -  
2049 - if (graph.getSelectionCount() == 1) {  
2050 - count += this.addActions(div, ["editData", "editLink"]);  
2051 - }  
2052 -  
2053 - if (count == 0) {  
2054 - div.style.display = "none";  
2055 - }  
2056 -  
2057 - return div;  
2058 -};  
2059 -  
2060 -/**  
2061 - *  
2062 - */  
2063 -ArrangePanel.prototype.addAlign = function (div) {  
2064 - var ss = this.editorUi.getSelectionState();  
2065 - var graph = this.editorUi.editor.graph;  
2066 - div.style.paddingTop = "6px";  
2067 - div.style.paddingBottom = "8px";  
2068 - div.appendChild(this.createTitle(mxResources.get("align")));  
2069 -  
2070 - var stylePanel = document.createElement("div");  
2071 - stylePanel.style.position = "relative";  
2072 - stylePanel.style.whiteSpace = "nowrap";  
2073 - stylePanel.style.paddingLeft = "0px";  
2074 - stylePanel.style.paddingBottom = "2px";  
2075 - stylePanel.style.borderWidth = "0px";  
2076 - stylePanel.style.width = "220px";  
2077 - stylePanel.className = "geToolbarContainer";  
2078 -  
2079 - if (ss.vertices.length > 1) {  
2080 - var left = this.editorUi.toolbar.addButton(  
2081 - "geSprite-alignleft",  
2082 - mxResources.get("left"),  
2083 - function () {  
2084 - graph.alignCells(mxConstants.ALIGN_LEFT);  
2085 - },  
2086 - stylePanel,  
2087 - );  
2088 - var center = this.editorUi.toolbar.addButton(  
2089 - "geSprite-aligncenter",  
2090 - mxResources.get("center"),  
2091 - function () {  
2092 - graph.alignCells(mxConstants.ALIGN_CENTER);  
2093 - },  
2094 - stylePanel,  
2095 - );  
2096 - var right = this.editorUi.toolbar.addButton(  
2097 - "geSprite-alignright",  
2098 - mxResources.get("right"),  
2099 - function () {  
2100 - graph.alignCells(mxConstants.ALIGN_RIGHT);  
2101 - },  
2102 - stylePanel,  
2103 - );  
2104 -  
2105 - var top = this.editorUi.toolbar.addButton(  
2106 - "geSprite-aligntop",  
2107 - mxResources.get("top"),  
2108 - function () {  
2109 - graph.alignCells(mxConstants.ALIGN_TOP);  
2110 - },  
2111 - stylePanel,  
2112 - );  
2113 - var middle = this.editorUi.toolbar.addButton(  
2114 - "geSprite-alignmiddle",  
2115 - mxResources.get("middle"),  
2116 - function () {  
2117 - graph.alignCells(mxConstants.ALIGN_MIDDLE);  
2118 - },  
2119 - stylePanel,  
2120 - );  
2121 - var bottom = this.editorUi.toolbar.addButton(  
2122 - "geSprite-alignbottom",  
2123 - mxResources.get("bottom"),  
2124 - function () {  
2125 - graph.alignCells(mxConstants.ALIGN_BOTTOM);  
2126 - },  
2127 - stylePanel,  
2128 - );  
2129 -  
2130 - this.styleButtons([left, center, right, top, middle, bottom]);  
2131 - right.style.marginRight = "10px";  
2132 - }  
2133 -  
2134 - div.appendChild(stylePanel);  
2135 - this.addActions(div, ["snapToGrid"]);  
2136 -  
2137 - return div;  
2138 -};  
2139 -  
2140 -/**  
2141 - *  
2142 - */  
2143 -ArrangePanel.prototype.addFlip = function (div) {  
2144 - var ui = this.editorUi;  
2145 - var editor = ui.editor;  
2146 - var graph = editor.graph;  
2147 - div.style.paddingTop = "6px";  
2148 - div.style.paddingBottom = "10px";  
2149 - var ss = this.editorUi.getSelectionState();  
2150 -  
2151 - var span = document.createElement("div");  
2152 - span.style.marginTop = "2px";  
2153 - span.style.marginBottom = "8px";  
2154 - span.style.fontWeight = "bold";  
2155 - mxUtils.write(span, mxResources.get("flip"));  
2156 - div.appendChild(span);  
2157 -  
2158 - var btn = mxUtils.button(mxResources.get("horizontal"), function (evt) {  
2159 - graph.flipCells(ss.cells, true);  
2160 - });  
2161 -  
2162 - btn.setAttribute("title", mxResources.get("horizontal"));  
2163 - btn.style.width = "104px";  
2164 - btn.style.marginRight = "2px";  
2165 - div.appendChild(btn);  
2166 -  
2167 - var btn = mxUtils.button(mxResources.get("vertical"), function (evt) {  
2168 - graph.flipCells(ss.cells, false);  
2169 - });  
2170 -  
2171 - btn.setAttribute("title", mxResources.get("vertical"));  
2172 - btn.style.width = "104px";  
2173 - div.appendChild(btn);  
2174 -  
2175 - return div;  
2176 -};  
2177 -  
2178 -/**  
2179 - *  
2180 - */  
2181 -ArrangePanel.prototype.addDistribute = function (div) {  
2182 - var ui = this.editorUi;  
2183 - var editor = ui.editor;  
2184 - var graph = editor.graph;  
2185 - div.style.paddingTop = "6px";  
2186 - div.style.paddingBottom = "12px";  
2187 -  
2188 - div.appendChild(this.createTitle(mxResources.get("distribute")));  
2189 -  
2190 - var btn = mxUtils.button(mxResources.get("horizontal"), function (evt) {  
2191 - graph.distributeCells(true);  
2192 - });  
2193 -  
2194 - btn.setAttribute("title", mxResources.get("horizontal"));  
2195 - btn.style.width = "104px";  
2196 - btn.style.marginRight = "2px";  
2197 - div.appendChild(btn);  
2198 -  
2199 - var btn = mxUtils.button(mxResources.get("vertical"), function (evt) {  
2200 - graph.distributeCells(false);  
2201 - });  
2202 -  
2203 - btn.setAttribute("title", mxResources.get("vertical"));  
2204 - btn.style.width = "104px";  
2205 - div.appendChild(btn);  
2206 -  
2207 - return div;  
2208 -};  
2209 -  
2210 -/**  
2211 - *  
2212 - */  
2213 -ArrangePanel.prototype.addAngle = function (div) {  
2214 - var ui = this.editorUi;  
2215 - var editor = ui.editor;  
2216 - var graph = editor.graph;  
2217 - var ss = ui.getSelectionState();  
2218 -  
2219 - div.style.paddingBottom = "8px";  
2220 -  
2221 - var span = document.createElement("div");  
2222 - span.style.position = "absolute";  
2223 - span.style.width = "70px";  
2224 - span.style.marginTop = "0px";  
2225 - span.style.fontWeight = "bold";  
2226 -  
2227 - var input = null;  
2228 - var update = null;  
2229 - var btn = null;  
2230 -  
2231 - if (ss.rotatable && !ss.table && !ss.row && !ss.cell) {  
2232 - mxUtils.write(span, mxResources.get("angle"));  
2233 - div.appendChild(span);  
2234 -  
2235 - input = this.addUnitInput(div, "°", 16, 52, function () {  
2236 - update.apply(this, arguments);  
2237 - });  
2238 -  
2239 - mxUtils.br(div);  
2240 - div.style.paddingTop = "10px";  
2241 - } else {  
2242 - div.style.paddingTop = "8px";  
2243 - }  
2244 -  
2245 - if (!ss.containsLabel) {  
2246 - var label = mxResources.get("reverse");  
2247 -  
2248 - if (ss.vertices.length > 0 && ss.edges.length > 0) {  
2249 - label = mxResources.get("turn") + " / " + label;  
2250 - } else if (ss.vertices.length > 0) {  
2251 - label = mxResources.get("turn");  
2252 - }  
2253 -  
2254 - btn = mxUtils.button(label, function (evt) {  
2255 - ui.actions.get("turn").funct(evt);  
2256 - });  
2257 -  
2258 - btn.setAttribute(  
2259 - "title",  
2260 - label + " (" + this.editorUi.actions.get("turn").shortcut + ")",  
2261 - );  
2262 - btn.style.width = "210px";  
2263 - div.appendChild(btn);  
2264 -  
2265 - if (input != null) {  
2266 - btn.style.marginTop = "8px";  
2267 - }  
2268 - }  
2269 -  
2270 - if (input != null) {  
2271 - var listener = mxUtils.bind(this, function (sender, evt, force) {  
2272 - if (force || document.activeElement != input) {  
2273 - ss = ui.getSelectionState();  
2274 - var tmp = parseFloat(  
2275 - mxUtils.getValue(ss.style, mxConstants.STYLE_ROTATION, 0),  
2276 - );  
2277 - input.value = isNaN(tmp) ? "" : tmp + "°";  
2278 - }  
2279 - });  
2280 -  
2281 - update = this.installInputHandler(  
2282 - input,  
2283 - mxConstants.STYLE_ROTATION,  
2284 - 0,  
2285 - 0,  
2286 - 360,  
2287 - "°",  
2288 - null,  
2289 - true,  
2290 - );  
2291 - this.addKeyHandler(input, listener);  
2292 -  
2293 - graph.getModel().addListener(mxEvent.CHANGE, listener);  
2294 - this.listeners.push({  
2295 - destroy: function () {  
2296 - graph.getModel().removeListener(listener);  
2297 - },  
2298 - });  
2299 - listener();  
2300 - }  
2301 -  
2302 - return div;  
2303 -};  
2304 -  
2305 -BaseFormatPanel.prototype.getUnit = function () {  
2306 - var unit = this.editorUi.editor.graph.view.unit;  
2307 -  
2308 - switch (unit) {  
2309 - case mxConstants.POINTS:  
2310 - return "pt";  
2311 - case mxConstants.INCHES:  
2312 - return '"';  
2313 - case mxConstants.MILLIMETERS:  
2314 - return "mm";  
2315 - case mxConstants.METERS:  
2316 - return "m";  
2317 - }  
2318 -};  
2319 -  
2320 -BaseFormatPanel.prototype.inUnit = function (pixels) {  
2321 - return this.editorUi.editor.graph.view.formatUnitText(pixels);  
2322 -};  
2323 -  
2324 -BaseFormatPanel.prototype.fromUnit = function (value) {  
2325 - var unit = this.editorUi.editor.graph.view.unit;  
2326 -  
2327 - switch (unit) {  
2328 - case mxConstants.POINTS:  
2329 - return value;  
2330 - case mxConstants.INCHES:  
2331 - return value * mxConstants.PIXELS_PER_INCH;  
2332 - case mxConstants.MILLIMETERS:  
2333 - return value * mxConstants.PIXELS_PER_MM;  
2334 - case mxConstants.METERS:  
2335 - return value * mxConstants.PIXELS_PER_MM * 1000;  
2336 - }  
2337 -};  
2338 -  
2339 -BaseFormatPanel.prototype.isFloatUnit = function () {  
2340 - return this.editorUi.editor.graph.view.unit != mxConstants.POINTS;  
2341 -};  
2342 -  
2343 -BaseFormatPanel.prototype.getUnitStep = function () {  
2344 - var unit = this.editorUi.editor.graph.view.unit;  
2345 -  
2346 - switch (unit) {  
2347 - case mxConstants.POINTS:  
2348 - return 1;  
2349 - case mxConstants.INCHES:  
2350 - return 0.1;  
2351 - case mxConstants.MILLIMETERS:  
2352 - return 0.5;  
2353 - case mxConstants.METERS:  
2354 - return 0.001;  
2355 - }  
2356 -};  
2357 -  
2358 -/**  
2359 - *  
2360 - */  
2361 -ArrangePanel.prototype.addGeometry = function (container) {  
2362 - var panel = this;  
2363 - var ui = this.editorUi;  
2364 - var graph = ui.editor.graph;  
2365 - var model = graph.getModel();  
2366 - var rect = ui.getSelectionState();  
2367 -  
2368 - var div = this.createPanel();  
2369 - div.style.paddingBottom = "8px";  
2370 -  
2371 - var span = document.createElement("div");  
2372 - span.style.position = "absolute";  
2373 - span.style.width = "50px";  
2374 - span.style.marginTop = "0px";  
2375 - span.style.fontWeight = "bold";  
2376 - mxUtils.write(span, mxResources.get("size"));  
2377 - div.appendChild(span);  
2378 -  
2379 - var widthUpdate, heightUpdate, leftUpdate, topUpdate;  
2380 - var width = this.addUnitInput(  
2381 - div,  
2382 - this.getUnit(),  
2383 - 87,  
2384 - 52,  
2385 - function () {  
2386 - widthUpdate.apply(this, arguments);  
2387 - },  
2388 - this.getUnitStep(),  
2389 - null,  
2390 - null,  
2391 - this.isFloatUnit(),  
2392 - );  
2393 - var height = this.addUnitInput(  
2394 - div,  
2395 - this.getUnit(),  
2396 - 16,  
2397 - 52,  
2398 - function () {  
2399 - heightUpdate.apply(this, arguments);  
2400 - },  
2401 - this.getUnitStep(),  
2402 - null,  
2403 - null,  
2404 - this.isFloatUnit(),  
2405 - );  
2406 -  
2407 - var autosizeBtn = document.createElement("div");  
2408 - autosizeBtn.className = "geSprite geSprite-fit";  
2409 - autosizeBtn.setAttribute(  
2410 - "title",  
2411 - mxResources.get("autosize") +  
2412 - " (" +  
2413 - this.editorUi.actions.get("autosize").shortcut +  
2414 - ")",  
2415 - );  
2416 - autosizeBtn.style.position = "relative";  
2417 - autosizeBtn.style.cursor = "pointer";  
2418 - autosizeBtn.style.marginTop = "-3px";  
2419 - autosizeBtn.style.border = "0px";  
2420 - autosizeBtn.style.left = "42px";  
2421 - mxUtils.setOpacity(autosizeBtn, 50);  
2422 -  
2423 - mxEvent.addListener(autosizeBtn, "mouseenter", function () {  
2424 - mxUtils.setOpacity(autosizeBtn, 100);  
2425 - });  
2426 -  
2427 - mxEvent.addListener(autosizeBtn, "mouseleave", function () {  
2428 - mxUtils.setOpacity(autosizeBtn, 50);  
2429 - });  
2430 -  
2431 - mxEvent.addListener(autosizeBtn, "click", function () {  
2432 - ui.actions.get("autosize").funct();  
2433 - });  
2434 -  
2435 - div.appendChild(autosizeBtn);  
2436 -  
2437 - if (rect.row) {  
2438 - width.style.visibility = "hidden";  
2439 - width.nextSibling.style.visibility = "hidden";  
2440 - } else {  
2441 - this.addLabel(div, mxResources.get("width"), 87);  
2442 - }  
2443 -  
2444 - this.addLabel(div, mxResources.get("height"), 16);  
2445 - mxUtils.br(div);  
2446 -  
2447 - var wrapper = document.createElement("div");  
2448 - wrapper.style.paddingTop = "8px";  
2449 - wrapper.style.paddingRight = "20px";  
2450 - wrapper.style.whiteSpace = "nowrap";  
2451 - wrapper.style.textAlign = "right";  
2452 - var opt = this.createCellOption(  
2453 - mxResources.get("constrainProportions"),  
2454 - mxConstants.STYLE_ASPECT,  
2455 - null,  
2456 - "fixed",  
2457 - "null",  
2458 - );  
2459 - opt.style.width = "210px";  
2460 - wrapper.appendChild(opt);  
2461 -  
2462 - if (!rect.cell && !rect.row) {  
2463 - div.appendChild(wrapper);  
2464 - } else {  
2465 - autosizeBtn.style.visibility = "hidden";  
2466 - }  
2467 -  
2468 - var constrainCheckbox = opt.getElementsByTagName("input")[0];  
2469 - this.addKeyHandler(width, listener);  
2470 - this.addKeyHandler(height, listener);  
2471 -  
2472 - widthUpdate = this.addGeometryHandler(width, function (geo, value, cell) {  
2473 - if (graph.isTableCell(cell)) {  
2474 - graph.setTableColumnWidth(cell, value - geo.width, true);  
2475 -  
2476 - // Blocks processing in caller  
2477 - return true;  
2478 - } else if (geo.width > 0) {  
2479 - var value = Math.max(1, panel.fromUnit(value));  
2480 -  
2481 - if (constrainCheckbox.checked) {  
2482 - geo.height = Math.round((geo.height * value * 100) / geo.width) / 100;  
2483 - }  
2484 -  
2485 - geo.width = value;  
2486 - }  
2487 - });  
2488 - heightUpdate = this.addGeometryHandler(height, function (geo, value, cell) {  
2489 - if (graph.isTableCell(cell)) {  
2490 - cell = graph.model.getParent(cell);  
2491 - }  
2492 -  
2493 - if (graph.isTableRow(cell)) {  
2494 - graph.setTableRowHeight(cell, value - geo.height);  
2495 -  
2496 - // Blocks processing in caller  
2497 - return true;  
2498 - } else if (geo.height > 0) {  
2499 - var value = Math.max(1, panel.fromUnit(value));  
2500 -  
2501 - if (constrainCheckbox.checked) {  
2502 - geo.width = Math.round((geo.width * value * 100) / geo.height) / 100;  
2503 - }  
2504 -  
2505 - geo.height = value;  
2506 - }  
2507 - });  
2508 -  
2509 - if (rect.resizable || rect.row || rect.cell) {  
2510 - container.appendChild(div);  
2511 - }  
2512 -  
2513 - var div2 = this.createPanel();  
2514 - div2.style.paddingBottom = "30px";  
2515 -  
2516 - var span = document.createElement("div");  
2517 - span.style.position = "absolute";  
2518 - span.style.width = "70px";  
2519 - span.style.marginTop = "0px";  
2520 - span.style.fontWeight = "bold";  
2521 - mxUtils.write(span, mxResources.get("position"));  
2522 - div2.appendChild(span);  
2523 -  
2524 - var left = this.addUnitInput(  
2525 - div2,  
2526 - this.getUnit(),  
2527 - 87,  
2528 - 52,  
2529 - function () {  
2530 - leftUpdate.apply(this, arguments);  
2531 - },  
2532 - this.getUnitStep(),  
2533 - null,  
2534 - null,  
2535 - this.isFloatUnit(),  
2536 - );  
2537 - var top = this.addUnitInput(  
2538 - div2,  
2539 - this.getUnit(),  
2540 - 16,  
2541 - 52,  
2542 - function () {  
2543 - topUpdate.apply(this, arguments);  
2544 - },  
2545 - this.getUnitStep(),  
2546 - null,  
2547 - null,  
2548 - this.isFloatUnit(),  
2549 - );  
2550 -  
2551 - mxUtils.br(div2);  
2552 -  
2553 - this.addLabel(div2, mxResources.get("left"), 87);  
2554 - this.addLabel(div2, mxResources.get("top"), 16);  
2555 -  
2556 - var listener = mxUtils.bind(this, function (sender, evt, force) {  
2557 - rect = ui.getSelectionState();  
2558 -  
2559 - if (  
2560 - !rect.containsLabel &&  
2561 - rect.vertices.length == graph.getSelectionCount() &&  
2562 - rect.width != null &&  
2563 - rect.height != null  
2564 - ) {  
2565 - div.style.display = "";  
2566 -  
2567 - if (force || document.activeElement != width) {  
2568 - width.value =  
2569 - this.inUnit(rect.width) +  
2570 - (rect.width == "" ? "" : " " + this.getUnit());  
2571 - }  
2572 -  
2573 - if (force || document.activeElement != height) {  
2574 - height.value =  
2575 - this.inUnit(rect.height) +  
2576 - (rect.height == "" ? "" : " " + this.getUnit());  
2577 - }  
2578 - } else {  
2579 - div.style.display = "none";  
2580 - }  
2581 -  
2582 - if (  
2583 - rect.vertices.length == graph.getSelectionCount() &&  
2584 - rect.x != null &&  
2585 - rect.y != null  
2586 - ) {  
2587 - div2.style.display = "";  
2588 -  
2589 - if (force || document.activeElement != left) {  
2590 - left.value =  
2591 - this.inUnit(rect.x) + (rect.x == "" ? "" : " " + this.getUnit());  
2592 - }  
2593 -  
2594 - if (force || document.activeElement != top) {  
2595 - top.value =  
2596 - this.inUnit(rect.y) + (rect.y == "" ? "" : " " + this.getUnit());  
2597 - }  
2598 - } else {  
2599 - div2.style.display = "none";  
2600 - }  
2601 - });  
2602 -  
2603 - this.addKeyHandler(left, listener);  
2604 - this.addKeyHandler(top, listener);  
2605 -  
2606 - model.addListener(mxEvent.CHANGE, listener);  
2607 - this.listeners.push({  
2608 - destroy: function () {  
2609 - model.removeListener(listener);  
2610 - },  
2611 - });  
2612 - listener();  
2613 -  
2614 - leftUpdate = this.addGeometryHandler(left, function (geo, value) {  
2615 - value = panel.fromUnit(value);  
2616 -  
2617 - if (geo.relative) {  
2618 - geo.offset.x = value;  
2619 - } else {  
2620 - geo.x = value;  
2621 - }  
2622 - });  
2623 - topUpdate = this.addGeometryHandler(top, function (geo, value) {  
2624 - value = panel.fromUnit(value);  
2625 -  
2626 - if (geo.relative) {  
2627 - geo.offset.y = value;  
2628 - } else {  
2629 - geo.y = value;  
2630 - }  
2631 - });  
2632 -  
2633 - if (rect.movable) {  
2634 - if (  
2635 - rect.edges.length == 0 &&  
2636 - rect.vertices.length == 1 &&  
2637 - model.isEdge(model.getParent(rect.vertices[0]))  
2638 - ) {  
2639 - var geo = graph.getCellGeometry(rect.vertices[0]);  
2640 -  
2641 - if (geo != null && geo.relative) {  
2642 - var btn = mxUtils.button(  
2643 - mxResources.get("center"),  
2644 - mxUtils.bind(this, function (evt) {  
2645 - model.beginUpdate();  
2646 - try {  
2647 - geo = geo.clone();  
2648 - geo.x = 0;  
2649 - geo.y = 0;  
2650 - geo.offset = new mxPoint();  
2651 - model.setGeometry(rect.vertices[0], geo);  
2652 - } finally {  
2653 - model.endUpdate();  
2654 - }  
2655 - }),  
2656 - );  
2657 -  
2658 - btn.setAttribute("title", mxResources.get("center"));  
2659 - btn.style.width = "210px";  
2660 - btn.style.position = "absolute";  
2661 - mxUtils.br(div2);  
2662 - mxUtils.br(div2);  
2663 - div2.appendChild(btn);  
2664 - }  
2665 - }  
2666 - container.appendChild(div2);  
2667 - }  
2668 -};  
2669 -  
2670 -/**  
2671 - *  
2672 - */  
2673 -ArrangePanel.prototype.addGeometryHandler = function (input, fn) {  
2674 - var ui = this.editorUi;  
2675 - var graph = ui.editor.graph;  
2676 - var initialValue = null;  
2677 - var panel = this;  
2678 -  
2679 - function update(evt) {  
2680 - if (input.value != "") {  
2681 - var value = parseFloat(input.value);  
2682 -  
2683 - if (isNaN(value)) {  
2684 - input.value = initialValue + " " + panel.getUnit();  
2685 - } else if (value != initialValue) {  
2686 - graph.getModel().beginUpdate();  
2687 - try {  
2688 - var cells = ui.getSelectionState().cells;  
2689 -  
2690 - for (var i = 0; i < cells.length; i++) {  
2691 - if (graph.getModel().isVertex(cells[i])) {  
2692 - var geo = graph.getCellGeometry(cells[i]);  
2693 -  
2694 - if (geo != null) {  
2695 - geo = geo.clone();  
2696 -  
2697 - if (!fn(geo, value, cells[i])) {  
2698 - var state = graph.view.getState(cells[i]);  
2699 -  
2700 - if (state != null && graph.isRecursiveVertexResize(state)) {  
2701 - graph.resizeChildCells(cells[i], geo);  
2702 - }  
2703 -  
2704 - graph.getModel().setGeometry(cells[i], geo);  
2705 - graph.constrainChildCells(cells[i]);  
2706 - }  
2707 - }  
2708 - }  
2709 - }  
2710 - } finally {  
2711 - graph.getModel().endUpdate();  
2712 - }  
2713 -  
2714 - initialValue = value;  
2715 - input.value = value + " " + panel.getUnit();  
2716 - }  
2717 - }  
2718 -  
2719 - mxEvent.consume(evt);  
2720 - }  
2721 -  
2722 - mxEvent.addListener(input, "blur", update);  
2723 - mxEvent.addListener(input, "change", update);  
2724 - mxEvent.addListener(input, "focus", function () {  
2725 - initialValue = input.value;  
2726 - });  
2727 -  
2728 - return update;  
2729 -};  
2730 -  
2731 -ArrangePanel.prototype.addEdgeGeometryHandler = function (input, fn) {  
2732 - var ui = this.editorUi;  
2733 - var graph = ui.editor.graph;  
2734 - var initialValue = null;  
2735 -  
2736 - function update(evt) {  
2737 - if (input.value != "") {  
2738 - var value = parseFloat(input.value);  
2739 -  
2740 - if (isNaN(value)) {  
2741 - input.value = initialValue + " pt";  
2742 - } else if (value != initialValue) {  
2743 - graph.getModel().beginUpdate();  
2744 - try {  
2745 - var cells = ui.getSelectionState().cells;  
2746 -  
2747 - for (var i = 0; i < cells.length; i++) {  
2748 - if (graph.getModel().isEdge(cells[i])) {  
2749 - var geo = graph.getCellGeometry(cells[i]);  
2750 -  
2751 - if (geo != null) {  
2752 - geo = geo.clone();  
2753 - fn(geo, value);  
2754 -  
2755 - graph.getModel().setGeometry(cells[i], geo);  
2756 - }  
2757 - }  
2758 - }  
2759 - } finally {  
2760 - graph.getModel().endUpdate();  
2761 - }  
2762 -  
2763 - initialValue = value;  
2764 - input.value = value + " pt";  
2765 - }  
2766 - }  
2767 -  
2768 - mxEvent.consume(evt);  
2769 - }  
2770 -  
2771 - mxEvent.addListener(input, "blur", update);  
2772 - mxEvent.addListener(input, "change", update);  
2773 - mxEvent.addListener(input, "focus", function () {  
2774 - initialValue = input.value;  
2775 - });  
2776 -  
2777 - return update;  
2778 -};  
2779 -  
2780 -/**  
2781 - *  
2782 - */  
2783 -ArrangePanel.prototype.addEdgeGeometry = function (container) {  
2784 - var ui = this.editorUi;  
2785 - var graph = ui.editor.graph;  
2786 - var rect = ui.getSelectionState();  
2787 - var div = this.createPanel();  
2788 -  
2789 - var span = document.createElement("div");  
2790 - span.style.position = "absolute";  
2791 - span.style.width = "70px";  
2792 - span.style.marginTop = "0px";  
2793 - span.style.fontWeight = "bold";  
2794 - mxUtils.write(span, mxResources.get("width"));  
2795 - div.appendChild(span);  
2796 -  
2797 - var widthUpdate, xtUpdate, ytUpdate, xsUpdate, ysUpdate;  
2798 - var width = this.addUnitInput(div, "pt", 12, 44, function () {  
2799 - widthUpdate.apply(this, arguments);  
2800 - });  
2801 -  
2802 - mxUtils.br(div);  
2803 - this.addKeyHandler(width, listener);  
2804 -  
2805 - var widthUpdate = mxUtils.bind(this, function (evt) {  
2806 - // Maximum stroke width is 999  
2807 - var value = parseInt(width.value);  
2808 - value = Math.min(999, Math.max(1, isNaN(value) ? 1 : value));  
2809 -  
2810 - if (  
2811 - value !=  
2812 - mxUtils.getValue(  
2813 - rect.style,  
2814 - "width",  
2815 - mxCellRenderer.defaultShapes["flexArrow"].prototype.defaultWidth,  
2816 - )  
2817 - ) {  
2818 - var cells = ui.getSelectionState().cells;  
2819 - graph.setCellStyles("width", value, cells);  
2820 - ui.fireEvent(  
2821 - new mxEventObject(  
2822 - "styleChanged",  
2823 - "keys",  
2824 - ["width"],  
2825 - "values",  
2826 - [value],  
2827 - "cells",  
2828 - cells,  
2829 - ),  
2830 - );  
2831 - }  
2832 -  
2833 - width.value = value + " pt";  
2834 - mxEvent.consume(evt);  
2835 - });  
2836 -  
2837 - mxEvent.addListener(width, "blur", widthUpdate);  
2838 - mxEvent.addListener(width, "change", widthUpdate);  
2839 -  
2840 - container.appendChild(div);  
2841 -  
2842 - var divs = this.createPanel();  
2843 - divs.style.paddingBottom = "30px";  
2844 -  
2845 - var span = document.createElement("div");  
2846 - span.style.position = "absolute";  
2847 - span.style.width = "70px";  
2848 - span.style.marginTop = "0px";  
2849 - mxUtils.write(span, mxResources.get("linestart"));  
2850 - divs.appendChild(span);  
2851 -  
2852 - var xs = this.addUnitInput(divs, "pt", 87, 52, function () {  
2853 - xsUpdate.apply(this, arguments);  
2854 - });  
2855 - var ys = this.addUnitInput(divs, "pt", 16, 52, function () {  
2856 - ysUpdate.apply(this, arguments);  
2857 - });  
2858 -  
2859 - mxUtils.br(divs);  
2860 - this.addLabel(divs, mxResources.get("left"), 87);  
2861 - this.addLabel(divs, mxResources.get("top"), 16);  
2862 - container.appendChild(divs);  
2863 - this.addKeyHandler(xs, listener);  
2864 - this.addKeyHandler(ys, listener);  
2865 -  
2866 - var divt = this.createPanel();  
2867 - divt.style.paddingBottom = "30px";  
2868 -  
2869 - var span = document.createElement("div");  
2870 - span.style.position = "absolute";  
2871 - span.style.width = "70px";  
2872 - span.style.marginTop = "0px";  
2873 - mxUtils.write(span, mxResources.get("lineend"));  
2874 - divt.appendChild(span);  
2875 -  
2876 - var xt = this.addUnitInput(divt, "pt", 87, 52, function () {  
2877 - xtUpdate.apply(this, arguments);  
2878 - });  
2879 - var yt = this.addUnitInput(divt, "pt", 16, 52, function () {  
2880 - ytUpdate.apply(this, arguments);  
2881 - });  
2882 -  
2883 - mxUtils.br(divt);  
2884 - this.addLabel(divt, mxResources.get("left"), 87);  
2885 - this.addLabel(divt, mxResources.get("top"), 16);  
2886 - container.appendChild(divt);  
2887 - this.addKeyHandler(xt, listener);  
2888 - this.addKeyHandler(yt, listener);  
2889 -  
2890 - var listener = mxUtils.bind(this, function (sender, evt, force) {  
2891 - rect = ui.getSelectionState();  
2892 - var cell = rect.cells[0];  
2893 -  
2894 - if (rect.style.shape == "link" || rect.style.shape == "flexArrow") {  
2895 - div.style.display = "";  
2896 -  
2897 - if (force || document.activeElement != width) {  
2898 - var value = mxUtils.getValue(  
2899 - rect.style,  
2900 - "width",  
2901 - mxCellRenderer.defaultShapes["flexArrow"].prototype.defaultWidth,  
2902 - );  
2903 - width.value = value + " pt";  
2904 - }  
2905 - } else {  
2906 - div.style.display = "none";  
2907 - }  
2908 -  
2909 - if (rect.cells.length == 1 && graph.model.isEdge(cell)) {  
2910 - var geo = graph.model.getGeometry(cell);  
2911 -  
2912 - if (  
2913 - geo.sourcePoint != null &&  
2914 - graph.model.getTerminal(cell, true) == null  
2915 - ) {  
2916 - xs.value = geo.sourcePoint.x;  
2917 - ys.value = geo.sourcePoint.y;  
2918 - } else {  
2919 - divs.style.display = "none";  
2920 - }  
2921 -  
2922 - if (  
2923 - geo.targetPoint != null &&  
2924 - graph.model.getTerminal(cell, false) == null  
2925 - ) {  
2926 - xt.value = geo.targetPoint.x;  
2927 - yt.value = geo.targetPoint.y;  
2928 - } else {  
2929 - divt.style.display = "none";  
2930 - }  
2931 - } else {  
2932 - divs.style.display = "none";  
2933 - divt.style.display = "none";  
2934 - }  
2935 - });  
2936 -  
2937 - xsUpdate = this.addEdgeGeometryHandler(xs, function (geo, value) {  
2938 - geo.sourcePoint.x = value;  
2939 - });  
2940 -  
2941 - ysUpdate = this.addEdgeGeometryHandler(ys, function (geo, value) {  
2942 - geo.sourcePoint.y = value;  
2943 - });  
2944 -  
2945 - xtUpdate = this.addEdgeGeometryHandler(xt, function (geo, value) {  
2946 - geo.targetPoint.x = value;  
2947 - });  
2948 -  
2949 - ytUpdate = this.addEdgeGeometryHandler(yt, function (geo, value) {  
2950 - geo.targetPoint.y = value;  
2951 - });  
2952 -  
2953 - graph.getModel().addListener(mxEvent.CHANGE, listener);  
2954 - this.listeners.push({  
2955 - destroy: function () {  
2956 - graph.getModel().removeListener(listener);  
2957 - },  
2958 - });  
2959 - listener();  
2960 -};  
2961 -  
2962 -/**  
2963 - * Adds the label menu items to the given menu and parent.  
2964 - */  
2965 -TextFormatPanel = function (format, editorUi, container) {  
2966 - BaseFormatPanel.call(this, format, editorUi, container);  
2967 - this.init();  
2968 -};  
2969 -  
2970 -mxUtils.extend(TextFormatPanel, BaseFormatPanel);  
2971 -  
2972 -/**  
2973 - * Adds the label menu items to the given menu and parent.  
2974 - */  
2975 -TextFormatPanel.prototype.init = function () {  
2976 - this.container.style.borderBottom = "none";  
2977 - this.addFont(this.container);  
2978 -};  
2979 -  
2980 -/**  
2981 - * Adds the label menu items to the given menu and parent.  
2982 - */  
2983 -TextFormatPanel.prototype.addFont = function (container) {  
2984 - var ui = this.editorUi;  
2985 - var editor = ui.editor;  
2986 - var graph = editor.graph;  
2987 - var ss = ui.getSelectionState();  
2988 -  
2989 - var title = this.createTitle(mxResources.get("font"));  
2990 - title.style.paddingLeft = "14px";  
2991 - title.style.paddingTop = "10px";  
2992 - title.style.paddingBottom = "6px";  
2993 - container.appendChild(title);  
2994 -  
2995 - var stylePanel = this.createPanel();  
2996 - stylePanel.style.paddingTop = "2px";  
2997 - stylePanel.style.paddingBottom = "2px";  
2998 - stylePanel.style.position = "relative";  
2999 - stylePanel.style.marginLeft = "-2px";  
3000 - stylePanel.style.borderWidth = "0px";  
3001 - stylePanel.className = "geToolbarContainer";  
3002 -  
3003 - if (graph.cellEditor.isContentEditing()) {  
3004 - var cssPanel = stylePanel.cloneNode();  
3005 -  
3006 - var cssMenu = this.editorUi.toolbar.addMenu(  
3007 - mxResources.get("style"),  
3008 - mxResources.get("style"),  
3009 - true,  
3010 - "formatBlock",  
3011 - cssPanel,  
3012 - null,  
3013 - true,  
3014 - );  
3015 - cssMenu.style.color = "rgb(112, 112, 112)";  
3016 - cssMenu.style.whiteSpace = "nowrap";  
3017 - cssMenu.style.overflow = "hidden";  
3018 - cssMenu.style.margin = "0px";  
3019 - this.addArrow(cssMenu);  
3020 - cssMenu.style.width = "200px";  
3021 - cssMenu.style.height = "15px";  
3022 -  
3023 - var arrow = cssMenu.getElementsByTagName("div")[0];  
3024 - arrow.style.cssFloat = "right";  
3025 - container.appendChild(cssPanel);  
3026 - }  
3027 -  
3028 - container.appendChild(stylePanel);  
3029 -  
3030 - var colorPanel = this.createPanel();  
3031 - colorPanel.style.marginTop = "8px";  
3032 - colorPanel.style.borderTop = "1px solid #c0c0c0";  
3033 - colorPanel.style.paddingTop = "6px";  
3034 - colorPanel.style.paddingBottom = "6px";  
3035 -  
3036 - var fontMenu = this.editorUi.toolbar.addMenu(  
3037 - "Helvetica",  
3038 - mxResources.get("fontFamily"),  
3039 - true,  
3040 - "fontFamily",  
3041 - stylePanel,  
3042 - null,  
3043 - true,  
3044 - );  
3045 - fontMenu.style.color = "rgb(112, 112, 112)";  
3046 - fontMenu.style.whiteSpace = "nowrap";  
3047 - fontMenu.style.overflow = "hidden";  
3048 - fontMenu.style.margin = "0px";  
3049 -  
3050 - this.addArrow(fontMenu);  
3051 - fontMenu.style.width = "200px";  
3052 - fontMenu.style.height = "15px";  
3053 -  
3054 - var stylePanel2 = stylePanel.cloneNode(false);  
3055 - stylePanel2.style.marginLeft = "-3px";  
3056 - var fontStyleItems = this.editorUi.toolbar.addItems(  
3057 - ["bold", "italic", "underline"],  
3058 - stylePanel2,  
3059 - true,  
3060 - );  
3061 - fontStyleItems[0].setAttribute(  
3062 - "title",  
3063 - mxResources.get("bold") +  
3064 - " (" +  
3065 - this.editorUi.actions.get("bold").shortcut +  
3066 - ")",  
3067 - );  
3068 - fontStyleItems[1].setAttribute(  
3069 - "title",  
3070 - mxResources.get("italic") +  
3071 - " (" +  
3072 - this.editorUi.actions.get("italic").shortcut +  
3073 - ")",  
3074 - );  
3075 - fontStyleItems[2].setAttribute(  
3076 - "title",  
3077 - mxResources.get("underline") +  
3078 - " (" +  
3079 - this.editorUi.actions.get("underline").shortcut +  
3080 - ")",  
3081 - );  
3082 -  
3083 - var verticalItem = this.editorUi.toolbar.addItems(  
3084 - ["vertical"],  
3085 - stylePanel2,  
3086 - true,  
3087 - )[0];  
3088 -  
3089 - container.appendChild(stylePanel2);  
3090 -  
3091 - this.styleButtons(fontStyleItems);  
3092 - this.styleButtons([verticalItem]);  
3093 -  
3094 - var stylePanel3 = stylePanel.cloneNode(false);  
3095 - stylePanel3.style.marginLeft = "-3px";  
3096 - stylePanel3.style.paddingBottom = "0px";  
3097 -  
3098 - // Helper function to return a wrapper function does not pass any arguments  
3099 - var callFn = function (fn) {  
3100 - return function () {  
3101 - return fn();  
3102 - };  
3103 - };  
3104 -  
3105 - var left = this.editorUi.toolbar.addButton(  
3106 - "geSprite-left",  
3107 - mxResources.get("left"),  
3108 - graph.cellEditor.isContentEditing()  
3109 - ? function (evt) {  
3110 - graph.cellEditor.alignText(mxConstants.ALIGN_LEFT, evt);  
3111 - ui.fireEvent(  
3112 - new mxEventObject(  
3113 - "styleChanged",  
3114 - "keys",  
3115 - [mxConstants.STYLE_ALIGN],  
3116 - "values",  
3117 - [mxConstants.ALIGN_LEFT],  
3118 - "cells",  
3119 - ss.cells,  
3120 - ),  
3121 - );  
3122 - }  
3123 - : callFn(  
3124 - this.editorUi.menus.createStyleChangeFunction(  
3125 - [mxConstants.STYLE_ALIGN],  
3126 - [mxConstants.ALIGN_LEFT],  
3127 - ),  
3128 - ),  
3129 - stylePanel3,  
3130 - );  
3131 - var center = this.editorUi.toolbar.addButton(  
3132 - "geSprite-center",  
3133 - mxResources.get("center"),  
3134 - graph.cellEditor.isContentEditing()  
3135 - ? function (evt) {  
3136 - graph.cellEditor.alignText(mxConstants.ALIGN_CENTER, evt);  
3137 - ui.fireEvent(  
3138 - new mxEventObject(  
3139 - "styleChanged",  
3140 - "keys",  
3141 - [mxConstants.STYLE_ALIGN],  
3142 - "values",  
3143 - [mxConstants.ALIGN_CENTER],  
3144 - "cells",  
3145 - ss.cells,  
3146 - ),  
3147 - );  
3148 - }  
3149 - : callFn(  
3150 - this.editorUi.menus.createStyleChangeFunction(  
3151 - [mxConstants.STYLE_ALIGN],  
3152 - [mxConstants.ALIGN_CENTER],  
3153 - ),  
3154 - ),  
3155 - stylePanel3,  
3156 - );  
3157 - var right = this.editorUi.toolbar.addButton(  
3158 - "geSprite-right",  
3159 - mxResources.get("right"),  
3160 - graph.cellEditor.isContentEditing()  
3161 - ? function (evt) {  
3162 - graph.cellEditor.alignText(mxConstants.ALIGN_RIGHT, evt);  
3163 - ui.fireEvent(  
3164 - new mxEventObject(  
3165 - "styleChanged",  
3166 - "keys",  
3167 - [mxConstants.STYLE_ALIGN],  
3168 - "values",  
3169 - [mxConstants.ALIGN_RIGHT],  
3170 - "cells",  
3171 - ss.cells,  
3172 - ),  
3173 - );  
3174 - }  
3175 - : callFn(  
3176 - this.editorUi.menus.createStyleChangeFunction(  
3177 - [mxConstants.STYLE_ALIGN],  
3178 - [mxConstants.ALIGN_RIGHT],  
3179 - ),  
3180 - ),  
3181 - stylePanel3,  
3182 - );  
3183 -  
3184 - this.styleButtons([left, center, right]);  
3185 -  
3186 - // Quick hack for strikethrough  
3187 - // TODO: Add translations and toggle state  
3188 - if (graph.cellEditor.isContentEditing()) {  
3189 - var strike = this.editorUi.toolbar.addButton(  
3190 - "geSprite-removeformat",  
3191 - mxResources.get("strikethrough"),  
3192 - function () {  
3193 - document.execCommand("strikeThrough", false, null);  
3194 - },  
3195 - stylePanel2,  
3196 - );  
3197 - this.styleButtons([strike]);  
3198 -  
3199 - strike.firstChild.style.background =  
3200 - "url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCI+PGRlZnM+PHBhdGggaWQ9ImEiIGQ9Ik0wIDBoMjR2MjRIMFYweiIvPjwvZGVmcz48Y2xpcFBhdGggaWQ9ImIiPjx1c2UgeGxpbms6aHJlZj0iI2EiIG92ZXJmbG93PSJ2aXNpYmxlIi8+PC9jbGlwUGF0aD48cGF0aCBjbGlwLXBhdGg9InVybCgjYikiIGZpbGw9IiMwMTAxMDEiIGQ9Ik03LjI0IDguNzVjLS4yNi0uNDgtLjM5LTEuMDMtLjM5LTEuNjcgMC0uNjEuMTMtMS4xNi40LTEuNjcuMjYtLjUuNjMtLjkzIDEuMTEtMS4yOS40OC0uMzUgMS4wNS0uNjMgMS43LS44My42Ni0uMTkgMS4zOS0uMjkgMi4xOC0uMjkuODEgMCAxLjU0LjExIDIuMjEuMzQuNjYuMjIgMS4yMy41NCAxLjY5Ljk0LjQ3LjQuODMuODggMS4wOCAxLjQzLjI1LjU1LjM4IDEuMTUuMzggMS44MWgtMy4wMWMwLS4zMS0uMDUtLjU5LS4xNS0uODUtLjA5LS4yNy0uMjQtLjQ5LS40NC0uNjgtLjItLjE5LS40NS0uMzMtLjc1LS40NC0uMy0uMS0uNjYtLjE2LTEuMDYtLjE2LS4zOSAwLS43NC4wNC0xLjAzLjEzLS4yOS4wOS0uNTMuMjEtLjcyLjM2LS4xOS4xNi0uMzQuMzQtLjQ0LjU1LS4xLjIxLS4xNS40My0uMTUuNjYgMCAuNDguMjUuODguNzQgMS4yMS4zOC4yNS43Ny40OCAxLjQxLjdINy4zOWMtLjA1LS4wOC0uMTEtLjE3LS4xNS0uMjV6TTIxIDEydi0ySDN2Mmg5LjYyYy4xOC4wNy40LjE0LjU1LjIuMzcuMTcuNjYuMzQuODcuNTEuMjEuMTcuMzUuMzYuNDMuNTcuMDcuMi4xMS40My4xMS42OSAwIC4yMy0uMDUuNDUtLjE0LjY2LS4wOS4yLS4yMy4zOC0uNDIuNTMtLjE5LjE1LS40Mi4yNi0uNzEuMzUtLjI5LjA4LS42My4xMy0xLjAxLjEzLS40MyAwLS44My0uMDQtMS4xOC0uMTNzLS42Ni0uMjMtLjkxLS40MmMtLjI1LS4xOS0uNDUtLjQ0LS41OS0uNzUtLjE0LS4zMS0uMjUtLjc2LS4yNS0xLjIxSDYuNGMwIC41NS4wOCAxLjEzLjI0IDEuNTguMTYuNDUuMzcuODUuNjUgMS4yMS4yOC4zNS42LjY2Ljk4LjkyLjM3LjI2Ljc4LjQ4IDEuMjIuNjUuNDQuMTcuOS4zIDEuMzguMzkuNDguMDguOTYuMTMgMS40NC4xMy44IDAgMS41My0uMDkgMi4xOC0uMjhzMS4yMS0uNDUgMS42Ny0uNzljLjQ2LS4zNC44Mi0uNzcgMS4wNy0xLjI3cy4zOC0xLjA3LjM4LTEuNzFjMC0uNi0uMS0xLjE0LS4zMS0xLjYxLS4wNS0uMTEtLjExLS4yMy0uMTctLjMzSDIxeiIvPjwvc3ZnPg==)";  
3201 - strike.firstChild.style.backgroundPosition = "2px 2px";  
3202 - strike.firstChild.style.backgroundSize = "18px 18px";  
3203 -  
3204 - this.styleButtons([strike]);  
3205 - }  
3206 -  
3207 - var top = this.editorUi.toolbar.addButton(  
3208 - "geSprite-top",  
3209 - mxResources.get("top"),  
3210 - callFn(  
3211 - this.editorUi.menus.createStyleChangeFunction(  
3212 - [mxConstants.STYLE_VERTICAL_ALIGN],  
3213 - [mxConstants.ALIGN_TOP],  
3214 - ),  
3215 - ),  
3216 - stylePanel3,  
3217 - );  
3218 - var middle = this.editorUi.toolbar.addButton(  
3219 - "geSprite-middle",  
3220 - mxResources.get("middle"),  
3221 - callFn(  
3222 - this.editorUi.menus.createStyleChangeFunction(  
3223 - [mxConstants.STYLE_VERTICAL_ALIGN],  
3224 - [mxConstants.ALIGN_MIDDLE],  
3225 - ),  
3226 - ),  
3227 - stylePanel3,  
3228 - );  
3229 - var bottom = this.editorUi.toolbar.addButton(  
3230 - "geSprite-bottom",  
3231 - mxResources.get("bottom"),  
3232 - callFn(  
3233 - this.editorUi.menus.createStyleChangeFunction(  
3234 - [mxConstants.STYLE_VERTICAL_ALIGN],  
3235 - [mxConstants.ALIGN_BOTTOM],  
3236 - ),  
3237 - ),  
3238 - stylePanel3,  
3239 - );  
3240 -  
3241 - this.styleButtons([top, middle, bottom]);  
3242 -  
3243 - container.appendChild(stylePanel3);  
3244 -  
3245 - // Hack for updating UI state below based on current text selection  
3246 - // currentTable is the current selected DOM table updated below  
3247 - var sub, sup, full, tableWrapper, currentTable, tableCell, tableRow;  
3248 -  
3249 - if (graph.cellEditor.isContentEditing()) {  
3250 - top.style.display = "none";  
3251 - middle.style.display = "none";  
3252 - bottom.style.display = "none";  
3253 - verticalItem.style.display = "none";  
3254 -  
3255 - full = this.editorUi.toolbar.addButton(  
3256 - "geSprite-justifyfull",  
3257 - mxResources.get("block"),  
3258 - function () {  
3259 - if (full.style.opacity == 1) {  
3260 - document.execCommand("justifyfull", false, null);  
3261 - }  
3262 - },  
3263 - stylePanel3,  
3264 - );  
3265 - full.style.marginRight = "9px";  
3266 - full.style.opacity = 1;  
3267 -  
3268 - this.styleButtons([  
3269 - full,  
3270 - (sub = this.editorUi.toolbar.addButton(  
3271 - "geSprite-subscript",  
3272 - mxResources.get("subscript") + " (" + Editor.ctrlKey + "+,)",  
3273 - function () {  
3274 - document.execCommand("subscript", false, null);  
3275 - },  
3276 - stylePanel3,  
3277 - )),  
3278 - (sup = this.editorUi.toolbar.addButton(  
3279 - "geSprite-superscript",  
3280 - mxResources.get("superscript") + " (" + Editor.ctrlKey + "+.)",  
3281 - function () {  
3282 - document.execCommand("superscript", false, null);  
3283 - },  
3284 - stylePanel3,  
3285 - )),  
3286 - ]);  
3287 - sub.style.marginLeft = "10px";  
3288 -  
3289 - var tmp = stylePanel3.cloneNode(false);  
3290 - tmp.style.paddingTop = "4px";  
3291 - var btns = [  
3292 - this.editorUi.toolbar.addButton(  
3293 - "geSprite-orderedlist",  
3294 - mxResources.get("numberedList"),  
3295 - function () {  
3296 - document.execCommand("insertorderedlist", false, null);  
3297 - },  
3298 - tmp,  
3299 - ),  
3300 - this.editorUi.toolbar.addButton(  
3301 - "geSprite-unorderedlist",  
3302 - mxResources.get("bulletedList"),  
3303 - function () {  
3304 - document.execCommand("insertunorderedlist", false, null);  
3305 - },  
3306 - tmp,  
3307 - ),  
3308 - this.editorUi.toolbar.addButton(  
3309 - "geSprite-outdent",  
3310 - mxResources.get("decreaseIndent"),  
3311 - function () {  
3312 - document.execCommand("outdent", false, null);  
3313 - },  
3314 - tmp,  
3315 - ),  
3316 - this.editorUi.toolbar.addButton(  
3317 - "geSprite-indent",  
3318 - mxResources.get("increaseIndent"),  
3319 - function () {  
3320 - document.execCommand("indent", false, null);  
3321 - },  
3322 - tmp,  
3323 - ),  
3324 - this.editorUi.toolbar.addButton(  
3325 - "geSprite-removeformat",  
3326 - mxResources.get("removeFormat"),  
3327 - function () {  
3328 - document.execCommand("removeformat", false, null);  
3329 - },  
3330 - tmp,  
3331 - ),  
3332 - this.editorUi.toolbar.addButton(  
3333 - "geSprite-code",  
3334 - mxResources.get("html"),  
3335 - function () {  
3336 - graph.cellEditor.toggleViewMode();  
3337 - },  
3338 - tmp,  
3339 - ),  
3340 - ];  
3341 - this.styleButtons(btns);  
3342 - btns[btns.length - 2].style.marginLeft = "10px";  
3343 -  
3344 - container.appendChild(tmp);  
3345 - } else {  
3346 - fontStyleItems[2].style.marginRight = "12px";  
3347 - right.style.marginRight = "12px";  
3348 - }  
3349 -  
3350 - // Label position  
3351 - var stylePanel4 = stylePanel.cloneNode(false);  
3352 - stylePanel4.style.marginLeft = "0px";  
3353 - stylePanel4.style.paddingTop = "8px";  
3354 - stylePanel4.style.paddingBottom = "4px";  
3355 - stylePanel4.style.fontWeight = "normal";  
3356 -  
3357 - mxUtils.write(stylePanel4, mxResources.get("position"));  
3358 -  
3359 - // Adds label position options  
3360 - var positionSelect = document.createElement("select");  
3361 - positionSelect.style.position = "absolute";  
3362 - positionSelect.style.left = "126px";  
3363 - positionSelect.style.width = "98px";  
3364 - positionSelect.style.border = "1px solid rgb(160, 160, 160)";  
3365 - positionSelect.style.borderRadius = "4px";  
3366 - positionSelect.style.marginTop = "-2px";  
3367 -  
3368 - var directions = [  
3369 - "topLeft",  
3370 - "top",  
3371 - "topRight",  
3372 - "left",  
3373 - "center",  
3374 - "right",  
3375 - "bottomLeft",  
3376 - "bottom",  
3377 - "bottomRight",  
3378 - ];  
3379 - var lset = {  
3380 - topLeft: [  
3381 - mxConstants.ALIGN_LEFT,  
3382 - mxConstants.ALIGN_TOP,  
3383 - mxConstants.ALIGN_RIGHT,  
3384 - mxConstants.ALIGN_BOTTOM,  
3385 - ],  
3386 - top: [  
3387 - mxConstants.ALIGN_CENTER,  
3388 - mxConstants.ALIGN_TOP,  
3389 - mxConstants.ALIGN_CENTER,  
3390 - mxConstants.ALIGN_BOTTOM,  
3391 - ],  
3392 - topRight: [  
3393 - mxConstants.ALIGN_RIGHT,  
3394 - mxConstants.ALIGN_TOP,  
3395 - mxConstants.ALIGN_LEFT,  
3396 - mxConstants.ALIGN_BOTTOM,  
3397 - ],  
3398 - left: [  
3399 - mxConstants.ALIGN_LEFT,  
3400 - mxConstants.ALIGN_MIDDLE,  
3401 - mxConstants.ALIGN_RIGHT,  
3402 - mxConstants.ALIGN_MIDDLE,  
3403 - ],  
3404 - center: [  
3405 - mxConstants.ALIGN_CENTER,  
3406 - mxConstants.ALIGN_MIDDLE,  
3407 - mxConstants.ALIGN_CENTER,  
3408 - mxConstants.ALIGN_MIDDLE,  
3409 - ],  
3410 - right: [  
3411 - mxConstants.ALIGN_RIGHT,  
3412 - mxConstants.ALIGN_MIDDLE,  
3413 - mxConstants.ALIGN_LEFT,  
3414 - mxConstants.ALIGN_MIDDLE,  
3415 - ],  
3416 - bottomLeft: [  
3417 - mxConstants.ALIGN_LEFT,  
3418 - mxConstants.ALIGN_BOTTOM,  
3419 - mxConstants.ALIGN_RIGHT,  
3420 - mxConstants.ALIGN_TOP,  
3421 - ],  
3422 - bottom: [  
3423 - mxConstants.ALIGN_CENTER,  
3424 - mxConstants.ALIGN_BOTTOM,  
3425 - mxConstants.ALIGN_CENTER,  
3426 - mxConstants.ALIGN_TOP,  
3427 - ],  
3428 - bottomRight: [  
3429 - mxConstants.ALIGN_RIGHT,  
3430 - mxConstants.ALIGN_BOTTOM,  
3431 - mxConstants.ALIGN_LEFT,  
3432 - mxConstants.ALIGN_TOP,  
3433 - ],  
3434 - };  
3435 -  
3436 - for (var i = 0; i < directions.length; i++) {  
3437 - var positionOption = document.createElement("option");  
3438 - positionOption.setAttribute("value", directions[i]);  
3439 - mxUtils.write(positionOption, mxResources.get(directions[i]));  
3440 - positionSelect.appendChild(positionOption);  
3441 - }  
3442 -  
3443 - stylePanel4.appendChild(positionSelect);  
3444 -  
3445 - // Writing direction  
3446 - var stylePanel5 = stylePanel.cloneNode(false);  
3447 - stylePanel5.style.marginLeft = "0px";  
3448 - stylePanel5.style.paddingTop = "4px";  
3449 - stylePanel5.style.paddingBottom = "4px";  
3450 - stylePanel5.style.fontWeight = "normal";  
3451 -  
3452 - mxUtils.write(stylePanel5, mxResources.get("writingDirection"));  
3453 -  
3454 - // Adds writing direction options  
3455 - // LATER: Handle reselect of same option in all selects (change event  
3456 - // is not fired for same option so have opened state on click) and  
3457 - // handle multiple different styles for current selection  
3458 - var dirSelect = document.createElement("select");  
3459 - dirSelect.style.position = "absolute";  
3460 - dirSelect.style.border = "1px solid rgb(160, 160, 160)";  
3461 - dirSelect.style.left = "126px";  
3462 - dirSelect.style.width = "98px";  
3463 - dirSelect.style.borderRadius = "4px";  
3464 - dirSelect.style.marginTop = "-2px";  
3465 -  
3466 - // NOTE: For automatic we use the value null since automatic  
3467 - // requires the text to be non formatted and non-wrapped  
3468 - var dirs = ["automatic", "leftToRight", "rightToLeft"];  
3469 - var dirSet = {  
3470 - automatic: null,  
3471 - leftToRight: mxConstants.TEXT_DIRECTION_LTR,  
3472 - rightToLeft: mxConstants.TEXT_DIRECTION_RTL,  
3473 - };  
3474 -  
3475 - for (var i = 0; i < dirs.length; i++) {  
3476 - var dirOption = document.createElement("option");  
3477 - dirOption.setAttribute("value", dirs[i]);  
3478 - mxUtils.write(dirOption, mxResources.get(dirs[i]));  
3479 - dirSelect.appendChild(dirOption);  
3480 - }  
3481 -  
3482 - stylePanel5.appendChild(dirSelect);  
3483 -  
3484 - if (!graph.isEditing()) {  
3485 - container.appendChild(stylePanel4);  
3486 -  
3487 - mxEvent.addListener(positionSelect, "change", function (evt) {  
3488 - graph.getModel().beginUpdate();  
3489 - try {  
3490 - var vals = lset[positionSelect.value];  
3491 -  
3492 - if (vals != null) {  
3493 - graph.setCellStyles(  
3494 - mxConstants.STYLE_LABEL_POSITION,  
3495 - vals[0],  
3496 - ss.cells,  
3497 - );  
3498 - graph.setCellStyles(  
3499 - mxConstants.STYLE_VERTICAL_LABEL_POSITION,  
3500 - vals[1],  
3501 - ss.cells,  
3502 - );  
3503 - graph.setCellStyles(mxConstants.STYLE_ALIGN, vals[2], ss.cells);  
3504 - graph.setCellStyles(  
3505 - mxConstants.STYLE_VERTICAL_ALIGN,  
3506 - vals[3],  
3507 - ss.cells,  
3508 - );  
3509 - }  
3510 - } finally {  
3511 - graph.getModel().endUpdate();  
3512 - }  
3513 -  
3514 - mxEvent.consume(evt);  
3515 - });  
3516 -  
3517 - // LATER: Update dir in text editor while editing and update style with label  
3518 - // NOTE: The tricky part is handling and passing on the auto value  
3519 - container.appendChild(stylePanel5);  
3520 -  
3521 - mxEvent.addListener(dirSelect, "change", function (evt) {  
3522 - graph.setCellStyles(  
3523 - mxConstants.STYLE_TEXT_DIRECTION,  
3524 - dirSet[dirSelect.value],  
3525 - ss.cells,  
3526 - );  
3527 - mxEvent.consume(evt);  
3528 - });  
3529 - }  
3530 -  
3531 - // Fontsize  
3532 - var input = document.createElement("input");  
3533 - input.style.position = "absolute";  
3534 - input.style.border = "1px solid rgb(160, 160, 160)";  
3535 - input.style.textAlign = "right";  
3536 - input.style.marginTop = "4px";  
3537 - input.style.left = "161px";  
3538 - input.style.width = "53px";  
3539 - input.style.borderRadius = "4px";  
3540 - input.style.height = "23px";  
3541 - input.style.boxSizing = "border-box";  
3542 - stylePanel2.appendChild(input);  
3543 -  
3544 - // Workaround for font size 4 if no text is selected is update font size below  
3545 - // after first character was entered (as the font element is lazy created)  
3546 - var pendingFontSize = null;  
3547 -  
3548 - var inputUpdate = this.installInputHandler(  
3549 - input,  
3550 - mxConstants.STYLE_FONTSIZE,  
3551 - Menus.prototype.defaultFontSize,  
3552 - 1,  
3553 - 999,  
3554 - " pt",  
3555 - function (fontSize) {  
3556 - // IE does not support containsNode  
3557 - // KNOWN: Fixes font size issues but bypasses undo  
3558 - if (window.getSelection && !mxClient.IS_IE && !mxClient.IS_IE11) {  
3559 - var selection = window.getSelection();  
3560 - var container =  
3561 - selection.rangeCount > 0  
3562 - ? selection.getRangeAt(0).commonAncestorContainer  
3563 - : graph.cellEditor.textarea;  
3564 -  
3565 - function updateSize(elt, ignoreContains) {  
3566 - if (  
3567 - graph.cellEditor.textarea != null &&  
3568 - elt != graph.cellEditor.textarea &&  
3569 - graph.cellEditor.textarea.contains(elt) &&  
3570 - (ignoreContains || selection.containsNode(elt, true))  
3571 - ) {  
3572 - if (elt.nodeName == "FONT") {  
3573 - elt.removeAttribute("size");  
3574 - elt.style.fontSize = fontSize + "px";  
3575 - } else {  
3576 - var css = mxUtils.getCurrentStyle(elt);  
3577 -  
3578 - if (css.fontSize != fontSize + "px") {  
3579 - if (  
3580 - mxUtils.getCurrentStyle(elt.parentNode).fontSize !=  
3581 - fontSize + "px"  
3582 - ) {  
3583 - elt.style.fontSize = fontSize + "px";  
3584 - } else {  
3585 - elt.style.fontSize = "";  
3586 - }  
3587 - }  
3588 - }  
3589 - }  
3590 -  
3591 - ui.fireEvent(  
3592 - new mxEventObject(  
3593 - "styleChanged",  
3594 - "keys",  
3595 - [mxConstants.STYLE_FONTSIZE],  
3596 - "values",  
3597 - [fontSize],  
3598 - "cells",  
3599 - ss.cells,  
3600 - ),  
3601 - );  
3602 - }  
3603 -  
3604 - // Wraps text node or mixed selection with leading text in a font element  
3605 - if (  
3606 - container == graph.cellEditor.textarea ||  
3607 - container.nodeType != mxConstants.NODETYPE_ELEMENT  
3608 - ) {  
3609 - document.execCommand("fontSize", false, "1");  
3610 - }  
3611 -  
3612 - if (container != graph.cellEditor.textarea) {  
3613 - container = container.parentNode;  
3614 - }  
3615 -  
3616 - if (  
3617 - container != null &&  
3618 - container.nodeType == mxConstants.NODETYPE_ELEMENT  
3619 - ) {  
3620 - var elts = container.getElementsByTagName("*");  
3621 - updateSize(container);  
3622 -  
3623 - for (var i = 0; i < elts.length; i++) {  
3624 - updateSize(elts[i]);  
3625 - }  
3626 - }  
3627 -  
3628 - input.value = fontSize + " pt";  
3629 - } else if (window.getSelection || document.selection) {  
3630 - // Checks selection  
3631 - var par = null;  
3632 -  
3633 - if (document.selection) {  
3634 - par = document.selection.createRange().parentElement();  
3635 - } else {  
3636 - var selection = window.getSelection();  
3637 -  
3638 - if (selection.rangeCount > 0) {  
3639 - par = selection.getRangeAt(0).commonAncestorContainer;  
3640 - }  
3641 - }  
3642 -  
3643 - // Node.contains does not work for text nodes in IE11  
3644 - function isOrContains(container, node) {  
3645 - while (node != null) {  
3646 - if (node === container) {  
3647 - return true;  
3648 - }  
3649 -  
3650 - node = node.parentNode;  
3651 - }  
3652 -  
3653 - return false;  
3654 - }  
3655 -  
3656 - if (par != null && isOrContains(graph.cellEditor.textarea, par)) {  
3657 - pendingFontSize = fontSize;  
3658 -  
3659 - // Workaround for can't set font size in px is to change font size afterwards  
3660 - document.execCommand("fontSize", false, "4");  
3661 - var elts = graph.cellEditor.textarea.getElementsByTagName("font");  
3662 -  
3663 - for (var i = 0; i < elts.length; i++) {  
3664 - if (elts[i].getAttribute("size") == "4") {  
3665 - elts[i].removeAttribute("size");  
3666 - elts[i].style.fontSize = pendingFontSize + "px";  
3667 -  
3668 - // Overrides fontSize in input with the one just assigned as a workaround  
3669 - // for potential fontSize values of parent elements that don't match  
3670 - window.setTimeout(function () {  
3671 - input.value = pendingFontSize + " pt";  
3672 - pendingFontSize = null;  
3673 - }, 0);  
3674 -  
3675 - break;  
3676 - }  
3677 - }  
3678 - }  
3679 - }  
3680 - },  
3681 - true,  
3682 - );  
3683 -  
3684 - var stepper = this.createStepper(  
3685 - input,  
3686 - inputUpdate,  
3687 - 1,  
3688 - 10,  
3689 - true,  
3690 - Menus.prototype.defaultFontSize,  
3691 - );  
3692 - stepper.style.display = input.style.display;  
3693 - stepper.style.marginTop = "4px";  
3694 - stepper.style.left = "214px";  
3695 -  
3696 - stylePanel2.appendChild(stepper);  
3697 -  
3698 - var arrow = fontMenu.getElementsByTagName("div")[0];  
3699 - arrow.style.cssFloat = "right";  
3700 -  
3701 - var bgColorApply = null;  
3702 - var currentBgColor = graph.shapeBackgroundColor;  
3703 -  
3704 - var fontColorApply = null;  
3705 - var currentFontColor = graph.shapeForegroundColor;  
3706 -  
3707 - var bgPanel = graph.cellEditor.isContentEditing()  
3708 - ? this.createColorOption(  
3709 - mxResources.get("backgroundColor"),  
3710 - function () {  
3711 - return currentBgColor;  
3712 - },  
3713 - function (color) {  
3714 - document.execCommand(  
3715 - "backcolor",  
3716 - false,  
3717 - color != mxConstants.NONE ? color : "transparent",  
3718 - );  
3719 - ui.fireEvent(  
3720 - new mxEventObject(  
3721 - "styleChanged",  
3722 - "keys",  
3723 - [mxConstants.STYLE_LABEL_BACKGROUNDCOLOR],  
3724 - "values",  
3725 - [color],  
3726 - "cells",  
3727 - ss.cells,  
3728 - ),  
3729 - );  
3730 - },  
3731 - graph.shapeBackgroundColor,  
3732 - {  
3733 - install: function (apply) {  
3734 - bgColorApply = apply;  
3735 - },  
3736 - destroy: function () {  
3737 - bgColorApply = null;  
3738 - },  
3739 - },  
3740 - null,  
3741 - true,  
3742 - )  
3743 - : this.createCellColorOption(  
3744 - mxResources.get("backgroundColor"),  
3745 - mxConstants.STYLE_LABEL_BACKGROUNDCOLOR,  
3746 - "default",  
3747 - null,  
3748 - function (color) {  
3749 - graph.updateLabelElements(ss.cells, function (elt) {  
3750 - elt.style.backgroundColor = null;  
3751 - });  
3752 - },  
3753 - graph.shapeBackgroundColor,  
3754 - );  
3755 - bgPanel.style.fontWeight = "bold";  
3756 -  
3757 - var borderPanel = this.createCellColorOption(  
3758 - mxResources.get("borderColor"),  
3759 - mxConstants.STYLE_LABEL_BORDERCOLOR,  
3760 - "default",  
3761 - null,  
3762 - null,  
3763 - graph.shapeForegroundColor,  
3764 - );  
3765 - borderPanel.style.fontWeight = "bold";  
3766 -  
3767 - var defs =  
3768 - ss.vertices.length >= 1  
3769 - ? graph.stylesheet.getDefaultVertexStyle()  
3770 - : graph.stylesheet.getDefaultEdgeStyle();  
3771 -  
3772 - var panel = graph.cellEditor.isContentEditing()  
3773 - ? this.createColorOption(  
3774 - mxResources.get("fontColor"),  
3775 - function () {  
3776 - return currentFontColor;  
3777 - },  
3778 - function (color) {  
3779 - if (mxClient.IS_FF) {  
3780 - // Workaround for Firefox that adds the font element around  
3781 - // anchor elements which ignore inherited colors is to move  
3782 - // the font element inside anchor elements  
3783 - var tmp = graph.cellEditor.textarea.getElementsByTagName("font");  
3784 - var oldFonts = [];  
3785 -  
3786 - for (var i = 0; i < tmp.length; i++) {  
3787 - oldFonts.push({  
3788 - node: tmp[i],  
3789 - color: tmp[i].getAttribute("color"),  
3790 - });  
3791 - }  
3792 -  
3793 - document.execCommand(  
3794 - "forecolor",  
3795 - false,  
3796 - color != mxConstants.NONE ? color : "transparent",  
3797 - );  
3798 - ui.fireEvent(  
3799 - new mxEventObject(  
3800 - "styleChanged",  
3801 - "keys",  
3802 - [mxConstants.STYLE_FONTCOLOR],  
3803 - "values",  
3804 - [color],  
3805 - "cells",  
3806 - ss.cells,  
3807 - ),  
3808 - );  
3809 -  
3810 - // Finds the new or changed font element  
3811 - var newFonts =  
3812 - graph.cellEditor.textarea.getElementsByTagName("font");  
3813 -  
3814 - for (var i = 0; i < newFonts.length; i++) {  
3815 - if (  
3816 - i >= oldFonts.length ||  
3817 - newFonts[i] != oldFonts[i].node ||  
3818 - (newFonts[i] == oldFonts[i].node &&  
3819 - newFonts[i].getAttribute("color") != oldFonts[i].color)  
3820 - ) {  
3821 - var child = newFonts[i].firstChild;  
3822 -  
3823 - // Moves the font element to inside the anchor element and adopts all children  
3824 - if (  
3825 - child != null &&  
3826 - child.nodeName == "A" &&  
3827 - child.nextSibling == null &&  
3828 - child.firstChild != null  
3829 - ) {  
3830 - var parent = newFonts[i].parentNode;  
3831 - parent.insertBefore(child, newFonts[i]);  
3832 - var tmp = child.firstChild;  
3833 -  
3834 - while (tmp != null) {  
3835 - var next = tmp.nextSibling;  
3836 - newFonts[i].appendChild(tmp);  
3837 - tmp = next;  
3838 - }  
3839 -  
3840 - child.appendChild(newFonts[i]);  
3841 - }  
3842 -  
3843 - break;  
3844 - }  
3845 - }  
3846 - } else {  
3847 - document.execCommand(  
3848 - "forecolor",  
3849 - false,  
3850 - color != mxConstants.NONE ? color : "transparent",  
3851 - );  
3852 - ui.fireEvent(  
3853 - new mxEventObject(  
3854 - "styleChanged",  
3855 - "keys",  
3856 - [mxConstants.STYLE_FONTCOLOR],  
3857 - "values",  
3858 - [color],  
3859 - "cells",  
3860 - ss.cells,  
3861 - ),  
3862 - );  
3863 - }  
3864 - },  
3865 - defs[mxConstants.STYLE_FONTCOLOR] != null  
3866 - ? defs[mxConstants.STYLE_FONTCOLOR]  
3867 - : graph.shapeForegroundColor,  
3868 - {  
3869 - install: function (apply) {  
3870 - fontColorApply = apply;  
3871 - },  
3872 - destroy: function () {  
3873 - fontColorApply = null;  
3874 - },  
3875 - },  
3876 - null,  
3877 - true,  
3878 - )  
3879 - : this.createCellColorOption(  
3880 - mxResources.get("fontColor"),  
3881 - mxConstants.STYLE_FONTCOLOR,  
3882 - "default",  
3883 - function (color) {  
3884 - if (color == mxConstants.NONE) {  
3885 - bgPanel.style.display = "none";  
3886 - } else {  
3887 - bgPanel.style.display = "";  
3888 - }  
3889 -  
3890 - borderPanel.style.display = bgPanel.style.display;  
3891 - },  
3892 - function (color) {  
3893 - if (color == mxConstants.NONE) {  
3894 - graph.setCellStyles(mxConstants.STYLE_NOLABEL, "1", ss.cells);  
3895 - } else {  
3896 - graph.setCellStyles(mxConstants.STYLE_NOLABEL, null, ss.cells);  
3897 - }  
3898 -  
3899 - graph.setCellStyles(mxConstants.STYLE_FONTCOLOR, color, ss.cells);  
3900 -  
3901 - graph.updateLabelElements(ss.cells, function (elt) {  
3902 - elt.removeAttribute("color");  
3903 - elt.style.color = null;  
3904 - });  
3905 - },  
3906 - graph.shapeForegroundColor,  
3907 - );  
3908 - panel.style.fontWeight = "bold";  
3909 -  
3910 - colorPanel.appendChild(panel);  
3911 - colorPanel.appendChild(bgPanel);  
3912 -  
3913 - if (!graph.cellEditor.isContentEditing()) {  
3914 - colorPanel.appendChild(borderPanel);  
3915 - }  
3916 -  
3917 - container.appendChild(colorPanel);  
3918 -  
3919 - var extraPanel = this.createPanel();  
3920 - extraPanel.style.paddingTop = "2px";  
3921 - extraPanel.style.paddingBottom = "4px";  
3922 -  
3923 - var wwCells = graph.filterSelectionCells(  
3924 - mxUtils.bind(this, function (cell) {  
3925 - var state = graph.view.getState(cell);  
3926 -  
3927 - return (  
3928 - state == null ||  
3929 - graph.isAutoSizeState(state) ||  
3930 - graph.getModel().isEdge(cell) ||  
3931 - (!graph.isTableRow(cell) &&  
3932 - !graph.isTableCell(cell) &&  
3933 - !graph.isCellResizable(cell))  
3934 - );  
3935 - }),  
3936 - );  
3937 -  
3938 - var wwOpt = this.createCellOption(  
3939 - mxResources.get("wordWrap"),  
3940 - mxConstants.STYLE_WHITE_SPACE,  
3941 - null,  
3942 - "wrap",  
3943 - "null",  
3944 - null,  
3945 - null,  
3946 - true,  
3947 - wwCells,  
3948 - );  
3949 - wwOpt.style.fontWeight = "bold";  
3950 -  
3951 - // Word wrap in edge labels only supported via labelWidth style  
3952 - if (wwCells.length > 0) {  
3953 - extraPanel.appendChild(wwOpt);  
3954 - }  
3955 -  
3956 - // Delegates switch of style to formattedText action as it also convertes newlines  
3957 - var htmlOpt = this.createCellOption(  
3958 - mxResources.get("formattedText"),  
3959 - "html",  
3960 - 0,  
3961 - null,  
3962 - null,  
3963 - null,  
3964 - ui.actions.get("formattedText"),  
3965 - );  
3966 - htmlOpt.style.fontWeight = "bold";  
3967 - extraPanel.appendChild(htmlOpt);  
3968 -  
3969 - var spacingPanel = this.createPanel();  
3970 - spacingPanel.style.paddingTop = "10px";  
3971 - spacingPanel.style.paddingBottom = "28px";  
3972 - spacingPanel.style.fontWeight = "normal";  
3973 -  
3974 - var span = document.createElement("div");  
3975 - span.style.position = "absolute";  
3976 - span.style.width = "70px";  
3977 - span.style.marginTop = "0px";  
3978 - span.style.fontWeight = "bold";  
3979 - mxUtils.write(span, mxResources.get("spacing"));  
3980 - spacingPanel.appendChild(span);  
3981 -  
3982 - var topUpdate, globalUpdate, leftUpdate, bottomUpdate, rightUpdate;  
3983 - var topSpacing = this.addUnitInput(spacingPanel, "pt", 87, 52, function () {  
3984 - topUpdate.apply(this, arguments);  
3985 - });  
3986 - var globalSpacing = this.addUnitInput(  
3987 - spacingPanel,  
3988 - "pt",  
3989 - 16,  
3990 - 52,  
3991 - function () {  
3992 - globalUpdate.apply(this, arguments);  
3993 - },  
3994 - );  
3995 -  
3996 - mxUtils.br(spacingPanel);  
3997 - this.addLabel(spacingPanel, mxResources.get("top"), 87);  
3998 - this.addLabel(spacingPanel, mxResources.get("global"), 16);  
3999 - mxUtils.br(spacingPanel);  
4000 - mxUtils.br(spacingPanel);  
4001 -  
4002 - var leftSpacing = this.addUnitInput(spacingPanel, "pt", 158, 52, function () {  
4003 - leftUpdate.apply(this, arguments);  
4004 - });  
4005 - var bottomSpacing = this.addUnitInput(  
4006 - spacingPanel,  
4007 - "pt",  
4008 - 87,  
4009 - 52,  
4010 - function () {  
4011 - bottomUpdate.apply(this, arguments);  
4012 - },  
4013 - );  
4014 - var rightSpacing = this.addUnitInput(spacingPanel, "pt", 16, 52, function () {  
4015 - rightUpdate.apply(this, arguments);  
4016 - });  
4017 -  
4018 - mxUtils.br(spacingPanel);  
4019 - this.addLabel(spacingPanel, mxResources.get("left"), 158);  
4020 - this.addLabel(spacingPanel, mxResources.get("bottom"), 87);  
4021 - this.addLabel(spacingPanel, mxResources.get("right"), 16);  
4022 -  
4023 - if (!graph.cellEditor.isContentEditing()) {  
4024 - container.appendChild(extraPanel);  
4025 - container.appendChild(  
4026 - this.createRelativeOption(  
4027 - mxResources.get("opacity"),  
4028 - mxConstants.STYLE_TEXT_OPACITY,  
4029 - ),  
4030 - );  
4031 - container.appendChild(spacingPanel);  
4032 - } else {  
4033 - var selState = null;  
4034 - var lineHeightInput = null;  
4035 -  
4036 - container.appendChild(  
4037 - this.createRelativeOption(  
4038 - mxResources.get("lineheight"),  
4039 - null,  
4040 - null,  
4041 - function (input) {  
4042 - var value = input.value == "" ? 120 : parseInt(input.value);  
4043 - value = Math.max(0, isNaN(value) ? 120 : value);  
4044 -  
4045 - if (selState != null) {  
4046 - graph.cellEditor.restoreSelection(selState);  
4047 - selState = null;  
4048 - }  
4049 -  
4050 - var selectedElement = graph.getSelectedElement();  
4051 - var node = selectedElement;  
4052 -  
4053 - while (  
4054 - node != null &&  
4055 - node.nodeType != mxConstants.NODETYPE_ELEMENT  
4056 - ) {  
4057 - node = node.parentNode;  
4058 - }  
4059 -  
4060 - if (  
4061 - node != null &&  
4062 - node == graph.cellEditor.textarea &&  
4063 - graph.cellEditor.textarea.firstChild != null  
4064 - ) {  
4065 - if (graph.cellEditor.textarea.firstChild.nodeName != "P") {  
4066 - graph.cellEditor.textarea.innerHTML =  
4067 - "<p>" + graph.cellEditor.textarea.innerHTML + "</p>";  
4068 - }  
4069 -  
4070 - node = graph.cellEditor.textarea.firstChild;  
4071 - }  
4072 -  
4073 - if (  
4074 - node != null &&  
4075 - graph.cellEditor.textarea != null &&  
4076 - node != graph.cellEditor.textarea &&  
4077 - graph.cellEditor.textarea.contains(node)  
4078 - ) {  
4079 - node.style.lineHeight = value / 100;  
4080 - }  
4081 -  
4082 - input.value = value + " %";  
4083 - },  
4084 - function (input) {  
4085 - // Used in CSS handler to update current value  
4086 - lineHeightInput = input;  
4087 -  
4088 - // KNOWN: Arrow up/down clear selection text in quirks/IE 8  
4089 - // Text size via arrow button limits to 16 in IE11. Why?  
4090 - mxEvent.addListener(input, "mousedown", function () {  
4091 - if (document.activeElement == graph.cellEditor.textarea) {  
4092 - selState = graph.cellEditor.saveSelection();  
4093 - }  
4094 - });  
4095 -  
4096 - mxEvent.addListener(input, "touchstart", function () {  
4097 - if (document.activeElement == graph.cellEditor.textarea) {  
4098 - selState = graph.cellEditor.saveSelection();  
4099 - }  
4100 - });  
4101 -  
4102 - input.value = "120 %";  
4103 - },  
4104 - ),  
4105 - );  
4106 -  
4107 - var insertPanel = stylePanel.cloneNode(false);  
4108 - insertPanel.style.paddingLeft = "0px";  
4109 - var insertBtns = this.editorUi.toolbar.addItems(  
4110 - ["link", "image"],  
4111 - insertPanel,  
4112 - true,  
4113 - );  
4114 -  
4115 - var btns = [  
4116 - this.editorUi.toolbar.addButton(  
4117 - "geSprite-horizontalrule",  
4118 - mxResources.get("insertHorizontalRule"),  
4119 - function () {  
4120 - document.execCommand("inserthorizontalrule", false);  
4121 - },  
4122 - insertPanel,  
4123 - ),  
4124 - this.editorUi.toolbar.addMenuFunctionInContainer(  
4125 - insertPanel,  
4126 - "geSprite-table",  
4127 - mxResources.get("table"),  
4128 - false,  
4129 - mxUtils.bind(this, function (menu) {  
4130 - this.editorUi.menus.addInsertTableItem(menu, null, null, false);  
4131 - }),  
4132 - ),  
4133 - ];  
4134 - this.styleButtons(insertBtns);  
4135 - this.styleButtons(btns);  
4136 -  
4137 - var wrapper2 = this.createPanel();  
4138 - wrapper2.style.paddingTop = "10px";  
4139 - wrapper2.style.paddingBottom = "10px";  
4140 - wrapper2.appendChild(this.createTitle(mxResources.get("insert")));  
4141 - wrapper2.appendChild(insertPanel);  
4142 - container.appendChild(wrapper2);  
4143 -  
4144 - var tablePanel = stylePanel.cloneNode(false);  
4145 - tablePanel.style.paddingLeft = "0px";  
4146 -  
4147 - var btns = [  
4148 - this.editorUi.toolbar.addButton(  
4149 - "geSprite-insertcolumnbefore",  
4150 - mxResources.get("insertColumnBefore"),  
4151 - mxUtils.bind(this, function () {  
4152 - try {  
4153 - if (currentTable != null) {  
4154 - graph.insertColumn(  
4155 - currentTable,  
4156 - tableCell != null ? tableCell.cellIndex : 0,  
4157 - );  
4158 - }  
4159 - } catch (e) {  
4160 - this.editorUi.handleError(e);  
4161 - }  
4162 - }),  
4163 - tablePanel,  
4164 - ),  
4165 - this.editorUi.toolbar.addButton(  
4166 - "geSprite-insertcolumnafter",  
4167 - mxResources.get("insertColumnAfter"),  
4168 - mxUtils.bind(this, function () {  
4169 - try {  
4170 - if (currentTable != null) {  
4171 - graph.insertColumn(  
4172 - currentTable,  
4173 - tableCell != null ? tableCell.cellIndex + 1 : -1,  
4174 - );  
4175 - }  
4176 - } catch (e) {  
4177 - this.editorUi.handleError(e);  
4178 - }  
4179 - }),  
4180 - tablePanel,  
4181 - ),  
4182 - this.editorUi.toolbar.addButton(  
4183 - "geSprite-deletecolumn",  
4184 - mxResources.get("deleteColumn"),  
4185 - mxUtils.bind(this, function () {  
4186 - try {  
4187 - if (currentTable != null && tableCell != null) {  
4188 - graph.deleteColumn(currentTable, tableCell.cellIndex);  
4189 - }  
4190 - } catch (e) {  
4191 - this.editorUi.handleError(e);  
4192 - }  
4193 - }),  
4194 - tablePanel,  
4195 - ),  
4196 - this.editorUi.toolbar.addButton(  
4197 - "geSprite-insertrowbefore",  
4198 - mxResources.get("insertRowBefore"),  
4199 - mxUtils.bind(this, function () {  
4200 - try {  
4201 - if (currentTable != null && tableRow != null) {  
4202 - graph.insertRow(currentTable, tableRow.sectionRowIndex);  
4203 - }  
4204 - } catch (e) {  
4205 - this.editorUi.handleError(e);  
4206 - }  
4207 - }),  
4208 - tablePanel,  
4209 - ),  
4210 - this.editorUi.toolbar.addButton(  
4211 - "geSprite-insertrowafter",  
4212 - mxResources.get("insertRowAfter"),  
4213 - mxUtils.bind(this, function () {  
4214 - try {  
4215 - if (currentTable != null && tableRow != null) {  
4216 - graph.insertRow(currentTable, tableRow.sectionRowIndex + 1);  
4217 - }  
4218 - } catch (e) {  
4219 - this.editorUi.handleError(e);  
4220 - }  
4221 - }),  
4222 - tablePanel,  
4223 - ),  
4224 - this.editorUi.toolbar.addButton(  
4225 - "geSprite-deleterow",  
4226 - mxResources.get("deleteRow"),  
4227 - mxUtils.bind(this, function () {  
4228 - try {  
4229 - if (currentTable != null && tableRow != null) {  
4230 - graph.deleteRow(currentTable, tableRow.sectionRowIndex);  
4231 - }  
4232 - } catch (e) {  
4233 - this.editorUi.handleError(e);  
4234 - }  
4235 - }),  
4236 - tablePanel,  
4237 - ),  
4238 - ];  
4239 - this.styleButtons(btns);  
4240 - btns[2].style.marginRight = "10px";  
4241 -  
4242 - var wrapper3 = this.createPanel();  
4243 - wrapper3.style.paddingTop = "10px";  
4244 - wrapper3.style.paddingBottom = "10px";  
4245 - wrapper3.appendChild(this.createTitle(mxResources.get("table")));  
4246 - wrapper3.appendChild(tablePanel);  
4247 -  
4248 - var tablePanel2 = stylePanel.cloneNode(false);  
4249 - tablePanel2.style.paddingLeft = "0px";  
4250 -  
4251 - var btns = [  
4252 - this.editorUi.toolbar.addButton(  
4253 - "geSprite-strokecolor",  
4254 - mxResources.get("borderColor"),  
4255 - mxUtils.bind(this, function (evt) {  
4256 - if (currentTable != null) {  
4257 - // Converts rgb(r,g,b) values  
4258 - var color = currentTable.style.borderColor.replace(  
4259 - /\brgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)/g,  
4260 - function ($0, $1, $2, $3) {  
4261 - return (  
4262 - "#" +  
4263 - ("0" + Number($1).toString(16)).substr(-2) +  
4264 - ("0" + Number($2).toString(16)).substr(-2) +  
4265 - ("0" + Number($3).toString(16)).substr(-2)  
4266 - );  
4267 - },  
4268 - );  
4269 - this.editorUi.pickColor(color, function (newColor) {  
4270 - var targetElt =  
4271 - tableCell != null && (evt == null || !mxEvent.isShiftDown(evt))  
4272 - ? tableCell  
4273 - : currentTable;  
4274 -  
4275 - graph.processElements(targetElt, function (elt) {  
4276 - elt.style.border = null;  
4277 - });  
4278 -  
4279 - if (newColor == null || newColor == mxConstants.NONE) {  
4280 - targetElt.removeAttribute("border");  
4281 - targetElt.style.border = "";  
4282 - targetElt.style.borderCollapse = "";  
4283 - } else {  
4284 - targetElt.setAttribute("border", "1");  
4285 - targetElt.style.border = "1px solid " + newColor;  
4286 - targetElt.style.borderCollapse = "collapse";  
4287 - }  
4288 - });  
4289 - }  
4290 - }),  
4291 - tablePanel2,  
4292 - ),  
4293 - this.editorUi.toolbar.addButton(  
4294 - "geSprite-fillcolor",  
4295 - mxResources.get("backgroundColor"),  
4296 - mxUtils.bind(this, function (evt) {  
4297 - // Converts rgb(r,g,b) values  
4298 - if (currentTable != null) {  
4299 - var color = currentTable.style.backgroundColor.replace(  
4300 - /\brgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)/g,  
4301 - function ($0, $1, $2, $3) {  
4302 - return (  
4303 - "#" +  
4304 - ("0" + Number($1).toString(16)).substr(-2) +  
4305 - ("0" + Number($2).toString(16)).substr(-2) +  
4306 - ("0" + Number($3).toString(16)).substr(-2)  
4307 - );  
4308 - },  
4309 - );  
4310 - this.editorUi.pickColor(color, function (newColor) {  
4311 - var targetElt =  
4312 - tableCell != null && (evt == null || !mxEvent.isShiftDown(evt))  
4313 - ? tableCell  
4314 - : currentTable;  
4315 -  
4316 - graph.processElements(targetElt, function (elt) {  
4317 - elt.style.backgroundColor = null;  
4318 - });  
4319 -  
4320 - if (newColor == null || newColor == mxConstants.NONE) {  
4321 - targetElt.style.backgroundColor = "";  
4322 - } else {  
4323 - targetElt.style.backgroundColor = newColor;  
4324 - }  
4325 - });  
4326 - }  
4327 - }),  
4328 - tablePanel2,  
4329 - ),  
4330 - this.editorUi.toolbar.addButton(  
4331 - "geSprite-fit",  
4332 - mxResources.get("spacing"),  
4333 - function () {  
4334 - if (currentTable != null) {  
4335 - var value = currentTable.getAttribute("cellPadding") || 0;  
4336 -  
4337 - var dlg = new FilenameDialog(  
4338 - ui,  
4339 - value,  
4340 - mxResources.get("apply"),  
4341 - mxUtils.bind(this, function (newValue) {  
4342 - if (newValue != null && newValue.length > 0) {  
4343 - currentTable.setAttribute("cellPadding", newValue);  
4344 - } else {  
4345 - currentTable.removeAttribute("cellPadding");  
4346 - }  
4347 - }),  
4348 - mxResources.get("spacing"),  
4349 - );  
4350 - ui.showDialog(dlg.container, 300, 80, true, true);  
4351 - dlg.init();  
4352 - }  
4353 - },  
4354 - tablePanel2,  
4355 - ),  
4356 - this.editorUi.toolbar.addButton(  
4357 - "geSprite-left",  
4358 - mxResources.get("left"),  
4359 - function () {  
4360 - if (currentTable != null) {  
4361 - currentTable.setAttribute("align", "left");  
4362 - }  
4363 - },  
4364 - tablePanel2,  
4365 - ),  
4366 - this.editorUi.toolbar.addButton(  
4367 - "geSprite-center",  
4368 - mxResources.get("center"),  
4369 - function () {  
4370 - if (currentTable != null) {  
4371 - currentTable.setAttribute("align", "center");  
4372 - }  
4373 - },  
4374 - tablePanel2,  
4375 - ),  
4376 - this.editorUi.toolbar.addButton(  
4377 - "geSprite-right",  
4378 - mxResources.get("right"),  
4379 - function () {  
4380 - if (currentTable != null) {  
4381 - currentTable.setAttribute("align", "right");  
4382 - }  
4383 - },  
4384 - tablePanel2,  
4385 - ),  
4386 - ];  
4387 - this.styleButtons(btns);  
4388 - btns[2].style.marginRight = "10px";  
4389 -  
4390 - wrapper3.appendChild(tablePanel2);  
4391 - container.appendChild(wrapper3);  
4392 -  
4393 - tableWrapper = wrapper3;  
4394 - }  
4395 -  
4396 - function setSelected(elt, selected) {  
4397 - elt.style.backgroundImage = selected  
4398 - ? Editor.isDarkMode()  
4399 - ? "linear-gradient(rgb(0 161 241) 0px, rgb(0, 97, 146) 100%)"  
4400 - : "linear-gradient(#c5ecff 0px,#87d4fb 100%)"  
4401 - : "";  
4402 - }  
4403 -  
4404 - var listener = mxUtils.bind(this, function (sender, evt, force) {  
4405 - ss = ui.getSelectionState();  
4406 - var fontStyle = mxUtils.getValue(ss.style, mxConstants.STYLE_FONTSTYLE, 0);  
4407 - setSelected(  
4408 - fontStyleItems[0],  
4409 - (fontStyle & mxConstants.FONT_BOLD) == mxConstants.FONT_BOLD,  
4410 - );  
4411 - setSelected(  
4412 - fontStyleItems[1],  
4413 - (fontStyle & mxConstants.FONT_ITALIC) == mxConstants.FONT_ITALIC,  
4414 - );  
4415 - setSelected(  
4416 - fontStyleItems[2],  
4417 - (fontStyle & mxConstants.FONT_UNDERLINE) == mxConstants.FONT_UNDERLINE,  
4418 - );  
4419 - fontMenu.firstChild.nodeValue = mxUtils.getValue(  
4420 - ss.style,  
4421 - mxConstants.STYLE_FONTFAMILY,  
4422 - Menus.prototype.defaultFont,  
4423 - );  
4424 -  
4425 - setSelected(  
4426 - verticalItem,  
4427 - mxUtils.getValue(ss.style, mxConstants.STYLE_HORIZONTAL, "1") == "0",  
4428 - );  
4429 -  
4430 - if (force || document.activeElement != input) {  
4431 - var tmp = parseFloat(  
4432 - mxUtils.getValue(  
4433 - ss.style,  
4434 - mxConstants.STYLE_FONTSIZE,  
4435 - Menus.prototype.defaultFontSize,  
4436 - ),  
4437 - );  
4438 - input.value = isNaN(tmp) ? "" : tmp + " pt";  
4439 - }  
4440 -  
4441 - var align = mxUtils.getValue(  
4442 - ss.style,  
4443 - mxConstants.STYLE_ALIGN,  
4444 - mxConstants.ALIGN_CENTER,  
4445 - );  
4446 - setSelected(left, align == mxConstants.ALIGN_LEFT);  
4447 - setSelected(center, align == mxConstants.ALIGN_CENTER);  
4448 - setSelected(right, align == mxConstants.ALIGN_RIGHT);  
4449 -  
4450 - var valign = mxUtils.getValue(  
4451 - ss.style,  
4452 - mxConstants.STYLE_VERTICAL_ALIGN,  
4453 - mxConstants.ALIGN_MIDDLE,  
4454 - );  
4455 - setSelected(top, valign == mxConstants.ALIGN_TOP);  
4456 - setSelected(middle, valign == mxConstants.ALIGN_MIDDLE);  
4457 - setSelected(bottom, valign == mxConstants.ALIGN_BOTTOM);  
4458 -  
4459 - var pos = mxUtils.getValue(  
4460 - ss.style,  
4461 - mxConstants.STYLE_LABEL_POSITION,  
4462 - mxConstants.ALIGN_CENTER,  
4463 - );  
4464 - var vpos = mxUtils.getValue(  
4465 - ss.style,  
4466 - mxConstants.STYLE_VERTICAL_LABEL_POSITION,  
4467 - mxConstants.ALIGN_MIDDLE,  
4468 - );  
4469 -  
4470 - if (pos == mxConstants.ALIGN_LEFT && vpos == mxConstants.ALIGN_TOP) {  
4471 - positionSelect.value = "topLeft";  
4472 - } else if (  
4473 - pos == mxConstants.ALIGN_CENTER &&  
4474 - vpos == mxConstants.ALIGN_TOP  
4475 - ) {  
4476 - positionSelect.value = "top";  
4477 - } else if (  
4478 - pos == mxConstants.ALIGN_RIGHT &&  
4479 - vpos == mxConstants.ALIGN_TOP  
4480 - ) {  
4481 - positionSelect.value = "topRight";  
4482 - } else if (  
4483 - pos == mxConstants.ALIGN_LEFT &&  
4484 - vpos == mxConstants.ALIGN_BOTTOM  
4485 - ) {  
4486 - positionSelect.value = "bottomLeft";  
4487 - } else if (  
4488 - pos == mxConstants.ALIGN_CENTER &&  
4489 - vpos == mxConstants.ALIGN_BOTTOM  
4490 - ) {  
4491 - positionSelect.value = "bottom";  
4492 - } else if (  
4493 - pos == mxConstants.ALIGN_RIGHT &&  
4494 - vpos == mxConstants.ALIGN_BOTTOM  
4495 - ) {  
4496 - positionSelect.value = "bottomRight";  
4497 - } else if (pos == mxConstants.ALIGN_LEFT) {  
4498 - positionSelect.value = "left";  
4499 - } else if (pos == mxConstants.ALIGN_RIGHT) {  
4500 - positionSelect.value = "right";  
4501 - } else {  
4502 - positionSelect.value = "center";  
4503 - }  
4504 -  
4505 - var dir = mxUtils.getValue(  
4506 - ss.style,  
4507 - mxConstants.STYLE_TEXT_DIRECTION,  
4508 - mxConstants.DEFAULT_TEXT_DIRECTION,  
4509 - );  
4510 -  
4511 - if (dir == mxConstants.TEXT_DIRECTION_RTL) {  
4512 - dirSelect.value = "rightToLeft";  
4513 - } else if (dir == mxConstants.TEXT_DIRECTION_LTR) {  
4514 - dirSelect.value = "leftToRight";  
4515 - } else if (dir == mxConstants.TEXT_DIRECTION_AUTO) {  
4516 - dirSelect.value = "automatic";  
4517 - }  
4518 -  
4519 - if (force || document.activeElement != globalSpacing) {  
4520 - var tmp = parseFloat(  
4521 - mxUtils.getValue(ss.style, mxConstants.STYLE_SPACING, 2),  
4522 - );  
4523 - globalSpacing.value = isNaN(tmp) ? "" : tmp + " pt";  
4524 - }  
4525 -  
4526 - if (force || document.activeElement != topSpacing) {  
4527 - var tmp = parseFloat(  
4528 - mxUtils.getValue(ss.style, mxConstants.STYLE_SPACING_TOP, 0),  
4529 - );  
4530 - topSpacing.value = isNaN(tmp) ? "" : tmp + " pt";  
4531 - }  
4532 -  
4533 - if (force || document.activeElement != rightSpacing) {  
4534 - var tmp = parseFloat(  
4535 - mxUtils.getValue(ss.style, mxConstants.STYLE_SPACING_RIGHT, 0),  
4536 - );  
4537 - rightSpacing.value = isNaN(tmp) ? "" : tmp + " pt";  
4538 - }  
4539 -  
4540 - if (force || document.activeElement != bottomSpacing) {  
4541 - var tmp = parseFloat(  
4542 - mxUtils.getValue(ss.style, mxConstants.STYLE_SPACING_BOTTOM, 0),  
4543 - );  
4544 - bottomSpacing.value = isNaN(tmp) ? "" : tmp + " pt";  
4545 - }  
4546 -  
4547 - if (force || document.activeElement != leftSpacing) {  
4548 - var tmp = parseFloat(  
4549 - mxUtils.getValue(ss.style, mxConstants.STYLE_SPACING_LEFT, 0),  
4550 - );  
4551 - leftSpacing.value = isNaN(tmp) ? "" : tmp + " pt";  
4552 - }  
4553 - });  
4554 -  
4555 - globalUpdate = this.installInputHandler(  
4556 - globalSpacing,  
4557 - mxConstants.STYLE_SPACING,  
4558 - 2,  
4559 - -999,  
4560 - 999,  
4561 - " pt",  
4562 - );  
4563 - topUpdate = this.installInputHandler(  
4564 - topSpacing,  
4565 - mxConstants.STYLE_SPACING_TOP,  
4566 - 0,  
4567 - -999,  
4568 - 999,  
4569 - " pt",  
4570 - );  
4571 - rightUpdate = this.installInputHandler(  
4572 - rightSpacing,  
4573 - mxConstants.STYLE_SPACING_RIGHT,  
4574 - 0,  
4575 - -999,  
4576 - 999,  
4577 - " pt",  
4578 - );  
4579 - bottomUpdate = this.installInputHandler(  
4580 - bottomSpacing,  
4581 - mxConstants.STYLE_SPACING_BOTTOM,  
4582 - 0,  
4583 - -999,  
4584 - 999,  
4585 - " pt",  
4586 - );  
4587 - leftUpdate = this.installInputHandler(  
4588 - leftSpacing,  
4589 - mxConstants.STYLE_SPACING_LEFT,  
4590 - 0,  
4591 - -999,  
4592 - 999,  
4593 - " pt",  
4594 - );  
4595 -  
4596 - this.addKeyHandler(input, listener);  
4597 - this.addKeyHandler(globalSpacing, listener);  
4598 - this.addKeyHandler(topSpacing, listener);  
4599 - this.addKeyHandler(rightSpacing, listener);  
4600 - this.addKeyHandler(bottomSpacing, listener);  
4601 - this.addKeyHandler(leftSpacing, listener);  
4602 -  
4603 - graph.getModel().addListener(mxEvent.CHANGE, listener);  
4604 - this.listeners.push({  
4605 - destroy: function () {  
4606 - graph.getModel().removeListener(listener);  
4607 - },  
4608 - });  
4609 - listener();  
4610 -  
4611 - if (graph.cellEditor.isContentEditing()) {  
4612 - var updating = false;  
4613 -  
4614 - var updateCssHandler = function () {  
4615 - if (!updating) {  
4616 - updating = true;  
4617 -  
4618 - window.setTimeout(function () {  
4619 - var node = graph.getSelectedEditingElement();  
4620 -  
4621 - if (node != null) {  
4622 - function getRelativeLineHeight(fontSize, css, elt) {  
4623 - if (elt.style != null && css != null) {  
4624 - var lineHeight = css.lineHeight;  
4625 -  
4626 - if (  
4627 - elt.style.lineHeight != null &&  
4628 - elt.style.lineHeight.substring(  
4629 - elt.style.lineHeight.length - 1,  
4630 - ) == "%"  
4631 - ) {  
4632 - return parseInt(elt.style.lineHeight) / 100;  
4633 - } else {  
4634 - return lineHeight.substring(lineHeight.length - 2) == "px"  
4635 - ? parseFloat(lineHeight) / fontSize  
4636 - : parseInt(lineHeight);  
4637 - }  
4638 - } else {  
4639 - return "";  
4640 - }  
4641 - }  
4642 -  
4643 - function getAbsoluteFontSize(css) {  
4644 - var fontSize = css != null ? css.fontSize : null;  
4645 -  
4646 - if (  
4647 - fontSize != null &&  
4648 - fontSize.substring(fontSize.length - 2) == "px"  
4649 - ) {  
4650 - return parseFloat(fontSize);  
4651 - } else {  
4652 - return mxConstants.DEFAULT_FONTSIZE;  
4653 - }  
4654 - }  
4655 -  
4656 - var css = mxUtils.getCurrentStyle(node);  
4657 - var fontSize = getAbsoluteFontSize(css);  
4658 - var lineHeight = getRelativeLineHeight(fontSize, css, node);  
4659 -  
4660 - // Finds common font size  
4661 - var elts = node.getElementsByTagName("*");  
4662 -  
4663 - // IE does not support containsNode  
4664 - if (  
4665 - elts.length > 0 &&  
4666 - window.getSelection &&  
4667 - !mxClient.IS_IE &&  
4668 - !mxClient.IS_IE11  
4669 - ) {  
4670 - var selection = window.getSelection();  
4671 -  
4672 - for (var i = 0; i < elts.length; i++) {  
4673 - if (selection.containsNode(elts[i], true)) {  
4674 - temp = mxUtils.getCurrentStyle(elts[i]);  
4675 - fontSize = Math.max(getAbsoluteFontSize(temp), fontSize);  
4676 - var lh = getRelativeLineHeight(fontSize, temp, elts[i]);  
4677 -  
4678 - if (lh != lineHeight || isNaN(lh)) {  
4679 - lineHeight = "";  
4680 - }  
4681 - }  
4682 - }  
4683 - }  
4684 -  
4685 - function hasParentOrOnlyChild(name) {  
4686 - if (  
4687 - graph.getParentByName(node, name, graph.cellEditor.textarea) !=  
4688 - null  
4689 - ) {  
4690 - return true;  
4691 - } else {  
4692 - var child = node;  
4693 -  
4694 - while (child != null && child.childNodes.length == 1) {  
4695 - child = child.childNodes[0];  
4696 -  
4697 - if (child.nodeName == name) {  
4698 - return true;  
4699 - }  
4700 - }  
4701 - }  
4702 -  
4703 - return false;  
4704 - }  
4705 -  
4706 - function isEqualOrPrefixed(str, value) {  
4707 - if (str != null && value != null) {  
4708 - if (str == value) {  
4709 - return true;  
4710 - } else if (str.length > value.length + 1) {  
4711 - return (  
4712 - str.substring(str.length - value.length - 1, str.length) ==  
4713 - "-" + value  
4714 - );  
4715 - }  
4716 - }  
4717 -  
4718 - return false;  
4719 - }  
4720 -  
4721 - if (css != null) {  
4722 - setSelected(  
4723 - fontStyleItems[0],  
4724 - css.fontWeight == "bold" ||  
4725 - css.fontWeight > 400 ||  
4726 - hasParentOrOnlyChild("B") ||  
4727 - hasParentOrOnlyChild("STRONG"),  
4728 - );  
4729 - setSelected(  
4730 - fontStyleItems[1],  
4731 - css.fontStyle == "italic" ||  
4732 - hasParentOrOnlyChild("I") ||  
4733 - hasParentOrOnlyChild("EM"),  
4734 - );  
4735 - setSelected(fontStyleItems[2], hasParentOrOnlyChild("U"));  
4736 - setSelected(sup, hasParentOrOnlyChild("SUP"));  
4737 - setSelected(sub, hasParentOrOnlyChild("SUB"));  
4738 -  
4739 - if (!graph.cellEditor.isTableSelected()) {  
4740 - var align =  
4741 - graph.cellEditor.align ||  
4742 - mxUtils.getValue(  
4743 - ss.style,  
4744 - mxConstants.STYLE_ALIGN,  
4745 - mxConstants.ALIGN_CENTER,  
4746 - );  
4747 -  
4748 - if (isEqualOrPrefixed(css.textAlign, "justify")) {  
4749 - setSelected(  
4750 - full,  
4751 - isEqualOrPrefixed(css.textAlign, "justify"),  
4752 - );  
4753 - setSelected(left, false);  
4754 - setSelected(center, false);  
4755 - setSelected(right, false);  
4756 - } else {  
4757 - setSelected(full, false);  
4758 - setSelected(left, align == mxConstants.ALIGN_LEFT);  
4759 - setSelected(center, align == mxConstants.ALIGN_CENTER);  
4760 - setSelected(right, align == mxConstants.ALIGN_RIGHT);  
4761 - }  
4762 - } else {  
4763 - setSelected(full, isEqualOrPrefixed(css.textAlign, "justify"));  
4764 - setSelected(left, isEqualOrPrefixed(css.textAlign, "left"));  
4765 - setSelected(center, isEqualOrPrefixed(css.textAlign, "center"));  
4766 - setSelected(right, isEqualOrPrefixed(css.textAlign, "right"));  
4767 - }  
4768 -  
4769 - currentTable = graph.getParentByName(  
4770 - node,  
4771 - "TABLE",  
4772 - graph.cellEditor.textarea,  
4773 - );  
4774 - tableRow =  
4775 - currentTable == null  
4776 - ? null  
4777 - : graph.getParentByName(node, "TR", currentTable);  
4778 - tableCell =  
4779 - currentTable == null  
4780 - ? null  
4781 - : graph.getParentByNames(node, ["TD", "TH"], currentTable);  
4782 - tableWrapper.style.display = currentTable != null ? "" : "none";  
4783 -  
4784 - if (document.activeElement != input) {  
4785 - if (  
4786 - node.nodeName == "FONT" &&  
4787 - node.getAttribute("size") == "4" &&  
4788 - pendingFontSize != null  
4789 - ) {  
4790 - node.removeAttribute("size");  
4791 - node.style.fontSize = pendingFontSize + " pt";  
4792 - pendingFontSize = null;  
4793 - } else {  
4794 - input.value = isNaN(fontSize) ? "" : fontSize + " pt";  
4795 - }  
4796 -  
4797 - var lh = parseFloat(lineHeight);  
4798 -  
4799 - if (!isNaN(lh)) {  
4800 - lineHeightInput.value = Math.round(lh * 100) + " %";  
4801 - } else {  
4802 - lineHeightInput.value = "100 %";  
4803 - }  
4804 - }  
4805 -  
4806 - // Updates the color picker for the current font  
4807 - if (fontColorApply != null) {  
4808 - if (  
4809 - css.color == "rgba(0, 0, 0, 0)" ||  
4810 - css.color == "transparent"  
4811 - ) {  
4812 - currentFontColor = mxConstants.NONE;  
4813 - } else {  
4814 - currentFontColor = mxUtils.rgba2hex(css.color);  
4815 - }  
4816 -  
4817 - fontColorApply(currentFontColor, true);  
4818 - }  
4819 -  
4820 - if (bgColorApply != null) {  
4821 - if (  
4822 - css.backgroundColor == "rgba(0, 0, 0, 0)" ||  
4823 - css.backgroundColor == "transparent"  
4824 - ) {  
4825 - currentBgColor = mxConstants.NONE;  
4826 - } else {  
4827 - currentBgColor = mxUtils.rgba2hex(css.backgroundColor);  
4828 - }  
4829 -  
4830 - bgColorApply(currentBgColor, true);  
4831 - }  
4832 -  
4833 - // Workaround for firstChild is null or not an object  
4834 - // in the log which seems to be IE8- only / 29.01.15  
4835 - if (fontMenu.firstChild != null) {  
4836 - fontMenu.firstChild.nodeValue = Graph.stripQuotes(  
4837 - css.fontFamily,  
4838 - );  
4839 - }  
4840 - }  
4841 - }  
4842 -  
4843 - updating = false;  
4844 - }, 0);  
4845 - }  
4846 - };  
4847 -  
4848 - if (  
4849 - mxClient.IS_FF ||  
4850 - mxClient.IS_EDGE ||  
4851 - mxClient.IS_IE ||  
4852 - mxClient.IS_IE11  
4853 - ) {  
4854 - mxEvent.addListener(  
4855 - graph.cellEditor.textarea,  
4856 - "DOMSubtreeModified",  
4857 - updateCssHandler,  
4858 - );  
4859 - }  
4860 -  
4861 - mxEvent.addListener(graph.cellEditor.textarea, "input", updateCssHandler);  
4862 - mxEvent.addListener(  
4863 - graph.cellEditor.textarea,  
4864 - "touchend",  
4865 - updateCssHandler,  
4866 - );  
4867 - mxEvent.addListener(graph.cellEditor.textarea, "mouseup", updateCssHandler);  
4868 - mxEvent.addListener(graph.cellEditor.textarea, "keyup", updateCssHandler);  
4869 - this.listeners.push({  
4870 - destroy: function () {  
4871 - // No need to remove listener since textarea is destroyed after edit  
4872 - },  
4873 - });  
4874 - updateCssHandler();  
4875 - }  
4876 -  
4877 - return container;  
4878 -};  
4879 -  
4880 -/**  
4881 - * 数据绑定格式化面板  
4882 - */  
4883 -DataFormatPanel = function (format, editorUi, container) {  
4884 - BaseFormatPanel.call(this, format, editorUi, container);  
4885 - this.init();  
4886 -};  
4887 -  
4888 -mxUtils.extend(DataFormatPanel, BaseFormatPanel);  
4889 -  
4890 -/**  
4891 - * 数据绑定面板初始化  
4892 - */  
4893 -DataFormatPanel.prototype.init = function () {  
4894 - this.container.style.borderBottom = "none";  
4895 - this.addDataFont(this.container);  
4896 -};  
4897 -  
4898 -// TODO 数据绑定  
4899 -DataFormatPanel.prototype.addDataFont = function (container) {  
4900 - const ui = this.editorUi;  
4901 - const editor = ui.editor;  
4902 - const graph = editor.graph;  
4903 - const ss = ui.getSelectionState();  
4904 - const vertices = ss.vertices || []  
4905 - const sidebarInstance = ui.sidebar  
4906 - console.log(vertices)  
4907 - console.log(ui)  
4908 -  
4909 - const hasModifyNotSave = editor.status  
4910 -  
4911 - /**  
4912 - * @description 不是单一节点则不进入数据绑定  
4913 - */  
4914 - if (!isSingleNode(vertices)) return  
4915 -  
4916 - // 组态id  
4917 - const configurationId = getRequest().configurationId;  
4918 - // 当前内容页的id  
4919 - const currentPageId = ui.currentPage.node;  
4920 -  
4921 - // 图形的id  
4922 - const graphId = vertices[0].id;  
4923 -  
4924 - // 解构全局属性layui要用到的模块  
4925 - const { layer, form, jquery: $, colorpicker, upload, element } = layui;  
4926 -  
4927 - const CONTAINER_FILTER = 'containerFilter'  
4928 - $(container).addClass('layui-form').attr('lay-filter', CONTAINER_FILTER)  
4929 -  
4930 - /**  
4931 - * @description 创建面版  
4932 - */  
4933 - const createPanel = this.createPanel  
4934 -  
4935 - /**  
4936 - * @description 创建标题  
4937 - */  
4938 - const createTitle = this.createTitle  
4939 -  
4940 -  
4941 - /**  
4942 - * @description 选中节点信息来源  
4943 - * @param {string} nodeInfo.id - 节点ID  
4944 - */  
4945 - const nodeInfo = getNodeInfo(vertices)  
4946 -  
4947 -  
4948 - /**  
4949 - * @description 组织树  
4950 - * @type {*[]}  
4951 - */  
4952 - let treeList = []  
4953 -  
4954 - /**  
4955 - * @description 当前选中的组织树节点  
4956 - * @type {null | string}  
4957 - */  
4958 - let currentCheckedOrgNode = null  
4959 -  
4960 - /**  
4961 - * @description 当前节点绑定数据  
4962 - * @type {null | {act: [], event: [], dataSources: []}}  
4963 - */  
4964 - let currentNodeData = null  
4965 -  
4966 - /**  
4967 - * @description 覆盖当前节点数据  
4968 - * @param {'act' | 'dataSources' | 'event'} key  
4969 - * @param {string}  
4970 - */  
4971 - function overrideCurrentData(key, uuid = 'id', value = {}) {  
4972 - if (!currentNodeData[key]) currentNodeData[key] = []  
4973 - const index = currentNodeData[key].findIndex(item => item[uuid] === value[uuid])  
4974 - ~index ? currentNodeData[key][index] = value : currentNodeData[key].push(value)  
4975 - }  
4976 -  
4977 - /**  
4978 - * @description 保存页面信息  
4979 - */  
4980 - async function autoSaveGraphInfo() {  
4981 - if (!hasModifyNotSave) return  
4982 - ui.actions.get(  
4983 - (ui.currentFile.mode == null || !ui.currentFile.isEditable())  
4984 - ? 'saveAs'  
4985 - : 'save')  
4986 - .funct();  
4987 - }  
4988 -  
4989 - /**  
4990 - * @description 获取弹出层绑定信息  
4991 - * @param {'DOWN' | 'UP' | 'SINGLE' | 'DOUBLE' | 'DISPLAY' | 'FLASH' | 'ROTATE' | 'IMAGE'} type - 类型  
4992 - * @param {'event' | 'act' } category - 类别  
4993 - */  
4994 - function getLayerBindInfo(category, type) {  
4995 - if (currentNodeData) {  
4996 - return currentNodeData[category]?.find(item => item.type === type) || {}  
4997 - }  
4998 - return {}  
4999 - }  
5000 -  
5001 - const enumCategory = {  
5002 - ACT: 'act',  
5003 - EVENT: 'event',  
5004 - DATA_SOURCE: 'dataSources',  
5005 - }  
5006 -  
5007 - const enumInteractionType = {  
5008 - DOWN: 'DOWN',  
5009 - UP: 'UP',  
5010 - SINGLE: 'SINGLE',  
5011 - DOUBLE: 'DOUBLE',  
5012 - }  
5013 -  
5014 - const enumDynamicEffectType = {  
5015 - DISPLAY: 'DISPLAY',  
5016 - FLASH: 'FLASH',  
5017 - ROTATE: 'ROTATE',  
5018 - IMAGE: 'IMAGE',  
5019 - SWITCH: 'SWITCH',  
5020 - RUNNING: 'RUNNING'  
5021 - }  
5022 -  
5023 - const interactionList = [  
5024 - {  
5025 - label: "按下",  
5026 - type: enumInteractionType.DOWN,  
5027 - category: enumCategory.EVENT,  
5028 - },  
5029 - {  
5030 - label: "抬起",  
5031 - type: enumInteractionType.UP,  
5032 - category: enumCategory.EVENT,  
5033 - },  
5034 - {  
5035 - label: "单击",  
5036 - type: enumInteractionType.SINGLE,  
5037 - category: enumCategory.EVENT,  
5038 - },  
5039 - {  
5040 - label: "双击",  
5041 - type: enumInteractionType.DOUBLE,  
5042 - category: enumCategory.EVENT,  
5043 - },  
5044 - ];  
5045 -  
5046 - const dynamicEffectList = [  
5047 - {  
5048 - label: "闪烁",  
5049 - type: enumDynamicEffectType.FLASH,  
5050 - category: enumCategory.ACT,  
5051 - },  
5052 - {  
5053 - label: "显示/隐藏",  
5054 - type: enumDynamicEffectType.DISPLAY,  
5055 - category: enumCategory.ACT,  
5056 - },  
5057 - {  
5058 - label: "旋转",  
5059 - type: enumDynamicEffectType.ROTATE,  
5060 - category: enumCategory.ACT,  
5061 - }  
5062 - ];  
5063 -  
5064 - const enumDataSourceConst = {  
5065 - ORG_ID: 'orgId',  
5066 - DEVICE_ID: 'deviceId',  
5067 - SLAVE_DEVICE_ID: 'slaveDeviceId',  
5068 - ATTR: 'attr',  
5069 - GATEWAY: 'GATEWAY',  
5070 - ADDITIONAL: 'additional'  
5071 - }  
5072 -  
5073 - /**  
5074 - * @description 刷新页面 用于在其他位置调用更新数据面板的操作,默认是个空函数,在生成数据源面板中进行了拓展  
5075 - */  
5076 - function echoRefreshFn() {  
5077 - }  
5078 -  
5079 - /**  
5080 - * @description 用于在其他位置获取数据源绑定的数据,在生成数据源面板中进行了改写  
5081 - * @return {{orgId: string, attr: string, deviceId: string, slaveDeviceId: string}}  
5082 - */  
5083 - function getDataSourceBindValue() {  
5084 -  
5085 - }  
5086 -  
5087 -  
5088 - // 获取url的请求参数函数  
5089 - function getRequest() {  
5090 - let url = location.search; //获取url中"?"符后的字串  
5091 - let theRequest = new Object();  
5092 - if (url.indexOf("?") != -1) {  
5093 - var str = url.substring(1);  
5094 - string = str.split("&");  
5095 - for (var i = 0; i < string.length; i++) {  
5096 - theRequest[string[i].split("=")[0]] = decodeURI(string[i].split("=")[1]);  
5097 - }  
5098 - }  
5099 - return theRequest;  
5100 - }  
5101 -  
5102 - /**  
5103 - * @description 单一节点  
5104 - */  
5105 - function isSingleNode(vertices) {  
5106 - return Array.isArray(vertices) && vertices.length === 1  
5107 - }  
5108 -  
5109 - /**  
5110 - * @description 获取节点信息  
5111 - * @returns {{id: string}} - 当前选中节点源信息  
5112 - */  
5113 - function getNodeInfo(node) {  
5114 - if (isSingleNode(node)) {  
5115 - return node[0]  
5116 - }  
5117 - return {}  
5118 - }  
5119 -  
5120 - /**  
5121 - * @description 初始化节点  
5122 - */  
5123 - async function initNode() {  
5124 - const basicAttr = sidebarInstance.enumCellBasicAttribute  
5125 - const permissionKey = sidebarInstance.enumPermissionPanel  
5126 - const { LINE_CHART, BAR_CHART, DASHBOARD_CHART } = Sidebar.prototype.enumComponentType  
5127 -  
5128 - const renderMapping = {  
5129 - [permissionKey.DATA_SOURCE]: createDataSourcePanel,  
5130 - [permissionKey.LINE_CHART_EXPAND]: createChartBindPanel.bind(this, LINE_CHART),  
5131 - [permissionKey.BAR_CHART_EXPAND]: createChartBindPanel.bind(this, BAR_CHART),  
5132 - [permissionKey.DASHBOARD_CHART_EXPAND]: createChartBindPanel.bind(this, DASHBOARD_CHART),  
5133 - [permissionKey.INTERACTION]: createInteractionPanel,  
5134 - [permissionKey.DYNAMIC_EFFECT]: createDynamicEffectPanel,  
5135 - [permissionKey.VAR_IMAGE]: createVarImagePanel,  
5136 - [permissionKey.VIDEO]: createVideoBindPanel,  
5137 - [permissionKey.SWITCH_STATE_SETTING]: createSwitchStateSettingPanel,  
5138 - [permissionKey.ONLY_SINGLE_EVENT]: createParamsSettingButtonPanel,  
5139 - [permissionKey.RUNNING_AND_STOP]: createRunningAndStopPanel  
5140 - }  
5141 -  
5142 -  
5143 - function permissionRender() {  
5144 - try {  
5145 - const cell = vertices[0]  
5146 - const permission = graph.getAttributeForCell(cell, basicAttr.COMPONENT_TYPE)  
5147 - const needDisplayPanel = sidebarInstance.getComponentPermission(permission)  
5148 - for (const key of needDisplayPanel) {  
5149 - renderMapping[key]()  
5150 - }  
5151 - if (needDisplayPanel.length) createSubmitPanel()  
5152 - UseLayUi.nextTick(() => form.render())  
5153 - } catch (e) {  
5154 - throw Error('component permission setting has some problem, please check your component permission bind on "Sidebar.prototype.init" method setComponentPermission')  
5155 - }  
5156 - }  
5157 -  
5158 - permissionRender()  
5159 - await getNodeBindInfo()  
5160 - }  
5161 -  
5162 - initNode();  
5163 -  
5164 -  
5165 - /**  
5166 - * @description 获取节点绑定信息  
5167 - */  
5168 - async function getNodeBindInfo() {  
5169 - const { id } = nodeInfo  
5170 - const [err, res] = await to(ConfigurationNodeApi.getConfigurationInfo('NODE', id))  
5171 - currentNodeData = res  
5172 - if (echoRefreshFn && typeof echoRefreshFn === 'function') echoRefreshFn()  
5173 - await echoActionType()  
5174 - }  
5175 -  
5176 - /**  
5177 - * @description 回显动效类型  
5178 - */  
5179 - async function echoActionType() {  
5180 - const act = currentNodeData.act ?? []  
5181 - const event = currentNodeData.event ?? []  
5182 - const actionType = {}  
5183 -  
5184 - const hasExistEl = $(`.layui-form[lay-filter="${CONTAINER_FILTER}"]`).find('input[type="checkbox"]')  
5185 - $(hasExistEl).each((i) => {  
5186 - $(hasExistEl[i]).attr('disabled', true)  
5187 - })  
5188 -  
5189 - for (const item of act) {  
5190 - const flag = !item.condition || !item.condition?.length  
5191 - $(`.interaction__container input[name="${item.type}"]`).attr('disabled', flag)  
5192 - actionType[item.type] = item.enabled  
5193 - }  
5194 - for (const item of event) {  
5195 - const flag = !item.content  
5196 - $(`.interaction__container input[name="${item.type}"]`).attr('disabled', flag)  
5197 - actionType[item.type] = item.enabled  
5198 - }  
5199 -  
5200 - form.val(CONTAINER_FILTER, actionType)  
5201 - }  
5202 -  
5203 - /**  
5204 - * @description 生成操作节点  
5205 - * @param {object[]} list  
5206 - */  
5207 - function generateActionEventNode(list) {  
5208 - const eventList = []  
5209 - const eventNodeCls = 'interaction__container'  
5210 - for (const item of list) {  
5211 - const checkbox = UseLayUi.createCheckBox({  
5212 - dataSource: item,  
5213 - layFilter: item.type,  
5214 - valueField: 'type',  
5215 - labelField: 'label',  
5216 - })  
5217 - const template = `  
5218 - <div class="${eventNodeCls}">  
5219 - <div>${checkbox}</div>  
5220 - <i id="${item.type}"></i>  
5221 - </div>`  
5222 - eventList.push(template)  
5223 - }  
5224 - return eventList  
5225 - }  
5226 -  
5227 - /**  
5228 - * @description 创建数据面板  
5229 - */  
5230 - function createDataSourcePanel() {  
5231 - const fragment = document.createDocumentFragment()  
5232 - const defaultPanel = createPanel()  
5233 - const title = createTitle('数据源')  
5234 - $(defaultPanel).addClass('override__panel--default')  
5235 - $(title).css({ padding: '6px 0 6px 6px' })  
5236 -  
5237 -  
5238 - async function mount() {  
5239 - const { component, echoDataSource, getValue } = generateDataSourceComponent({ validate: false })  
5240 - $(fragment).append(title).append(component)  
5241 - $(container).append(fragment)  
5242 -  
5243 - /**  
5244 - * @description 回显数据  
5245 - * @type {Function}  
5246 - */  
5247 - const refreshFn = echoRefreshFn  
5248 - echoRefreshFn = function () {  
5249 - refreshFn.apply(this)  
5250 - const { dataSources: [dataSource] = [] } = currentNodeData || {}  
5251 - echoDataSource(dataSource)  
5252 - form.render(null, CONTAINER_FILTER)  
5253 - }  
5254 -  
5255 - // 改写获取数据源绑定的值  
5256 - getDataSourceBindValue = getValue  
5257 - }  
5258 -  
5259 - mount()  
5260 - }  
5261 -  
5262 - function createLineChartPanel() {  
5263 - const { LINE_CHART } = Sidebar.prototype.enumComponentType  
5264 - createChartBindPanel(true)  
5265 - }  
5266 -  
5267 - function createBarChartPanel() {  
5268 - const { LINE_CHART } = Sidebar.prototype.enumComponentType  
5269 -  
5270 - createChartBindPanel(false)  
5271 - }  
5272 -  
5273 - function createDashboardPanel() {  
5274 - const { LINE_CHART } = Sidebar.prototype.enumComponentType  
5275 -  
5276 - }  
5277 - /**  
5278 - * @description 创建视频绑定面板  
5279 - */  
5280 - function createVideoBindPanel() {  
5281 -  
5282 - const enumConst = {  
5283 - ORG_ID: 'orgId',  
5284 - RECORD_ID: 'id',  
5285 - VIDEO_URL: 'videoUrl',  
5286 - ACCESSMODE: 'accessMode',  
5287 - VIDEO_FLAG: 'videoComponentFlag'  
5288 - }  
5289 -  
5290 - const enumActionEL = {  
5291 - VIDEO_FILTER: 'videoFilter',  
5292 - PANEL_EL: 'videoPanelControl',  
5293 - ORG_EL: 'orgTreeEl'  
5294 - }  
5295 -  
5296 - const fragment = document.createDocumentFragment()  
5297 - const title = createTitle('视频绑定')  
5298 - $(title).addClass('override__title--default')  
5299 -  
5300 - const defaultPanel = createPanel()  
5301 - $(defaultPanel).addClass('override__panel--default')  
5302 - $(defaultPanel).append(`<div id="${enumActionEL.ORG_EL}" class="video-panel-org__override"></div>`)  
5303 - $(defaultPanel).append(`<div class="layui-form-item" style="display: none;"><input name="${enumConst.ACCESSMODE}" /></div>`)  
5304 - $(defaultPanel).append(`<div class="layui-form-item" style="display: none;"><input name="${enumConst.VIDEO_FLAG}" value="true" /></div>`)  
5305 - $(defaultPanel).append(`<div class="layui-form-item" style="display: none;"><input name="${enumConst.VIDEO_URL}" /></div>`)  
5306 -  
5307 - const videoBindSelect = UseLayUi.createSelect({  
5308 - label: '视频流',  
5309 - layFilter: enumActionEL.VIDEO_FILTER,  
5310 - className: 'data-source__component-select',  
5311 - bindValueFiled: enumConst.RECORD_ID  
5312 - })  
5313 - $(defaultPanel).append(`<div id="${enumActionEL.PANEL_EL}">${videoBindSelect}</div>`)  
5314 -  
5315 - fragment.append(title)  
5316 - fragment.append(defaultPanel)  
5317 - $(container).append(fragment)  
5318 -  
5319 - function init() {  
5320 -  
5321 - let orgId = null;  
5322 -  
5323 - let recordOptions = []  
5324 -  
5325 - let treeList = []  
5326 -  
5327 - const refreshFN = echoRefreshFn  
5328 - echoRefreshFn = async function () {  
5329 - refreshFN.apply(this, arguments)  
5330 - await echoData()  
5331 - }  
5332 - async function echoData() {  
5333 - const { videoUrl, orgId: organizationId, accessMode, id } = currentNodeData?.dataSources?.[0]?.additional || {}  
5334 - orgId = organizationId  
5335 - await getStreamingMediaByOrgId()  
5336 - form.val(CONTAINER_FILTER, { videoUrl, accessMode, id })  
5337 - UseLayUi.nextTick(() => {  
5338 - const node = UseLayUi.findTreeObjectByField(treeList, organizationId)  
5339 - $(`#${enumActionEL.ORG_EL} input[name="${enumConst.ORG_ID}"]`).val(organizationId).parent().find('span').html(node?.name)  
5340 - })  
5341 - }  
5342 -  
5343 -  
5344 -  
5345 - /**  
5346 - * @description 创建组织树  
5347 - */  
5348 - async function createOrgTreeSelect() {  
5349 - const [err, res] = await to(ConfigurationNodeApi.getOrgTree())  
5350 - treeList = res  
5351 - if (err) return  
5352 - UseLayUi.createTreeSelect({  
5353 - elem: `#${enumActionEL.ORG_EL}`,  
5354 - layFilter: enumConst.ORG_ID,  
5355 - label: '组织',  
5356 - singleUsage: false,  
5357 - layVerify: 'required',  
5358 - layVerType: 'tips',  
5359 - treeProps: {  
5360 - data: res,  
5361 - onlyIconControl: true,  
5362 - click(node) {  
5363 - orgId = node.data.id  
5364 - getStreamingMediaByOrgId()  
5365 - form.val(CONTAINER_FILTER, {  
5366 - [enumConst.RECORD_ID]: null  
5367 - })  
5368 - },  
5369 - },  
5370 - })  
5371 - }  
5372 -  
5373 - async function getStreamingMediaByOrgId() {  
5374 - const [err, res] = await to(ConfigurationNodeApi.getStreamingMediaList(orgId))  
5375 - recordOptions = res.items  
5376 - const options = UseLayUi.generateOptionTemplate({ dataSource: res.items || [] })  
5377 - $(`#${enumActionEL.PANEL_EL} select[name="${enumConst.RECORD_ID}"]`).html(options)  
5378 - form.render()  
5379 - }  
5380 -  
5381 - function createLinsten() {  
5382 - form.on(`select(${enumActionEL.VIDEO_FILTER})`, event => {  
5383 - const { value } = event  
5384 - const item = recordOptions.find(item => item.id === value)  
5385 - form.val(CONTAINER_FILTER, {  
5386 - [enumConst.ACCESSMODE]: item[enumConst.ACCESSMODE],  
5387 - [enumConst.VIDEO_URL]: item[enumConst.VIDEO_URL],  
5388 - })  
5389 - })  
5390 - }  
5391 -  
5392 - createOrgTreeSelect()  
5393 - createLinsten()  
5394 - }  
5395 -  
5396 - init()  
5397 - }  
5398 -  
5399 - /**  
5400 - * @description 创建开关组件的状态设置面板  
5401 - */  
5402 - function createSwitchStateSettingPanel() {  
5403 - dynamicEffectList.length = 0  
5404 - dynamicEffectList.push({  
5405 - label: '状态设置',  
5406 - type: enumDynamicEffectType.SWITCH,  
5407 - category: enumCategory.ACT,  
5408 - })  
5409 - createDynamicEffectPanel()  
5410 - createParamsSettingButtonPanel()  
5411 - }  
5412 -  
5413 - /**  
5414 - * @description 参数设置按钮面板创建  
5415 - */  
5416 - function createParamsSettingButtonPanel() {  
5417 - const singleClick = interactionList.find(item => item.type === enumInteractionType.SINGLE)  
5418 - interactionList.length = 0  
5419 - interactionList.push(singleClick)  
5420 - createInteractionPanel()  
5421 - }  
5422 -  
5423 - /**  
5424 - * @description 水流动效  
5425 - */  
5426 - function createRunningAndStopPanel() {  
5427 - dynamicEffectList.push({  
5428 - label: '水流动效',  
5429 - type: enumDynamicEffectType.RUNNING,  
5430 - category: enumCategory.ACT  
5431 - })  
5432 - }  
5433 -  
5434 - /**  
5435 - * @description 是否是折线图  
5436 - * @param {boolean} isLineChart  
5437 - */  
5438 - function createChartBindPanel(chartType) {  
5439 - const fragment = document.createDocumentFragment()  
5440 - const chartBindContainer = document.createElement('div')  
5441 - chartBindContainer.setAttribute('class', 'chart-panel__style')  
5442 - chartBindContainer.style.padding = '10px'  
5443 - const title = createTitle('展示类型')  
5444 - $(title).addClass('override__title--default')  
5445 -  
5446 - const enumActionEL = {  
5447 - SCOPE_FILTER: 'bindChartScopeFilter',  
5448 -  
5449 - INTERVAL_EL: 'bindChartIntervalSelect',  
5450 -  
5451 - UNIT_EL: 'bindChartUnit'  
5452 - }  
5453 - const { LINE_CHART, BAR_CHART, DASHBOARD_CHART } = Sidebar.prototype.enumComponentType  
5454 -  
5455 - const enumBindKey = HandleDataSource.enumConst  
5456 - const enumDataType = HandleDataSource.enumDataBindType  
5457 - const enumConst = {  
5458 - DATA_TYPE: enumBindKey.DATA_TYPE,  
5459 -  
5460 - REAL: enumDataType.REAL,  
5461 -  
5462 - HISTORY: enumDataType.HISTORY,  
5463 -  
5464 - /**  
5465 - * @description 范围  
5466 - */  
5467 - EFFECT_SCOPE: enumBindKey.EFFECT_SCOPE,  
5468 -  
5469 - /**  
5470 - * @description 聚合  
5471 - */  
5472 - AGG: enumBindKey.AGG,  
5473 -  
5474 - /**  
5475 - * @description 间隔  
5476 - */  
5477 - INTERVAL: enumBindKey.INTERVAL,  
5478 -  
5479 - /**  
5480 - * @description 单位  
5481 - */  
5482 - UNIT: enumBindKey.UNIT  
5483 - }  
5484 -  
5485 - const enumTimeUnit = {  
5486 - SECOND: 'second',  
5487 - MINUTE: 'MINUTE',  
5488 - HOUR: 'HOUR',  
5489 - DAY: 'DAY',  
5490 - }  
5491 -  
5492 - const unitMapping = {  
5493 - [enumTimeUnit.SECOND]: '秒',  
5494 - [enumTimeUnit.MINUTE]: '分',  
5495 - [enumTimeUnit.HOUR]: '小时',  
5496 - [enumTimeUnit.DAY]: '天',  
5497 - }  
5498 -  
5499 - const unitConversion = {  
5500 - [enumTimeUnit.SECOND]: 1 * 1000,  
5501 - [enumTimeUnit.MINUTE]: 1 * 60 * 1000,  
5502 - [enumTimeUnit.HOUR]: 1 * 60 * 60 * 1000,  
5503 - [enumTimeUnit.DAY]: 1 * 60 * 60 * 24 * 1000,  
5504 - }  
5505 -  
5506 - const defaultIntervalOptions = [  
5507 - {  
5508 - id: 1,  
5509 - unit: enumTimeUnit.SECOND,  
5510 - linkage: [  
5511 - { id: 1, unit: enumTimeUnit.SECOND }  
5512 - ]  
5513 - },  
5514 - {  
5515 - id: 5,  
5516 - unit: enumTimeUnit.SECOND,  
5517 - linkage: [  
5518 - { id: 1, unit: enumTimeUnit.SECOND }  
5519 - ]  
5520 - },  
5521 - {  
5522 - id: 10,  
5523 - unit: enumTimeUnit.SECOND,  
5524 - linkage: [  
5525 - { id: 1, unit: enumTimeUnit.SECOND }  
5526 - ]  
5527 - },  
5528 - {  
5529 - id: 15,  
5530 - unit: enumTimeUnit.SECOND,  
5531 - linkage: [  
5532 - { id: 1, unit: enumTimeUnit.SECOND }  
5533 - ]  
5534 - },  
5535 - {  
5536 - id: 30,  
5537 - unit: enumTimeUnit.SECOND,  
5538 - linkage: [  
5539 - { id: 1, unit: enumTimeUnit.SECOND }  
5540 - ]  
5541 - },  
5542 - {  
5543 - id: 1,  
5544 - unit: enumTimeUnit.MINUTE,  
5545 - linkage: [  
5546 - { id: 1, unit: enumTimeUnit.SECOND },  
5547 - { id: 5, unit: enumTimeUnit.SECOND },  
5548 - ]  
5549 - },  
5550 - {  
5551 - id: 2,  
5552 - unit: enumTimeUnit.MINUTE,  
5553 - linkage: [  
5554 - { id: 1, unit: enumTimeUnit.SECOND },  
5555 - { id: 5, unit: enumTimeUnit.SECOND },  
5556 - { id: 10, unit: enumTimeUnit.SECOND },  
5557 - { id: 15, unit: enumTimeUnit.SECOND },  
5558 - ]  
5559 - },  
5560 - {  
5561 - id: 5,  
5562 - unit: enumTimeUnit.MINUTE,  
5563 - linkage: [  
5564 - { id: 1, unit: enumTimeUnit.SECOND },  
5565 - { id: 5, unit: enumTimeUnit.SECOND },  
5566 - { id: 10, unit: enumTimeUnit.SECOND },  
5567 - { id: 15, unit: enumTimeUnit.SECOND },  
5568 - { id: 30, unit: enumTimeUnit.SECOND },  
5569 - ]  
5570 - },  
5571 - {  
5572 - id: 10,  
5573 - unit: enumTimeUnit.MINUTE,  
5574 - linkage: [  
5575 - { id: 5, unit: enumTimeUnit.SECOND },  
5576 - { id: 10, unit: enumTimeUnit.SECOND },  
5577 - { id: 15, unit: enumTimeUnit.SECOND },  
5578 - { id: 30, unit: enumTimeUnit.SECOND },  
5579 - { id: 1, unit: enumTimeUnit.MINUTE },  
5580 - ]  
5581 - },  
5582 - {  
5583 - id: 15,  
5584 - unit: enumTimeUnit.MINUTE,  
5585 - linkage: [  
5586 - { id: 5, unit: enumTimeUnit.SECOND },  
5587 - { id: 10, unit: enumTimeUnit.SECOND },  
5588 - { id: 15, unit: enumTimeUnit.SECOND },  
5589 - { id: 30, unit: enumTimeUnit.SECOND },  
5590 - { id: 1, unit: enumTimeUnit.MINUTE },  
5591 - { id: 2, unit: enumTimeUnit.MINUTE },  
5592 - ]  
5593 - },  
5594 - {  
5595 - id: 30,  
5596 - unit: enumTimeUnit.MINUTE,  
5597 - linkage: [  
5598 - { id: 5, unit: enumTimeUnit.SECOND },  
5599 - { id: 10, unit: enumTimeUnit.SECOND },  
5600 - { id: 15, unit: enumTimeUnit.SECOND },  
5601 - { id: 30, unit: enumTimeUnit.SECOND },  
5602 - { id: 1, unit: enumTimeUnit.MINUTE },  
5603 - { id: 2, unit: enumTimeUnit.MINUTE },  
5604 - ]  
5605 - },  
5606 - {  
5607 - id: 1,  
5608 - unit: enumTimeUnit.HOUR,  
5609 - linkage: [  
5610 - { id: 10, unit: enumTimeUnit.SECOND },  
5611 - { id: 15, unit: enumTimeUnit.SECOND },  
5612 - { id: 30, unit: enumTimeUnit.SECOND },  
5613 - { id: 1, unit: enumTimeUnit.MINUTE },  
5614 - { id: 2, unit: enumTimeUnit.MINUTE },  
5615 - { id: 5, unit: enumTimeUnit.MINUTE },  
5616 - ]  
5617 - },  
5618 - {  
5619 - id: 2,  
5620 - unit: enumTimeUnit.HOUR,  
5621 - linkage: [  
5622 - { id: 15, unit: enumTimeUnit.SECOND },  
5623 - { id: 30, unit: enumTimeUnit.SECOND },  
5624 - { id: 1, unit: enumTimeUnit.MINUTE },  
5625 - { id: 2, unit: enumTimeUnit.MINUTE },  
5626 - { id: 5, unit: enumTimeUnit.MINUTE },  
5627 - { id: 10, unit: enumTimeUnit.MINUTE },  
5628 - { id: 15, unit: enumTimeUnit.MINUTE },  
5629 - ]  
5630 - },  
5631 - {  
5632 - id: 5,  
5633 - unit: enumTimeUnit.HOUR,  
5634 - linkage: [  
5635 - { id: 1, unit: enumTimeUnit.MINUTE },  
5636 - { id: 2, unit: enumTimeUnit.MINUTE },  
5637 - { id: 5, unit: enumTimeUnit.MINUTE },  
5638 - { id: 10, unit: enumTimeUnit.MINUTE },  
5639 - { id: 15, unit: enumTimeUnit.MINUTE },  
5640 - { id: 30, unit: enumTimeUnit.MINUTE },  
5641 - ]  
5642 - },  
5643 - {  
5644 - id: 10,  
5645 - unit: enumTimeUnit.HOUR,  
5646 - linkage: [  
5647 - { id: 2, unit: enumTimeUnit.MINUTE },  
5648 - { id: 5, unit: enumTimeUnit.MINUTE },  
5649 - { id: 10, unit: enumTimeUnit.MINUTE },  
5650 - { id: 15, unit: enumTimeUnit.MINUTE },  
5651 - { id: 30, unit: enumTimeUnit.MINUTE },  
5652 - { id: 1, unit: enumTimeUnit.HOUR },  
5653 - ]  
5654 - },  
5655 - {  
5656 - id: 12,  
5657 - unit: enumTimeUnit.HOUR,  
5658 - linkage: [  
5659 - { id: 2, unit: enumTimeUnit.MINUTE },  
5660 - { id: 5, unit: enumTimeUnit.MINUTE },  
5661 - { id: 10, unit: enumTimeUnit.MINUTE },  
5662 - { id: 15, unit: enumTimeUnit.MINUTE },  
5663 - { id: 30, unit: enumTimeUnit.MINUTE },  
5664 - { id: 1, unit: enumTimeUnit.HOUR },  
5665 - ]  
5666 - },  
5667 - {  
5668 - id: 1,  
5669 - unit: enumTimeUnit.DAY,  
5670 - linkage: [  
5671 - { id: 5, unit: enumTimeUnit.MINUTE },  
5672 - { id: 10, unit: enumTimeUnit.MINUTE },  
5673 - { id: 15, unit: enumTimeUnit.MINUTE },  
5674 - { id: 30, unit: enumTimeUnit.MINUTE },  
5675 - { id: 1, unit: enumTimeUnit.HOUR },  
5676 - { id: 2, unit: enumTimeUnit.HOUR },  
5677 - ]  
5678 - },  
5679 - {  
5680 - id: 7,  
5681 - unit: enumTimeUnit.DAY,  
5682 - linkage: [  
5683 - { id: 30, unit: enumTimeUnit.MINUTE },  
5684 - { id: 1, unit: enumTimeUnit.HOUR },  
5685 - { id: 2, unit: enumTimeUnit.HOUR },  
5686 - { id: 5, unit: enumTimeUnit.HOUR },  
5687 - { id: 10, unit: enumTimeUnit.HOUR },  
5688 - { id: 12, unit: enumTimeUnit.HOUR },  
5689 - { id: 1, unit: enumTimeUnit.DAY },  
5690 - ]  
5691 - },  
5692 - {  
5693 - id: 30,  
5694 - unit: enumTimeUnit.DAY,  
5695 - linkage: [  
5696 - { id: 2, unit: enumTimeUnit.HOUR },  
5697 - { id: 5, unit: enumTimeUnit.HOUR },  
5698 - { id: 10, unit: enumTimeUnit.HOUR },  
5699 - { id: 12, unit: enumTimeUnit.HOUR },  
5700 - { id: 1, unit: enumTimeUnit.DAY },  
5701 - ]  
5702 - },  
5703 - ].map(item => {  
5704 - return {  
5705 - id: item.id * unitConversion[item.unit],  
5706 - name: item.id + unitMapping[item.unit],  
5707 - linkage: item.linkage.map(item => {  
5708 - return {  
5709 - id: item.id * unitConversion[item.unit],  
5710 - name: item.id + unitMapping[item.unit],  
5711 - }  
5712 - })  
5713 - }  
5714 - })  
5715 -  
5716 - const aggergationOptions = [  
5717 - { id: 'AVG', name: '平均值' },  
5718 - { id: 'MIN', name: '最小值' },  
5719 - { id: 'MAX', name: '最大值' },  
5720 - { id: 'SUM', name: '求和' },  
5721 - { id: 'COUNT', name: '计数' },  
5722 - { id: 'NONE', name: '空' },  
5723 - ]  
5724 -  
5725 - function generateDataType() {  
5726 - const realOption = (checked) => `<input type="radio" name="${enumConst.DATA_TYPE}" value="${enumConst.REAL}" title="实时" ${checked ? 'checked' : ''}>`  
5727 - const historyOption = (checked) => `<input type="radio" name="${enumConst.DATA_TYPE}" value="${enumConst.HISTORY}" title="历史" ${checked ? 'checked' : ''}>`  
5728 -  
5729 - if (chartType === LINE_CHART) {  
5730 - return realOption() + historyOption(true)  
5731 - } else if (chartType === BAR_CHART) {  
5732 - return historyOption(true)  
5733 - } else if (chartType === DASHBOARD_CHART) {  
5734 - return realOption(true)  
5735 - }  
5736 - return realOption() + historyOption(true)  
5737 - }  
5738 -  
5739 - function createSwitchBindTypeRadio() {  
5740 - return `  
5741 - <div class="layui-form-item">  
5742 - <label class="layui-form-label">数据类型</label>  
5743 - <div class="layui-input-block">  
5744 - ${generateDataType()}  
5745 - </div>  
5746 - </div>`  
5747 - }  
5748 -  
5749 - function createQueryScopeSelect() {  
5750 - const template = UseLayUi.generateOptionTemplate({  
5751 - dataSource: defaultIntervalOptions,  
5752 - addPlaceholderOption: false  
5753 - })  
5754 - return `  
5755 - <div class="layui-form-item">  
5756 - <label class="layui-form-label">时间周期</label>  
5757 - <div class="layui-input-block">  
5758 - <select name="${enumConst.EFFECT_SCOPE}" lay-filter="${enumActionEL.SCOPE_FILTER}">  
5759 - ${template}  
5760 - </select>  
5761 - </div>  
5762 - </div>`  
5763 - }  
5764 -  
5765 - function createAggregationSelect() {  
5766 - const template = UseLayUi.generateOptionTemplate({  
5767 - dataSource: aggergationOptions,  
5768 - addPlaceholderOption: false  
5769 - })  
5770 - return `  
5771 - <div class="layui-form-item">  
5772 - <label class="layui-form-label">聚合方式</label>  
5773 - <div class="layui-input-block">  
5774 - <select name="${enumConst.AGG}">  
5775 - ${template}  
5776 - </select>  
5777 - </div>  
5778 - </div>`  
5779 - }  
5780 -  
5781 - function createIntervalSelect() {  
5782 - return `  
5783 - <div class="layui-form-item">  
5784 - <label class="layui-form-label">间隔时间</label>  
5785 - <div class="layui-input-block">  
5786 - <select id="${enumActionEL.INTERVAL_EL}" name="${enumConst.INTERVAL}" lay-filter="${enumConst.INTERVAL}">  
5787 - <option value="1000">1</option>  
5788 - </select>  
5789 - </div>  
5790 - </div>`  
5791 - }  
5792 -  
5793 - function createUnitInput() {  
5794 - return `  
5795 - <div class="layui-form-item">  
5796 - <label class="layui-form-label">单位</label>  
5797 - <div class="layui-input-block" style="flex: 1;">  
5798 - <input id="${enumActionEL.UNIT_EL}" class="layui-input" value="°C" name="${enumConst.UNIT}" lay-filter="${enumConst.UNIT}" />  
5799 - </div>  
5800 - </div>`  
5801 - }  
5802 -  
5803 - function generatorEventlisten() {  
5804 - form.on(`select(${enumActionEL.SCOPE_FILTER})`, event => {  
5805 - const value = event.value || 0  
5806 - linkageIntervalSelect(value)  
5807 - })  
5808 - }  
5809 -  
5810 - function linkageIntervalSelect(value) {  
5811 - const options = defaultIntervalOptions.find(item => Number(item.id) === Number(value))?.linkage  
5812 - const template = UseLayUi.generateOptionTemplate({  
5813 - dataSource: options,  
5814 - addPlaceholderOption: false  
5815 - })  
5816 - $(`#${enumActionEL.INTERVAL_EL}`).html(template)  
5817 - form.render('select')  
5818 - }  
5819 -  
5820 - /**  
5821 - * @description 回显  
5822 - */  
5823 - function echoData() {  
5824 - const { dataSources = [] } = currentNodeData  
5825 - const { additional = {} } = dataSources[0] || {}  
5826 - const { [enumBindKey.EFFECT_SCOPE]: effectScope = 1000 } = additional  
5827 - linkageIntervalSelect(effectScope)  
5828 - form.val(CONTAINER_FILTER, additional)  
5829 - }  
5830 -  
5831 - const refresh = echoRefreshFn  
5832 - echoRefreshFn = function () {  
5833 - refresh.apply(this, arguments)  
5834 - echoData()  
5835 - }  
5836 -  
5837 - fragment.append(title)  
5838 - $(chartBindContainer).append(createSwitchBindTypeRadio())  
5839 - $(chartBindContainer).append(createQueryScopeSelect())  
5840 - $(chartBindContainer).append(createAggregationSelect())  
5841 - $(chartBindContainer).append(createIntervalSelect())  
5842 - chartType === DASHBOARD_CHART && $(chartBindContainer).append(createUnitInput())  
5843 - fragment.append(chartBindContainer)  
5844 - $(container).append(fragment)  
5845 - generatorEventlisten()  
5846 - }  
5847 -  
5848 - /**  
5849 - * @description 创建数据交互模块  
5850 - */  
5851 - function createInteractionPanel() {  
5852 - const fragment = document.createDocumentFragment()  
5853 - const title = createTitle('数据交互')  
5854 - $(title).addClass('override__title--default')  
5855 - fragment.append(title)  
5856 - generateActionEventNode(interactionList).forEach(item => {  
5857 - const panel = createPanel()  
5858 - $(panel).addClass('override__panel--default').append(item)  
5859 - $(fragment).append(panel)  
5860 - })  
5861 - $(container).append(fragment)  
5862 - }  
5863 -  
5864 -  
5865 - /**  
5866 - * @description 创建动效面版  
5867 - */  
5868 - function createDynamicEffectPanel() {  
5869 - const fragment = document.createDocumentFragment()  
5870 - const title = createTitle('数据动效')  
5871 - $(title).addClass('override__title--default')  
5872 - fragment.append(title)  
5873 - generateActionEventNode(dynamicEffectList).forEach(item => {  
5874 - const panel = createPanel()  
5875 - $(panel).addClass('override__panel--default').append(item)  
5876 - $(fragment).append(panel)  
5877 - })  
5878 - $(container).append(fragment)  
5879 - }  
5880 -  
5881 - /**  
5882 - * @description 变量图片动效面板  
5883 - */  
5884 - function createVarImagePanel() {  
5885 - dynamicEffectList.push({  
5886 - label: '设置变量值图片',  
5887 - type: enumDynamicEffectType.IMAGE,  
5888 - category: enumCategory.ACT,  
5889 - })  
5890 - createDynamicEffectPanel()  
5891 - }  
5892 -  
5893 - /**  
5894 - * @description 创建提交按钮  
5895 - */  
5896 - function createSubmitPanel() {  
5897 - const panel = createPanel()  
5898 - $(panel).addClass('data-source__submit-panel').append(`<button type="button" lay-submit lay-filter="formDataSource" class="layui-btn">保存</button>`)  
5899 - $(container).append(panel)  
5900 - form.on('submit(formDataSource)', async function (data) {  
5901 - if (!hasSavePermission()) {  
5902 - UseLayUi.topErrorMsg('没有权限')  
5903 - return  
5904 - }  
5905 - const { field } = data  
5906 - const value = getValueOnSubmit(field)  
5907 - await to(autoSaveGraphInfo())  
5908 - const [err, res] = await to(ConfigurationNodeApi.updateNodeInfo(value))  
5909 - if (err) return  
5910 - UseLayUi.successMsg()  
5911 - await getNodeBindInfo()  
5912 - return false;  
5913 - });  
5914 - }  
5915 -  
5916 - function getValueOnSubmit(field) {  
5917 - const basicAttr = sidebarInstance.enumCellBasicAttribute  
5918 - const componentType = sidebarInstance.enumComponentType  
5919 -  
5920 - const renderMapping = {  
5921 - [componentType.VAR_IMAGE]: getSubmitValue,  
5922 - [componentType.CHARTS]: getSubmitValue,  
5923 - [componentType.TITLE]: getSubmitValue,  
5924 - [componentType.VARIABLE]: getSubmitValue,  
5925 - [componentType.LINE]: getSubmitValue,  
5926 - [componentType.REAL_TIME]: getSubmitValue,  
5927 - [componentType.LINE_CHART]: getSubmitValue,  
5928 - [componentType.BAR_CHART]: getSubmitValue,  
5929 - [componentType.DASHBOARD_CHART]: getSubmitValue,  
5930 - [componentType.DEFAULT]: getSubmitValue,  
5931 - [componentType.VIDEO]: getVideoSubmitValue,  
5932 - [componentType.SWITCH]: getSwitchSubmitValue,  
5933 - [componentType.PARAMS_SETTING_BUTTON]: getSwitchSubmitValue,  
5934 - [componentType.IMAGE]: getSubmitValue  
5935 - }  
5936 -  
5937 - const cell = vertices[0]  
5938 - const type = graph.getAttributeForCell(cell, basicAttr.COMPONENT_TYPE)  
5939 - return renderMapping[type]?.(field) || {}  
5940 -  
5941 - function getSubmitValue(field) {  
5942 - const ENABLED_FLAG = 'on'  
5943 - const additionalKey = HandleDataSource.enumConst  
5944 -  
5945 - const value = {  
5946 - configurationId,  
5947 - contentId: currentPageId.id,  
5948 - nodeId: graphId,  
5949 - [enumCategory.ACT]: [],  
5950 - [enumCategory.EVENT]: [],  
5951 - [enumCategory.DATA_SOURCE]: {  
5952 - [enumDataSourceConst.ORG_ID]: field[enumDataSourceConst.ORG_ID],  
5953 - [enumDataSourceConst.DEVICE_ID]: field[enumDataSourceConst.DEVICE_ID],  
5954 - [enumDataSourceConst.SLAVE_DEVICE_ID]: field[enumDataSourceConst.SLAVE_DEVICE_ID] ? field[enumDataSourceConst.SLAVE_DEVICE_ID] : '',  
5955 - [enumDataSourceConst.ATTR]: field[enumDataSourceConst.ATTR],  
5956 - [enumDataSourceConst.ADDITIONAL]: field[additionalKey.DATA_TYPE] ? {  
5957 - [additionalKey.AGG]: field[additionalKey.AGG],  
5958 - [additionalKey.DATA_TYPE]: field[additionalKey.DATA_TYPE],  
5959 - [additionalKey.INTERVAL]: field[additionalKey.INTERVAL],  
5960 - [additionalKey.EFFECT_SCOPE]: field[additionalKey.EFFECT_SCOPE],  
5961 - ...(field[additionalKey.UNIT] ? { [additionalKey.UNIT]: field[additionalKey.UNIT] } : {})  
5962 - } : null  
5963 - },  
5964 - }  
5965 - const allType = [...interactionList, ...dynamicEffectList]  
5966 - for (const item of allType) {  
5967 - if (field[item.type] === ENABLED_FLAG) {  
5968 - const enableItem = currentNodeData[item.category].find(each => each.type === item.type)  
5969 - if (!enableItem) continue  
5970 - value[item.category].push({  
5971 - type: item.type,  
5972 - enabled: true,  
5973 - })  
5974 - } else {  
5975 - value[item.category].push({  
5976 - type: item.type,  
5977 - enabled: false,  
5978 - })  
5979 - }  
5980 - }  
5981 -  
5982 - return value  
5983 - }  
5984 -  
5985 - function getVideoSubmitValue() {  
5986 - const value = {  
5987 - configurationId,  
5988 - contentId: currentPageId.id,  
5989 - nodeId: graphId,  
5990 - [enumCategory.DATA_SOURCE]: {  
5991 - [enumDataSourceConst.ORG_ID]: 'b4dd6e2b-6e0f-413c-bf5a-70133bd571e8',  
5992 - [enumDataSourceConst.DEVICE_ID]: '6d9043f0-f1f7-11ec-98ad-a9680487d1e0',  
5993 - [enumDataSourceConst.ATTR]: 'attr',  
5994 - [enumDataSourceConst.ADDITIONAL]: field  
5995 - },  
5996 - }  
5997 - return value  
5998 - }  
5999 -  
6000 - /**  
6001 - * @description 处理开关组件的保存值  
6002 - * @returns  
6003 - */  
6004 - function getSwitchSubmitValue(field) {  
6005 - const dataSources = getDataSourceBindValue()  
6006 - const enableStatus = getEnableStatus(field)  
6007 - return { configurationId, contentId: currentPageId.id, nodeId: graphId, dataSources, ...enableStatus }  
6008 - }  
6009 -  
6010 -  
6011 - /**  
6012 - * @description 获取开启状态  
6013 - */  
6014 - function getEnableStatus(field = {}) {  
6015 - const ENABLED_FLAG = 'on'  
6016 - const value = {}  
6017 - const hasExistEl = $(`.layui-form[lay-filter="${CONTAINER_FILTER}"]`).find('input[type="checkbox"]')  
6018 -  
6019 - // 筛选页面中存在的数据动效事件交互复选框  
6020 - const allState = []  
6021 - $(hasExistEl).each((i) => {  
6022 - const state = $(hasExistEl[i]).attr('name')  
6023 - allState.push(state)  
6024 - })  
6025 - const allType = [...interactionList, ...dynamicEffectList].filter(item => allState.includes(item.type))  
6026 -  
6027 - for (const item of allType) {  
6028 - !value[item.category] && (value[item.category] = [])  
6029 - value[item.category].push({  
6030 - type: item.type,  
6031 - enabled: field[item.type] === ENABLED_FLAG,  
6032 - })  
6033 - }  
6034 - return value  
6035 - }  
6036 - }  
6037 -  
6038 - /**  
6039 - * @description 处理设置变量图片  
6040 - */  
6041 - function handleSettingVarImage(event) {  
6042 -  
6043 - const enumActionEl = {  
6044 - /**  
6045 - * @description layer 保存按钮  
6046 - */  
6047 - LAYER_SUBMIT_FILTER: 'varImageLayerFilter',  
6048 -  
6049 - /**  
6050 - * @description 上传图片layer 按钮控制  
6051 - */  
6052 - IMAGE_LAYER_FILTER: 'uploadImageLayerFilter',  
6053 -  
6054 - /**  
6055 - * @description 行控制  
6056 - */  
6057 - ROW_FILTER: 'varImageTableRowFilter',  
6058 -  
6059 - /**  
6060 - * @description 颜色控制  
6061 - */  
6062 - COLOR_PICKER_FILTER: 'varImageTableColorPickerFilter',  
6063 -  
6064 - /**  
6065 - * @description 最小值控制  
6066 - */  
6067 - MIN_FILTER: 'varImageTableMinFilter',  
6068 -  
6069 - /**  
6070 - * @description 最大值控制  
6071 - */  
6072 - MAX_FILTER: 'varImageTableMaxFilter',  
6073 -  
6074 - /**  
6075 - * @description 表体  
6076 - */  
6077 - TABLE_BODY_EL: 'variableImageTable',  
6078 -  
6079 - /**  
6080 - * @description 添加行控制  
6081 - */  
6082 - ADD_ROW_EL: 'variableImageTableAddRow',  
6083 -  
6084 - /**  
6085 - * @description 设置图片控制  
6086 - */  
6087 - SET_IMG_EL: 'variableImageTableSetImgEl',  
6088 -  
6089 - /**  
6090 - * @description 预览区域控制  
6091 - */  
6092 - PREVIEW_IMG_CONTAINER: 'img__container',  
6093 -  
6094 - /**  
6095 - * @description 删除图片控制  
6096 - */  
6097 - DEL_PREVIEW_IMG: 'img__delete',  
6098 -  
6099 - /**  
6100 - * @description 删除行控制  
6101 - */  
6102 - DEL_ROW_EL: 'variableImageTableDelRow',  
6103 -  
6104 - /**  
6105 - * @description  
6106 - */  
6107 - DATA_SOURCE_COMP_EL: 'varImgDataSourceEl',  
6108 -  
6109 - /**  
6110 - * @description 默认图片  
6111 - */  
6112 - DEFAULT_IMAGE_EL: 'defaultImageEl',  
6113 -  
6114 - /**  
6115 - * @description 行预览  
6116 - */  
6117 - ROW_PREVIEW_IMG: 'rowPreviewImg',  
6118 -  
6119 - /**  
6120 - * @description 默认图片filter  
6121 - */  
6122 - DEFAULT_IMAGE_FILTER: 'defaultImageFilter'  
6123 - }  
6124 -  
6125 - const enumConst = HandleDynamicEffect.enumVarImageConst  
6126 -  
6127 - let addRowNumber = 0  
6128 -  
6129 - let getDataSourceValue = () => {  
6130 - }  
6131 -  
6132 - const getRowFilter = (rowNumber) => `${enumActionEl.ROW_FILTER}${rowNumber}`  
6133 -  
6134 - /**  
6135 - * @description 监听表格中的事件  
6136 - */  
6137 - function generatorEventListen() {  
6138 - createInputListener()  
6139 - createAddRowEvent()  
6140 - createDelRowEvent()  
6141 - }  
6142 -  
6143 - /**  
6144 - * @description 删除行  
6145 - */  
6146 - function createDelRowEvent() {  
6147 - $(`#${enumActionEl.TABLE_BODY_EL}`).on('click', `.${enumActionEl.DEL_ROW_EL}`, (event) => {  
6148 - $(event.target).parents('tr').remove()  
6149 - })  
6150 - }  
6151 -  
6152 - /**  
6153 - * @description 添加行事件  
6154 - */  
6155 - function createAddRowEvent() {  
6156 - $(`#${enumActionEl.ADD_ROW_EL}`).on('click', () => {  
6157 - addRecord()  
6158 - })  
6159 - }  
6160 -  
6161 - /**  
6162 - * @description 创建输入验证  
6163 - */  
6164 - function createInputListener() {  
6165 - $(`#${enumActionEl.TABLE_BODY_EL}`)  
6166 - .on('input', `.${enumActionEl.MIN_FILTER}`, event => {  
6167 - const minVal = $(event.target).val()  
6168 - const maxVal = $(event.target).parents('tr').find(`input.${enumActionEl.MAX_FILTER}`).val()  
6169 - if (maxVal !== '' && Number(minVal) > Number(maxVal)) {  
6170 - layer.tips('输入值大于最大值', $(event.target), {  
6171 - tips: 1,  
6172 - });  
6173 - }  
6174 - })  
6175 - .on('input', `.${enumActionEl.MAX_FILTER}`, event => {  
6176 - const maxVal = $(event.target).val()  
6177 - const minVal = $(event.target).parents('tr').find(`input.${enumActionEl.MIN_FILTER}`).val()  
6178 - if (minVal !== '' && Number(maxVal) < Number(minVal)) {  
6179 - layer.tips('输入值小于最小值', $(event.target), {  
6180 - tips: 1,  
6181 - });  
6182 - }  
6183 - })  
6184 - }  
6185 -  
6186 - /**  
6187 - * @description 添加记录  
6188 - */  
6189 - function addRecord() {  
6190 - const rowFormFilter = getRowFilter(addRowNumber)  
6191 - const content = `  
6192 - <tr class="layui-form" lay-filter="${rowFormFilter}">  
6193 - <td>  
6194 - <div class="layui-form-item">  
6195 - <input class="layui-input ${enumActionEl.MIN_FILTER}" autocomplete="off" type="number" name="${enumConst.MIN}" lay-filter="${enumConst.MIN}" lay-verType="tips" lay-verify="required" />  
6196 - </div>  
6197 - </td>  
6198 - <td>  
6199 - <div class="layui-form-item">  
6200 - <input class="layui-input ${enumActionEl.MAX_FILTER}"" autocomplete="off" type="number" name="${enumConst.MAX}" lay-filter="${enumConst.MAX}" lay-verType="tips" lay-verify="required" />  
6201 - </div>  
6202 - </td>  
6203 - <td>  
6204 - <div class="${enumActionEl.ROW_PREVIEW_IMG}"></div>  
6205 - </td>  
6206 - <td style="text-align: center">  
6207 - <button type="button" class="layui-btn layui-btn-primary layui-border-red ${enumActionEl.DEL_ROW_EL}">删除</button>  
6208 - </td>  
6209 - </tr>  
6210 - `  
6211 - $(`#${enumActionEl.TABLE_BODY_EL}`).append(content)  
6212 - form.render()  
6213 - const el = $(`#${enumActionEl.TABLE_BODY_EL} tr[lay-filter="${rowFormFilter}"] .${enumActionEl.ROW_PREVIEW_IMG}`)  
6214 - generateUploadImgContainer({ el })  
6215 - addRowNumber++  
6216 - }  
6217 -  
6218 -  
6219 - /**  
6220 - * @description 回显数据  
6221 - */  
6222 - function echoFormData(info) {  
6223 - const { condition = [] } = info  
6224 - for (let index = 0; index < condition.length; index++) {  
6225 - const item = condition[index]  
6226 - if (item[enumConst.DEFAULT_IMAGE_FLAG]) continue  
6227 - addRecord()  
6228 - const rowFilter = getRowFilter(index)  
6229 - $(`#${enumActionEl.TABLE_BODY_EL}`).find(`tr[lay-filter="${rowFilter}"] .${enumActionEl.PREVIEW_IMG_CONTAINER}>img`).attr('src', item[enumConst.IMAGE_GALLERY_IMAGE_PATH])  
6230 - form.val(rowFilter, { ...item })  
6231 - }  
6232 - }  
6233 -  
6234 - function echoDefaultImage(info) {  
6235 - const { condition } = info  
6236 - const data = condition.find(item => item[enumConst.DEFAULT_IMAGE_FLAG])  
6237 - if (data) {  
6238 - $(`#${enumActionEl.DEFAULT_IMAGE_EL}`).find(`.${enumActionEl.PREVIEW_IMG_CONTAINER}>img`).attr('src', data[enumConst.IMAGE_GALLERY_IMAGE_PATH])  
6239 - form.val(enumActionEl.DEFAULT_IMAGE_FILTER, { ...data })  
6240 - }  
6241 - }  
6242 -  
6243 - /**  
6244 - * @description 验证最大最小值  
6245 - * @param tableData  
6246 - * @returns {boolean}  
6247 - */  
6248 - function validate(tableData) {  
6249 - let validateFlag = true  
6250 - for (let i = 0; i < tableData.length; i++) {  
6251 - const { min, max } = tableData[i]  
6252 - if (Number(min) > Number(max)) {  
6253 - validateFlag = false  
6254 - layer.tips('输入值大于最大值', $(`#${enumActionEl.TABLE_BODY_EL} tr`).eq(i).find(`input[name="${enumConst.MIN}"]`))  
6255 - break  
6256 - } else if (Number(max) < Number(min)) {  
6257 - validateFlag = false  
6258 - layer.tips('输入值小于最小值', $(`#${enumActionEl.TABLE_BODY_EL} tr`).eq(i).find(`input[name="${enumConst.MAX}"]`))  
6259 - break  
6260 - }  
6261 - }  
6262 - return validateFlag  
6263 - }  
6264 -  
6265 - /**  
6266 - * @description  
6267 - */  
6268 - async function submit(callback) {  
6269 - if (!hasPermission()) return  
6270 - const data = Array.from({ length: addRowNumber }).map((_, row) => form.val(getRowFilter(row))).filter(item => Object.keys(item).length)  
6271 - const defaultImageConfig = form.val(enumActionEl.DEFAULT_IMAGE_FILTER)  
6272 - defaultImageConfig[enumConst.DEFAULT_IMAGE_FLAG] = true  
6273 - data.push(defaultImageConfig)  
6274 - if (!validate(data)) return  
6275 - const formVal = getDataSourceValue()  
6276 - const formModel = {  
6277 - configurationId,  
6278 - contentId: currentPageId.id,  
6279 - ...formVal,  
6280 - id: graphId,  
6281 - condition: data,  
6282 - type: event.data.type,  
6283 - }  
6284 - await to(autoSaveGraphInfo())  
6285 - const [err, res] = await to(ConfigurationNodeApi.updateNodeAct(formModel))  
6286 - if (err) return  
6287 - UseLayUi.successMsg()  
6288 - callback()  
6289 - }  
6290 -  
6291 - function createLayerForm(type) {  
6292 - const content = `  
6293 - <div class="layui-form" lay-filter="${enumActionEl.DEFAULT_IMAGE_FILTER}" style="display: flex; align-items: center; padding-top: 10px;">  
6294 - <div style="width: 60px; padding: 9px 10px 9px 20px;">默认图片</div>  
6295 - <div id="${enumActionEl.DEFAULT_IMAGE_EL}" style="padding: 0;"></div>  
6296 - </div>  
6297 - <div style="width: 300px; padding: 0 0 0 20px;" id="${enumActionEl.DATA_SOURCE_COMP_EL}"></div>  
6298 - <div class="override__table" style="padding: 0 20px">  
6299 - <table class="layui-table" >  
6300 - <thead>  
6301 - <tr>  
6302 - <th style="text-align:center">最小值(>=)</th>  
6303 - <th style="text-align:center">最大值(<=)</th>  
6304 - <th style="text-align:center">对应图片</th>  
6305 - <th style="text-align:center">操作</th>  
6306 - </tr>  
6307 - </thead>  
6308 - <tbody id="${enumActionEl.TABLE_BODY_EL}"></tbody>  
6309 - </table>  
6310 - </div>  
6311 - <div style="display:flex;justify-content:center;">  
6312 - <button type="button" class="layui-btn layui-btn-primary layui-border-blue" id="${enumActionEl.ADD_ROW_EL}">添加一条</button>  
6313 - </div>  
6314 - `  
6315 -  
6316 - layer.open({  
6317 - title: '变量值图片功能',  
6318 - type: 1,  
6319 - content,  
6320 - skin: 'event-layer__override',  
6321 - area: '700px',  
6322 - btn: ["保存", "取消"],  
6323 - shade: ["0.7", "#fafafa"],  
6324 - offset: '100px',  
6325 - yes(index) {  
6326 - form.on(`submit(${enumActionEl.LAYER_SUBMIT_FILTER})`, data => {  
6327 - submit(() => {  
6328 - layer.close(index)  
6329 - getNodeBindInfo()  
6330 - })  
6331 - })  
6332 - },  
6333 - but2(index, layero) {  
6334 - return false  
6335 - },  
6336 - async success(layero, index) {  
6337 - $(layero).addClass('layui-form').find('.layui-layer-btn0').attr({  
6338 - 'lay-submit': '',  
6339 - 'lay-filter': enumActionEl.LAYER_SUBMIT_FILTER,  
6340 - })  
6341 - const { component, echoDataSource, getValue } = generateDataSourceComponent()  
6342 - getDataSourceValue = getValue  
6343 -  
6344 - const el = $(`#${enumActionEl.DEFAULT_IMAGE_EL}`)  
6345 - generateUploadImgContainer({ el })  
6346 -  
6347 - $(`#${enumActionEl.DATA_SOURCE_COMP_EL}`).append(component)  
6348 - form.render()  
6349 - const info = getLayerBindInfo('act', type)  
6350 - const { condition = [] } = info  
6351 - if (!condition.length) {  
6352 - addRecord()  
6353 - } else {  
6354 - echoDataSource(info)  
6355 - echoFormData(info)  
6356 - echoDefaultImage(info)  
6357 - }  
6358 - generatorEventListen()  
6359 - },  
6360 - })  
6361 - }  
6362 -  
6363 - createLayerForm(event.data.type)  
6364 - }  
6365 -  
6366 - /**  
6367 - * @description 处理数据交互 - down || up 按下与抬起  
6368 - */  
6369 - function handleDownOrUpEvent(event) {  
6370 -  
6371 - // 事件类型  
6372 - const enumEventType = {  
6373 - DOWN: "按下",  
6374 - UP: "抬起",  
6375 - SINGLE: "单击",  
6376 - DOUBLE: "双击",  
6377 - };  
6378 -  
6379 - const enumActionEl = {  
6380 -  
6381 - /**  
6382 - * @description 表单控制 filter  
6383 - */  
6384 - FORM_FILTER: 'interactionFormFilter',  
6385 -  
6386 - /**  
6387 - * @description 表体节点  
6388 - */  
6389 - DEVICE_DATA_BODY_EL: 'deviceDataTbody',  
6390 -  
6391 - /**  
6392 - * @description 删除行节点  
6393 - */  
6394 - DEL_ROW_EL: 'deleteRow',  
6395 -  
6396 - /**  
6397 - * @description 增加行节点  
6398 - */  
6399 - ADD_ROW_EL: 'addRow',  
6400 -  
6401 - /**  
6402 - * @descripton  
6403 - */  
6404 - ROW_FILTER: 'interactionRowFilter',  
6405 -  
6406 - /**  
6407 - * @description json editor  
6408 - */  
6409 - EDITOR_JSON: 'editor__json-',  
6410 -  
6411 - /**  
6412 - * @description 弹出层保存 filter  
6413 - */  
6414 - LAYER_SUBMIT_FILTER: 'interactionLayerSubmit',  
6415 -  
6416 - /**  
6417 - * @description ace builder  
6418 - */  
6419 - JSON: 'ace__builder-json',  
6420 -  
6421 - /**  
6422 - * @description 组织树节点  
6423 - */  
6424 - ORG_EL: 'interactionOrgTree',  
6425 - }  
6426 -  
6427 -  
6428 - /**  
6429 - * @description 所有设备选项  
6430 - * @type {{id: string, name: string, deviceType: string}[]}  
6431 - */  
6432 - let allDeviceOptions = []  
6433 -  
6434 - let addRowNumber = 0  
6435 -  
6436 - /**  
6437 - * @description 组织id  
6438 - * @type {null}  
6439 - */  
6440 - let orgId = null  
6441 -  
6442 - const recordData = {  
6443 - orgId: null,  
6444 - enabled: false  
6445 - }  
6446 -  
6447 - const getRowFilter = (rowNumber) => `${enumActionEl.ROW_FILTER}${rowNumber}`  
6448 -  
6449 - /**  
6450 - * @description 枚举常量  
6451 - * @enum DEVICE  
6452 - */  
6453 - const enumConst = {  
6454 - /**  
6455 - * @description 设备  
6456 - */  
6457 - DEVICE: 'deviceId',  
6458 - /**  
6459 - * @description 子设备  
6460 - */  
6461 - SLAVE_DEVICE: 'slaveDeviceId',  
6462 - /**  
6463 - * @description 变量  
6464 - */  
6465 - ATTR: 'attr',  
6466 - /**  
6467 - * @description 下发值  
6468 - */  
6469 - VALUE: 'value',  
6470 -  
6471 - /**  
6472 - * @description 方式  
6473 - */  
6474 - WAY: 'way',  
6475 -  
6476 - /**  
6477 - * @description 组织id  
6478 - */  
6479 - ORG_ID: 'orgId',  
6480 - }  
6481 -  
6482 - const sendInstructionWay = {  
6483 - ONE_WAY: 'oneway',  
6484 - TWO_WAY: 'twoway',  
6485 - }  
6486 -  
6487 - /**  
6488 - * @description 创建回显数据 查询出所有网关设备和直连设备  
6489 - */  
6490 - async function getAllGatewayDeviceAndConnectionDevice() {  
6491 - if (!recordData.orgId) return  
6492 - const [err, res] = await to(ConfigurationNodeApi.getAllGatewayDeviceAndConnectionDevice(recordData.orgId))  
6493 - allDeviceOptions = res  
6494 - mountAllDeviceToSelect()  
6495 - }  
6496 -  
6497 - /**  
6498 - * @description 将设备选项挂载到节点中  
6499 - */  
6500 - function mountAllDeviceToSelect() {  
6501 - const generateOption = UseLayUi.generateOptionTemplate({ dataSource: allDeviceOptions })  
6502 - $(`#${enumActionEl.DEVICE_DATA_BODY_EL}`).find(`select[name="${enumConst.DEVICE}"]`).html(generateOption)  
6503 - UseLayUi.nextTick(() => form.render('select'))  
6504 - }  
6505 -  
6506 - /**  
6507 - * @description 创建JSON编辑器  
6508 - * @param el  
6509 - * @param datum  
6510 - */  
6511 - function createEditor(el, datum = {}) {  
6512 - const editor = ace.edit(el, {  
6513 - maxLines: 10, // 最大行数,超过会自动出现滚动条  
6514 - minLines: 5, // 最小行数,还未到最大行数时,编辑器会自动伸缩大小  
6515 - fontSize: 14, // 编辑器内字体大小  
6516 - tabSize: 2, // 制表符设置为 4 个空格大小  
6517 - });  
6518 - editor.session.setMode("ace/mode/json");  
6519 - editor.getSession().on('change', (event, editor) => {  
6520 - $(`#${el}`).parent().find(`textarea[name="${enumConst.VALUE}"]`).val(editor.getValue())  
6521 - })  
6522 - editor.setValue(datum[enumConst.VALUE] ? datum[enumConst.VALUE] : "{}")  
6523 - }  
6524 -  
6525 - /**  
6526 - * @description 创建组织树  
6527 - */  
6528 - async function createOrgTreeSelect() {  
6529 - const [err, res] = await to(ConfigurationNodeApi.getOrgTree())  
6530 - treeList = res  
6531 - if (err) return  
6532 - UseLayUi.createTreeSelect({  
6533 - elem: `#${enumActionEl.ORG_EL}`,  
6534 - layFilter: enumConst.ORG_ID,  
6535 - label: '组织',  
6536 - singleUsage: false,  
6537 - layVerify: 'required',  
6538 - layVerType: 'tips',  
6539 - treeProps: {  
6540 - data: res,  
6541 - onlyIconControl: true,  
6542 - click(node) {  
6543 - recordData.orgId = node.data.id  
6544 - getAllGatewayDeviceAndConnectionDevice()  
6545 - },  
6546 - },  
6547 - })  
6548 - }  
6549 -  
6550 -  
6551 -  
6552 - /**  
6553 - * @description 添加行  
6554 - * @param datum  
6555 - */  
6556 - function addRecord(datum) {  
6557 - const content = `  
6558 - <tr class="layui-form" lay-filter="${getRowFilter(addRowNumber)}">  
6559 - <td>  
6560 - <select name="${enumConst.DEVICE}" lay-filter="${enumConst.DEVICE}" lay-verType="tips" lay-verify="required"></select>  
6561 - </td>  
6562 - <td>  
6563 - <form action="" style="display: flex">  
6564 - <div class="override__radio-default">  
6565 - <input id="${getRowFilter(addRowNumber)}${sendInstructionWay.ONE_WAY}" type="radio" name="${enumConst.WAY}" lay-ignore value="${sendInstructionWay.ONE_WAY}" title="单向" checked="">  
6566 - <label for="${getRowFilter(addRowNumber)}${sendInstructionWay.ONE_WAY}" class="override__radio-label">单向</label>  
6567 - </div>  
6568 - <div class="override__radio-default">  
6569 - <input id="${getRowFilter(addRowNumber)}${sendInstructionWay.TWO_WAY}" type="radio" name="${enumConst.WAY}" lay-ignore value="${sendInstructionWay.TWO_WAY}" title="双向">  
6570 - <label for="${getRowFilter(addRowNumber)}${sendInstructionWay.TWO_WAY}" class="override__radio-label">双向</label>  
6571 - </div>  
6572 - </form>  
6573 - </td>  
6574 - <td class="${enumActionEl.JSON}">  
6575 - <div style="width: 100%;height: 100%;">  
6576 - <div id="${enumActionEl.EDITOR_JSON}${addRowNumber}"></div>  
6577 - <textarea style="display: none" name="${enumConst.VALUE}" placeholder="请输入命令" lay-verType="tips" class="layui-textarea"></textarea>  
6578 - </div>  
6579 - </td>  
6580 - <td>  
6581 - <button type="button" class="layui-btn layui-btn-primary layui-border-red ${enumActionEl.DEL_ROW_EL}">删除</button>  
6582 - </td>  
6583 - </tr>  
6584 - `  
6585 - $(`#${enumActionEl.DEVICE_DATA_BODY_EL}`).append(content)  
6586 - setDeviceOptions(addRowNumber)  
6587 - createEditor(`${enumActionEl.EDITOR_JSON}${addRowNumber}`, datum)  
6588 - form.render('select', getRowFilter(addRowNumber))  
6589 - addRowNumber++  
6590 - }  
6591 -  
6592 -  
6593 - /**  
6594 - * @description 删除行  
6595 - */  
6596 - function createDeleteRowListenEvent() {  
6597 - $(`#${enumActionEl.DEVICE_DATA_BODY_EL}`).on('click', `.${enumActionEl.DEL_ROW_EL}`, (event) => {  
6598 - // $(event.target).parents('tr').find('editor')  
6599 - $(event.target).parents('tr').remove()  
6600 - })  
6601 - }  
6602 -  
6603 - /**  
6604 - * @description 新增行  
6605 - */  
6606 - function createAddRowListenEvent() {  
6607 - $(`#${enumActionEl.ADD_ROW_EL}`).on('click', () => {  
6608 - addRecord()  
6609 - const generateOption = UseLayUi.generateOptionTemplate({ dataSource: allDeviceOptions })  
6610 - $(`#${enumActionEl.DEVICE_DATA_BODY_EL} tr`).last().find(`select[name="${enumConst.DEVICE}"]`).html(generateOption)  
6611 - form.render('select')  
6612 - })  
6613 - }  
6614 -  
6615 - /**  
6616 - * @description 设置设备选项  
6617 - */  
6618 - function setDeviceOptions(row) {  
6619 - const generateOption = UseLayUi.generateOptionTemplate({ dataSource: allDeviceOptions })  
6620 - $(`#${enumActionEl.DEVICE_DATA_BODY_EL} tr[lay-filter="${getRowFilter(row)}"]`).find(`select[name="${enumConst.DEVICE}"]`).html(generateOption)  
6621 - }  
6622 -  
6623 - /**  
6624 - * @description 下拉选项挂载  
6625 - */  
6626 - function createSelectOptionMountEvent() {  
6627 - $(`#${enumActionEl.DEVICE_DATA_BODY_EL}`).on('click', '.layui-form-select', event => {  
6628 - const width = event.currentTarget.offsetWidth || 200  
6629 - const height = event.currentTarget.offsetHeight || 38  
6630 - const offset = $(event.currentTarget).offset()  
6631 - $(event.currentTarget).find('dl').css({  
6632 - position: 'fixed',  
6633 - 'min-width': width + 'px',  
6634 - top: offset.top + height + 'px',  
6635 - left: offset.left + 'px'  
6636 - })  
6637 - })  
6638 - }  
6639 -  
6640 - /**  
6641 - * @description 生成事件监听  
6642 - */  
6643 - function generatorEventListen() {  
6644 - createDeleteRowListenEvent()  
6645 - createAddRowListenEvent()  
6646 - createSelectOptionMountEvent()  
6647 - }  
6648 -  
6649 - /**  
6650 - * @description 回显表单数据  
6651 - */  
6652 - function echoFormData(info) {  
6653 - const { content: { data = [] } = {} } = info  
6654 - data.forEach((datum, index) => {  
6655 - addRecord(datum)  
6656 - form.val(getRowFilter(index), datum)  
6657 - })  
6658 - }  
6659 -  
6660 - /**  
6661 - * @description 回显组织树  
6662 - */  
6663 - function echoOrgTree(id) {  
6664 - recordData.orgId = id  
6665 - const node = UseLayUi.findTreeObjectByField(treeList, id)  
6666 - UseLayUi.nextTick(() => {  
6667 - $(`#${enumActionEl.ORG_EL} input[name="${enumConst.ORG_ID}"]`).val(recordData.orgId).parent().find('span').html(node?.name)  
6668 - })  
6669 - }  
6670 -  
6671 - /**  
6672 - * @description 判断是否为正确的JSON结构  
6673 - * @param {string} string  
6674 - * @returns  
6675 - */  
6676 - function isJson(string) {  
6677 - if (typeof string === 'string') {  
6678 - try {  
6679 - const obj = JSON.parse(string)  
6680 - if (typeof obj === 'object' && obj !== null) {  
6681 - return true  
6682 - }  
6683 - } catch (e) {  
6684 - return false  
6685 - }  
6686 - }  
6687 - return false  
6688 - }  
6689 -  
6690 - /**  
6691 - * @description 表单验证  
6692 - * @param tableData  
6693 - * @returns {boolean}  
6694 - */  
6695 - function validate(tableData) {  
6696 - let validateFlag = true  
6697 -  
6698 - const formModel = form.val(enumActionEl.FORM_FILTER)  
6699 - if (!formModel[enumConst.ORG_ID]) return false  
6700 -  
6701 - for (let i = 0; i < tableData.length; i++) {  
6702 - const { value } = tableData[i]  
6703 - if (!isJson(value)) {  
6704 - validateFlag = false  
6705 - layer.tips('下发值不正确', $(`#${enumActionEl.DEVICE_DATA_BODY_EL} tr`).eq(i).find(`td.${enumActionEl.JSON}`), { tips: 1 })  
6706 - break  
6707 - }  
6708 - }  
6709 - return validateFlag  
6710 - }  
6711 -  
6712 -  
6713 -  
6714 - /**  
6715 - * @description 保存  
6716 - */  
6717 - async function submit(callback) {  
6718 - if (!hasPermission()) return  
6719 - const data = Array.from({ length: addRowNumber }).map((_, row) => form.val(getRowFilter(row))).filter(item => Object.keys(item).length)  
6720 - if (!validate(data)) return  
6721 - const formModal = {  
6722 - ...recordData,  
6723 - configurationId,  
6724 - // orgId,  
6725 - contentId: currentPageId.id,  
6726 - id: graphId,  
6727 - content: {  
6728 - data,  
6729 - },  
6730 - type: event.data.type,  
6731 - };  
6732 - await to(autoSaveGraphInfo())  
6733 - const [err, res] = await to(ConfigurationNodeApi.updateNodeEvent(formModal))  
6734 - if (err) return  
6735 - UseLayUi.successMsg()  
6736 - callback()  
6737 - }  
6738 -  
6739 - /**  
6740 - * @description 创建弹出层表单  
6741 - * @param event  
6742 - */  
6743 - function createLayerForm(type) {  
6744 - const content = `  
6745 - <form class="layui-form" lay-filter="${enumActionEl.FORM_FILTER}">  
6746 - <div style="width:400px">  
6747 - <div class="layui-form-item">  
6748 - <label class="layui-form-label">事件</label>  
6749 - <div class="layui-input-block">  
6750 - <input type="text" name="event" class="layui-input" value="${enumEventType[type]}" disabled>  
6751 - </div>  
6752 - </div>  
6753 - <div class="layui-form-item">  
6754 - <label class="layui-form-label">动作</label>  
6755 - <div class="layui-input-block">  
6756 - <select name="action" lay-verify="required">  
6757 - <option value="0" selected>给变量赋值</option>  
6758 - </select>  
6759 - </div>  
6760 - </div>  
6761 - <div class="layui-form-item">  
6762 - <label class="layui-form-label">类型</label>  
6763 - <div class="layui-input-block">  
6764 - <input type="radio" name="type" value="1" title="联网设备" checked>  
6765 - <input type="radio" name="type" value="2" title="产品/场景" disabled>  
6766 - </div>  
6767 - </div>  
6768 - <div id="${enumActionEl.ORG_EL}"></div>  
6769 - </div>  
6770 - </form>  
6771 - <div class="override__table">  
6772 - <table class="layui-table" >  
6773 - <thead>  
6774 - <tr>  
6775 - <th style="text-align:center">选择设备</th>  
6776 - <th style="text-align:center">单向 / 双向</th>  
6777 - <th style="text-align:center">下发值</th>  
6778 - <th style="text-align:center">操作</th>  
6779 - </tr>  
6780 - </thead>  
6781 - <tbody id="${enumActionEl.DEVICE_DATA_BODY_EL}"></tbody>  
6782 - </table>  
6783 - <div style="display:flex;justify-content:center;">  
6784 - <button type="button" class="layui-btn layui-btn-primary layui-border-blue" id="${enumActionEl.ADD_ROW_EL}">添加一条</button>  
6785 - </div>  
6786 - </div>`  
6787 -  
6788 - layer.open({  
6789 - title: '创建交互',  
6790 - content,  
6791 - skin: 'event-layer__override',  
6792 - // area: ["1100px", "700px"],  
6793 - area: '1100px',  
6794 - offset: '100px',  
6795 - btn: ["保存", "取消"],  
6796 - shade: ["0.7", "#fafafa"],  
6797 - yes(index) {  
6798 - form.on(`submit(${enumActionEl.LAYER_SUBMIT_FILTER})`, data => {  
6799 - submit(() => {  
6800 - layer.close(index)  
6801 - getNodeBindInfo()  
6802 - })  
6803 - })  
6804 - },  
6805 - but2(index, layero) {  
6806 - return false  
6807 - },  
6808 - async success(layero, index) {  
6809 - $(layero).addClass('layui-form').find('.layui-layer-btn0').attr({  
6810 - 'lay-submit': '',  
6811 - 'lay-filter': enumActionEl.LAYER_SUBMIT_FILTER,  
6812 - })  
6813 - await createOrgTreeSelect()  
6814 - const info = getLayerBindInfo('event', type)  
6815 - const { content: { data = [] } = {}, orgId, enabled } = info  
6816 - Object.assign(recordData, { orgId, enabled })  
6817 - await getAllGatewayDeviceAndConnectionDevice()  
6818 - if (!info || !data.length) {  
6819 - addRecord()  
6820 - } else {  
6821 - echoFormData(info)  
6822 - }  
6823 - generatorEventListen()  
6824 - form.render()  
6825 - echoOrgTree(orgId)  
6826 - },  
6827 - })  
6828 - }  
6829 -  
6830 - createLayerForm(event.data.type)  
6831 - }  
6832 -  
6833 - /**  
6834 - * @description 处理单击 or 双击事件  
6835 - */  
6836 - function handleClickOrDbClick(event) {  
6837 - const basicAttr = sidebarInstance.enumCellBasicAttribute  
6838 - const componentType = sidebarInstance.enumComponentType  
6839 - const currentNodeType = nodeInfo.getAttribute(basicAttr.COMPONENT_TYPE)  
6840 - const isControlComponent = [componentType.SWITCH, componentType.PARAMS_SETTING_BUTTON].includes(currentNodeType)  
6841 -  
6842 - const enumEventType = {  
6843 - DOWN: "按下",  
6844 - UP: "抬起",  
6845 - SINGLE: "单击",  
6846 - DOUBLE: "双击",  
6847 - };  
6848 -  
6849 - /**  
6850 - * @description  
6851 - */  
6852 - const enumConst = {  
6853 - EVENT: 'event',  
6854 - ACTION: 'actionType',  
6855 - PAGE_VALUE: 'pageValue',  
6856 - LINK_VALUE: 'linkValue',  
6857 -  
6858 - /**  
6859 - * @description 下发指令  
6860 - */  
6861 - COMMAND: 'command',  
6862 -  
6863 - /**  
6864 - * @description 属性占位符  
6865 - */  
6866 - ATTR_PLACEHOLDER: 'attrPlaceholder',  
6867 -  
6868 - WAY: 'way'  
6869 - }  
6870 -  
6871 - /**  
6872 - * @description 动作类型  
6873 - */  
6874 - const enumActionType = DispatchCenter.enumPageType  
6875 -  
6876 - const enumGetValue = {  
6877 - [enumActionType.PAGE]: enumConst.PAGE_VALUE,  
6878 - [enumActionType.LINK]: enumConst.LINK_VALUE,  
6879 - }  
6880 -  
6881 - const enumWayType = {  
6882 - ONE_WAY: 'oneway',  
6883 - TWO_WAY: 'twoway'  
6884 - }  
6885 -  
6886 - const enumActionEl = {  
6887 - /**  
6888 - * @description 表单 lay-filter  
6889 - */  
6890 - FORM_FILTER: 'formModelFilter',  
6891 -  
6892 - /**  
6893 - * @description 动作 lay-filter  
6894 - */  
6895 - ACTION_SELECT_FILTER: 'actionSelectFilter',  
6896 -  
6897 - /**  
6898 - * @description 链接 ID  
6899 - */  
6900 - LINK_EL_ID: 'staticlinkPage',  
6901 -  
6902 - /**  
6903 - * @description 页面 ID  
6904 - */  
6905 - PAGE_EL_ID: 'dynamicInputPage',  
6906 -  
6907 - /**  
6908 - * @description layer submit filter  
6909 - */  
6910 - LAYER_SUBMIT_FILTER: 'dynamicLinkLayerFilter',  
6911 -  
6912 - /**  
6913 - * @description JSON 编辑器容器  
6914 - */  
6915 - EDITOR_CONTAINER: 'editorContainerEL',  
6916 -  
6917 - /**  
6918 - * @description JSON 编辑器  
6919 - */  
6920 - EDITOR: 'EDITOR',  
6921 -  
6922 - WAY_SELECT: 'dynamicWaySelectEl'  
6923 - }  
6924 -  
6925 - /**  
6926 - * @description  
6927 - */  
6928 - const recordData = {  
6929 - enabled: false  
6930 - }  
6931 -  
6932 - /**  
6933 - * @description 回显数据  
6934 - */  
6935 - function echoFormData(data) {  
6936 - const { content = {} } = data  
6937 - const val = {  
6938 - [enumConst.ACTION]: content.type,  
6939 - [enumGetValue[content.type]]: content.value,  
6940 - [enumConst.WAY]: content[enumConst.WAY]  
6941 - }  
6942 - controlFormDisplay(content.type)  
6943 - form.val(enumActionEl.FORM_FILTER, val)  
6944 - }  
6945 -  
6946 - /**  
6947 - * @description 控制form  
6948 - * @param {enumActionType} value  
6949 - */  
6950 - function controlFormDisplay(value) {  
6951 - if (value === enumActionType.PAGE) {  
6952 - $(`#${enumActionEl.LINK_EL_ID}`).css({ display: 'none' })  
6953 - $(`#${enumActionEl.PAGE_EL_ID}`).css({ display: 'block' })  
6954 - $(`#${enumActionEl.EDITOR_CONTAINER}`).css({ display: 'none' })  
6955 - $(`#${enumActionEl.WAY_SELECT}`).css({ display: 'none' })  
6956 - } else if (value === enumActionType.LINK) {  
6957 - $(`#${enumActionEl.PAGE_EL_ID}`).css({ display: 'none' })  
6958 - $(`#${enumActionEl.LINK_EL_ID}`).css({ display: 'block' })  
6959 - $(`#${enumActionEl.EDITOR_CONTAINER}`).css({ display: 'none' })  
6960 - $(`#${enumActionEl.WAY_SELECT}`).css({ display: 'none' })  
6961 - } else if (value === enumActionType.PARAMS_SETTING) {  
6962 - $(`#${enumActionEl.LINK_EL_ID}`).css({ display: 'none' })  
6963 - $(`#${enumActionEl.PAGE_EL_ID}`).css({ display: 'none' })  
6964 - $(`#${enumActionEl.EDITOR_CONTAINER}`).css({ display: 'flex' })  
6965 - $(`#${enumActionEl.WAY_SELECT}`).css({ display: 'block' })  
6966 - }  
6967 - }  
6968 -  
6969 - /**  
6970 - * @description 编辑数据交互  
6971 - */  
6972 - async function submit(callback) {  
6973 - if (!hasPermission()) return  
6974 - const formVal = form.val(enumActionEl.FORM_FILTER)  
6975 - const isParamsSetting = formVal[enumConst.ACTION] === enumActionType.PARAMS_SETTING  
6976 - const { COMPONENT_TYPE } = Sidebar.prototype.enumCellBasicAttribute  
6977 - const { SWITCH } = Sidebar.prototype.enumComponentType  
6978 - const isSwitchComponent = vertices[0].getAttribute(COMPONENT_TYPE) === SWITCH  
6979 -  
6980 - if (isParamsSetting && isSwitchComponent && (!currentNodeData.act || !currentNodeData.act.find(item => item.type === enumDynamicEffectType.SWITCH))) {  
6981 - UseLayUi.topErrorMsg('请先配置数据动效中的状态设置')  
6982 - return  
6983 - }  
6984 -  
6985 - if (isParamsSetting) {  
6986 - if (!isJson(formVal[enumConst.COMMAND])) {  
6987 - UseLayUi.topErrorMsg('命令配置存在错误')  
6988 - return  
6989 - }  
6990 - }  
6991 -  
6992 - const data = {  
6993 - type: event.data.type,  
6994 - configurationId,  
6995 - contentId: currentPageId.id,  
6996 - id: graphId,  
6997 - orgId: 'b4dd6e2b-6e0f-413c-bf5a-70133bd571e8',  
6998 - ...recordData,  
6999 - content: {  
7000 - type: formVal[enumConst.ACTION],  
7001 - value: formVal[enumGetValue[formVal[enumConst.ACTION]]],  
7002 - ...(isParamsSetting ? {  
7003 - [enumConst.COMMAND]: formVal[enumConst.COMMAND],  
7004 - [enumConst.WAY]: formVal[enumConst.WAY]  
7005 - } : {}),  
7006 - },  
7007 - }  
7008 - await to(autoSaveGraphInfo())  
7009 - const [err, res] = await to(ConfigurationNodeApi.updateNodeEvent(data))  
7010 - if (err) return  
7011 - isControlComponent && overrideCurrentData('event', 'type', res)  
7012 - isControlComponent && echoActionType()  
7013 - UseLayUi.successMsg()  
7014 - callback()  
7015 - }  
7016 -  
7017 - /**  
7018 - * @description 生成 动作选项  
7019 - */  
7020 - function generatorActionOptions() {  
7021 - const options = [  
7022 - { name: '打开链接', id: enumActionType.LINK },  
7023 - { name: '打开页面', id: enumActionType.PAGE },  
7024 - ...(isControlComponent ? [{ name: '参数设置', id: enumActionType.PARAMS_SETTING }] : []),  
7025 - { name: '给变量赋值', id: enumActionType.PROPS, disabled: true },  
7026 - ]  
7027 - return UseLayUi.generateOptionTemplate({ dataSource: options, addPlaceholderOption: false })  
7028 - }  
7029 -  
7030 - /**  
7031 - * @description 生产页面选项  
7032 - */  
7033 - function generatorPageOptions() {  
7034 - const options = ui.pages.map(item => ({ name: item.getName(), id: item.getId() }))  
7035 - return UseLayUi.generateOptionTemplate({ dataSource: options, addPlaceholderOption: false })  
7036 - }  
7037 -  
7038 - function generatorEventListen() {  
7039 - form.on(`select(${enumActionEl.ACTION_SELECT_FILTER})`, (data) => {  
7040 - const { value } = data  
7041 - controlFormDisplay(value)  
7042 - })  
7043 - }  
7044 -  
7045 - function isJson(string) {  
7046 - if (typeof string === 'string') {  
7047 - try {  
7048 - const obj = JSON.parse(string)  
7049 - if (typeof obj === 'object' && obj !== null) {  
7050 - return true  
7051 - }  
7052 - } catch (e) {  
7053 - return false  
7054 - }  
7055 - }  
7056 - return false  
7057 - }  
7058 -  
7059 - function jsonParse(value) {  
7060 - try {  
7061 - return JSON.parse(value)  
7062 - } catch (error) {  
7063 - return {}  
7064 - }  
7065 - }  
7066 -  
7067 -  
7068 - /**  
7069 - * @description 创建JSON编辑器  
7070 - * @param el  
7071 - * @param datum  
7072 - */  
7073 - function createEditor(record) {  
7074 - let defaultValue = { [enumConst.ATTR_PLACEHOLDER]: 0 }  
7075 - const editor = ace.edit(enumActionEl.EDITOR, {  
7076 - maxLines: 18, // 最大行数,超过会自动出现滚动条  
7077 - minLines: 10, // 最小行数,还未到最大行数时,编辑器会自动伸缩大小  
7078 - fontSize: 14, // 编辑器内字体大小  
7079 - tabSize: 2, // 制表符设置为 4 个空格大小  
7080 - });  
7081 - if (record.content && record.content[enumConst.COMMAND]) defaultValue = jsonParse(record.content[enumConst.COMMAND])  
7082 - const stringValue = JSON.stringify(defaultValue, null, 2)  
7083 - editor.insert(stringValue)  
7084 - $(`#${enumActionEl.EDITOR_CONTAINER}`).parent().find(`textarea[name="${enumConst.COMMAND}"]`).val(stringValue)  
7085 - editor.session.setMode("ace/mode/json");  
7086 - editor.getSession().on('change', (event, editor) => {  
7087 - $(`#${enumActionEl.EDITOR_CONTAINER}`).parent().find(`textarea[name="${enumConst.COMMAND}"]`).val(editor.getValue())  
7088 - })  
7089 - }  
7090 -  
7091 - /**  
7092 - * @description 创建弹窗表单  
7093 - */  
7094 - function createLayerForm(type) {  
7095 -  
7096 - const content = `  
7097 - <form class="layui-form" lay-filter="${enumActionEl.FORM_FILTER}">  
7098 - <div style="width: 450px">  
7099 - <div class="layui-form-item">  
7100 - <label class="layui-form-label">事件</label>  
7101 - <div class="layui-input-block">  
7102 - <input type="text" name="${enumConst.EVENT}" disabled class="layui-input" value="${enumEventType[type]}">  
7103 - </div>  
7104 - </div>  
7105 - <div class="layui-form-item">  
7106 - <label class="layui-form-label">动作</label>  
7107 - <div class="layui-input-block">  
7108 - <select name="${enumConst.ACTION}" lay-verType="tips" lay-verify="required" lay-filter="${enumActionEl.ACTION_SELECT_FILTER}">  
7109 - ${generatorActionOptions()}  
7110 - </select>  
7111 - </div>  
7112 - </div>  
7113 - <div class="layui-form-item" id="${enumActionEl.LINK_EL_ID}">  
7114 - <label class="layui-form-label">链接</label>  
7115 - <div class="layui-input-block">  
7116 - <input type="text" lay-verType="tips" name="${enumConst.LINK_VALUE}" class="layui-input">  
7117 - </div>  
7118 - </div>  
7119 - <div class="layui-form-item" id="${enumActionEl.PAGE_EL_ID}" style="display:none">  
7120 - <label class="layui-form-label">页面</label>  
7121 - <div class="layui-input-block">  
7122 - <select name="${enumConst.PAGE_VALUE}" lay-verType="tips" id="pageSelect">  
7123 - ${generatorPageOptions()}  
7124 - </select>  
7125 - </div>  
7126 - </div>  
7127 - <div class="layui-form-item" id="${enumActionEl.WAY_SELECT}" style="display:none">  
7128 - <label class="layui-form-label">单向/双向 ${createHelpMessage(`单向:服务器向网关设备、直连设备发送指令。发送指令后,设备不会返回任何信息。\n  
7129 - 双向:服务器向网关设备、直连设备发送指令。发送指令后,设备返回响应信息。`, 'way')}</label>  
7130 - <div class="layui-input-block">  
7131 - <input type="radio" name="${enumConst.WAY}" value="${enumWayType.ONE_WAY}" title="单向" checked="">  
7132 - <input type="radio" name="${enumConst.WAY}" value="${enumWayType.TWO_WAY}" title="双向">  
7133 - </div>  
7134 - </div>  
7135 - <div id="${enumActionEl.EDITOR_CONTAINER}" style="display: none;">  
7136 - <div style="width: 80px; text-align: right; padding: 9px 15px;flex: 0 0 80px;">命令 ${createHelpMessage('用户预览模式下,点击参数设置后。输入的变量值将作为"attrPlaceholder"的值,并以JSON格式下发给服务器。', 'command')}</div>  
7137 - <div id="${enumActionEl.EDITOR}" style="width: 100%; height: 100%;border: 2px solid #eee;"></div>  
7138 - <textarea name="${enumConst.COMMAND}" style="display: none;" />  
7139 - </div>  
7140 - </div>  
7141 - </form>  
7142 - `  
7143 -  
7144 - layer.open({  
7145 - title: "创建交互",  
7146 - content,  
7147 - area: ["800px", "500px"],  
7148 - btn: ["保存", "取消"],  
7149 - yes(index) {  
7150 - form.on(`submit(${enumActionEl.LAYER_SUBMIT_FILTER})`, data => {  
7151 - submit(() => {  
7152 - layer.close(index)  
7153 - !isControlComponent && getNodeBindInfo()  
7154 - })  
7155 - })  
7156 - },  
7157 - btn2(index) {  
7158 - layer.close(index);  
7159 - },  
7160 - success(layero) {  
7161 - $(layero).addClass('layui-form').find('.layui-layer-btn0').attr({  
7162 - 'lay-submit': '',  
7163 - 'lay-filter': enumActionEl.LAYER_SUBMIT_FILTER,  
7164 - })  
7165 - generatorEventListen()  
7166 - const info = getLayerBindInfo('event', type)  
7167 - Object.assign(recordData, { enabled: info.enabled })  
7168 - createEditor(info)  
7169 - form.render(null, enumActionEl.FORM_FILTER)  
7170 - if (info) echoFormData(info)  
7171 - },  
7172 - shade: ["0.7", "#fafafa"],  
7173 - });  
7174 - }  
7175 -  
7176 - createLayerForm(event.data.type)  
7177 - }  
7178 -  
7179 - /**  
7180 - * @description 处理数据动效  
7181 - */  
7182 - function handleDataDynamicEffect(event) {  
7183 -  
7184 - const IS_DISPLAY = event.data.type === enumDynamicEffectType.DISPLAY  
7185 - const IS_RUNNING = event.data.type === enumDynamicEffectType.RUNNING  
7186 -  
7187 - const enumEventType = {  
7188 - FLASH: '闪烁',  
7189 - DISPLAY: '显示/隐藏',  
7190 - ROTATE: '旋转',  
7191 - RUNNING: '水流动效'  
7192 - }  
7193 -  
7194 - const enumActionEl = {  
7195 - ROW_FILTER: 'dataDynamicEffectRowFilter',  
7196 - FORM_FILTER: 'dataDynamicEffectFormFilter',  
7197 - TABLE_BODY_EL: 'dataDynamicEffectTbody',  
7198 - TYPE_EL: 'dataDynamicEffectType',  
7199 - DEL_BTN_EL: 'dataDynamicEffectDelBtn',  
7200 - ADD_BTN_EL: 'dataDynamicEffectAddBtn',  
7201 - DISPLAY_SWITCH_EL: 'visibleOrHidden',  
7202 - LAYER_SUBMIT_FILTER: 'dynamicEffectLayerFilter',  
7203 - MIN_FILTER: 'dynamicEffectMinFilter',  
7204 - MAX_FILTER: 'dynamicEffectMaxFilter',  
7205 - DATA_SOURCE_COMP_EL: 'dynamicDataSourceCompEl',  
7206 - }  
7207 -  
7208 - const getRowFilter = (rowNumber) => `${enumActionEl.ROW_FILTER}${rowNumber}`  
7209 -  
7210 - /**  
7211 - * @description  
7212 - */  
7213 - const enumConst = {  
7214 - MIN: 'min',  
7215 - MAX: 'max',  
7216 - TYPE: 'type',  
7217 - ORG_ID: 'orgId',  
7218 - DEVICE_ID: 'deviceId',  
7219 - SLAVE_DEVICE_ID: 'slaveDeviceId',  
7220 - ATTR: 'attr',  
7221 - GATEWAY: 'GATEWAY',  
7222 - }  
7223 -  
7224 - const enumDisplayType = HandleDynamicEffect.enumDisplayType  
7225 -  
7226 - const enumRunningType = HandleDynamicEffect.enumRunningType  
7227 -  
7228 - const displayOptions = [  
7229 - { name: '显示', id: enumDisplayType.SHOW },  
7230 - { name: '隐藏', id: enumDisplayType.HIDDEN },  
7231 - ]  
7232 -  
7233 - const runningOptions = [  
7234 - { name: '流动', id: enumRunningType.RUN },  
7235 - { name: '静止', id: enumRunningType.STOP },  
7236 - ]  
7237 -  
7238 - /**  
7239 - * @description  
7240 - */  
7241 - let addRowNumber = 0  
7242 -  
7243 - const recordData = {  
7244 - enabled: false  
7245 - }  
7246 -  
7247 - function generateStateOptions(options = []) {  
7248 - const template = UseLayUi.generateOptionTemplate({ dataSource: options, addPlaceholderOption: false })  
7249 - return `  
7250 - <div class="layui-form-item" style="margin-bottom: 0px">  
7251 - <div class="layui-input-block" style="margin-left: 0px;">  
7252 - <select name="${enumConst.TYPE}" lay-verType="tips" lay-verify="required">${template}</select>  
7253 - </div>  
7254 - </div>  
7255 - `  
7256 - }  
7257 -  
7258 - /**  
7259 - * @description 添加一条记录  
7260 - */  
7261 - function addRecord() {  
7262 - const content = `  
7263 - <tr class="layui-form" lay-filter="${getRowFilter(addRowNumber)}">  
7264 - ${IS_DISPLAY && `<td>${generateStateOptions(displayOptions)}</td>`}  
7265 - ${IS_RUNNING && `<td>${generateStateOptions(runningOptions)}</td>`}  
7266 - <td>  
7267 - <input autocomplete="off" lay-verType="tips" lay-verify="required" type="number" name="${enumConst.MIN}" class="layui-input ${enumActionEl.MIN_FILTER}">  
7268 - </td>  
7269 - <td>  
7270 - <input autocomplete="off" lay-verType="tips" lay-verify="required" type="number" name="${enumConst.MAX}" class="layui-input ${enumActionEl.MAX_FILTER}">  
7271 - </td>  
7272 - <td style="text-align: center;">  
7273 - <button type="button" class="layui-btn layui-btn-primary layui-border-red ${enumActionEl.DEL_BTN_EL}">删除</button>  
7274 - </td>  
7275 - </tr>  
7276 - `  
7277 - addRowNumber++  
7278 - $(`#${enumActionEl.TABLE_BODY_EL}`).append(content)  
7279 - if (IS_DISPLAY || IS_RUNNING) {  
7280 - form.render()  
7281 - }  
7282 - }  
7283 -  
7284 - /**  
7285 - * @description 创建添加记录事件  
7286 - */  
7287 - function createAddRowListenEvent() {  
7288 - $(`#${enumActionEl.ADD_BTN_EL}`).on('click', () => {  
7289 - addRecord()  
7290 - })  
7291 - }  
7292 -  
7293 - /**  
7294 - * @description 创建删除行事件  
7295 - */  
7296 - function createDeleteRowListenEvent() {  
7297 - $(`#${enumActionEl.TABLE_BODY_EL}`).on('click', `.${enumActionEl.DEL_BTN_EL}`, (event) => {  
7298 - $(event.target).parents('tr').remove()  
7299 - })  
7300 - }  
7301 -  
7302 -  
7303 - /**  
7304 - * @description 创建输入监听  
7305 - */  
7306 - function createInputListener() {  
7307 - $(`#${enumActionEl.TABLE_BODY_EL}`)  
7308 - .on('input', `.${enumActionEl.MIN_FILTER}`, event => {  
7309 - const minVal = $(event.target).val()  
7310 - const maxVal = $(event.target).parents('tr').find(`input.${enumActionEl.MAX_FILTER}`).val()  
7311 - if (maxVal !== '' && Number(minVal) > Number(maxVal)) {  
7312 - layer.tips('输入值大于最大值', $(event.target), {  
7313 - tips: 1,  
7314 - });  
7315 - }  
7316 - })  
7317 - .on('input', `.${enumActionEl.MAX_FILTER}`, event => {  
7318 - const maxVal = $(event.target).val()  
7319 - const minVal = $(event.target).parents('tr').find(`input.${enumActionEl.MIN_FILTER}`).val()  
7320 - if (minVal !== '' && Number(maxVal) < Number(minVal)) {  
7321 - layer.tips('输入值小于最小值', $(event.target), {  
7322 - tips: 1,  
7323 - });  
7324 - }  
7325 - })  
7326 - }  
7327 -  
7328 -  
7329 - /**  
7330 - * @description 下拉选项挂载  
7331 - */  
7332 - function createSelectOptionMountEvent() {  
7333 - $(`#${enumActionEl.TABLE_BODY_EL}`).on('click', '.layui-form-select', event => {  
7334 - const width = event.currentTarget.offsetWidth || 200  
7335 - const height = event.currentTarget.offsetHeight || 38  
7336 - const offset = $(event.currentTarget).offset()  
7337 - $(event.currentTarget).find('dl').css({  
7338 - position: 'fixed',  
7339 - 'min-width': width + 'px',  
7340 - top: offset.top + height + 'px',  
7341 - left: offset.left + 'px'  
7342 - })  
7343 - })  
7344 - }  
7345 -  
7346 - /**  
7347 - * @description 创建事件监听  
7348 - */  
7349 - function createEventListen() {  
7350 - createInputListener()  
7351 - createAddRowListenEvent()  
7352 - createDeleteRowListenEvent()  
7353 - createSelectOptionMountEvent()  
7354 - }  
7355 -  
7356 - /**  
7357 - * @description 回显数据  
7358 - */  
7359 - function echoData(info) {  
7360 - const { condition = [] } = info  
7361 - echoEachData(condition)  
7362 - }  
7363 -  
7364 - /**  
7365 - * @description 回显行数据  
7366 - */  
7367 - function echoEachData(condition = []) {  
7368 - condition.forEach((item, index) => {  
7369 - addRecord()  
7370 - form.val(getRowFilter(index), { ...item })  
7371 - })  
7372 - }  
7373 -  
7374 - function validate(tableData) {  
7375 - let validateFlag = true  
7376 - for (let i = 0; i < tableData.length; i++) {  
7377 - const { min, max } = tableData[i]  
7378 - if (Number(min) > Number(max)) {  
7379 - validateFlag = false  
7380 - layer.tips('输入值大于最大值', $(`#${enumActionEl.TABLE_BODY_EL} tr`).eq(i).find(`input[name="${enumConst.MIN}"]`), { tips: 1 })  
7381 - break  
7382 - } else if (Number(max) < Number(min)) {  
7383 - validateFlag = false  
7384 - layer.tips('输入值小于最小值', $(`#${enumActionEl.TABLE_BODY_EL} tr`).eq(i).find(`input[name="${enumConst.MAX}"]`), { tips: 1 })  
7385 - break  
7386 - }  
7387 - }  
7388 - return validateFlag  
7389 - }  
7390 -  
7391 - async function submit(callback) {  
7392 - if (!hasPermission()) return  
7393 - const tableData = Array.from({ length: addRowNumber }).map((_, index) => form.val(getRowFilter(index))).filter(obj => Object.keys(obj).length)  
7394 - if (!validate(tableData)) return  
7395 - const formVal = form.val(enumActionEl.FORM_FILTER)  
7396 - const formModel = {  
7397 - configurationId,  
7398 - contentId: currentPageId.id,  
7399 - ...formVal,  
7400 - id: graphId,  
7401 - condition: tableData,  
7402 - type: event.data.type,  
7403 - ...recordData  
7404 - }  
7405 - await to(autoSaveGraphInfo())  
7406 - const [err, res] = await to(ConfigurationNodeApi.updateNodeAct(formModel))  
7407 - if (err) return  
7408 - UseLayUi.successMsg()  
7409 - callback()  
7410 - }  
7411 -  
7412 - function isExistInArea(min, max, value) {  
7413 - return Number(value) >= Number(min) && Number(value) <= Number(max)  
7414 - }  
7415 -  
7416 - function createLayerForm(type) {  
7417 - const content = `  
7418 - <form class="layui-form" lay-filter="${enumActionEl.FORM_FILTER}">  
7419 - <div style="width:400px">  
7420 - <div class="layui-form-item">  
7421 - <label class="layui-form-label">类型</label>  
7422 - <div class="layui-input-block">  
7423 - <input type="radio" name="type" value="1" title="联网设备" checked>  
7424 - <input type="radio" name="type" value="2" title="产品/场景" disabled>  
7425 - </div>  
7426 - </div>  
7427 -  
7428 - <div id="${enumActionEl.DATA_SOURCE_COMP_EL}"></div>  
7429 -  
7430 - </div>  
7431 - </form>  
7432 - <div class="override__table">  
7433 - <table class="layui-table" >  
7434 - <thead>  
7435 - <tr>  
7436 - ${IS_DISPLAY ? '<th style="text-align:center">类型</th>' : ''}  
7437 - ${IS_RUNNING ? '<th style="text-align:center">类型</th>' : ''}  
7438 - <th style="text-align:center">最小值(>=)</th>  
7439 - <th style="text-align:center">最大值(<=)</th>  
7440 - <th style="text-align:center">操作</th>  
7441 - </tr>  
7442 - </thead>  
7443 - <tbody id="${enumActionEl.TABLE_BODY_EL}"></tbody>  
7444 - </table>  
7445 - <div style="display:flex;justify-content:center;">  
7446 - <button type="button" class="layui-btn layui-btn-primary layui-border-blue" id="${enumActionEl.ADD_BTN_EL}">添加一条</button>  
7447 - </div>  
7448 - </div>  
7449 - `  
7450 -  
7451 - layer.open({  
7452 - title: enumEventType[type],  
7453 - content,  
7454 - skin: 'event-layer__override',  
7455 - btn: ['保存', '取消'],  
7456 - offset: '100px',  
7457 - area: (IS_DISPLAY || IS_RUNNING) ? '1000px' : '800PX',  
7458 - success(layero) {  
7459 - $(layero).addClass('layui-form').find('.layui-layer-btn0').attr({  
7460 - 'lay-submit': '',  
7461 - 'lay-filter': enumActionEl.LAYER_SUBMIT_FILTER,  
7462 - })  
7463 -  
7464 - // render data source tree  
7465 - const {  
7466 - component,  
7467 - echoDataSource,  
7468 - } = generateDataSourceComponent({ overrideClass: 'dynamic-effect__data-source-comp--override' })  
7469 - $(`#${enumActionEl.DATA_SOURCE_COMP_EL}`).append(component)  
7470 - form.render()  
7471 -  
7472 - const info = getLayerBindInfo('act', type)  
7473 - const { condition = [], enabled } = info  
7474 - Object.assign(recordData, { enabled })  
7475 - if (info && condition.length) {  
7476 - echoDataSource(info)  
7477 - echoData(info)  
7478 - } else {  
7479 - addRecord()  
7480 - }  
7481 - createEventListen()  
7482 - form.render()  
7483 - },  
7484 - yes(index) {  
7485 - form.on(`submit(${enumActionEl.LAYER_SUBMIT_FILTER})`, data => {  
7486 - submit(() => {  
7487 - layer.close(index)  
7488 - getNodeBindInfo()  
7489 - })  
7490 - })  
7491 - },  
7492 - btn2() {  
7493 -  
7494 - },  
7495 - })  
7496 - }  
7497 -  
7498 - createLayerForm(event.data.type)  
7499 -  
7500 - }  
7501 -  
7502 -  
7503 - /**  
7504 - * @description  
7505 - * @param {} event  
7506 - */  
7507 - function handleStateSetting(event) {  
7508 -  
7509 - const enumActionEl = {  
7510 - TABLE_BODY_EL: 'stateTableBodyEl',  
7511 - LAYER_SUBMIT_FILTER: 'stateSettingSubmitFilter',  
7512 - ENABLE_FILTER: 'enableFilter',  
7513 - CLOSE_FILTER: 'closeFilter',  
7514 - SET_IMG_EL: 'variableImageTableSetImgEl',  
7515 - PREVIEW_IMG_CONTAINER: 'img__container',  
7516 - DEL_PREVIEW_IMG: 'img__delete',  
7517 - PREVIEW_CONTAINER: 'previewContainer'  
7518 - }  
7519 -  
7520 - const enumConst = {  
7521 -  
7522 - TYPE: 'type',  
7523 -  
7524 - /**  
7525 - * @description 开启类型  
7526 - */  
7527 - ENABLE_TYPE: 'enable',  
7528 -  
7529 - /**  
7530 - * @description 关闭类型  
7531 - */  
7532 - CLOSE_TYPE: 'close',  
7533 -  
7534 - /**  
7535 - * @description 图片来源  
7536 - */  
7537 - IMAGE_ORIGIN: 'imageOrigin',  
7538 -  
7539 - /**  
7540 - * @description 图库图形类别  
7541 - */  
7542 - IMAGE_GALLERY_CATEGORY: 'category',  
7543 -  
7544 - /**  
7545 - * @description 图表图形路径  
7546 - */  
7547 - IMAGE_GALLERY_IMAGE_PATH: 'imagePath',  
7548 -  
7549 - /**  
7550 - * @description 状态设置 值  
7551 - */  
7552 - VALUE: 'value'  
7553 - }  
7554 -  
7555 - const recordData = {  
7556 - enabled: false  
7557 - }  
7558 -  
7559 - const StateDefaultValue = {  
7560 - enable: {  
7561 - [enumConst.TYPE]: enumConst.ENABLE_TYPE,  
7562 - [enumConst.IMAGE_ORIGIN]: 'gallery',  
7563 - [enumConst.IMAGE_GALLERY_CATEGORY]: 'switch',  
7564 - [enumConst.IMAGE_GALLERY_IMAGE_PATH]: `${Proxy_Prefix}/images/thingskit/switch-on.svg`,  
7565 - },  
7566 - close: {  
7567 - [enumConst.TYPE]: enumConst.CLOSE_TYPE,  
7568 - [enumConst.IMAGE_ORIGIN]: 'gallery',  
7569 - [enumConst.IMAGE_GALLERY_CATEGORY]: 'switch',  
7570 - [enumConst.IMAGE_GALLERY_IMAGE_PATH]: `${Proxy_Prefix}/images/thingskit/switch-off.svg`,  
7571 - }  
7572 - }  
7573 -  
7574 - function createUploadImgContainer(info) {  
7575 - const enableEl = $(`#${enumActionEl.TABLE_BODY_EL} tr[lay-filter="${enumActionEl.ENABLE_FILTER}"] .${enumActionEl.PREVIEW_CONTAINER}`)  
7576 - const closeEl = $(`#${enumActionEl.TABLE_BODY_EL} tr[lay-filter="${enumActionEl.CLOSE_FILTER}"] .${enumActionEl.PREVIEW_CONTAINER}`)  
7577 - generateUploadImgContainer({ el: enableEl })  
7578 - generateUploadImgContainer({ el: closeEl })  
7579 - }  
7580 -  
7581 - function addRecord(filter, state, defaultValue) {  
7582 - return `  
7583 - <tr class="layui-form" lay-filter="${filter}">  
7584 - <td>  
7585 - ${state}  
7586 - </td>  
7587 - <td>  
7588 - <div class="layui-form-item">  
7589 - <input class="layui-input" autocomplete="off" type="number" name="${enumConst.VALUE}" lay-verType="tips" lay-verify="required" />  
7590 - <input class="layui-input" autocomplete="off" style="display: none;" name="${enumConst.TYPE}" lay-verType="tips" lay-verify="required" />  
7591 - </div>  
7592 - </td>  
7593 - <td class=${enumActionEl.PREVIEW_CONTAINER}>  
7594 - </td>  
7595 - </tr>`  
7596 - }  
7597 -  
7598 - /**  
7599 - * @descrition 回显数据  
7600 - */  
7601 - function echoData(info = {}) {  
7602 - const { condition = [] } = info  
7603 -  
7604 - condition.forEach(item => {  
7605 - if (item[enumConst.TYPE] === enumConst.ENABLE_TYPE) {  
7606 - setRowFormValue(enumActionEl.ENABLE_FILTER, item)  
7607 - } else if (item[enumConst.TYPE] === enumConst.CLOSE_TYPE) {  
7608 - setRowFormValue(enumActionEl.CLOSE_FILTER, item)  
7609 - }  
7610 - })  
7611 -  
7612 - form.render()  
7613 - }  
7614 -  
7615 - /**  
7616 - * @description 初始化数据  
7617 - */  
7618 - function initialData() {  
7619 - setRowFormValue(enumActionEl.ENABLE_FILTER, StateDefaultValue.enable)  
7620 - setRowFormValue(enumActionEl.CLOSE_FILTER, StateDefaultValue.close)  
7621 - }  
7622 -  
7623 - function setRowFormValue(formFilter, value = {}) {  
7624 - form.val(formFilter, value)  
7625 - $(`#${enumActionEl.TABLE_BODY_EL} tr[lay-filter="${formFilter}"] .${enumActionEl.SET_IMG_EL} img`).attr('src', value[enumConst.IMAGE_GALLERY_IMAGE_PATH])  
7626 - form.render()  
7627 - }  
7628 -  
7629 - async function submit(callback) {  
7630 - if (!hasPermission()) return  
7631 -  
7632 - const enableValue = form.val(enumActionEl.ENABLE_FILTER)  
7633 - const closeValue = form.val(enumActionEl.CLOSE_FILTER)  
7634 -  
7635 - const formVal = getDataSourceBindValue()  
7636 -  
7637 - if (![formVal.deviceId && formVal.orgId].every(Boolean)) {  
7638 - UseLayUi.topErrorMsg('请先选择数据源')  
7639 - return  
7640 - }  
7641 -  
7642 - const formModel = {  
7643 - configurationId,  
7644 - contentId: currentPageId.id,  
7645 - ...formVal,  
7646 - id: graphId,  
7647 - condition: [enableValue, closeValue],  
7648 - type: event.data.type,  
7649 - ...recordData  
7650 - }  
7651 - await to(autoSaveGraphInfo())  
7652 - const [err, res] = await to(ConfigurationNodeApi.updateNodeAct(formModel))  
7653 - if (err) return  
7654 - overrideCurrentData('act', 'type', res)  
7655 - echoActionType()  
7656 - UseLayUi.successMsg()  
7657 - callback()  
7658 - }  
7659 -  
7660 - function createLayerForm(type) {  
7661 - const content = `  
7662 - <table class="layui-table">  
7663 - <colgroup>  
7664 - <col width="150">  
7665 - <col width="150">  
7666 - <col>  
7667 - </colgroup>  
7668 - <thead>  
7669 - <tr>  
7670 - <th>状态</th>  
7671 - <th>值</th>  
7672 - <th>展示图片</th>  
7673 - </tr>  
7674 - </thead>  
7675 - <tbody id="${enumActionEl.TABLE_BODY_EL}">  
7676 - ${addRecord(enumActionEl.ENABLE_FILTER, '开启')}  
7677 - ${addRecord(enumActionEl.CLOSE_FILTER, '关闭')}  
7678 - </tbody>  
7679 - </table>`  
7680 -  
7681 - layer.open({  
7682 - title: '状态设置',  
7683 - content,  
7684 - skin: 'event-layer__override',  
7685 - btn: ['保存', '取消'],  
7686 - offset: '100px',  
7687 - area: '500px',  
7688 - success(layero) {  
7689 - $(layero).addClass('layui-form').find('.layui-layer-btn0').attr({  
7690 - 'lay-submit': '',  
7691 - 'lay-filter': enumActionEl.LAYER_SUBMIT_FILTER,  
7692 - })  
7693 - createUploadImgContainer()  
7694 -  
7695 - const info = getLayerBindInfo('act', type)  
7696 - const { condition = [], enabled } = info  
7697 - Object.assign(recordData, { enabled })  
7698 -  
7699 - if (info && condition.length) {  
7700 - echoData(info)  
7701 - } else {  
7702 - initialData()  
7703 - }  
7704 - },  
7705 - yes(index) {  
7706 - form.on(`submit(${enumActionEl.LAYER_SUBMIT_FILTER})`, data => {  
7707 - submit(() => {  
7708 - layer.close(index)  
7709 - // getNodeBindInfo()  
7710 - })  
7711 - })  
7712 - },  
7713 - btn2() {  
7714 -  
7715 - },  
7716 - })  
7717 - }  
7718 -  
7719 - createLayerForm(event.data.type)  
7720 - }  
7721 -  
7722 - /**  
7723 - * @description 生成数据源组件  
7724 - * @param {object} options  
7725 - * @param {string} [options.overrideClass = ''] options.overrideClass  
7726 - * @param {boolean} [options.validate = true ] options.validate  
7727 - */  
7728 - function generateDataSourceComponent(options = {}) {  
7729 - const { overrideClass = '', validate = true } = options  
7730 - const componentFilter = `data-source__component-filter-${Date.now()}`  
7731 - const componentId = `data-source__component-${Date.now()}`  
7732 -  
7733 - const validateRule = validate ? { layVerify: 'required', layVerType: 'tips' } : {}  
7734 -  
7735 - const enumDataSourceConst = {  
7736 - ORG_ID: 'orgId',  
7737 - DEVICE_ID: 'deviceId',  
7738 - SLAVE_DEVICE_ID: 'slaveDeviceId',  
7739 - ATTR: 'attr',  
7740 - GATEWAY: 'GATEWAY',  
7741 - }  
7742 - /**  
7743 - * @description  
7744 - * @type {{id: string, deviceType: string, name: string}[]}  
7745 - */  
7746 - let deviceList = []  
7747 -  
7748 - const component = document.createElement('div')  
7749 -  
7750 - $(component)  
7751 - .addClass(`layui-form data-source__component-style ${overrideClass}`)  
7752 - .attr({  
7753 - id: componentId,  
7754 - 'lay-filter': componentFilter,  
7755 - })  
7756 -  
7757 - init()  
7758 -  
7759 - function init() {  
7760 - generatorOrgTres()  
7761 - generatorDeviceSelect()  
7762 - generatorSlaveDevice()  
7763 - generatorAttrSelect()  
7764 - }  
7765 -  
7766 -  
7767 - /**  
7768 - * @description 根据组织ID获取设备  
7769 - */  
7770 - async function getDevicesByOrgId(organizationId) {  
7771 - if (organizationId) {  
7772 - const items = deviceList = await ConfigurationNodeApi.getMasterDevice(organizationId);  
7773 - $(`#${componentId} `).find(`select[name="${enumDataSourceConst.DEVICE_ID}"]`).html(UseLayUi.generateOptionTemplate({ dataSource: items }))  
7774 - form.render('select', componentFilter)  
7775 - }  
7776 - }  
7777 -  
7778 - /**  
7779 - * @description 通过主设备ID获取从设备  
7780 - */  
7781 - async function getSlaveDeviceByMasterDeviceId(orgId, deviceId) {  
7782 - if (deviceId && currentCheckedOrgNode) {  
7783 - const items = await ConfigurationNodeApi.getSlaveDevice(orgId, deviceId);  
7784 - $(`#${componentId} `).find(`select[name="${enumDataSourceConst.SLAVE_DEVICE_ID}"]`).html(UseLayUi.generateOptionTemplate({ dataSource: items }))  
7785 - form.render('select', componentFilter)  
7786 - }  
7787 - }  
7788 -  
7789 - /**  
7790 - * @description 根据设备ID获取属性  
7791 - */  
7792 - async function getAttrByDeviceId(tbDeviceId) {  
7793 - if (tbDeviceId) {  
7794 - const [err, res] = await to(ConfigurationNodeApi.getDeviceAttr(tbDeviceId))  
7795 - $(`#${componentId} `).find(`select[name="${enumDataSourceConst.ATTR}"]`).html(UseLayUi.generateOptionTemplate({ dataSource: res }))  
7796 - form.render('select', componentFilter)  
7797 - }  
7798 - }  
7799 -  
7800 -  
7801 - /**  
7802 - * @description 生成组织选择  
7803 - */  
7804 - async function generatorOrgTres() {  
7805 - const orgContainerId = `data-source__component--org-${Date.now()}`  
7806 - const orgContainer = `<div id="${orgContainerId}"></div>`  
7807 - $(component).append(orgContainer)  
7808 -  
7809 - const [err, res] = await to(ConfigurationNodeApi.getOrgTree())  
7810 - if (err) return  
7811 - treeList = res  
7812 -  
7813 - UseLayUi.createTreeSelect({  
7814 - elem: `#${orgContainerId}`,  
7815 - layFilter: enumDataSourceConst.ORG_ID,  
7816 - label: '组织',  
7817 - singleUsage: false,  
7818 - className: 'data-source__component-select',  
7819 - ...validateRule,  
7820 - treeProps: {  
7821 - data: treeList,  
7822 - onlyIconControl: true,  
7823 - click(node) {  
7824 - currentCheckedOrgNode = node.data.id  
7825 - form.val(componentFilter, {  
7826 - [enumDataSourceConst.DEVICE_ID]: null,  
7827 - [enumDataSourceConst.SLAVE_DEVICE_ID]: null,  
7828 - [enumDataSourceConst.ATTR]: null,  
7829 - })  
7830 - getDevicesByOrgId(node.data.id)  
7831 - },  
7832 - },  
7833 - })  
7834 - }  
7835 -  
7836 - /**  
7837 - * @description 生成设备选择器  
7838 - */  
7839 - function generatorDeviceSelect() {  
7840 - const deviceSelect = UseLayUi.createSelect({  
7841 - label: '设备',  
7842 - bindValueFiled: enumDataSourceConst.DEVICE_ID,  
7843 - layFilter: `${componentFilter}--${enumDataSourceConst.DEVICE_ID}`,  
7844 - className: 'data-source__component-select',  
7845 - ...validateRule,  
7846 - onClick(data) {  
7847 - const { value } = data  
7848 - const selected = deviceList.find(item => item.id === value)  
7849 - form.val(componentFilter, {  
7850 - [enumDataSourceConst.SLAVE_DEVICE_ID]: null,  
7851 - [enumDataSourceConst.ATTR]: null,  
7852 - })  
7853 - if (!selected) return  
7854 - if (selected.deviceType === enumDataSourceConst.GATEWAY) {  
7855 - $(`#${componentId}`).find(`select[name="${enumDataSourceConst.SLAVE_DEVICE_ID}"]`)  
7856 - .attr('lay-verify', 'required').attr('lay-verType', 'tips')  
7857 - .parentsUntil(`#${componentId}`).show()  
7858 - getSlaveDeviceByMasterDeviceId(currentCheckedOrgNode, selected.id)  
7859 - } else {  
7860 - $(`#${componentId}`).find(`select[name="${enumDataSourceConst.SLAVE_DEVICE_ID}"]`)  
7861 - .attr('lay-verify', '').attr('lay-verType', 'tips')  
7862 - .parentsUntil(`#${componentId}`).hide()  
7863 - getAttrByDeviceId(selected.id)  
7864 - }  
7865 - },  
7866 - })  
7867 - $(component).append(deviceSelect)  
7868 - }  
7869 -  
7870 - /**  
7871 - * @description 生成从设备选择器  
7872 - */  
7873 - function generatorSlaveDevice() {  
7874 - const slaveDeviceSelect = UseLayUi.createSelect({  
7875 - label: '子设备',  
7876 - bindValueFiled: enumDataSourceConst.SLAVE_DEVICE_ID,  
7877 - layFilter: `${componentFilter}--${enumDataSourceConst.SLAVE_DEVICE_ID}`,  
7878 - className: 'data-source__component-select',  
7879 - onClick(data) {  
7880 - const { value } = data  
7881 - form.val(componentFilter, {  
7882 - [enumDataSourceConst.ATTR]: null,  
7883 - })  
7884 - getAttrByDeviceId(value)  
7885 - },  
7886 - })  
7887 - $(component).append(slaveDeviceSelect)  
7888 - }  
7889 -  
7890 - /**  
7891 - * @description 生成属性选择器  
7892 - */  
7893 - function generatorAttrSelect() {  
7894 - const attrsSelect = UseLayUi.createSelect({  
7895 - label: '属性',  
7896 - bindValueFiled: enumDataSourceConst.ATTR,  
7897 - layFilter: `${componentFilter}--${enumDataSourceConst.ATTR}`,  
7898 - className: 'data-source__component-select',  
7899 - ...validateRule,  
7900 - })  
7901 - $(component).append(attrsSelect)  
7902 - }  
7903 -  
7904 - /**  
7905 - * @description 回显数据  
7906 - * @param {{orgId: string, deviceId: string, slaveDeviceId?: string, attr: string}} dataSource  
7907 - */  
7908 - function echoDataSource(dataSource = {}) {  
7909 - const { orgId, deviceId, slaveDeviceId, attr } = dataSource  
7910 - const queue = []  
7911 - if (orgId) {  
7912 - currentCheckedOrgNode = orgId  
7913 - queue.push(getDevicesByOrgId(orgId))  
7914 - }  
7915 - if (slaveDeviceId) {  
7916 - queue.push(getSlaveDeviceByMasterDeviceId(orgId, deviceId))  
7917 - $(`#${componentId}`).find(`select[name="${enumDataSourceConst.SLAVE_DEVICE_ID}"]`).parentsUntil(`#${componentId}`).show()  
7918 - queue.push(getAttrByDeviceId(slaveDeviceId))  
7919 - } else {  
7920 - $(`#${componentId}`).find(`select[name="${enumDataSourceConst.SLAVE_DEVICE_ID}"]`).parentsUntil(`#${componentId}`).hide()  
7921 - queue.push(getAttrByDeviceId(deviceId))  
7922 - }  
7923 - Promise.all(queue)  
7924 - .finally(() => {  
7925 - const orgNode = UseLayUi.findTreeObjectByField(treeList, currentCheckedOrgNode)  
7926 - $(`#${componentId} input[name="${enumDataSourceConst.ORG_ID}"]`).parent().find('span').html(orgNode?.name)  
7927 - form.val(componentFilter, {  
7928 - orgId,  
7929 - deviceId,  
7930 - slaveDeviceId,  
7931 - attr,  
7932 - })  
7933 - })  
7934 - }  
7935 -  
7936 - /**  
7937 - *  
7938 - * @returns {{orgId: string, attr: string, deviceId: string, slaveDeviceId: string}}  
7939 - */  
7940 - function getValue() {  
7941 - return form.val(componentFilter)  
7942 - }  
7943 -  
7944 - return { component, getValue, componentId, componentFilter, echoDataSource }  
7945 - }  
7946 -  
7947 - /**  
7948 - * @description 生成上传弹出层组件  
7949 - */  
7950 - function generateUploadLayerComponent(callback) {  
7951 -  
7952 - const enumActionEl = {  
7953 - /**  
7954 - * @description 图片选中区域节点  
7955 - */  
7956 - IMG_SELECT_CONTAINER_EL: 'imgSelectContainerEl',  
7957 -  
7958 - /**  
7959 - * @description 切换图片来源控制  
7960 - */  
7961 - SWITCH_IMG_ORIGIN_FILTER: 'switchImgOriginFilter',  
7962 -  
7963 - /**  
7964 - * @description 图片选中侧边栏节点  
7965 - */  
7966 - VAR_IMG_CONTAINER_SIDEBAR: 'var-image__container-sidebar',  
7967 -  
7968 - /**  
7969 - * @description 图库图形选择区域  
7970 - */  
7971 - VAR_IMG_CONTAINER_CONTENT: 'var-image__container-content',  
7972 -  
7973 - /**  
7974 - * @description 图库图形项  
7975 - */  
7976 - VAR_IMG_ITEM: 'var-image__img-item',  
7977 -  
7978 - /**  
7979 - * @description 图库图形选中控制  
7980 - */  
7981 - VAR_IMG_ITEM_CHECKED: 'var-image__img-item--checked',  
7982 -  
7983 - /**  
7984 - * @description 图库图形类别节点  
7985 - */  
7986 - VAR_IMG_CATEGORY: 'var-image__category',  
7987 -  
7988 - /**  
7989 - * @description 图库图形类别选择状态  
7990 - */  
7991 - VAR_IMG_CATEGORY_CHECKED: 'var-image__category--checked',  
7992 -  
7993 - /**  
7994 - * @description 本地上传图片节点  
7995 - */  
7996 - UPLOAD_LOCAL_FILE_EL: 'var-image__container--local',  
7997 -  
7998 - /**  
7999 - * @description 本地上传图片状态  
8000 - */  
8001 - IMAGE_UPLOAD_STATE_EL: 'var-image__upload-state',  
8002 -  
8003 - /**  
8004 - * @description 预览图片状态  
8005 - */  
8006 - IMAGE_PREVIEW_EL: 'preview__img--preview',  
8007 -  
8008 - /**  
8009 - * @description 本地图片上传删除按钮  
8010 - */  
8011 - IMAGE_DEL_PREVIEW_EL: 'var-image__del-icon',  
8012 - }  
8013 -  
8014 - const enumConst = {  
8015 - /**  
8016 - * @description 图片来源  
8017 - */  
8018 - IMAGE_ORIGIN: 'imageOrigin',  
8019 -  
8020 - /**  
8021 - * @description 图库图形类别  
8022 - */  
8023 - IMAGE_GALLERY_CATEGORY: 'category',  
8024 -  
8025 - /**  
8026 - * @description 图表图形路径  
8027 - */  
8028 - IMAGE_GALLERY_IMAGE_PATH: 'imagePath',  
8029 - }  
8030 -  
8031 - /**  
8032 - * @description 图片来源枚举类型  
8033 - */  
8034 - const enumImageOriginType = {  
8035 - LOCAL: 'local',  
8036 - GALLERY: 'gallery',  
8037 - }  
8038 -  
8039 - let imageState = {}  
8040 -  
8041 - /**  
8042 - * @description 设置选中样式  
8043 - * @param event  
8044 - * @param nodeClass  
8045 - * @param styleClass  
8046 - */  
8047 - function setImageSelectedStyle(event, nodeClass, styleClass) {  
8048 - if (!$(event.target).hasClass(nodeClass)) return  
8049 - $(`.${nodeClass}`).each(function () {  
8050 - $(this).removeClass(styleClass)  
8051 - })  
8052 - $(event.target).addClass(styleClass)  
8053 - }  
8054 -  
8055 - /**  
8056 - * @description 切换图库图形  
8057 - * @param event  
8058 - */  
8059 - function switchGalleryLib(event) {  
8060 - const key = $(event.target).attr(enumConst.IMAGE_GALLERY_CATEGORY)  
8061 - const category = sidebarInstance.getVariableImageLib(key)  
8062 - if (key && category) {  
8063 - $(`#${enumActionEl.VAR_IMG_CONTAINER_CONTENT}`).html(  
8064 - category.lib.reduce((prev, next) => prev + `<div class="${enumActionEl.VAR_IMG_ITEM}" title="${next.name}"><img src="${next.staticPath}" alt=""></div>`, ''),  
8065 - )  
8066 - }  
8067 - }  
8068 -  
8069 - /**  
8070 - * @description 图片来源事件监听  
8071 - */  
8072 - function generatorSelectImgEventListener() {  
8073 - $(`#${enumActionEl.VAR_IMG_CONTAINER_CONTENT}`).on('click', event => {  
8074 - setImageSelectedStyle(event, enumActionEl.VAR_IMG_ITEM, enumActionEl.VAR_IMG_ITEM_CHECKED)  
8075 - imageState[enumConst.IMAGE_GALLERY_IMAGE_PATH] = $(event.target).find('img').attr('src')  
8076 - })  
8077 - $(`#${enumActionEl.VAR_IMG_CONTAINER_SIDEBAR}`).on('click', event => {  
8078 - setImageSelectedStyle(event, enumActionEl.VAR_IMG_CATEGORY, enumActionEl.VAR_IMG_CATEGORY_CHECKED)  
8079 - imageState[enumConst.IMAGE_GALLERY_CATEGORY] = $(event.target).attr(enumConst.IMAGE_GALLERY_CATEGORY)  
8080 - imageState[enumConst.IMAGE_GALLERY_IMAGE_PATH] = null  
8081 - switchGalleryLib(event)  
8082 - })  
8083 - }  
8084 -  
8085 -  
8086 - /**  
8087 - * @description 创建本地图片上传区域  
8088 - */  
8089 - function createLocalFileContainer() {  
8090 - return `  
8091 - <div id="${enumActionEl.UPLOAD_LOCAL_FILE_EL}" class="layui-upload">  
8092 - <div class="preview__img">  
8093 - <img src="" class="layui-upload-img" id="${enumActionEl.IMAGE_PREVIEW_EL}">  
8094 - <div class="var_image__add-icon">+</div>  
8095 - <div class="var-image__del-icon">x</div>  
8096 - </div>  
8097 - <div class="layui-upload-list"></div>  
8098 - </div>  
8099 - <div style="margin-top: 10px;" id="${enumActionEl.IMAGE_UPLOAD_STATE_EL}"></div>  
8100 - <div style="margin-top: 10px;">图片格式支持png、jpg(jpeg)、gif, 大小不能超过5M</div>`  
8101 - }  
8102 -  
8103 - /**  
8104 - * @description 创建图库图形上传区域  
8105 - */  
8106 - function createGalleryFileContainer() {  
8107 - const category = sidebarInstance.getAllVariableImageLib()  
8108 - const defaultShow = category[0] || { lib: [] }  
8109 - return `  
8110 - <div class="var-image__container--gallery">  
8111 - <div id="${enumActionEl.VAR_IMG_CONTAINER_SIDEBAR}">  
8112 - ${category.reduce((prev, next) => prev + `<div class="${enumActionEl.VAR_IMG_CATEGORY}" ${enumConst.IMAGE_GALLERY_CATEGORY}="${next.key}">${next.label}</div>`, '')}  
8113 - </div>  
8114 - <div id="${enumActionEl.VAR_IMG_CONTAINER_CONTENT}">  
8115 - ${defaultShow.lib.reduce((prev, next) => prev + `<div class="${enumActionEl.VAR_IMG_ITEM}" title="${next.name}"><img src="${next.staticPath}" alt=""></div>`, '')}  
8116 - </div>  
8117 - </div>`  
8118 - }  
8119 -  
8120 - /**  
8121 - * @description 上传  
8122 - */  
8123 - function uploadFileEvent() {  
8124 - $(`.${enumActionEl.IMAGE_DEL_PREVIEW_EL}`).on('click', (event) => {  
8125 - event.stopPropagation()  
8126 - $(`#${enumActionEl.IMAGE_PREVIEW_EL}`).attr('src', '')  
8127 - imageState[enumConst.IMAGE_GALLERY_IMAGE_PATH] = null  
8128 - })  
8129 - upload.render({  
8130 - elem: `#${enumActionEl.UPLOAD_LOCAL_FILE_EL}`,  
8131 - auto: false,  
8132 - size: 1024 * 5,  
8133 - url: '/yt/oss/upload',  
8134 - method: 'post',  
8135 - choose(obj) {  
8136 - obj.preview(async function (index, file, result) {  
8137 - const formData = new FormData()  
8138 - formData.set('file', file)  
8139 - $(`#${enumActionEl.IMAGE_UPLOAD_STATE_EL}`).html('上传中...')  
8140 - const [err, res] = await to(ConfigurationNodeApi.uploadImg(formData))  
8141 - if (!err) {  
8142 - $(`#${enumActionEl.IMAGE_PREVIEW_EL}`).attr('src', result)  
8143 - const { fileStaticUri = '' } = res  
8144 - imageState[enumConst.IMAGE_GALLERY_IMAGE_PATH] = fileStaticUri  
8145 - $(`#${enumActionEl.IMAGE_UPLOAD_STATE_EL}`).html('上传成功').css({ color: '#5fb878' })  
8146 - } else {  
8147 - $(`#${enumActionEl.IMAGE_UPLOAD_STATE_EL}`).html('上传失败').css({ color: 'red' })  
8148 - }  
8149 - });  
8150 - },  
8151 - });  
8152 - }  
8153 -  
8154 - /**  
8155 - * @description 切换  
8156 - */  
8157 - function switchUploadImgTypeEventListener() {  
8158 - form.on(`radio(${enumActionEl.SWITCH_IMG_ORIGIN_FILTER})`, event => {  
8159 - const { value } = event  
8160 - imageState = {}  
8161 - if (value === enumImageOriginType.LOCAL) {  
8162 - $(`#${enumActionEl.IMG_SELECT_CONTAINER_EL}`).html(createLocalFileContainer())  
8163 - imageState[enumConst.IMAGE_ORIGIN] = enumImageOriginType.LOCAL  
8164 - uploadFileEvent()  
8165 - } else if (value === enumImageOriginType.GALLERY) {  
8166 - $(`#${enumActionEl.IMG_SELECT_CONTAINER_EL}`).html(createGalleryFileContainer())  
8167 - const defaultChecked = $(`.${enumActionEl.VAR_IMG_CATEGORY}`).eq(0)  
8168 - defaultChecked.addClass(enumActionEl.VAR_IMG_CATEGORY_CHECKED)  
8169 - imageState[enumConst.IMAGE_GALLERY_CATEGORY] = defaultChecked.attr(enumConst.IMAGE_GALLERY_CATEGORY)  
8170 - imageState[enumConst.IMAGE_ORIGIN] = enumImageOriginType.GALLERY  
8171 - generatorSelectImgEventListener()  
8172 - }  
8173 - })  
8174 - }  
8175 -  
8176 -  
8177 - /**  
8178 - * @description 初始化并设置默认值  
8179 - */  
8180 - function initSelectImg() {  
8181 - switchUploadImgTypeEventListener()  
8182 - uploadFileEvent()  
8183 - imageState[enumConst.IMAGE_ORIGIN] = enumImageOriginType.LOCAL  
8184 - form.render()  
8185 - }  
8186 -  
8187 - /**  
8188 - * @description 创建上传图片layer  
8189 - */  
8190 - function createUploadImgLayer() {  
8191 - const content = `  
8192 - <div class="layui-form">  
8193 - <div class="layui-form-item">  
8194 - <div class="var-image__radio">  
8195 - <input type="radio" lay-filter="${enumActionEl.SWITCH_IMG_ORIGIN_FILTER}" name="${enumConst.IMAGE}" value="${enumImageOriginType.LOCAL}" title="本地图片" checked="">  
8196 - <input type="radio" lay-filter="${enumActionEl.SWITCH_IMG_ORIGIN_FILTER}" name="${enumConst.IMAGE}" value="${enumImageOriginType.GALLERY}" title="图库图形">  
8197 - </div>  
8198 - </div>  
8199 - </div>  
8200 - <div id="${enumActionEl.IMG_SELECT_CONTAINER_EL}">  
8201 - ${createLocalFileContainer()}  
8202 - </div>  
8203 - `  
8204 -  
8205 - layer.open({  
8206 - title: '图片',  
8207 - type: 1,  
8208 - content,  
8209 - skin: 'event-layer__override',  
8210 - area: '600px',  
8211 - btn: ["应用", "取消"],  
8212 - shade: ["0.7", "#fafafa"],  
8213 - yes(index) {  
8214 - layer.close(index)  
8215 - if (callback && typeof callback === 'function') callback(imageState)  
8216 - },  
8217 - but2(index, layero) {  
8218 - imageState = {}  
8219 - layer.close(index)  
8220 - },  
8221 - // zIndex: layer.zIndex,  
8222 - async success(layero, index) {  
8223 - // layer.setTop(layero);  
8224 - $(layero).addClass('layui-form').find('.layui-layer-btn0').attr({  
8225 - 'lay-submit': '',  
8226 - 'lay-filter': enumActionEl.IMAGE_LAYER_FILTER,  
8227 - })  
8228 - initSelectImg()  
8229 - },  
8230 - })  
8231 - }  
8232 -  
8233 - createUploadImgLayer()  
8234 -  
8235 - return { record: imageState }  
8236 - }  
8237 -  
8238 -  
8239 - /**  
8240 - * @description TODO 图片上传容器  
8241 - * @param {} option  
8242 - * @param {} option.el  
8243 - */  
8244 - function generateUploadImgContainer({ el }) {  
8245 -  
8246 -  
8247 - const enumConst = {  
8248 - /**  
8249 - * @description 图片来源  
8250 - */  
8251 - IMAGE_ORIGIN: 'imageOrigin',  
8252 -  
8253 - /**  
8254 - * @description 图库图形类别  
8255 - */  
8256 - IMAGE_GALLERY_CATEGORY: 'category',  
8257 -  
8258 - /**  
8259 - * @description 图表图形路径  
8260 - */  
8261 - IMAGE_GALLERY_IMAGE_PATH: 'imagePath',  
8262 - }  
8263 -  
8264 - const enumActionEl = {  
8265 -  
8266 - CONTAINER_FILTER: 'imgContainerFilter',  
8267 -  
8268 - /**  
8269 - * @description  
8270 - */  
8271 - SET_IMG_EL: 'variableImageTableSetImgEl',  
8272 -  
8273 - /**  
8274 - * @description 预览  
8275 - */  
8276 - PREVIEW_IMG_CONTAINER: 'img__container',  
8277 -  
8278 - /**  
8279 - * @description 删除  
8280 - */  
8281 - DEL_PREVIEW_IMG: 'img__delete',  
8282 - }  
8283 -  
8284 - const getFormFilter = `${enumActionEl.CONTAINER_FILTER}-${Date.now() - Math.random()}`  
8285 -  
8286 - function createTemplate() {  
8287 - return `  
8288 - <div class="layui-form ${enumActionEl.SET_IMG_EL}" lay-filter="${getFormFilter}">  
8289 - <input name="${enumConst.IMAGE_GALLERY_CATEGORY}" type="text" style="display: none">  
8290 - <input name="${enumConst.IMAGE_GALLERY_IMAGE_PATH}" type="text" style="display: none">  
8291 - <input name="${enumConst.IMAGE_ORIGIN}" type="text" style="display: none">  
8292 - <div class="${enumActionEl.PREVIEW_IMG_CONTAINER}">  
8293 - <img src="" alt="">  
8294 - <div class="${enumActionEl.DEL_PREVIEW_IMG}">x</div>  
8295 - <div class="add__button">+</div>  
8296 - </div>  
8297 - </div>  
8298 - `  
8299 - }  
8300 -  
8301 - /**  
8302 - * @description 设置回显  
8303 - * @param {} value  
8304 - */  
8305 - function setValue(value = {}) {  
8306 - form.val(getFormFilter, value)  
8307 - }  
8308 -  
8309 - /**  
8310 - * @description 获取值  
8311 - * @returns  
8312 - */  
8313 - function getValue() {  
8314 - return form.val(getFormFilter) || {}  
8315 - }  
8316 -  
8317 - function mount() {  
8318 - if (!el) throw Error('mount element is required')  
8319 - $(el).append(createTemplate())  
8320 - generateEventLinstenner()  
8321 - }  
8322 -  
8323 - // TODO 生成容器监听事件  
8324 - function generateEventLinstenner() {  
8325 - $(el).on('click', `.${enumActionEl.SET_IMG_EL}`, (event) => {  
8326 - if ($(event.target).hasClass(enumActionEl.DEL_PREVIEW_IMG)) {  
8327 - $(el).find(`div[lay-filter="${getFormFilter}"] img`).attr('src', '')  
8328 - form.val(getFormFilter, {  
8329 - [enumConst.IMAGE_ORIGIN]: null,  
8330 - [enumConst.IMAGE_GALLERY_CATEGORY]: null,  
8331 - [enumConst.IMAGE_GALLERY_IMAGE_PATH]: null,  
8332 - })  
8333 - return  
8334 - }  
8335 - generateUploadLayerComponent((imageState) => {  
8336 - $(el).find('img').attr('src', imageState[enumConst.IMAGE_GALLERY_IMAGE_PATH])  
8337 - form.val(getFormFilter, imageState)  
8338 - })  
8339 - })  
8340 - }  
8341 -  
8342 - mount()  
8343 - return { getValue, setValue }  
8344 - }  
8345 -  
8346 - function createHelpMessage(message, className) {  
8347 - return `  
8348 - <div class="thingskit-help-message ${className}">  
8349 - <img src="${Proxy_Prefix}/images/thingskit/question.svg"/>  
8350 - <div class="thingskit-help-container">  
8351 - <div class="thingskit-help-content">${message}</div>  
8352 - <div class="thingskit-help-arrow"></div>  
8353 - </div>  
8354 - </div>  
8355 - `  
8356 - }  
8357 -  
8358 - function hasPermission() {  
8359 - let flag = hasSavePermission()  
8360 - if (!flag) UseLayUi.topErrorMsg('没有权限')  
8361 - return flag  
8362 - }  
8363 -  
8364 - // 异步设置此处才能生效 -- 设置默认select和样式和初始化侧边栏生成组件和事件绑定  
8365 - setTimeout(() => {  
8366 -  
8367 - function proxyFn(fn) {  
8368 - return (...args) => {  
8369 - const currentDataSource = getDataSourceBindValue() || {}  
8370 -  
8371 - to(ConfigurationNodeApi.updateNodeInfo({  
8372 - configurationId,  
8373 - contentId: currentPageId.id,  
8374 - nodeId: graphId,  
8375 - [enumCategory.DATA_SOURCE]: currentDataSource  
8376 - }))  
8377 - fn.apply(null, args)  
8378 - }  
8379 - }  
8380 -  
8381 - // TODO 数据交互事件  
8382 - $(`#${enumDynamicEffectType.IMAGE}`).click({ type: enumDynamicEffectType.IMAGE }, proxyFn(handleSettingVarImage));  
8383 -  
8384 - $(`#${enumInteractionType.DOWN}`).click({ type: enumInteractionType.DOWN }, proxyFn(handleDownOrUpEvent));  
8385 - $(`#${enumInteractionType.UP}`).click({ type: enumInteractionType.UP }, proxyFn(handleDownOrUpEvent));  
8386 - $(`#${enumInteractionType.SINGLE}`).click({ type: enumInteractionType.SINGLE }, proxyFn(handleClickOrDbClick));  
8387 - $(`#${enumInteractionType.DOUBLE}`).click({ type: enumInteractionType.DOUBLE }, proxyFn(handleClickOrDbClick));  
8388 - // 数据动效事件  
8389 - $(`#${enumDynamicEffectType.FLASH}`).click({ type: enumDynamicEffectType.FLASH }, proxyFn(handleDataDynamicEffect));  
8390 - $(`#${enumDynamicEffectType.DISPLAY}`).click({ type: enumDynamicEffectType.DISPLAY }, proxyFn(handleDataDynamicEffect));  
8391 - $(`#${enumDynamicEffectType.ROTATE}`).click({ type: enumDynamicEffectType.ROTATE }, proxyFn(handleDataDynamicEffect));  
8392 - $(`#${enumDynamicEffectType.RUNNING}`).click({ type: enumDynamicEffectType.RUNNING }, proxyFn(handleDataDynamicEffect))  
8393 -  
8394 - $(`#${enumDynamicEffectType.SWITCH}`).click({ type: enumDynamicEffectType.SWITCH }, proxyFn(handleStateSetting))  
8395 -  
8396 - });  
8397 -};  
8398 -  
8399 -/**  
8400 - * Adds the label menu items to the given menu and parent.  
8401 - */  
8402 -StyleFormatPanel = function (format, editorUi, container) {  
8403 - BaseFormatPanel.call(this, format, editorUi, container);  
8404 - this.init();  
8405 -};  
8406 -  
8407 -mxUtils.extend(StyleFormatPanel, BaseFormatPanel);  
8408 -  
8409 -/**  
8410 - *  
8411 - */  
8412 -StyleFormatPanel.prototype.defaultStrokeColor = "black";  
8413 -  
8414 -/**  
8415 - * Adds the label menu items to the given menu and parent.  
8416 - */  
8417 -StyleFormatPanel.prototype.init = function () {  
8418 - var ui = this.editorUi;  
8419 - var editor = ui.editor;  
8420 - var graph = editor.graph;  
8421 - var ss = ui.getSelectionState();  
8422 -  
8423 - if (!ss.containsLabel && ss.cells.length > 0) {  
8424 - if (  
8425 - ss.containsImage &&  
8426 - ss.vertices.length == 1 &&  
8427 - ss.style.shape == "image" &&  
8428 - ss.style.image != null &&  
8429 - ss.style.image.substring(0, 19) == "data:image/svg+xml;"  
8430 - ) {  
8431 - this.container.appendChild(this.addSvgStyles(this.createPanel()));  
8432 - }  
8433 -  
8434 - if (ss.fill) {  
8435 - this.container.appendChild(this.addFill(this.createPanel()));  
8436 - }  
8437 -  
8438 - this.container.appendChild(this.addStroke(this.createPanel()));  
8439 - this.container.appendChild(this.addLineJumps(this.createPanel()));  
8440 - var opacityPanel = this.createRelativeOption(  
8441 - mxResources.get("opacity"),  
8442 - mxConstants.STYLE_OPACITY,  
8443 - );  
8444 - opacityPanel.style.paddingTop = "8px";  
8445 - opacityPanel.style.paddingBottom = "8px";  
8446 - this.container.appendChild(opacityPanel);  
8447 - this.container.appendChild(this.addEffects(this.createPanel()));  
8448 - }  
8449 -  
8450 - // TODO thingsKit 编辑样式 隐藏  
8451 - // var opsPanel = this.addEditOps(this.createPanel());  
8452 -  
8453 - // if (opsPanel.firstChild != null) {  
8454 - // mxUtils.br(opsPanel);  
8455 - // }  
8456 -  
8457 - // this.container.appendChild(this.addStyleOps(opsPanel));  
8458 -};  
8459 -  
8460 -/**  
8461 - * Use browser for parsing CSS.  
8462 - */  
8463 -StyleFormatPanel.prototype.getCssRules = function (css) {  
8464 - var doc = document.implementation.createHTMLDocument("");  
8465 - var styleElement = document.createElement("style");  
8466 -  
8467 - mxUtils.setTextContent(styleElement, css);  
8468 - doc.body.appendChild(styleElement);  
8469 -  
8470 - return styleElement.sheet.cssRules;  
8471 -};  
8472 -  
8473 -/**  
8474 - * Adds the label menu items to the given menu and parent.  
8475 - */  
8476 -StyleFormatPanel.prototype.addSvgStyles = function (container) {  
8477 - var ui = this.editorUi;  
8478 - var graph = ui.editor.graph;  
8479 - var ss = ui.getSelectionState();  
8480 - container.style.paddingTop = "6px";  
8481 - container.style.paddingBottom = "6px";  
8482 - container.style.fontWeight = "bold";  
8483 - container.style.display = "none";  
8484 -  
8485 - try {  
8486 - var exp = ss.style.editableCssRules;  
8487 -  
8488 - if (exp != null) {  
8489 - var regex = new RegExp(exp);  
8490 -  
8491 - var data = ss.style.image.substring(ss.style.image.indexOf(",") + 1);  
8492 - var xml = window.atob ? atob(data) : Base64.decode(data, true);  
8493 - var svg = mxUtils.parseXml(xml);  
8494 -  
8495 - if (svg != null) {  
8496 - var styles = svg.getElementsByTagName("style");  
8497 -  
8498 - for (var i = 0; i < styles.length; i++) {  
8499 - var rules = this.getCssRules(mxUtils.getTextContent(styles[i]));  
8500 -  
8501 - for (var j = 0; j < rules.length; j++) {  
8502 - this.addSvgRule(  
8503 - container,  
8504 - rules[j],  
8505 - svg,  
8506 - styles[i],  
8507 - rules,  
8508 - j,  
8509 - regex,  
8510 - );  
8511 - }  
8512 - }  
8513 - }  
8514 - }  
8515 - } catch (e) {  
8516 - // ignore  
8517 - }  
8518 -  
8519 - return container;  
8520 -};  
8521 -  
8522 -/**  
8523 - * Adds the label menu items to the given menu and parent.  
8524 - */  
8525 -StyleFormatPanel.prototype.addSvgRule = function (  
8526 - container,  
8527 - rule,  
8528 - svg,  
8529 - styleElem,  
8530 - rules,  
8531 - ruleIndex,  
8532 - regex,  
8533 -) {  
8534 - var ui = this.editorUi;  
8535 - var graph = ui.editor.graph;  
8536 -  
8537 - if (regex.test(rule.selectorText)) {  
8538 - function rgb2hex(rgb) {  
8539 - rgb = rgb.match(  
8540 - /^rgba?[\s+]?\([\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?/i,  
8541 - );  
8542 -  
8543 - return rgb && rgb.length === 4  
8544 - ? "#" +  
8545 - ("0" + parseInt(rgb[1], 10).toString(16)).slice(-2) +  
8546 - ("0" + parseInt(rgb[2], 10).toString(16)).slice(-2) +  
8547 - ("0" + parseInt(rgb[3], 10).toString(16)).slice(-2)  
8548 - : "";  
8549 - }  
8550 -  
8551 - var addStyleRule = mxUtils.bind(this, function (rule, key, label) {  
8552 - var value = mxUtils.trim(rule.style[key]);  
8553 -  
8554 - if (value != "" && value.substring(0, 4) != "url(") {  
8555 - var option = this.createColorOption(  
8556 - label + " " + rule.selectorText,  
8557 - function () {  
8558 - return rgb2hex(value);  
8559 - },  
8560 - mxUtils.bind(this, function (color) {  
8561 - rules[ruleIndex].style[key] = color;  
8562 - var cssTxt = "";  
8563 -  
8564 - for (var i = 0; i < rules.length; i++) {  
8565 - cssTxt += rules[i].cssText + " ";  
8566 - }  
8567 -  
8568 - styleElem.textContent = cssTxt;  
8569 - var xml = mxUtils.getXml(svg.documentElement);  
8570 -  
8571 - graph.setCellStyles(  
8572 - mxConstants.STYLE_IMAGE,  
8573 - "data:image/svg+xml," +  
8574 - (window.btoa ? btoa(xml) : Base64.encode(xml, true)),  
8575 - ui.getSelectionState().cells,  
8576 - );  
8577 - }),  
8578 - "#ffffff",  
8579 - {  
8580 - install: function (apply) {  
8581 - // ignore  
8582 - },  
8583 - destroy: function () {  
8584 - // ignore  
8585 - },  
8586 - },  
8587 - );  
8588 -  
8589 - container.appendChild(option);  
8590 -  
8591 - // Shows container if rules are added  
8592 - container.style.display = "";  
8593 - }  
8594 - });  
8595 -  
8596 - addStyleRule(rule, "fill", mxResources.get("fill"));  
8597 - addStyleRule(rule, "stroke", mxResources.get("line"));  
8598 - addStyleRule(rule, "stop-color", mxResources.get("gradient"));  
8599 - }  
8600 -};  
8601 -  
8602 -/**  
8603 - * Adds the label menu items to the given menu and parent.  
8604 - */  
8605 -StyleFormatPanel.prototype.addEditOps = function (div) {  
8606 - var ss = this.editorUi.getSelectionState();  
8607 - var btn = null;  
8608 -  
8609 - if (ss.cells.length == 1) {  
8610 - btn = mxUtils.button(  
8611 - mxResources.get("editStyle"),  
8612 - mxUtils.bind(this, function (evt) {  
8613 - this.editorUi.actions.get("editStyle").funct();  
8614 - }),  
8615 - );  
8616 -  
8617 - btn.setAttribute(  
8618 - "title",  
8619 - mxResources.get("editStyle") +  
8620 - " (" +  
8621 - this.editorUi.actions.get("editStyle").shortcut +  
8622 - ")",  
8623 - );  
8624 - btn.style.width = "210px";  
8625 - btn.style.marginBottom = "2px";  
8626 -  
8627 - div.appendChild(btn);  
8628 - }  
8629 -  
8630 - if (ss.image && ss.cells.length > 0) {  
8631 - var btn2 = mxUtils.button(  
8632 - mxResources.get("editImage"),  
8633 - mxUtils.bind(this, function (evt) {  
8634 - this.editorUi.actions.get("image").funct();  
8635 - }),  
8636 - );  
8637 -  
8638 - btn2.setAttribute("title", mxResources.get("editImage"));  
8639 - btn2.style.marginBottom = "2px";  
8640 -  
8641 - if (btn == null) {  
8642 - btn2.style.width = "210px";  
8643 - } else {  
8644 - btn.style.width = "104px";  
8645 - btn2.style.width = "104px";  
8646 - btn2.style.marginLeft = "2px";  
8647 - }  
8648 -  
8649 - div.appendChild(btn2);  
8650 - }  
8651 -  
8652 - return div;  
8653 -};  
8654 -  
8655 -/**  
8656 - * Adds the label menu items to the given menu and parent.  
8657 - */  
8658 -StyleFormatPanel.prototype.addFill = function (container) {  
8659 - var ui = this.editorUi;  
8660 - var graph = ui.editor.graph;  
8661 - var ss = ui.getSelectionState();  
8662 - container.style.paddingTop = "6px";  
8663 - container.style.paddingBottom = "6px";  
8664 -  
8665 - // Adds gradient direction option  
8666 - var gradientSelect = document.createElement("select");  
8667 - gradientSelect.style.position = "absolute";  
8668 - gradientSelect.style.left = "104px";  
8669 - gradientSelect.style.width = "70px";  
8670 - gradientSelect.style.height = "22px";  
8671 - gradientSelect.style.padding = "0px";  
8672 - gradientSelect.style.marginTop = "-3px";  
8673 - gradientSelect.style.borderRadius = "4px";  
8674 - gradientSelect.style.border = "1px solid rgb(160, 160, 160)";  
8675 - gradientSelect.style.boxSizing = "border-box";  
8676 -  
8677 - var fillStyleSelect = gradientSelect.cloneNode(false);  
8678 -  
8679 - // Stops events from bubbling to color option event handler  
8680 - mxEvent.addListener(gradientSelect, "click", function (evt) {  
8681 - mxEvent.consume(evt);  
8682 - });  
8683 - mxEvent.addListener(fillStyleSelect, "click", function (evt) {  
8684 - mxEvent.consume(evt);  
8685 - });  
8686 -  
8687 - var defs =  
8688 - ss.vertices.length >= 1  
8689 - ? graph.stylesheet.getDefaultVertexStyle()  
8690 - : graph.stylesheet.getDefaultEdgeStyle();  
8691 -  
8692 - var gradientPanel = this.createCellColorOption(  
8693 - mxResources.get("gradient"),  
8694 - mxConstants.STYLE_GRADIENTCOLOR,  
8695 - defs[mxConstants.STYLE_GRADIENTCOLOR] != null  
8696 - ? defs[mxConstants.STYLE_GRADIENTCOLOR]  
8697 - : "#ffffff",  
8698 - function (color) {  
8699 - if (color == null || color == mxConstants.NONE) {  
8700 - gradientSelect.style.display = "none";  
8701 - } else {  
8702 - gradientSelect.style.display = "";  
8703 - }  
8704 - },  
8705 - function (color) {  
8706 - graph.updateCellStyles(  
8707 - { gradientColor: color },  
8708 - graph.getSelectionCells(),  
8709 - );  
8710 - },  
8711 - );  
8712 -  
8713 - var fillKey =  
8714 - ss.style.shape == "image"  
8715 - ? mxConstants.STYLE_IMAGE_BACKGROUND  
8716 - : mxConstants.STYLE_FILLCOLOR;  
8717 -  
8718 - var fillPanel = this.createCellColorOption(  
8719 - mxResources.get("fill"),  
8720 - fillKey,  
8721 - "default",  
8722 - null,  
8723 - mxUtils.bind(this, function (color) {  
8724 - graph.setCellStyles(fillKey, color, ss.cells);  
8725 - }),  
8726 - graph.shapeBackgroundColor,  
8727 - );  
8728 -  
8729 - fillPanel.style.fontWeight = "bold";  
8730 - var tmpColor = mxUtils.getValue(ss.style, fillKey, null);  
8731 - gradientPanel.style.display =  
8732 - tmpColor != null &&  
8733 - tmpColor != mxConstants.NONE &&  
8734 - ss.fill &&  
8735 - ss.style.shape != "image"  
8736 - ? ""  
8737 - : "none";  
8738 -  
8739 - var directions = [  
8740 - mxConstants.DIRECTION_NORTH,  
8741 - mxConstants.DIRECTION_EAST,  
8742 - mxConstants.DIRECTION_SOUTH,  
8743 - mxConstants.DIRECTION_WEST,  
8744 - mxConstants.DIRECTION_RADIAL,  
8745 - ];  
8746 -  
8747 - for (var i = 0; i < directions.length; i++) {  
8748 - var gradientOption = document.createElement("option");  
8749 - gradientOption.setAttribute("value", directions[i]);  
8750 - mxUtils.write(gradientOption, mxResources.get(directions[i]));  
8751 - gradientSelect.appendChild(gradientOption);  
8752 - }  
8753 -  
8754 - gradientPanel.appendChild(gradientSelect);  
8755 -  
8756 - for (var i = 0; i < Editor.roughFillStyles.length; i++) {  
8757 - var fillStyleOption = document.createElement("option");  
8758 - fillStyleOption.setAttribute("value", Editor.roughFillStyles[i].val);  
8759 - mxUtils.write(fillStyleOption, Editor.roughFillStyles[i].dispName);  
8760 - fillStyleSelect.appendChild(fillStyleOption);  
8761 - }  
8762 -  
8763 - fillPanel.appendChild(fillStyleSelect);  
8764 -  
8765 - var listener = mxUtils.bind(this, function () {  
8766 - ss = ui.getSelectionState();  
8767 - var value = mxUtils.getValue(  
8768 - ss.style,  
8769 - mxConstants.STYLE_GRADIENT_DIRECTION,  
8770 - mxConstants.DIRECTION_SOUTH,  
8771 - );  
8772 - var fillStyle = mxUtils.getValue(ss.style, "fillStyle", "auto");  
8773 -  
8774 - // Handles empty string which is not allowed as a value  
8775 - if (value == "") {  
8776 - value = mxConstants.DIRECTION_SOUTH;  
8777 - }  
8778 -  
8779 - gradientSelect.value = value;  
8780 - fillStyleSelect.value = fillStyle;  
8781 - container.style.display = ss.fill ? "" : "none";  
8782 -  
8783 - var fillColor = mxUtils.getValue(ss.style, fillKey, null);  
8784 -  
8785 - if (  
8786 - !ss.fill ||  
8787 - fillColor == null ||  
8788 - fillColor == mxConstants.NONE ||  
8789 - ss.style.shape == "filledEdge"  
8790 - ) {  
8791 - fillStyleSelect.style.display = "none";  
8792 - gradientPanel.style.display = "none";  
8793 - } else {  
8794 - fillStyleSelect.style.display = ss.style.sketch == "1" ? "" : "none";  
8795 - gradientPanel.style.display =  
8796 - !ss.containsImage &&  
8797 - (ss.style.sketch != "1" || fillStyle == "solid" || fillStyle == "auto")  
8798 - ? ""  
8799 - : "none";  
8800 - }  
8801 - });  
8802 -  
8803 - graph.getModel().addListener(mxEvent.CHANGE, listener);  
8804 - this.listeners.push({  
8805 - destroy: function () {  
8806 - graph.getModel().removeListener(listener);  
8807 - },  
8808 - });  
8809 - listener();  
8810 -  
8811 - mxEvent.addListener(gradientSelect, "change", function (evt) {  
8812 - graph.setCellStyles(  
8813 - mxConstants.STYLE_GRADIENT_DIRECTION,  
8814 - gradientSelect.value,  
8815 - ss.cells,  
8816 - );  
8817 - ui.fireEvent(  
8818 - new mxEventObject(  
8819 - "styleChanged",  
8820 - "keys",  
8821 - [mxConstants.STYLE_GRADIENT_DIRECTION],  
8822 - "values",  
8823 - [gradientSelect.value],  
8824 - "cells",  
8825 - ss.cells,  
8826 - ),  
8827 - );  
8828 - mxEvent.consume(evt);  
8829 - });  
8830 -  
8831 - mxEvent.addListener(fillStyleSelect, "change", function (evt) {  
8832 - graph.setCellStyles("fillStyle", fillStyleSelect.value, ss.cells);  
8833 - ui.fireEvent(  
8834 - new mxEventObject(  
8835 - "styleChanged",  
8836 - "keys",  
8837 - ["fillStyle"],  
8838 - "values",  
8839 - [fillStyleSelect.value],  
8840 - "cells",  
8841 - ss.cells,  
8842 - ),  
8843 - );  
8844 - mxEvent.consume(evt);  
8845 - });  
8846 -  
8847 - container.appendChild(fillPanel);  
8848 - container.appendChild(gradientPanel);  
8849 -  
8850 - // Adds custom colors  
8851 - var custom = this.getCustomColors();  
8852 -  
8853 - for (var i = 0; i < custom.length; i++) {  
8854 - container.appendChild(  
8855 - this.createCellColorOption(  
8856 - custom[i].title,  
8857 - custom[i].key,  
8858 - custom[i].defaultValue,  
8859 - ),  
8860 - );  
8861 - }  
8862 -  
8863 - return container;  
8864 -};  
8865 -  
8866 -/**  
8867 - * Adds the label menu items to the given menu and parent.  
8868 - */  
8869 -StyleFormatPanel.prototype.getCustomColors = function () {  
8870 - var ss = this.editorUi.getSelectionState();  
8871 - var result = [];  
8872 -  
8873 - if (ss.swimlane) {  
8874 - result.push({  
8875 - title: mxResources.get("laneColor"),  
8876 - key: "swimlaneFillColor",  
8877 - defaultValue: "default",  
8878 - });  
8879 - }  
8880 -  
8881 - return result;  
8882 -};  
8883 -  
8884 -/**  
8885 - * Adds the label menu items to the given menu and parent.  
8886 - */  
8887 -StyleFormatPanel.prototype.addStroke = function (container) {  
8888 - var ui = this.editorUi;  
8889 - var graph = ui.editor.graph;  
8890 - var ss = ui.getSelectionState();  
8891 -  
8892 - container.style.paddingTop = "6px";  
8893 - container.style.paddingBottom = "4px";  
8894 - container.style.whiteSpace = "normal";  
8895 -  
8896 - var colorPanel = document.createElement("div");  
8897 - colorPanel.style.fontWeight = "bold";  
8898 -  
8899 - if (!ss.stroke) {  
8900 - colorPanel.style.display = "none";  
8901 - }  
8902 -  
8903 - // Adds gradient direction option  
8904 - var styleSelect = document.createElement("select");  
8905 - styleSelect.style.position = "absolute";  
8906 - styleSelect.style.height = "22px";  
8907 - styleSelect.style.padding = "0px";  
8908 - styleSelect.style.marginTop = "-3px";  
8909 - styleSelect.style.boxSizing = "border-box";  
8910 - styleSelect.style.left = "94px";  
8911 - styleSelect.style.width = "80px";  
8912 - styleSelect.style.border = "1px solid rgb(160, 160, 160)";  
8913 - styleSelect.style.borderRadius = "4px";  
8914 -  
8915 - var styles = ["sharp", "rounded", "curved"];  
8916 -  
8917 - for (var i = 0; i < styles.length; i++) {  
8918 - var styleOption = document.createElement("option");  
8919 - styleOption.setAttribute("value", styles[i]);  
8920 - mxUtils.write(styleOption, mxResources.get(styles[i]));  
8921 - styleSelect.appendChild(styleOption);  
8922 - }  
8923 -  
8924 - mxEvent.addListener(styleSelect, "change", function (evt) {  
8925 - graph.getModel().beginUpdate();  
8926 - try {  
8927 - var keys = [mxConstants.STYLE_ROUNDED, mxConstants.STYLE_CURVED];  
8928 - // Default for rounded is 1  
8929 - var values = ["0", null];  
8930 -  
8931 - if (styleSelect.value == "rounded") {  
8932 - values = ["1", null];  
8933 - } else if (styleSelect.value == "curved") {  
8934 - values = [null, "1"];  
8935 - }  
8936 -  
8937 - for (var i = 0; i < keys.length; i++) {  
8938 - graph.setCellStyles(keys[i], values[i], ss.cells);  
8939 - }  
8940 -  
8941 - ui.fireEvent(  
8942 - new mxEventObject(  
8943 - "styleChanged",  
8944 - "keys",  
8945 - keys,  
8946 - "values",  
8947 - values,  
8948 - "cells",  
8949 - ss.cells,  
8950 - ),  
8951 - );  
8952 - } finally {  
8953 - graph.getModel().endUpdate();  
8954 - }  
8955 -  
8956 - mxEvent.consume(evt);  
8957 - });  
8958 -  
8959 - // Stops events from bubbling to color option event handler  
8960 - mxEvent.addListener(styleSelect, "click", function (evt) {  
8961 - mxEvent.consume(evt);  
8962 - });  
8963 -  
8964 - var strokeKey =  
8965 - ss.style.shape == "image"  
8966 - ? mxConstants.STYLE_IMAGE_BORDER  
8967 - : mxConstants.STYLE_STROKECOLOR;  
8968 - var label =  
8969 - ss.style.shape == "image"  
8970 - ? mxResources.get("border")  
8971 - : mxResources.get("line");  
8972 -  
8973 - var lineColor = this.createCellColorOption(  
8974 - label,  
8975 - strokeKey,  
8976 - "default",  
8977 - null,  
8978 - mxUtils.bind(this, function (color) {  
8979 - graph.setCellStyles(strokeKey, color, ss.cells);  
8980 - }),  
8981 - graph.shapeForegroundColor,  
8982 - );  
8983 -  
8984 - lineColor.appendChild(styleSelect);  
8985 - colorPanel.appendChild(lineColor);  
8986 -  
8987 - // Used if only edges selected  
8988 - var stylePanel = colorPanel.cloneNode(false);  
8989 - stylePanel.style.fontWeight = "normal";  
8990 - stylePanel.style.whiteSpace = "nowrap";  
8991 - stylePanel.style.position = "relative";  
8992 - stylePanel.style.paddingLeft = "0px";  
8993 - stylePanel.style.marginBottom = "2px";  
8994 - stylePanel.style.overflow = "hidden";  
8995 - stylePanel.style.marginTop = "2px";  
8996 - stylePanel.style.width = "220px";  
8997 - stylePanel.className = "geToolbarContainer";  
8998 -  
8999 - var addItem = mxUtils.bind(  
9000 - this,  
9001 - function (menu, width, cssName, keys, values) {  
9002 - var item = this.editorUi.menus.styleChange(  
9003 - menu,  
9004 - "",  
9005 - keys,  
9006 - values,  
9007 - "geIcon",  
9008 - null,  
9009 - );  
9010 -  
9011 - var pat = document.createElement("div");  
9012 - pat.style.width = width + "px";  
9013 - pat.style.height = "1px";  
9014 - pat.style.borderBottom = "1px " + cssName + " " + this.defaultStrokeColor;  
9015 - pat.style.paddingTop = "6px";  
9016 -  
9017 - item.firstChild.firstChild.style.padding = "0px 4px 0px 4px";  
9018 - item.firstChild.firstChild.style.width = width + "px";  
9019 - item.firstChild.firstChild.appendChild(pat);  
9020 -  
9021 - return item;  
9022 - },  
9023 - );  
9024 -  
9025 - var pattern = this.editorUi.toolbar.addMenuFunctionInContainer(  
9026 - stylePanel,  
9027 - "geSprite-orthogonal",  
9028 - mxResources.get("pattern"),  
9029 - false,  
9030 - mxUtils.bind(this, function (menu) {  
9031 - addItem(  
9032 - menu,  
9033 - 75,  
9034 - "solid",  
9035 - [mxConstants.STYLE_DASHED, mxConstants.STYLE_DASH_PATTERN],  
9036 - [null, null],  
9037 - ).setAttribute("title", mxResources.get("solid"));  
9038 - addItem(  
9039 - menu,  
9040 - 75,  
9041 - "dashed",  
9042 - [mxConstants.STYLE_DASHED, mxConstants.STYLE_DASH_PATTERN],  
9043 - ["1", null],  
9044 - ).setAttribute("title", mxResources.get("dashed"));  
9045 - addItem(  
9046 - menu,  
9047 - 75,  
9048 - "dotted",  
9049 - [mxConstants.STYLE_DASHED, mxConstants.STYLE_DASH_PATTERN],  
9050 - ["1", "1 1"],  
9051 - ).setAttribute("title", mxResources.get("dotted") + " (1)");  
9052 - addItem(  
9053 - menu,  
9054 - 75,  
9055 - "dotted",  
9056 - [mxConstants.STYLE_DASHED, mxConstants.STYLE_DASH_PATTERN],  
9057 - ["1", "1 2"],  
9058 - ).setAttribute("title", mxResources.get("dotted") + " (2)");  
9059 - addItem(  
9060 - menu,  
9061 - 75,  
9062 - "dotted",  
9063 - [mxConstants.STYLE_DASHED, mxConstants.STYLE_DASH_PATTERN],  
9064 - ["1", "1 4"],  
9065 - ).setAttribute("title", mxResources.get("dotted") + " (3)");  
9066 - }),  
9067 - );  
9068 -  
9069 - // Used for mixed selection (vertices and edges)  
9070 - var altStylePanel = stylePanel.cloneNode(false);  
9071 -  
9072 - var edgeShape = this.editorUi.toolbar.addMenuFunctionInContainer(  
9073 - altStylePanel,  
9074 - "geSprite-connection",  
9075 - mxResources.get("connection"),  
9076 - false,  
9077 - mxUtils.bind(this, function (menu) {  
9078 - this.editorUi.menus  
9079 - .styleChange(  
9080 - menu,  
9081 - "",  
9082 - [  
9083 - mxConstants.STYLE_SHAPE,  
9084 - mxConstants.STYLE_STARTSIZE,  
9085 - mxConstants.STYLE_ENDSIZE,  
9086 - "width",  
9087 - ],  
9088 - [null, null, null, null],  
9089 - "geIcon geSprite geSprite-connection",  
9090 - null,  
9091 - true,  
9092 - )  
9093 - .setAttribute("title", mxResources.get("line"));  
9094 - this.editorUi.menus  
9095 - .styleChange(  
9096 - menu,  
9097 - "",  
9098 - [  
9099 - mxConstants.STYLE_SHAPE,  
9100 - mxConstants.STYLE_STARTSIZE,  
9101 - mxConstants.STYLE_ENDSIZE,  
9102 - "width",  
9103 - ],  
9104 - ["link", null, null, null],  
9105 - "geIcon geSprite geSprite-linkedge",  
9106 - null,  
9107 - true,  
9108 - )  
9109 - .setAttribute("title", mxResources.get("link"));  
9110 - this.editorUi.menus  
9111 - .styleChange(  
9112 - menu,  
9113 - "",  
9114 - [  
9115 - mxConstants.STYLE_SHAPE,  
9116 - mxConstants.STYLE_STARTSIZE,  
9117 - mxConstants.STYLE_ENDSIZE,  
9118 - "width",  
9119 - ],  
9120 - ["flexArrow", null, null, null],  
9121 - "geIcon geSprite geSprite-arrow",  
9122 - null,  
9123 - true,  
9124 - )  
9125 - .setAttribute("title", mxResources.get("arrow"));  
9126 - this.editorUi.menus  
9127 - .styleChange(  
9128 - menu,  
9129 - "",  
9130 - [  
9131 - mxConstants.STYLE_SHAPE,  
9132 - mxConstants.STYLE_STARTSIZE,  
9133 - mxConstants.STYLE_ENDSIZE,  
9134 - "width",  
9135 - ],  
9136 - ["arrow", null, null, null],  
9137 - "geIcon geSprite geSprite-simplearrow",  
9138 - null,  
9139 - true,  
9140 - )  
9141 - .setAttribute("title", mxResources.get("simpleArrow"));  
9142 - }),  
9143 - );  
9144 -  
9145 - var altPattern = this.editorUi.toolbar.addMenuFunctionInContainer(  
9146 - altStylePanel,  
9147 - "geSprite-orthogonal",  
9148 - mxResources.get("pattern"),  
9149 - false,  
9150 - mxUtils.bind(this, function (menu) {  
9151 - addItem(  
9152 - menu,  
9153 - 33,  
9154 - "solid",  
9155 - [mxConstants.STYLE_DASHED, mxConstants.STYLE_DASH_PATTERN],  
9156 - [null, null],  
9157 - ).setAttribute("title", mxResources.get("solid"));  
9158 - addItem(  
9159 - menu,  
9160 - 33,  
9161 - "dashed",  
9162 - [mxConstants.STYLE_DASHED, mxConstants.STYLE_DASH_PATTERN],  
9163 - ["1", null],  
9164 - ).setAttribute("title", mxResources.get("dashed"));  
9165 - addItem(  
9166 - menu,  
9167 - 33,  
9168 - "dotted",  
9169 - [mxConstants.STYLE_DASHED, mxConstants.STYLE_DASH_PATTERN],  
9170 - ["1", "1 1"],  
9171 - ).setAttribute("title", mxResources.get("dotted") + " (1)");  
9172 - addItem(  
9173 - menu,  
9174 - 33,  
9175 - "dotted",  
9176 - [mxConstants.STYLE_DASHED, mxConstants.STYLE_DASH_PATTERN],  
9177 - ["1", "1 2"],  
9178 - ).setAttribute("title", mxResources.get("dotted") + " (2)");  
9179 - addItem(  
9180 - menu,  
9181 - 33,  
9182 - "dotted",  
9183 - [mxConstants.STYLE_DASHED, mxConstants.STYLE_DASH_PATTERN],  
9184 - ["1", "1 4"],  
9185 - ).setAttribute("title", mxResources.get("dotted") + " (3)");  
9186 - }),  
9187 - );  
9188 -  
9189 - var stylePanel2 = stylePanel.cloneNode(false);  
9190 -  
9191 - // Stroke width  
9192 - var input = document.createElement("input");  
9193 - input.style.position = "absolute";  
9194 - input.style.textAlign = "right";  
9195 - input.style.marginTop = "2px";  
9196 - input.style.width = "52px";  
9197 - input.style.height = "21px";  
9198 - input.style.left = "146px";  
9199 - input.style.border = "1px solid rgb(160, 160, 160)";  
9200 - input.style.borderRadius = "4px";  
9201 - input.style.boxSizing = "border-box";  
9202 - input.setAttribute("title", mxResources.get("linewidth"));  
9203 -  
9204 - stylePanel.appendChild(input);  
9205 -  
9206 - var altInput = input.cloneNode(true);  
9207 - altStylePanel.appendChild(altInput);  
9208 -  
9209 - function update(evt) {  
9210 - // Maximum stroke width is 999  
9211 - var value = parseFloat(input.value);  
9212 - value = Math.min(999, Math.max(0, isNaN(value) ? 1 : value));  
9213 -  
9214 - if (value != mxUtils.getValue(ss.style, mxConstants.STYLE_STROKEWIDTH, 1)) {  
9215 - graph.setCellStyles(mxConstants.STYLE_STROKEWIDTH, value, ss.cells);  
9216 - ui.fireEvent(  
9217 - new mxEventObject(  
9218 - "styleChanged",  
9219 - "keys",  
9220 - [mxConstants.STYLE_STROKEWIDTH],  
9221 - "values",  
9222 - [value],  
9223 - "cells",  
9224 - ss.cells,  
9225 - ),  
9226 - );  
9227 - }  
9228 -  
9229 - input.value = value + " pt";  
9230 - mxEvent.consume(evt);  
9231 - }  
9232 -  
9233 - function altUpdate(evt) {  
9234 - // Maximum stroke width is 999  
9235 - var value = parseFloat(altInput.value);  
9236 - value = Math.min(999, Math.max(0, isNaN(value) ? 1 : value));  
9237 -  
9238 - if (value != mxUtils.getValue(ss.style, mxConstants.STYLE_STROKEWIDTH, 1)) {  
9239 - graph.setCellStyles(mxConstants.STYLE_STROKEWIDTH, value, ss.cells);  
9240 - ui.fireEvent(  
9241 - new mxEventObject(  
9242 - "styleChanged",  
9243 - "keys",  
9244 - [mxConstants.STYLE_STROKEWIDTH],  
9245 - "values",  
9246 - [value],  
9247 - "cells",  
9248 - ss.cells,  
9249 - ),  
9250 - );  
9251 - }  
9252 -  
9253 - altInput.value = value + " pt";  
9254 - mxEvent.consume(evt);  
9255 - }  
9256 -  
9257 - var stepper = this.createStepper(input, update, 1, 9);  
9258 - stepper.style.display = input.style.display;  
9259 - stepper.style.marginTop = "2px";  
9260 - stepper.style.left = "198px";  
9261 - stylePanel.appendChild(stepper);  
9262 -  
9263 - var altStepper = this.createStepper(altInput, altUpdate, 1, 9);  
9264 - altStepper.style.display = altInput.style.display;  
9265 - altStepper.style.marginTop = "2px";  
9266 - altInput.style.position = "absolute";  
9267 - altStepper.style.left = "198px";  
9268 - altStylePanel.appendChild(altStepper);  
9269 -  
9270 - mxEvent.addListener(input, "blur", update);  
9271 - mxEvent.addListener(input, "change", update);  
9272 -  
9273 - mxEvent.addListener(altInput, "blur", altUpdate);  
9274 - mxEvent.addListener(altInput, "change", altUpdate);  
9275 -  
9276 - var edgeStyle = this.editorUi.toolbar.addMenuFunctionInContainer(  
9277 - stylePanel2,  
9278 - "geSprite-orthogonal",  
9279 - mxResources.get("waypoints"),  
9280 - false,  
9281 - mxUtils.bind(this, function (menu) {  
9282 - if (ss.style.shape != "arrow") {  
9283 - this.editorUi.menus  
9284 - .edgeStyleChange(  
9285 - menu,  
9286 - "",  
9287 - [  
9288 - mxConstants.STYLE_EDGE,  
9289 - mxConstants.STYLE_CURVED,  
9290 - mxConstants.STYLE_NOEDGESTYLE,  
9291 - ],  
9292 - [null, null, null],  
9293 - "geIcon geSprite geSprite-straight",  
9294 - null,  
9295 - true,  
9296 - )  
9297 - .setAttribute("title", mxResources.get("straight"));  
9298 - this.editorUi.menus  
9299 - .edgeStyleChange(  
9300 - menu,  
9301 - "",  
9302 - [  
9303 - mxConstants.STYLE_EDGE,  
9304 - mxConstants.STYLE_CURVED,  
9305 - mxConstants.STYLE_NOEDGESTYLE,  
9306 - ],  
9307 - ["orthogonalEdgeStyle", null, null],  
9308 - "geIcon geSprite geSprite-orthogonal",  
9309 - null,  
9310 - true,  
9311 - )  
9312 - .setAttribute("title", mxResources.get("orthogonal"));  
9313 - this.editorUi.menus  
9314 - .edgeStyleChange(  
9315 - menu,  
9316 - "",  
9317 - [  
9318 - mxConstants.STYLE_EDGE,  
9319 - mxConstants.STYLE_ELBOW,  
9320 - mxConstants.STYLE_CURVED,  
9321 - mxConstants.STYLE_NOEDGESTYLE,  
9322 - ],  
9323 - ["elbowEdgeStyle", null, null, null],  
9324 - "geIcon geSprite geSprite-horizontalelbow",  
9325 - null,  
9326 - true,  
9327 - )  
9328 - .setAttribute("title", mxResources.get("simple"));  
9329 - this.editorUi.menus  
9330 - .edgeStyleChange(  
9331 - menu,  
9332 - "",  
9333 - [  
9334 - mxConstants.STYLE_EDGE,  
9335 - mxConstants.STYLE_ELBOW,  
9336 - mxConstants.STYLE_CURVED,  
9337 - mxConstants.STYLE_NOEDGESTYLE,  
9338 - ],  
9339 - ["elbowEdgeStyle", "vertical", null, null],  
9340 - "geIcon geSprite geSprite-verticalelbow",  
9341 - null,  
9342 - true,  
9343 - )  
9344 - .setAttribute("title", mxResources.get("simple"));  
9345 - this.editorUi.menus  
9346 - .edgeStyleChange(  
9347 - menu,  
9348 - "",  
9349 - [  
9350 - mxConstants.STYLE_EDGE,  
9351 - mxConstants.STYLE_ELBOW,  
9352 - mxConstants.STYLE_CURVED,  
9353 - mxConstants.STYLE_NOEDGESTYLE,  
9354 - ],  
9355 - ["isometricEdgeStyle", null, null, null],  
9356 - "geIcon geSprite geSprite-horizontalisometric",  
9357 - null,  
9358 - true,  
9359 - )  
9360 - .setAttribute("title", mxResources.get("isometric"));  
9361 - this.editorUi.menus  
9362 - .edgeStyleChange(  
9363 - menu,  
9364 - "",  
9365 - [  
9366 - mxConstants.STYLE_EDGE,  
9367 - mxConstants.STYLE_ELBOW,  
9368 - mxConstants.STYLE_CURVED,  
9369 - mxConstants.STYLE_NOEDGESTYLE,  
9370 - ],  
9371 - ["isometricEdgeStyle", "vertical", null, null],  
9372 - "geIcon geSprite geSprite-verticalisometric",  
9373 - null,  
9374 - true,  
9375 - )  
9376 - .setAttribute("title", mxResources.get("isometric"));  
9377 -  
9378 - if (ss.style.shape == "connector") {  
9379 - this.editorUi.menus  
9380 - .edgeStyleChange(  
9381 - menu,  
9382 - "",  
9383 - [  
9384 - mxConstants.STYLE_EDGE,  
9385 - mxConstants.STYLE_CURVED,  
9386 - mxConstants.STYLE_NOEDGESTYLE,  
9387 - ],  
9388 - ["orthogonalEdgeStyle", "1", null],  
9389 - "geIcon geSprite geSprite-curved",  
9390 - null,  
9391 - true,  
9392 - )  
9393 - .setAttribute("title", mxResources.get("curved"));  
9394 - }  
9395 -  
9396 - this.editorUi.menus  
9397 - .edgeStyleChange(  
9398 - menu,  
9399 - "",  
9400 - [  
9401 - mxConstants.STYLE_EDGE,  
9402 - mxConstants.STYLE_CURVED,  
9403 - mxConstants.STYLE_NOEDGESTYLE,  
9404 - ],  
9405 - ["entityRelationEdgeStyle", null, null],  
9406 - "geIcon geSprite geSprite-entity",  
9407 - null,  
9408 - true,  
9409 - )  
9410 - .setAttribute("title", mxResources.get("entityRelation"));  
9411 - }  
9412 - }),  
9413 - );  
9414 -  
9415 - var lineStart = this.editorUi.toolbar.addMenuFunctionInContainer(  
9416 - stylePanel2,  
9417 - "geSprite-startclassic",  
9418 - mxResources.get("linestart"),  
9419 - false,  
9420 - mxUtils.bind(this, function (menu) {  
9421 - if (  
9422 - ss.style.shape == "connector" ||  
9423 - ss.style.shape == "flexArrow" ||  
9424 - ss.style.shape == "filledEdge"  
9425 - ) {  
9426 - var item = this.editorUi.menus.edgeStyleChange(  
9427 - menu,  
9428 - "",  
9429 - [mxConstants.STYLE_STARTARROW, "startFill"],  
9430 - [mxConstants.NONE, 0],  
9431 - "geIcon",  
9432 - null,  
9433 - false,  
9434 - );  
9435 - item.setAttribute("title", mxResources.get("none"));  
9436 -  
9437 - var font = document.createElement("font");  
9438 - font.style.fontSize = "10px";  
9439 - mxUtils.write(font, mxResources.get("none"));  
9440 - item.firstChild.firstChild.appendChild(font);  
9441 -  
9442 - if (ss.style.shape == "connector" || ss.style.shape == "filledEdge") {  
9443 - Format.processMenuIcon(  
9444 - this.editorUi.menus.edgeStyleChange(  
9445 - menu,  
9446 - "",  
9447 - [mxConstants.STYLE_STARTARROW, "startFill"],  
9448 - [mxConstants.ARROW_CLASSIC, 1],  
9449 - null,  
9450 - null,  
9451 - false,  
9452 - Format.classicFilledMarkerImage.src,  
9453 - ),  
9454 - );  
9455 - Format.processMenuIcon(  
9456 - this.editorUi.menus.edgeStyleChange(  
9457 - menu,  
9458 - "",  
9459 - [mxConstants.STYLE_STARTARROW, "startFill"],  
9460 - [mxConstants.ARROW_CLASSIC_THIN, 1],  
9461 - null,  
9462 - null,  
9463 - false,  
9464 - Format.classicThinFilledMarkerImage.src,  
9465 - ),  
9466 - );  
9467 - Format.processMenuIcon(  
9468 - this.editorUi.menus.edgeStyleChange(  
9469 - menu,  
9470 - "",  
9471 - [mxConstants.STYLE_STARTARROW, "startFill"],  
9472 - [mxConstants.ARROW_OPEN, 0],  
9473 - null,  
9474 - null,  
9475 - false,  
9476 - Format.openFilledMarkerImage.src,  
9477 - ),  
9478 - );  
9479 - Format.processMenuIcon(  
9480 - this.editorUi.menus.edgeStyleChange(  
9481 - menu,  
9482 - "",  
9483 - [mxConstants.STYLE_STARTARROW, "startFill"],  
9484 - [mxConstants.ARROW_OPEN_THIN, 0],  
9485 - null,  
9486 - null,  
9487 - false,  
9488 - Format.openThinFilledMarkerImage.src,  
9489 - ),  
9490 - );  
9491 - Format.processMenuIcon(  
9492 - this.editorUi.menus.edgeStyleChange(  
9493 - menu,  
9494 - "",  
9495 - [mxConstants.STYLE_STARTARROW, "startFill"],  
9496 - ["openAsync", 0],  
9497 - null,  
9498 - null,  
9499 - false,  
9500 - Format.openAsyncFilledMarkerImage.src,  
9501 - ),  
9502 - );  
9503 - Format.processMenuIcon(  
9504 - this.editorUi.menus.edgeStyleChange(  
9505 - menu,  
9506 - "",  
9507 - [mxConstants.STYLE_STARTARROW, "startFill"],  
9508 - [mxConstants.ARROW_BLOCK, 1],  
9509 - null,  
9510 - null,  
9511 - false,  
9512 - Format.blockFilledMarkerImage.src,  
9513 - ),  
9514 - );  
9515 - Format.processMenuIcon(  
9516 - this.editorUi.menus.edgeStyleChange(  
9517 - menu,  
9518 - "",  
9519 - [mxConstants.STYLE_STARTARROW, "startFill"],  
9520 - [mxConstants.ARROW_BLOCK_THIN, 1],  
9521 - null,  
9522 - null,  
9523 - false,  
9524 - Format.blockThinFilledMarkerImage.src,  
9525 - ),  
9526 - );  
9527 - Format.processMenuIcon(  
9528 - this.editorUi.menus.edgeStyleChange(  
9529 - menu,  
9530 - "",  
9531 - [mxConstants.STYLE_STARTARROW, "startFill"],  
9532 - ["async", 1],  
9533 - null,  
9534 - null,  
9535 - false,  
9536 - Format.asyncFilledMarkerImage.src,  
9537 - ),  
9538 - );  
9539 - Format.processMenuIcon(  
9540 - this.editorUi.menus.edgeStyleChange(  
9541 - menu,  
9542 - "",  
9543 - [mxConstants.STYLE_STARTARROW, "startFill"],  
9544 - [mxConstants.ARROW_OVAL, 1],  
9545 - null,  
9546 - null,  
9547 - false,  
9548 - Format.ovalFilledMarkerImage.src,  
9549 - ),  
9550 - );  
9551 - Format.processMenuIcon(  
9552 - this.editorUi.menus.edgeStyleChange(  
9553 - menu,  
9554 - "",  
9555 - [mxConstants.STYLE_STARTARROW, "startFill"],  
9556 - [mxConstants.ARROW_DIAMOND, 1],  
9557 - null,  
9558 - null,  
9559 - false,  
9560 - Format.diamondFilledMarkerImage.src,  
9561 - ),  
9562 - );  
9563 - Format.processMenuIcon(  
9564 - this.editorUi.menus.edgeStyleChange(  
9565 - menu,  
9566 - "",  
9567 - [mxConstants.STYLE_STARTARROW, "startFill"],  
9568 - [mxConstants.ARROW_DIAMOND_THIN, 1],  
9569 - null,  
9570 - null,  
9571 - false,  
9572 - Format.diamondThinFilledMarkerImage.src,  
9573 - ),  
9574 - );  
9575 - Format.processMenuIcon(  
9576 - this.editorUi.menus.edgeStyleChange(  
9577 - menu,  
9578 - "",  
9579 - [mxConstants.STYLE_STARTARROW, "startFill"],  
9580 - [mxConstants.ARROW_CLASSIC, 0],  
9581 - null,  
9582 - null,  
9583 - false,  
9584 - Format.classicMarkerImage.src,  
9585 - ),  
9586 - );  
9587 - Format.processMenuIcon(  
9588 - this.editorUi.menus.edgeStyleChange(  
9589 - menu,  
9590 - "",  
9591 - [mxConstants.STYLE_STARTARROW, "startFill"],  
9592 - [mxConstants.ARROW_CLASSIC_THIN, 0],  
9593 - null,  
9594 - null,  
9595 - false,  
9596 - Format.classicThinMarkerImage.src,  
9597 - ),  
9598 - );  
9599 - Format.processMenuIcon(  
9600 - this.editorUi.menus.edgeStyleChange(  
9601 - menu,  
9602 - "",  
9603 - [mxConstants.STYLE_STARTARROW, "startFill"],  
9604 - [mxConstants.ARROW_BLOCK, 0],  
9605 - null,  
9606 - null,  
9607 - false,  
9608 - Format.blockMarkerImage.src,  
9609 - ),  
9610 - );  
9611 - Format.processMenuIcon(  
9612 - this.editorUi.menus.edgeStyleChange(  
9613 - menu,  
9614 - "",  
9615 - [mxConstants.STYLE_STARTARROW, "startFill"],  
9616 - [mxConstants.ARROW_BLOCK_THIN, 0],  
9617 - null,  
9618 - null,  
9619 - false,  
9620 - Format.blockThinMarkerImage.src,  
9621 - ),  
9622 - );  
9623 - Format.processMenuIcon(  
9624 - this.editorUi.menus.edgeStyleChange(  
9625 - menu,  
9626 - "",  
9627 - [mxConstants.STYLE_STARTARROW, "startFill"],  
9628 - ["async", 0],  
9629 - null,  
9630 - null,  
9631 - false,  
9632 - Format.asyncMarkerImage.src,  
9633 - ),  
9634 - );  
9635 - Format.processMenuIcon(  
9636 - this.editorUi.menus.edgeStyleChange(  
9637 - menu,  
9638 - "",  
9639 - [mxConstants.STYLE_STARTARROW, "startFill"],  
9640 - [mxConstants.ARROW_OVAL, 0],  
9641 - null,  
9642 - null,  
9643 - false,  
9644 - Format.ovalMarkerImage.src,  
9645 - ),  
9646 - );  
9647 - Format.processMenuIcon(  
9648 - this.editorUi.menus.edgeStyleChange(  
9649 - menu,  
9650 - "",  
9651 - [mxConstants.STYLE_STARTARROW, "startFill"],  
9652 - [mxConstants.ARROW_DIAMOND, 0],  
9653 - null,  
9654 - null,  
9655 - false,  
9656 - Format.diamondMarkerImage.src,  
9657 - ),  
9658 - );  
9659 - Format.processMenuIcon(  
9660 - this.editorUi.menus.edgeStyleChange(  
9661 - menu,  
9662 - "",  
9663 - [mxConstants.STYLE_STARTARROW, "startFill"],  
9664 - [mxConstants.ARROW_DIAMOND_THIN, 0],  
9665 - null,  
9666 - null,  
9667 - false,  
9668 - Format.diamondThinMarkerImage.src,  
9669 - ),  
9670 - );  
9671 - Format.processMenuIcon(  
9672 - this.editorUi.menus.edgeStyleChange(  
9673 - menu,  
9674 - "",  
9675 - [mxConstants.STYLE_STARTARROW, "startFill"],  
9676 - ["box", 0],  
9677 - null,  
9678 - null,  
9679 - false,  
9680 - Format.boxMarkerImage.src,  
9681 - ),  
9682 - );  
9683 - Format.processMenuIcon(  
9684 - this.editorUi.menus.edgeStyleChange(  
9685 - menu,  
9686 - "",  
9687 - [mxConstants.STYLE_STARTARROW, "startFill"],  
9688 - ["halfCircle", 0],  
9689 - null,  
9690 - null,  
9691 - false,  
9692 - Format.halfCircleMarkerImage.src,  
9693 - ),  
9694 - );  
9695 - Format.processMenuIcon(  
9696 - this.editorUi.menus.edgeStyleChange(  
9697 - menu,  
9698 - "",  
9699 - [mxConstants.STYLE_STARTARROW, "startFill"],  
9700 - ["dash", 0],  
9701 - null,  
9702 - null,  
9703 - false,  
9704 - Format.dashMarkerImage.src,  
9705 - ),  
9706 - );  
9707 - Format.processMenuIcon(  
9708 - this.editorUi.menus.edgeStyleChange(  
9709 - menu,  
9710 - "",  
9711 - [mxConstants.STYLE_STARTARROW, "startFill"],  
9712 - ["cross", 0],  
9713 - null,  
9714 - null,  
9715 - false,  
9716 - Format.crossMarkerImage.src,  
9717 - ),  
9718 - );  
9719 - Format.processMenuIcon(  
9720 - this.editorUi.menus.edgeStyleChange(  
9721 - menu,  
9722 - "",  
9723 - [mxConstants.STYLE_STARTARROW, "startFill"],  
9724 - ["circlePlus", 0],  
9725 - null,  
9726 - null,  
9727 - false,  
9728 - Format.circlePlusMarkerImage.src,  
9729 - ),  
9730 - );  
9731 - Format.processMenuIcon(  
9732 - this.editorUi.menus.edgeStyleChange(  
9733 - menu,  
9734 - "",  
9735 - [mxConstants.STYLE_STARTARROW, "startFill"],  
9736 - ["circle", 1],  
9737 - null,  
9738 - null,  
9739 - false,  
9740 - Format.circleMarkerImage.src,  
9741 - ),  
9742 - );  
9743 - Format.processMenuIcon(  
9744 - this.editorUi.menus.edgeStyleChange(  
9745 - menu,  
9746 - "",  
9747 - [mxConstants.STYLE_STARTARROW, "startFill"],  
9748 - ["baseDash", 0],  
9749 - null,  
9750 - null,  
9751 - false,  
9752 - Format.baseDashMarkerImage.src,  
9753 - ),  
9754 - );  
9755 - Format.processMenuIcon(  
9756 - this.editorUi.menus.edgeStyleChange(  
9757 - menu,  
9758 - "",  
9759 - [mxConstants.STYLE_STARTARROW, "startFill"],  
9760 - ["ERone", 0],  
9761 - null,  
9762 - null,  
9763 - false,  
9764 - Format.EROneMarkerImage.src,  
9765 - ),  
9766 - );  
9767 - Format.processMenuIcon(  
9768 - this.editorUi.menus.edgeStyleChange(  
9769 - menu,  
9770 - "",  
9771 - [mxConstants.STYLE_STARTARROW, "startFill"],  
9772 - ["ERmandOne", 0],  
9773 - null,  
9774 - null,  
9775 - false,  
9776 - Format.ERmandOneMarkerImage.src,  
9777 - ),  
9778 - );  
9779 - Format.processMenuIcon(  
9780 - this.editorUi.menus.edgeStyleChange(  
9781 - menu,  
9782 - "",  
9783 - [mxConstants.STYLE_STARTARROW, "startFill"],  
9784 - ["ERmany", 0],  
9785 - null,  
9786 - null,  
9787 - false,  
9788 - Format.ERmanyMarkerImage.src,  
9789 - ),  
9790 - );  
9791 - Format.processMenuIcon(  
9792 - this.editorUi.menus.edgeStyleChange(  
9793 - menu,  
9794 - "",  
9795 - [mxConstants.STYLE_STARTARROW, "startFill"],  
9796 - ["ERoneToMany", 0],  
9797 - null,  
9798 - null,  
9799 - false,  
9800 - Format.ERoneToManyMarkerImage.src,  
9801 - ),  
9802 - );  
9803 - Format.processMenuIcon(  
9804 - this.editorUi.menus.edgeStyleChange(  
9805 - menu,  
9806 - "",  
9807 - [mxConstants.STYLE_STARTARROW, "startFill"],  
9808 - ["ERzeroToOne", 0],  
9809 - null,  
9810 - null,  
9811 - false,  
9812 - Format.ERzeroToOneMarkerImage.src,  
9813 - ),  
9814 - );  
9815 - Format.processMenuIcon(  
9816 - this.editorUi.menus.edgeStyleChange(  
9817 - menu,  
9818 - "",  
9819 - [mxConstants.STYLE_STARTARROW, "startFill"],  
9820 - ["ERzeroToMany", 0],  
9821 - null,  
9822 - null,  
9823 - false,  
9824 - Format.ERzeroToManyMarkerImage.src,  
9825 - ),  
9826 - );  
9827 - Format.processMenuIcon(  
9828 - this.editorUi.menus.edgeStyleChange(  
9829 - menu,  
9830 - "",  
9831 - [mxConstants.STYLE_STARTARROW, "startFill"],  
9832 - ["doubleBlock", 0],  
9833 - null,  
9834 - null,  
9835 - false,  
9836 - Format.doubleBlockMarkerImage.src,  
9837 - ),  
9838 - );  
9839 - Format.processMenuIcon(  
9840 - this.editorUi.menus.edgeStyleChange(  
9841 - menu,  
9842 - "",  
9843 - [mxConstants.STYLE_STARTARROW, "startFill"],  
9844 - ["doubleBlock", 1],  
9845 - null,  
9846 - null,  
9847 - false,  
9848 - Format.doubleBlockFilledMarkerImage.src,  
9849 - ),  
9850 - );  
9851 - } else {  
9852 - this.editorUi.menus  
9853 - .edgeStyleChange(  
9854 - menu,  
9855 - "",  
9856 - [mxConstants.STYLE_STARTARROW],  
9857 - [mxConstants.ARROW_BLOCK],  
9858 - "geIcon geSprite geSprite-startblocktrans",  
9859 - null,  
9860 - false,  
9861 - )  
9862 - .setAttribute("title", mxResources.get("block"));  
9863 - }  
9864 -  
9865 - menu.div.style.width = "40px";  
9866 -  
9867 - window.setTimeout(  
9868 - mxUtils.bind(this, function () {  
9869 - if (menu.div != null) {  
9870 - mxUtils.fit(menu.div);  
9871 - }  
9872 - }),  
9873 - 0,  
9874 - );  
9875 - }  
9876 - }),  
9877 - );  
9878 -  
9879 - var lineEnd = this.editorUi.toolbar.addMenuFunctionInContainer(  
9880 - stylePanel2,  
9881 - "geSprite-endclassic",  
9882 - mxResources.get("lineend"),  
9883 - false,  
9884 - mxUtils.bind(this, function (menu) {  
9885 - if (  
9886 - ss.style.shape == "connector" ||  
9887 - ss.style.shape == "flexArrow" ||  
9888 - ss.style.shape == "filledEdge"  
9889 - ) {  
9890 - var item = this.editorUi.menus.edgeStyleChange(  
9891 - menu,  
9892 - "",  
9893 - [mxConstants.STYLE_ENDARROW, "endFill"],  
9894 - [mxConstants.NONE, 0],  
9895 - "geIcon",  
9896 - null,  
9897 - false,  
9898 - );  
9899 - item.setAttribute("title", mxResources.get("none"));  
9900 -  
9901 - var font = document.createElement("font");  
9902 - font.style.fontSize = "10px";  
9903 - mxUtils.write(font, mxResources.get("none"));  
9904 - item.firstChild.firstChild.appendChild(font);  
9905 -  
9906 - if (ss.style.shape == "connector" || ss.style.shape == "filledEdge") {  
9907 - Format.processMenuIcon(  
9908 - this.editorUi.menus.edgeStyleChange(  
9909 - menu,  
9910 - "",  
9911 - [mxConstants.STYLE_ENDARROW, "endFill"],  
9912 - [mxConstants.ARROW_CLASSIC, 1],  
9913 - null,  
9914 - null,  
9915 - false,  
9916 - Format.classicFilledMarkerImage.src,  
9917 - ),  
9918 - "scaleX(-1)",  
9919 - );  
9920 - Format.processMenuIcon(  
9921 - this.editorUi.menus.edgeStyleChange(  
9922 - menu,  
9923 - "",  
9924 - [mxConstants.STYLE_ENDARROW, "endFill"],  
9925 - [mxConstants.ARROW_CLASSIC_THIN, 1],  
9926 - null,  
9927 - null,  
9928 - false,  
9929 - Format.classicThinFilledMarkerImage.src,  
9930 - ),  
9931 - "scaleX(-1)",  
9932 - );  
9933 - Format.processMenuIcon(  
9934 - this.editorUi.menus.edgeStyleChange(  
9935 - menu,  
9936 - "",  
9937 - [mxConstants.STYLE_ENDARROW, "endFill"],  
9938 - [mxConstants.ARROW_OPEN, 0],  
9939 - null,  
9940 - null,  
9941 - false,  
9942 - Format.openFilledMarkerImage.src,  
9943 - ),  
9944 - "scaleX(-1)",  
9945 - );  
9946 - Format.processMenuIcon(  
9947 - this.editorUi.menus.edgeStyleChange(  
9948 - menu,  
9949 - "",  
9950 - [mxConstants.STYLE_ENDARROW, "endFill"],  
9951 - [mxConstants.ARROW_OPEN_THIN, 0],  
9952 - null,  
9953 - null,  
9954 - false,  
9955 - Format.openThinFilledMarkerImage.src,  
9956 - ),  
9957 - "scaleX(-1)",  
9958 - );  
9959 - Format.processMenuIcon(  
9960 - this.editorUi.menus.edgeStyleChange(  
9961 - menu,  
9962 - "",  
9963 - [mxConstants.STYLE_ENDARROW, "endFill"],  
9964 - ["openAsync", 0],  
9965 - null,  
9966 - null,  
9967 - false,  
9968 - Format.openAsyncFilledMarkerImage.src,  
9969 - ),  
9970 - "scaleX(-1)",  
9971 - );  
9972 - Format.processMenuIcon(  
9973 - this.editorUi.menus.edgeStyleChange(  
9974 - menu,  
9975 - "",  
9976 - [mxConstants.STYLE_ENDARROW, "endFill"],  
9977 - [mxConstants.ARROW_BLOCK, 1],  
9978 - null,  
9979 - null,  
9980 - false,  
9981 - Format.blockFilledMarkerImage.src,  
9982 - ),  
9983 - "scaleX(-1)",  
9984 - );  
9985 - Format.processMenuIcon(  
9986 - this.editorUi.menus.edgeStyleChange(  
9987 - menu,  
9988 - "",  
9989 - [mxConstants.STYLE_ENDARROW, "endFill"],  
9990 - [mxConstants.ARROW_BLOCK_THIN, 1],  
9991 - null,  
9992 - null,  
9993 - false,  
9994 - Format.blockThinFilledMarkerImage.src,  
9995 - ),  
9996 - "scaleX(-1)",  
9997 - );  
9998 - Format.processMenuIcon(  
9999 - this.editorUi.menus.edgeStyleChange(  
10000 - menu,  
10001 - "",  
10002 - [mxConstants.STYLE_ENDARROW, "endFill"],  
10003 - ["async", 1],  
10004 - null,  
10005 - null,  
10006 - false,  
10007 - Format.asyncFilledMarkerImage.src,  
10008 - ),  
10009 - "scaleX(-1)",  
10010 - );  
10011 - Format.processMenuIcon(  
10012 - this.editorUi.menus.edgeStyleChange(  
10013 - menu,  
10014 - "",  
10015 - [mxConstants.STYLE_ENDARROW, "endFill"],  
10016 - [mxConstants.ARROW_OVAL, 1],  
10017 - null,  
10018 - null,  
10019 - false,  
10020 - Format.ovalFilledMarkerImage.src,  
10021 - ),  
10022 - "scaleX(-1)",  
10023 - );  
10024 - Format.processMenuIcon(  
10025 - this.editorUi.menus.edgeStyleChange(  
10026 - menu,  
10027 - "",  
10028 - [mxConstants.STYLE_ENDARROW, "endFill"],  
10029 - [mxConstants.ARROW_DIAMOND, 1],  
10030 - null,  
10031 - null,  
10032 - false,  
10033 - Format.diamondFilledMarkerImage.src,  
10034 - ),  
10035 - "scaleX(-1)",  
10036 - );  
10037 - Format.processMenuIcon(  
10038 - this.editorUi.menus.edgeStyleChange(  
10039 - menu,  
10040 - "",  
10041 - [mxConstants.STYLE_ENDARROW, "endFill"],  
10042 - [mxConstants.ARROW_DIAMOND_THIN, 1],  
10043 - null,  
10044 - null,  
10045 - false,  
10046 - Format.diamondThinFilledMarkerImage.src,  
10047 - ),  
10048 - "scaleX(-1)",  
10049 - );  
10050 - Format.processMenuIcon(  
10051 - this.editorUi.menus.edgeStyleChange(  
10052 - menu,  
10053 - "",  
10054 - [mxConstants.STYLE_ENDARROW, "endFill"],  
10055 - [mxConstants.ARROW_CLASSIC, 0],  
10056 - null,  
10057 - null,  
10058 - false,  
10059 - Format.classicMarkerImage.src,  
10060 - ),  
10061 - "scaleX(-1)",  
10062 - );  
10063 - Format.processMenuIcon(  
10064 - this.editorUi.menus.edgeStyleChange(  
10065 - menu,  
10066 - "",  
10067 - [mxConstants.STYLE_ENDARROW, "endFill"],  
10068 - [mxConstants.ARROW_CLASSIC_THIN, 0],  
10069 - null,  
10070 - null,  
10071 - false,  
10072 - Format.classicThinMarkerImage.src,  
10073 - ),  
10074 - "scaleX(-1)",  
10075 - );  
10076 - Format.processMenuIcon(  
10077 - this.editorUi.menus.edgeStyleChange(  
10078 - menu,  
10079 - "",  
10080 - [mxConstants.STYLE_ENDARROW, "endFill"],  
10081 - [mxConstants.ARROW_BLOCK, 0],  
10082 - null,  
10083 - null,  
10084 - false,  
10085 - Format.blockMarkerImage.src,  
10086 - ),  
10087 - "scaleX(-1)",  
10088 - );  
10089 - Format.processMenuIcon(  
10090 - this.editorUi.menus.edgeStyleChange(  
10091 - menu,  
10092 - "",  
10093 - [mxConstants.STYLE_ENDARROW, "endFill"],  
10094 - [mxConstants.ARROW_BLOCK_THIN, 0],  
10095 - null,  
10096 - null,  
10097 - false,  
10098 - Format.blockThinMarkerImage.src,  
10099 - ),  
10100 - "scaleX(-1)",  
10101 - );  
10102 - Format.processMenuIcon(  
10103 - this.editorUi.menus.edgeStyleChange(  
10104 - menu,  
10105 - "",  
10106 - [mxConstants.STYLE_ENDARROW, "endFill"],  
10107 - ["async", 0],  
10108 - null,  
10109 - null,  
10110 - false,  
10111 - Format.asyncMarkerImage.src,  
10112 - ),  
10113 - "scaleX(-1)",  
10114 - );  
10115 - Format.processMenuIcon(  
10116 - this.editorUi.menus.edgeStyleChange(  
10117 - menu,  
10118 - "",  
10119 - [mxConstants.STYLE_ENDARROW, "endFill"],  
10120 - [mxConstants.ARROW_OVAL, 0],  
10121 - null,  
10122 - null,  
10123 - false,  
10124 - Format.ovalMarkerImage.src,  
10125 - ),  
10126 - "scaleX(-1)",  
10127 - );  
10128 - Format.processMenuIcon(  
10129 - this.editorUi.menus.edgeStyleChange(  
10130 - menu,  
10131 - "",  
10132 - [mxConstants.STYLE_ENDARROW, "endFill"],  
10133 - [mxConstants.ARROW_DIAMOND, 0],  
10134 - null,  
10135 - null,  
10136 - false,  
10137 - Format.diamondMarkerImage.src,  
10138 - ),  
10139 - "scaleX(-1)",  
10140 - );  
10141 - Format.processMenuIcon(  
10142 - this.editorUi.menus.edgeStyleChange(  
10143 - menu,  
10144 - "",  
10145 - [mxConstants.STYLE_ENDARROW, "endFill"],  
10146 - [mxConstants.ARROW_DIAMOND_THIN, 0],  
10147 - null,  
10148 - null,  
10149 - false,  
10150 - Format.diamondThinMarkerImage.src,  
10151 - ),  
10152 - "scaleX(-1)",  
10153 - );  
10154 - Format.processMenuIcon(  
10155 - this.editorUi.menus.edgeStyleChange(  
10156 - menu,  
10157 - "",  
10158 - [mxConstants.STYLE_ENDARROW, "endFill"],  
10159 - ["box", 0],  
10160 - null,  
10161 - null,  
10162 - false,  
10163 - Format.boxMarkerImage.src,  
10164 - ),  
10165 - "scaleX(-1)",  
10166 - );  
10167 - Format.processMenuIcon(  
10168 - this.editorUi.menus.edgeStyleChange(  
10169 - menu,  
10170 - "",  
10171 - [mxConstants.STYLE_ENDARROW, "endFill"],  
10172 - ["halfCircle", 0],  
10173 - null,  
10174 - null,  
10175 - false,  
10176 - Format.halfCircleMarkerImage.src,  
10177 - ),  
10178 - "scaleX(-1)",  
10179 - );  
10180 - Format.processMenuIcon(  
10181 - this.editorUi.menus.edgeStyleChange(  
10182 - menu,  
10183 - "",  
10184 - [mxConstants.STYLE_ENDARROW, "endFill"],  
10185 - ["dash", 0],  
10186 - null,  
10187 - null,  
10188 - false,  
10189 - Format.dashMarkerImage.src,  
10190 - ),  
10191 - "scaleX(-1)",  
10192 - );  
10193 - Format.processMenuIcon(  
10194 - this.editorUi.menus.edgeStyleChange(  
10195 - menu,  
10196 - "",  
10197 - [mxConstants.STYLE_ENDARROW, "endFill"],  
10198 - ["cross", 0],  
10199 - null,  
10200 - null,  
10201 - false,  
10202 - Format.crossMarkerImage.src,  
10203 - ),  
10204 - "scaleX(-1)",  
10205 - );  
10206 - Format.processMenuIcon(  
10207 - this.editorUi.menus.edgeStyleChange(  
10208 - menu,  
10209 - "",  
10210 - [mxConstants.STYLE_ENDARROW, "endFill"],  
10211 - ["circlePlus", 0],  
10212 - null,  
10213 - null,  
10214 - false,  
10215 - Format.circlePlusMarkerImage.src,  
10216 - ),  
10217 - "scaleX(-1)",  
10218 - );  
10219 - Format.processMenuIcon(  
10220 - this.editorUi.menus.edgeStyleChange(  
10221 - menu,  
10222 - "",  
10223 - [mxConstants.STYLE_ENDARROW, "endFill"],  
10224 - ["circle", 0],  
10225 - null,  
10226 - null,  
10227 - false,  
10228 - Format.circleMarkerImage.src,  
10229 - ),  
10230 - "scaleX(-1)",  
10231 - );  
10232 - Format.processMenuIcon(  
10233 - this.editorUi.menus.edgeStyleChange(  
10234 - menu,  
10235 - "",  
10236 - [mxConstants.STYLE_ENDARROW, "endFill"],  
10237 - ["baseDash", 0],  
10238 - null,  
10239 - null,  
10240 - false,  
10241 - Format.baseDashMarkerImage.src,  
10242 - ),  
10243 - "scaleX(-1)",  
10244 - );  
10245 - Format.processMenuIcon(  
10246 - this.editorUi.menus.edgeStyleChange(  
10247 - menu,  
10248 - "",  
10249 - [mxConstants.STYLE_ENDARROW, "endFill"],  
10250 - ["ERone", 0],  
10251 - null,  
10252 - null,  
10253 - false,  
10254 - Format.EROneMarkerImage.src,  
10255 - ),  
10256 - "scaleX(-1)",  
10257 - );  
10258 - Format.processMenuIcon(  
10259 - this.editorUi.menus.edgeStyleChange(  
10260 - menu,  
10261 - "",  
10262 - [mxConstants.STYLE_ENDARROW, "endFill"],  
10263 - ["ERmandOne", 0],  
10264 - null,  
10265 - null,  
10266 - false,  
10267 - Format.ERmandOneMarkerImage.src,  
10268 - ),  
10269 - "scaleX(-1)",  
10270 - );  
10271 - Format.processMenuIcon(  
10272 - this.editorUi.menus.edgeStyleChange(  
10273 - menu,  
10274 - "",  
10275 - [mxConstants.STYLE_ENDARROW, "endFill"],  
10276 - ["ERmany", 0],  
10277 - null,  
10278 - null,  
10279 - false,  
10280 - Format.ERmanyMarkerImage.src,  
10281 - ),  
10282 - "scaleX(-1)",  
10283 - );  
10284 - Format.processMenuIcon(  
10285 - this.editorUi.menus.edgeStyleChange(  
10286 - menu,  
10287 - "",  
10288 - [mxConstants.STYLE_ENDARROW, "endFill"],  
10289 - ["ERoneToMany", 0],  
10290 - null,  
10291 - null,  
10292 - false,  
10293 - Format.ERoneToManyMarkerImage.src,  
10294 - ),  
10295 - "scaleX(-1)",  
10296 - );  
10297 - Format.processMenuIcon(  
10298 - this.editorUi.menus.edgeStyleChange(  
10299 - menu,  
10300 - "",  
10301 - [mxConstants.STYLE_ENDARROW, "endFill"],  
10302 - ["ERzeroToOne", 0],  
10303 - null,  
10304 - null,  
10305 - false,  
10306 - Format.ERzeroToOneMarkerImage.src,  
10307 - ),  
10308 - "scaleX(-1)",  
10309 - );  
10310 - Format.processMenuIcon(  
10311 - this.editorUi.menus.edgeStyleChange(  
10312 - menu,  
10313 - "",  
10314 - [mxConstants.STYLE_ENDARROW, "endFill"],  
10315 - ["ERzeroToMany", 0],  
10316 - null,  
10317 - null,  
10318 - false,  
10319 - Format.ERzeroToManyMarkerImage.src,  
10320 - ),  
10321 - "scaleX(-1)",  
10322 - );  
10323 - Format.processMenuIcon(  
10324 - this.editorUi.menus.edgeStyleChange(  
10325 - menu,  
10326 - "",  
10327 - [mxConstants.STYLE_ENDARROW, "endFill"],  
10328 - ["doubleBlock", 0],  
10329 - null,  
10330 - null,  
10331 - false,  
10332 - Format.doubleBlockMarkerImage.src,  
10333 - ),  
10334 - "scaleX(-1)",  
10335 - );  
10336 - Format.processMenuIcon(  
10337 - this.editorUi.menus.edgeStyleChange(  
10338 - menu,  
10339 - "",  
10340 - [mxConstants.STYLE_ENDARROW, "endFill"],  
10341 - ["doubleBlock", 1],  
10342 - null,  
10343 - null,  
10344 - false,  
10345 - Format.doubleBlockFilledMarkerImage.src,  
10346 - ),  
10347 - "scaleX(-1)",  
10348 - );  
10349 - } else {  
10350 - this.editorUi.menus  
10351 - .edgeStyleChange(  
10352 - menu,  
10353 - "",  
10354 - [mxConstants.STYLE_ENDARROW],  
10355 - [mxConstants.ARROW_BLOCK],  
10356 - "geIcon geSprite geSprite-endblocktrans",  
10357 - null,  
10358 - false,  
10359 - )  
10360 - .setAttribute("title", mxResources.get("block"));  
10361 - }  
10362 -  
10363 - menu.div.style.width = "40px";  
10364 -  
10365 - window.setTimeout(  
10366 - mxUtils.bind(this, function () {  
10367 - if (menu.div != null) {  
10368 - mxUtils.fit(menu.div);  
10369 - }  
10370 - }),  
10371 - 0,  
10372 - );  
10373 - }  
10374 - }),  
10375 - );  
10376 -  
10377 - var elt = this.addArrow(edgeShape, 8);  
10378 - elt.nextSibling.style.position = "relative";  
10379 - elt.nextSibling.style.top = "-2px";  
10380 - elt = this.addArrow(edgeStyle, 10);  
10381 - elt.nextSibling.style.position = "relative";  
10382 - elt.nextSibling.style.top = "-3px";  
10383 - edgeStyle.getElementsByTagName("img")[0].style.top = "-1px";  
10384 - this.addArrow(lineStart);  
10385 - this.addArrow(lineEnd);  
10386 -  
10387 - var symbol = this.addArrow(pattern, 9);  
10388 - symbol.className = "geIcon";  
10389 - symbol.style.width = "auto";  
10390 -  
10391 - var altSymbol = this.addArrow(altPattern, 9);  
10392 - altSymbol.className = "geIcon";  
10393 - altSymbol.style.width = "22px";  
10394 -  
10395 - var solid = document.createElement("div");  
10396 - solid.style.width = "84px";  
10397 - solid.style.height = "1px";  
10398 - solid.style.borderBottom = "1px solid " + this.defaultStrokeColor;  
10399 - solid.style.marginBottom = "7px";  
10400 - symbol.appendChild(solid);  
10401 -  
10402 - var altSolid = document.createElement("div");  
10403 - altSolid.style.width = "23px";  
10404 - altSolid.style.height = "1px";  
10405 - altSolid.style.borderBottom = "1px solid " + this.defaultStrokeColor;  
10406 - altSolid.style.marginBottom = "7px";  
10407 - altSymbol.appendChild(altSolid);  
10408 -  
10409 - pattern.style.height = "15px";  
10410 - pattern.style.marginLeft = "16px";  
10411 - altPattern.style.height = "15px";  
10412 - altPattern.style.marginLeft = "3px";  
10413 - edgeShape.style.marginLeft = "10px";  
10414 - edgeShape.style.height = "15px";  
10415 - edgeStyle.style.marginLeft = "10px";  
10416 - edgeStyle.style.height = "17px";  
10417 - lineStart.style.marginLeft = "3px";  
10418 - lineStart.style.height = "17px";  
10419 - lineEnd.style.marginLeft = "3px";  
10420 - lineEnd.style.height = "17px";  
10421 -  
10422 - container.appendChild(colorPanel);  
10423 - container.appendChild(altStylePanel);  
10424 - container.appendChild(stylePanel);  
10425 -  
10426 - var arrowPanel = stylePanel.cloneNode(false);  
10427 - arrowPanel.style.padding = "5px 4px 6px 0px";  
10428 - arrowPanel.style.fontWeight = "normal";  
10429 -  
10430 - var span = document.createElement("div");  
10431 - span.style.position = "absolute";  
10432 - span.style.marginLeft = "0px";  
10433 - span.style.marginBottom = "12px";  
10434 - span.style.marginTop = "2px";  
10435 - span.style.fontWeight = "normal";  
10436 - span.style.width = "76px";  
10437 -  
10438 - mxUtils.write(span, mxResources.get("lineend"));  
10439 - arrowPanel.appendChild(span);  
10440 -  
10441 - var endSpacingUpdate, endSizeUpdate;  
10442 - var endSpacing = this.addUnitInput(arrowPanel, "pt", 98, 52, function () {  
10443 - endSpacingUpdate.apply(this, arguments);  
10444 - });  
10445 - var endSize = this.addUnitInput(arrowPanel, "pt", 30, 52, function () {  
10446 - endSizeUpdate.apply(this, arguments);  
10447 - });  
10448 -  
10449 - mxUtils.br(arrowPanel);  
10450 -  
10451 - var spacer = document.createElement("div");  
10452 - spacer.style.height = "8px";  
10453 - arrowPanel.appendChild(spacer);  
10454 -  
10455 - span = span.cloneNode(false);  
10456 - mxUtils.write(span, mxResources.get("linestart"));  
10457 - arrowPanel.appendChild(span);  
10458 -  
10459 - var startSpacingUpdate, startSizeUpdate;  
10460 - var startSpacing = this.addUnitInput(arrowPanel, "pt", 98, 52, function () {  
10461 - startSpacingUpdate.apply(this, arguments);  
10462 - });  
10463 - var startSize = this.addUnitInput(arrowPanel, "pt", 30, 52, function () {  
10464 - startSizeUpdate.apply(this, arguments);  
10465 - });  
10466 -  
10467 - mxUtils.br(arrowPanel);  
10468 - this.addLabel(arrowPanel, mxResources.get("spacing"), 98, 52);  
10469 - this.addLabel(arrowPanel, mxResources.get("size"), 30, 52);  
10470 - mxUtils.br(arrowPanel);  
10471 -  
10472 - var perimeterPanel = colorPanel.cloneNode(false);  
10473 - perimeterPanel.style.fontWeight = "normal";  
10474 - perimeterPanel.style.position = "relative";  
10475 - perimeterPanel.style.paddingLeft = "16px";  
10476 - perimeterPanel.style.marginBottom = "2px";  
10477 - perimeterPanel.style.marginTop = "6px";  
10478 - perimeterPanel.style.borderWidth = "0px";  
10479 - perimeterPanel.style.paddingBottom = "18px";  
10480 -  
10481 - var span = document.createElement("div");  
10482 - span.style.position = "absolute";  
10483 - span.style.marginLeft = "3px";  
10484 - span.style.marginBottom = "12px";  
10485 - span.style.marginTop = "1px";  
10486 - span.style.fontWeight = "normal";  
10487 - span.style.width = "120px";  
10488 - mxUtils.write(span, mxResources.get("perimeter"));  
10489 - perimeterPanel.appendChild(span);  
10490 -  
10491 - var perimeterUpdate;  
10492 - var perimeterSpacing = this.addUnitInput(  
10493 - perimeterPanel,  
10494 - "pt",  
10495 - 30,  
10496 - 52,  
10497 - function () {  
10498 - perimeterUpdate.apply(this, arguments);  
10499 - },  
10500 - );  
10501 -  
10502 - if (ss.edges.length == ss.cells.length) {  
10503 - container.appendChild(stylePanel2);  
10504 - container.appendChild(arrowPanel);  
10505 - } else if (ss.vertices.length == ss.cells.length) {  
10506 - container.appendChild(perimeterPanel);  
10507 - }  
10508 -  
10509 - var listener = mxUtils.bind(this, function (sender, evt, force) {  
10510 - ss = ui.getSelectionState();  
10511 -  
10512 - if (force || document.activeElement != input) {  
10513 - var tmp = parseFloat(  
10514 - mxUtils.getValue(ss.style, mxConstants.STYLE_STROKEWIDTH, 1),  
10515 - );  
10516 - input.value = isNaN(tmp) ? "" : tmp + " pt";  
10517 - }  
10518 -  
10519 - if (force || document.activeElement != altInput) {  
10520 - var tmp = parseFloat(  
10521 - mxUtils.getValue(ss.style, mxConstants.STYLE_STROKEWIDTH, 1),  
10522 - );  
10523 - altInput.value = isNaN(tmp) ? "" : tmp + " pt";  
10524 - }  
10525 -  
10526 - styleSelect.style.visibility =  
10527 - ss.style.shape == "connector" || ss.style.shape == "filledEdge"  
10528 - ? ""  
10529 - : "hidden";  
10530 -  
10531 - if (mxUtils.getValue(ss.style, mxConstants.STYLE_CURVED, null) == "1") {  
10532 - styleSelect.value = "curved";  
10533 - } else if (  
10534 - mxUtils.getValue(ss.style, mxConstants.STYLE_ROUNDED, null) == "1"  
10535 - ) {  
10536 - styleSelect.value = "rounded";  
10537 - }  
10538 -  
10539 - if (mxUtils.getValue(ss.style, mxConstants.STYLE_DASHED, null) == "1") {  
10540 - if (  
10541 - mxUtils.getValue(ss.style, mxConstants.STYLE_DASH_PATTERN, null) == null  
10542 - ) {  
10543 - solid.style.borderBottom = "1px dashed " + this.defaultStrokeColor;  
10544 - } else {  
10545 - solid.style.borderBottom = "1px dotted " + this.defaultStrokeColor;  
10546 - }  
10547 - } else {  
10548 - solid.style.borderBottom = "1px solid " + this.defaultStrokeColor;  
10549 - }  
10550 -  
10551 - altSolid.style.borderBottom = solid.style.borderBottom;  
10552 -  
10553 - // Updates toolbar icon for edge style  
10554 - var edgeStyleDiv = edgeStyle.getElementsByTagName("div")[0];  
10555 -  
10556 - if (edgeStyleDiv != null) {  
10557 - var es = mxUtils.getValue(ss.style, mxConstants.STYLE_EDGE, null);  
10558 -  
10559 - if (  
10560 - mxUtils.getValue(ss.style, mxConstants.STYLE_NOEDGESTYLE, null) == "1"  
10561 - ) {  
10562 - es = null;  
10563 - }  
10564 -  
10565 - if (  
10566 - es == "orthogonalEdgeStyle" &&  
10567 - mxUtils.getValue(ss.style, mxConstants.STYLE_CURVED, null) == "1"  
10568 - ) {  
10569 - edgeStyleDiv.className = "geSprite geSprite-curved";  
10570 - } else if (es == "straight" || es == "none" || es == null) {  
10571 - edgeStyleDiv.className = "geSprite geSprite-straight";  
10572 - } else if (es == "entityRelationEdgeStyle") {  
10573 - edgeStyleDiv.className = "geSprite geSprite-entity";  
10574 - } else if (es == "elbowEdgeStyle") {  
10575 - edgeStyleDiv.className =  
10576 - "geSprite " +  
10577 - (mxUtils.getValue(ss.style, mxConstants.STYLE_ELBOW, null) ==  
10578 - "vertical"  
10579 - ? "geSprite-verticalelbow"  
10580 - : "geSprite-horizontalelbow");  
10581 - } else if (es == "isometricEdgeStyle") {  
10582 - edgeStyleDiv.className =  
10583 - "geSprite " +  
10584 - (mxUtils.getValue(ss.style, mxConstants.STYLE_ELBOW, null) ==  
10585 - "vertical"  
10586 - ? "geSprite-verticalisometric"  
10587 - : "geSprite-horizontalisometric");  
10588 - } else {  
10589 - edgeStyleDiv.className = "geSprite geSprite-orthogonal";  
10590 - }  
10591 - }  
10592 -  
10593 - // Updates icon for edge shape  
10594 - var edgeShapeDiv = edgeShape.getElementsByTagName("div")[0];  
10595 -  
10596 - if (edgeShapeDiv != null) {  
10597 - if (ss.style.shape == "link") {  
10598 - edgeShapeDiv.className = "geSprite geSprite-linkedge";  
10599 - } else if (ss.style.shape == "flexArrow") {  
10600 - edgeShapeDiv.className = "geSprite geSprite-arrow";  
10601 - } else if (ss.style.shape == "arrow") {  
10602 - edgeShapeDiv.className = "geSprite geSprite-simplearrow";  
10603 - } else {  
10604 - edgeShapeDiv.className = "geSprite geSprite-connection";  
10605 - }  
10606 - }  
10607 -  
10608 - if (ss.edges.length == ss.cells.length) {  
10609 - altStylePanel.style.display = "";  
10610 - stylePanel.style.display = "none";  
10611 - } else {  
10612 - altStylePanel.style.display = "none";  
10613 - stylePanel.style.display = "";  
10614 - }  
10615 -  
10616 - if (  
10617 - Graph.lineJumpsEnabled &&  
10618 - ss.edges.length > 0 &&  
10619 - ss.vertices.length == 0 &&  
10620 - ss.lineJumps  
10621 - ) {  
10622 - container.style.borderBottomStyle = "none";  
10623 - }  
10624 -  
10625 - function updateArrow(marker, fill, elt, prefix) {  
10626 - var markerDiv = elt.getElementsByTagName("div")[0];  
10627 -  
10628 - if (markerDiv != null) {  
10629 - markerDiv.className = ui.getCssClassForMarker(  
10630 - prefix,  
10631 - ss.style.shape,  
10632 - marker,  
10633 - fill,  
10634 - );  
10635 - markerDiv.nextSibling.style.marginLeft = "1px";  
10636 - markerDiv.nextSibling.style.paddingRight = "5px";  
10637 -  
10638 - if (markerDiv.className == "geSprite geSprite-noarrow") {  
10639 - markerDiv.innerHTML = mxUtils.htmlEntities(mxResources.get("none"));  
10640 - markerDiv.style.backgroundImage = "none";  
10641 - markerDiv.style.verticalAlign = "top";  
10642 - markerDiv.style.marginTop = "4px";  
10643 - markerDiv.style.fontSize = "10px";  
10644 - markerDiv.style.filter = "none";  
10645 - markerDiv.style.color = this.defaultStrokeColor;  
10646 - markerDiv.nextSibling.style.marginTop = "0px";  
10647 - } else {  
10648 - markerDiv.nextSibling.style.position = "relative";  
10649 - markerDiv.nextSibling.style.top = "-2px";  
10650 - }  
10651 - }  
10652 -  
10653 - return markerDiv;  
10654 - }  
10655 -  
10656 - var sourceDiv = updateArrow(  
10657 - mxUtils.getValue(ss.style, mxConstants.STYLE_STARTARROW, null),  
10658 - mxUtils.getValue(ss.style, "startFill", "1"),  
10659 - lineStart,  
10660 - "start",  
10661 - );  
10662 - var targetDiv = updateArrow(  
10663 - mxUtils.getValue(ss.style, mxConstants.STYLE_ENDARROW, null),  
10664 - mxUtils.getValue(ss.style, "endFill", "1"),  
10665 - lineEnd,  
10666 - "end",  
10667 - );  
10668 -  
10669 - // Special cases for markers  
10670 - if (sourceDiv != null && targetDiv != null) {  
10671 - if (ss.style.shape == "arrow") {  
10672 - sourceDiv.className = "geSprite geSprite-noarrow";  
10673 - targetDiv.className = "geSprite geSprite-endblocktrans";  
10674 - } else if (ss.style.shape == "link") {  
10675 - sourceDiv.className = "geSprite geSprite-noarrow";  
10676 - targetDiv.className = "geSprite geSprite-noarrow";  
10677 - }  
10678 - }  
10679 -  
10680 - mxUtils.setOpacity(edgeStyle, ss.style.shape == "arrow" ? 30 : 100);  
10681 -  
10682 - if (  
10683 - ss.style.shape != "connector" &&  
10684 - ss.style.shape != "flexArrow" &&  
10685 - ss.style.shape != "filledEdge"  
10686 - ) {  
10687 - mxUtils.setOpacity(lineStart, 30);  
10688 - mxUtils.setOpacity(lineEnd, 30);  
10689 - } else {  
10690 - mxUtils.setOpacity(lineStart, 100);  
10691 - mxUtils.setOpacity(lineEnd, 100);  
10692 - }  
10693 -  
10694 - if (force || document.activeElement != startSize) {  
10695 - var tmp = parseInt(  
10696 - mxUtils.getValue(  
10697 - ss.style,  
10698 - mxConstants.STYLE_STARTSIZE,  
10699 - mxConstants.DEFAULT_MARKERSIZE,  
10700 - ),  
10701 - );  
10702 - startSize.value = isNaN(tmp) ? "" : tmp + " pt";  
10703 - }  
10704 -  
10705 - if (force || document.activeElement != startSpacing) {  
10706 - var tmp = parseInt(  
10707 - mxUtils.getValue(  
10708 - ss.style,  
10709 - mxConstants.STYLE_SOURCE_PERIMETER_SPACING,  
10710 - 0,  
10711 - ),  
10712 - );  
10713 - startSpacing.value = isNaN(tmp) ? "" : tmp + " pt";  
10714 - }  
10715 -  
10716 - if (force || document.activeElement != endSize) {  
10717 - var tmp = parseInt(  
10718 - mxUtils.getValue(  
10719 - ss.style,  
10720 - mxConstants.STYLE_ENDSIZE,  
10721 - mxConstants.DEFAULT_MARKERSIZE,  
10722 - ),  
10723 - );  
10724 - endSize.value = isNaN(tmp) ? "" : tmp + " pt";  
10725 - }  
10726 -  
10727 - if (force || document.activeElement != startSpacing) {  
10728 - var tmp = parseInt(  
10729 - mxUtils.getValue(  
10730 - ss.style,  
10731 - mxConstants.STYLE_TARGET_PERIMETER_SPACING,  
10732 - 0,  
10733 - ),  
10734 - );  
10735 - endSpacing.value = isNaN(tmp) ? "" : tmp + " pt";  
10736 - }  
10737 -  
10738 - if (force || document.activeElement != perimeterSpacing) {  
10739 - var tmp = parseInt(  
10740 - mxUtils.getValue(ss.style, mxConstants.STYLE_PERIMETER_SPACING, 0),  
10741 - );  
10742 - perimeterSpacing.value = isNaN(tmp) ? "" : tmp + " pt";  
10743 - }  
10744 - });  
10745 -  
10746 - startSizeUpdate = this.installInputHandler(  
10747 - startSize,  
10748 - mxConstants.STYLE_STARTSIZE,  
10749 - mxConstants.DEFAULT_MARKERSIZE,  
10750 - 0,  
10751 - 999,  
10752 - " pt",  
10753 - );  
10754 - startSpacingUpdate = this.installInputHandler(  
10755 - startSpacing,  
10756 - mxConstants.STYLE_SOURCE_PERIMETER_SPACING,  
10757 - 0,  
10758 - -999,  
10759 - 999,  
10760 - " pt",  
10761 - );  
10762 - endSizeUpdate = this.installInputHandler(  
10763 - endSize,  
10764 - mxConstants.STYLE_ENDSIZE,  
10765 - mxConstants.DEFAULT_MARKERSIZE,  
10766 - 0,  
10767 - 999,  
10768 - " pt",  
10769 - );  
10770 - endSpacingUpdate = this.installInputHandler(  
10771 - endSpacing,  
10772 - mxConstants.STYLE_TARGET_PERIMETER_SPACING,  
10773 - 0,  
10774 - -999,  
10775 - 999,  
10776 - " pt",  
10777 - );  
10778 - perimeterUpdate = this.installInputHandler(  
10779 - perimeterSpacing,  
10780 - mxConstants.STYLE_PERIMETER_SPACING,  
10781 - 0,  
10782 - 0,  
10783 - 999,  
10784 - " pt",  
10785 - );  
10786 -  
10787 - this.addKeyHandler(input, listener);  
10788 - this.addKeyHandler(startSize, listener);  
10789 - this.addKeyHandler(startSpacing, listener);  
10790 - this.addKeyHandler(endSize, listener);  
10791 - this.addKeyHandler(endSpacing, listener);  
10792 - this.addKeyHandler(perimeterSpacing, listener);  
10793 -  
10794 - graph.getModel().addListener(mxEvent.CHANGE, listener);  
10795 - this.listeners.push({  
10796 - destroy: function () {  
10797 - graph.getModel().removeListener(listener);  
10798 - },  
10799 - });  
10800 - listener();  
10801 -  
10802 - return container;  
10803 -};  
10804 -  
10805 -/**  
10806 - * Adds UI for configuring line jumps.  
10807 - */  
10808 -StyleFormatPanel.prototype.addLineJumps = function (container) {  
10809 - var ui = this.editorUi;  
10810 - var editor = ui.editor;  
10811 - var graph = editor.graph;  
10812 - var ss = ui.getSelectionState();  
10813 -  
10814 - if (  
10815 - Graph.lineJumpsEnabled &&  
10816 - ss.edges.length > 0 &&  
10817 - ss.vertices.length == 0 &&  
10818 - ss.lineJumps  
10819 - ) {  
10820 - container.style.padding = "2px 0px 24px 14px";  
10821 -  
10822 - var span = document.createElement("div");  
10823 - span.style.position = "absolute";  
10824 - span.style.maxWidth = "82px";  
10825 - span.style.overflow = "hidden";  
10826 - span.style.textOverflow = "ellipsis";  
10827 -  
10828 - mxUtils.write(span, mxResources.get("lineJumps"));  
10829 - container.appendChild(span);  
10830 -  
10831 - var styleSelect = document.createElement("select");  
10832 - styleSelect.style.position = "absolute";  
10833 - styleSelect.style.height = "21px";  
10834 - styleSelect.style.padding = "0px";  
10835 - styleSelect.style.marginTop = "-2px";  
10836 - styleSelect.style.boxSizing = "border-box";  
10837 - styleSelect.style.right = "76px";  
10838 - styleSelect.style.width = "54px";  
10839 - styleSelect.style.border = "1px solid rgb(160, 160, 160)";  
10840 - styleSelect.style.borderRadius = "4px";  
10841 -  
10842 - var styles = ["none", "arc", "gap", "sharp", "line"];  
10843 -  
10844 - for (var i = 0; i < styles.length; i++) {  
10845 - var styleOption = document.createElement("option");  
10846 - styleOption.setAttribute("value", styles[i]);  
10847 - mxUtils.write(styleOption, mxResources.get(styles[i]));  
10848 - styleSelect.appendChild(styleOption);  
10849 - }  
10850 -  
10851 - mxEvent.addListener(styleSelect, "change", function (evt) {  
10852 - graph.getModel().beginUpdate();  
10853 - try {  
10854 - graph.setCellStyles("jumpStyle", styleSelect.value, ss.cells);  
10855 - ui.fireEvent(  
10856 - new mxEventObject(  
10857 - "styleChanged",  
10858 - "keys",  
10859 - ["jumpStyle"],  
10860 - "values",  
10861 - [styleSelect.value],  
10862 - "cells",  
10863 - ss.cells,  
10864 - ),  
10865 - );  
10866 - } finally {  
10867 - graph.getModel().endUpdate();  
10868 - }  
10869 -  
10870 - mxEvent.consume(evt);  
10871 - });  
10872 -  
10873 - // Stops events from bubbling to color option event handler  
10874 - mxEvent.addListener(styleSelect, "click", function (evt) {  
10875 - mxEvent.consume(evt);  
10876 - });  
10877 -  
10878 - container.appendChild(styleSelect);  
10879 -  
10880 - var jumpSizeUpdate;  
10881 -  
10882 - var jumpSize = this.addUnitInput(container, "pt", 16, 42, function () {  
10883 - jumpSizeUpdate.apply(this, arguments);  
10884 - });  
10885 -  
10886 - jumpSizeUpdate = this.installInputHandler(  
10887 - jumpSize,  
10888 - "jumpSize",  
10889 - Graph.defaultJumpSize,  
10890 - 0,  
10891 - 999,  
10892 - " pt",  
10893 - );  
10894 -  
10895 - var listener = mxUtils.bind(this, function (sender, evt, force) {  
10896 - ss = ui.getSelectionState();  
10897 - styleSelect.value = mxUtils.getValue(ss.style, "jumpStyle", "none");  
10898 -  
10899 - if (force || document.activeElement != jumpSize) {  
10900 - var tmp = parseInt(  
10901 - mxUtils.getValue(ss.style, "jumpSize", Graph.defaultJumpSize),  
10902 - );  
10903 - jumpSize.value = isNaN(tmp) ? "" : tmp + " pt";  
10904 - }  
10905 - });  
10906 -  
10907 - this.addKeyHandler(jumpSize, listener);  
10908 -  
10909 - graph.getModel().addListener(mxEvent.CHANGE, listener);  
10910 - this.listeners.push({  
10911 - destroy: function () {  
10912 - graph.getModel().removeListener(listener);  
10913 - },  
10914 - });  
10915 - listener();  
10916 - } else {  
10917 - container.style.display = "none";  
10918 - }  
10919 -  
10920 - return container;  
10921 -};  
10922 -  
10923 -/**  
10924 - * Adds the label menu items to the given menu and parent.  
10925 - */  
10926 -StyleFormatPanel.prototype.addEffects = function (div) {  
10927 - var ui = this.editorUi;  
10928 - var editor = ui.editor;  
10929 - var graph = editor.graph;  
10930 - var ss = ui.getSelectionState();  
10931 -  
10932 - div.style.paddingTop = "4px";  
10933 - div.style.paddingBottom = "0px";  
10934 -  
10935 - var table = document.createElement("table");  
10936 -  
10937 - table.style.width = "210px";  
10938 - table.style.fontWeight = "bold";  
10939 - table.style.tableLayout = "fixed";  
10940 - var tbody = document.createElement("tbody");  
10941 - var row = document.createElement("tr");  
10942 - row.style.padding = "0px";  
10943 - var left = document.createElement("td");  
10944 - left.style.padding = "0px";  
10945 - left.style.width = "50%";  
10946 - left.setAttribute("valign", "top");  
10947 -  
10948 - var right = left.cloneNode(true);  
10949 - right.style.paddingLeft = "8px";  
10950 - row.appendChild(left);  
10951 - row.appendChild(right);  
10952 - tbody.appendChild(row);  
10953 - table.appendChild(tbody);  
10954 - div.appendChild(table);  
10955 -  
10956 - var current = left;  
10957 - var count = 0;  
10958 -  
10959 - var addOption = mxUtils.bind(this, function (label, key, defaultValue) {  
10960 - var opt = this.createCellOption(label, key, defaultValue);  
10961 - opt.style.width = "100%";  
10962 - current.appendChild(opt);  
10963 - current = current == left ? right : left;  
10964 - count++;  
10965 - });  
10966 -  
10967 - var listener = mxUtils.bind(this, function (sender, evt, force) {  
10968 - ss = ui.getSelectionState();  
10969 -  
10970 - left.innerHTML = "";  
10971 - right.innerHTML = "";  
10972 - current = left;  
10973 -  
10974 - if (ss.rounded) {  
10975 - addOption(mxResources.get("rounded"), mxConstants.STYLE_ROUNDED, 0);  
10976 - }  
10977 -  
10978 - if (ss.swimlane) {  
10979 - addOption(mxResources.get("divider"), "swimlaneLine", 1);  
10980 - }  
10981 -  
10982 - if (!ss.containsImage) {  
10983 - addOption(mxResources.get("shadow"), mxConstants.STYLE_SHADOW, 0);  
10984 - }  
10985 -  
10986 - if (ss.glass) {  
10987 - addOption(mxResources.get("glass"), mxConstants.STYLE_GLASS, 0);  
10988 - }  
10989 -  
10990 - addOption(mxResources.get("sketch"), "sketch", 0);  
10991 - });  
10992 -  
10993 - graph.getModel().addListener(mxEvent.CHANGE, listener);  
10994 - this.listeners.push({  
10995 - destroy: function () {  
10996 - graph.getModel().removeListener(listener);  
10997 - },  
10998 - });  
10999 - listener();  
11000 -  
11001 - return div;  
11002 -};  
11003 -  
11004 -/**  
11005 - * Adds the label menu items to the given menu and parent.  
11006 - */  
11007 -StyleFormatPanel.prototype.addStyleOps = function (div) {  
11008 - div.style.paddingTop = "10px";  
11009 - div.style.paddingBottom = "10px";  
11010 -  
11011 - this.addActions(div, ["setAsDefaultStyle"]);  
11012 -  
11013 - return div;  
11014 -};  
11015 -  
11016 -/**  
11017 - * Adds the label menu items to the given menu and parent.  
11018 - */  
11019 -DiagramStylePanel = function (format, editorUi, container) {  
11020 - BaseFormatPanel.call(this, format, editorUi, container);  
11021 - this.init();  
11022 -};  
11023 -  
11024 -mxUtils.extend(DiagramStylePanel, BaseFormatPanel);  
11025 -  
11026 -/**  
11027 - * Adds the label menu items to the given menu and parent.  
11028 - */  
11029 -DiagramStylePanel.prototype.init = function () {  
11030 - var ui = this.editorUi;  
11031 - var editor = ui.editor;  
11032 - var graph = editor.graph;  
11033 -  
11034 - this.darkModeChangedListener = mxUtils.bind(this, function () {  
11035 - this.format.cachedStyleEntries = [];  
11036 - });  
11037 -  
11038 - ui.addListener("darkModeChanged", this.darkModeChangedListener);  
11039 - this.container.appendChild(this.addView(this.createPanel()));  
11040 -};  
11041 -  
11042 -/**  
11043 - * Adds the label menu items to the given menu and parent.  
11044 - */  
11045 -DiagramStylePanel.prototype.addView = function (div) {  
11046 - var ui = this.editorUi;  
11047 - var editor = ui.editor;  
11048 - var graph = editor.graph;  
11049 - var model = graph.getModel();  
11050 - var gridColor = graph.view.gridColor;  
11051 -  
11052 - div.style.whiteSpace = "normal";  
11053 -  
11054 - var sketch =  
11055 - graph.currentVertexStyle["sketch"] == "1" &&  
11056 - graph.currentEdgeStyle["sketch"] == "1";  
11057 - var rounded = graph.currentVertexStyle["rounded"] == "1";  
11058 - var curved = graph.currentEdgeStyle["curved"] == "1";  
11059 -  
11060 - var opts = document.createElement("div");  
11061 - opts.style.marginRight = "16px";  
11062 - div.style.paddingTop = "8px";  
11063 -  
11064 - var table = document.createElement("table");  
11065 -  
11066 - table.style.width = "210px";  
11067 - table.style.fontWeight = "bold";  
11068 -  
11069 - var tbody = document.createElement("tbody");  
11070 - var row = document.createElement("tr");  
11071 - row.style.padding = "0px";  
11072 -  
11073 - var left = document.createElement("td");  
11074 - left.style.padding = "0px";  
11075 - left.style.width = "50%";  
11076 - left.setAttribute("valign", "middle");  
11077 -  
11078 - var right = left.cloneNode(true);  
11079 - right.style.paddingLeft = "8px";  
11080 -  
11081 - // Sketch  
11082 - if (urlParams["sketch"] != "1") {  
11083 - opts.style.paddingBottom = "12px";  
11084 - row.appendChild(left);  
11085 -  
11086 - left.appendChild(  
11087 - this.createOption(  
11088 - mxResources.get("sketch"),  
11089 - function () {  
11090 - return sketch;  
11091 - },  
11092 - function (checked) {  
11093 - sketch = checked;  
11094 -  
11095 - if (checked) {  
11096 - graph.currentEdgeStyle["sketch"] = "1";  
11097 - graph.currentVertexStyle["sketch"] = "1";  
11098 - } else {  
11099 - delete graph.currentEdgeStyle["sketch"];  
11100 - delete graph.currentVertexStyle["sketch"];  
11101 - }  
11102 -  
11103 - graph.updateCellStyles(  
11104 - { sketch: checked ? "1" : null },  
11105 - graph.getVerticesAndEdges(),  
11106 - );  
11107 - },  
11108 - null,  
11109 - function (div) {  
11110 - div.style.width = "auto";  
11111 - },  
11112 - ),  
11113 - );  
11114 - }  
11115 -  
11116 - row.appendChild(right);  
11117 - tbody.appendChild(row);  
11118 - table.appendChild(tbody);  
11119 -  
11120 - // Rounded  
11121 - right.appendChild(  
11122 - this.createOption(  
11123 - mxResources.get("rounded"),  
11124 - function () {  
11125 - return rounded;  
11126 - },  
11127 - function (checked) {  
11128 - rounded = checked;  
11129 -  
11130 - if (checked) {  
11131 - graph.currentEdgeStyle["rounded"] = "1";  
11132 - graph.currentVertexStyle["rounded"] = "1";  
11133 - } else {  
11134 - delete graph.currentEdgeStyle["rounded"];  
11135 - delete graph.currentVertexStyle["rounded"];  
11136 - }  
11137 -  
11138 - graph.updateCellStyles(  
11139 - { rounded: checked ? "1" : "0" },  
11140 - graph.getVerticesAndEdges(),  
11141 - );  
11142 - },  
11143 - null,  
11144 - function (div) {  
11145 - div.style.width = "auto";  
11146 - },  
11147 - ),  
11148 - );  
11149 -  
11150 - // Curved  
11151 - if (urlParams["sketch"] != "1") {  
11152 - left = left.cloneNode(false);  
11153 - right = right.cloneNode(false);  
11154 - row = row.cloneNode(false);  
11155 - row.appendChild(left);  
11156 - row.appendChild(right);  
11157 - tbody.appendChild(row);  
11158 -  
11159 - left.appendChild(  
11160 - this.createOption(  
11161 - mxResources.get("curved"),  
11162 - function () {  
11163 - return curved;  
11164 - },  
11165 - function (checked) {  
11166 - curved = checked;  
11167 -  
11168 - if (checked) {  
11169 - graph.currentEdgeStyle["curved"] = "1";  
11170 - } else {  
11171 - delete graph.currentEdgeStyle["curved"];  
11172 - }  
11173 -  
11174 - graph.updateCellStyles(  
11175 - { curved: checked ? "1" : null },  
11176 - graph.getVerticesAndEdges(false, true),  
11177 - );  
11178 - },  
11179 - null,  
11180 - function (div) {  
11181 - div.style.width = "auto";  
11182 - },  
11183 - ),  
11184 - );  
11185 - }  
11186 -  
11187 - opts.appendChild(table);  
11188 - div.appendChild(opts);  
11189 -  
11190 - var defaultStyles = [  
11191 - "fillColor",  
11192 - "strokeColor",  
11193 - "fontColor",  
11194 - "gradientColor",  
11195 - ];  
11196 -  
11197 - var updateCells = mxUtils.bind(this, function (styles, graphStyle) {  
11198 - var cells = graph.getVerticesAndEdges();  
11199 -  
11200 - model.beginUpdate();  
11201 - try {  
11202 - for (var i = 0; i < cells.length; i++) {  
11203 - var style = graph.getCellStyle(cells[i]);  
11204 -  
11205 - // Handles special label background color  
11206 - if (style["labelBackgroundColor"] != null) {  
11207 - graph.updateCellStyles(  
11208 - {  
11209 - labelBackgroundColor:  
11210 - graphStyle != null ? graphStyle.background : null,  
11211 - },  
11212 - [cells[i]],  
11213 - );  
11214 - }  
11215 -  
11216 - var edge = model.isEdge(cells[i]);  
11217 - var newStyle = model.getStyle(cells[i]);  
11218 - var current = edge ? graph.currentEdgeStyle : graph.currentVertexStyle;  
11219 -  
11220 - for (var j = 0; j < styles.length; j++) {  
11221 - if (  
11222 - (style[styles[j]] != null &&  
11223 - style[styles[j]] != mxConstants.NONE) ||  
11224 - (styles[j] != mxConstants.STYLE_FILLCOLOR &&  
11225 - styles[j] != mxConstants.STYLE_STROKECOLOR)  
11226 - ) {  
11227 - newStyle = mxUtils.setStyle(  
11228 - newStyle,  
11229 - styles[j],  
11230 - current[styles[j]],  
11231 - );  
11232 - }  
11233 - }  
11234 -  
11235 - model.setStyle(cells[i], newStyle);  
11236 - }  
11237 - } finally {  
11238 - model.endUpdate();  
11239 - }  
11240 - });  
11241 -  
11242 - var removeStyles = mxUtils.bind(this, function (style, styles, defaultStyle) {  
11243 - if (style != null) {  
11244 - for (var j = 0; j < styles.length; j++) {  
11245 - if (  
11246 - (style[styles[j]] != null && style[styles[j]] != mxConstants.NONE) ||  
11247 - (styles[j] != mxConstants.STYLE_FILLCOLOR &&  
11248 - styles[j] != mxConstants.STYLE_STROKECOLOR)  
11249 - ) {  
11250 - style[styles[j]] = defaultStyle[styles[j]];  
11251 - }  
11252 - }  
11253 - }  
11254 - });  
11255 -  
11256 - var applyStyle = mxUtils.bind(  
11257 - this,  
11258 - function (style, result, cell, graphStyle, theGraph) {  
11259 - if (style != null) {  
11260 - if (cell != null) {  
11261 - // Handles special label background color  
11262 - if (result["labelBackgroundColor"] != null) {  
11263 - var bg = graphStyle != null ? graphStyle.background : null;  
11264 - theGraph = theGraph != null ? theGraph : graph;  
11265 -  
11266 - if (bg == null) {  
11267 - bg = theGraph.background;  
11268 - }  
11269 -  
11270 - if (bg == null) {  
11271 - bg = theGraph.defaultPageBackgroundColor;  
11272 - }  
11273 -  
11274 - result["labelBackgroundColor"] = bg;  
11275 - }  
11276 - }  
11277 -  
11278 - for (var key in style) {  
11279 - if (  
11280 - cell == null ||  
11281 - (result[key] != null && result[key] != mxConstants.NONE) ||  
11282 - (key != mxConstants.STYLE_FILLCOLOR &&  
11283 - key != mxConstants.STYLE_STROKECOLOR)  
11284 - ) {  
11285 - result[key] = style[key];  
11286 - }  
11287 - }  
11288 - }  
11289 - },  
11290 - );  
11291 -  
11292 - if (urlParams["sketch"] != "1") {  
11293 - var btn = mxUtils.button(  
11294 - mxResources.get("reset"),  
11295 - mxUtils.bind(this, function (evt) {  
11296 - var all = graph.getVerticesAndEdges(true, true);  
11297 -  
11298 - if (all.length > 0) {  
11299 - model.beginUpdate();  
11300 - try {  
11301 - graph.updateCellStyles({ sketch: null, rounded: null }, all);  
11302 - graph.updateCellStyles(  
11303 - { curved: null },  
11304 - graph.getVerticesAndEdges(false, true),  
11305 - );  
11306 - } finally {  
11307 - model.endUpdate();  
11308 - }  
11309 - }  
11310 -  
11311 - ui.clearDefaultStyle();  
11312 - }),  
11313 - );  
11314 -  
11315 - btn.setAttribute("title", mxResources.get("reset"));  
11316 - btn.style.textOverflow = "ellipsis";  
11317 - btn.style.maxWidth = "90px";  
11318 - right.appendChild(btn);  
11319 - }  
11320 -  
11321 - var createPreview = mxUtils.bind(  
11322 - this,  
11323 - function (commonStyle, vertexStyle, edgeStyle, graphStyle, container) {  
11324 - // Wrapper needed to catch events  
11325 - var div = document.createElement("div");  
11326 - div.style.position = "absolute";  
11327 - div.style.display = "inline-block";  
11328 - div.style.overflow = "hidden";  
11329 - div.style.pointerEvents = "none";  
11330 - div.style.width = "100%";  
11331 - div.style.height = "100%";  
11332 - container.appendChild(div);  
11333 -  
11334 - var graph2 = new Graph(div, null, null, graph.getStylesheet());  
11335 -  
11336 - graph2.resetViewOnRootChange = false;  
11337 - graph2.foldingEnabled = false;  
11338 - graph2.gridEnabled = false;  
11339 - graph2.autoScroll = false;  
11340 - graph2.setTooltips(false);  
11341 - graph2.setConnectable(false);  
11342 - graph2.setPanning(false);  
11343 - graph2.setEnabled(false);  
11344 -  
11345 - graph2.getCellStyle = function (cell, resolve) {  
11346 - resolve = resolve != null ? resolve : true;  
11347 - var result = mxUtils.clone(graph.getCellStyle.apply(this, arguments));  
11348 - var defaultStyle = graph.stylesheet.getDefaultVertexStyle();  
11349 - var appliedStyle = vertexStyle;  
11350 -  
11351 - if (model.isEdge(cell)) {  
11352 - defaultStyle = graph.stylesheet.getDefaultEdgeStyle();  
11353 - appliedStyle = edgeStyle;  
11354 - }  
11355 -  
11356 - removeStyles(result, defaultStyles, defaultStyle);  
11357 - applyStyle(commonStyle, result, cell, graphStyle, graph2);  
11358 - applyStyle(appliedStyle, result, cell, graphStyle, graph2);  
11359 -  
11360 - if (resolve) {  
11361 - result = graph.postProcessCellStyle(cell, result);  
11362 - }  
11363 -  
11364 - return result;  
11365 - };  
11366 -  
11367 - // Avoid HTML labels to capture events in bubble phase  
11368 - graph2.model.beginUpdate();  
11369 - try {  
11370 - var v1 = graph2.insertVertex(  
11371 - graph2.getDefaultParent(),  
11372 - null,  
11373 - "Shape",  
11374 - 14,  
11375 - 8,  
11376 - 70,  
11377 - 40,  
11378 - "strokeWidth=2;",  
11379 - );  
11380 - var e1 = graph2.insertEdge(  
11381 - graph2.getDefaultParent(),  
11382 - null,  
11383 - "Connector",  
11384 - v1,  
11385 - v1,  
11386 - "edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;endSize=5;strokeWidth=2;",  
11387 - );  
11388 - e1.geometry.points = [new mxPoint(32, 70)];  
11389 - e1.geometry.offset = new mxPoint(0, 8);  
11390 - } finally {  
11391 - graph2.model.endUpdate();  
11392 - }  
11393 - },  
11394 - );  
11395 -  
11396 - // Entries  
11397 - var entries = document.createElement("div");  
11398 - entries.style.position = "relative";  
11399 - div.appendChild(entries);  
11400 -  
11401 - // Cached entries  
11402 - if (this.format.cachedStyleEntries == null) {  
11403 - this.format.cachedStyleEntries = [];  
11404 - }  
11405 -  
11406 - function addKeys(style, result) {  
11407 - for (var key in style) {  
11408 - result.push(key);  
11409 - }  
11410 -  
11411 - return result;  
11412 - }  
11413 -  
11414 - var addEntry = mxUtils.bind(  
11415 - this,  
11416 - function (commonStyle, vertexStyle, edgeStyle, graphStyle, index) {  
11417 - var panel = this.format.cachedStyleEntries[index];  
11418 -  
11419 - if (panel == null) {  
11420 - panel = document.createElement("div");  
11421 - panel.style.display = "inline-block";  
11422 - panel.style.position = "relative";  
11423 - panel.style.width = "96px";  
11424 - panel.style.height = "90px";  
11425 - panel.style.cursor = "pointer";  
11426 - panel.style.border = "1px solid gray";  
11427 - panel.style.borderRadius = "8px";  
11428 - panel.style.margin = "2px";  
11429 - panel.style.overflow = "hidden";  
11430 -  
11431 - if (graphStyle != null && graphStyle.background != null) {  
11432 - panel.style.backgroundColor = graphStyle.background;  
11433 - }  
11434 -  
11435 - createPreview(commonStyle, vertexStyle, edgeStyle, graphStyle, panel);  
11436 -  
11437 - mxEvent.addGestureListeners(  
11438 - panel,  
11439 - mxUtils.bind(this, function (evt) {  
11440 - panel.style.opacity = 0.5;  
11441 - }),  
11442 - null,  
11443 - mxUtils.bind(this, function (evt) {  
11444 - panel.style.opacity = 1;  
11445 - graph.currentVertexStyle = mxUtils.clone(graph.defaultVertexStyle);  
11446 - graph.currentEdgeStyle = mxUtils.clone(graph.defaultEdgeStyle);  
11447 -  
11448 - applyStyle(commonStyle, graph.currentVertexStyle);  
11449 - applyStyle(commonStyle, graph.currentEdgeStyle);  
11450 - applyStyle(vertexStyle, graph.currentVertexStyle);  
11451 - applyStyle(edgeStyle, graph.currentEdgeStyle);  
11452 -  
11453 - if (urlParams["sketch"] == "1") {  
11454 - sketch = Editor.sketchMode;  
11455 - }  
11456 -  
11457 - if (sketch) {  
11458 - graph.currentEdgeStyle["sketch"] = "1";  
11459 - graph.currentVertexStyle["sketch"] = "1";  
11460 - } else {  
11461 - graph.currentEdgeStyle["sketch"] = "0";  
11462 - graph.currentVertexStyle["sketch"] = "0";  
11463 - }  
11464 -  
11465 - if (rounded) {  
11466 - graph.currentVertexStyle["rounded"] = "1";  
11467 - graph.currentEdgeStyle["rounded"] = "1";  
11468 - } else {  
11469 - graph.currentVertexStyle["rounded"] = "0";  
11470 - graph.currentEdgeStyle["rounded"] = "1";  
11471 - }  
11472 -  
11473 - if (curved) {  
11474 - graph.currentEdgeStyle["curved"] = "1";  
11475 - } else {  
11476 - graph.currentEdgeStyle["curved"] = "0";  
11477 - }  
11478 -  
11479 - model.beginUpdate();  
11480 - try {  
11481 - updateCells(  
11482 - addKeys(commonStyle, defaultStyles.slice()),  
11483 - graphStyle,  
11484 - );  
11485 -  
11486 - var change = new ChangePageSetup(  
11487 - ui,  
11488 - graphStyle != null ? graphStyle.background : null,  
11489 - );  
11490 - change.ignoreImage = true;  
11491 - model.execute(change);  
11492 -  
11493 - model.execute(  
11494 - new ChangeGridColor(  
11495 - ui,  
11496 - graphStyle != null && graphStyle.gridColor != null  
11497 - ? graphStyle.gridColor  
11498 - : gridColor,  
11499 - ),  
11500 - );  
11501 - } finally {  
11502 - model.endUpdate();  
11503 - }  
11504 - }),  
11505 - );  
11506 -  
11507 - mxEvent.addListener(  
11508 - panel,  
11509 - "mouseenter",  
11510 - mxUtils.bind(this, function (evt) {  
11511 - var prev = graph.getCellStyle;  
11512 - var prevBg = graph.background;  
11513 - var prevGrid = graph.view.gridColor;  
11514 -  
11515 - graph.background =  
11516 - graphStyle != null ? graphStyle.background : null;  
11517 - graph.view.gridColor =  
11518 - graphStyle != null && graphStyle.gridColor != null  
11519 - ? graphStyle.gridColor  
11520 - : gridColor;  
11521 -  
11522 - graph.getCellStyle = function (cell, resolve) {  
11523 - resolve = resolve != null ? resolve : true;  
11524 - var result = mxUtils.clone(prev.apply(this, arguments));  
11525 -  
11526 - var defaultStyle = graph.stylesheet.getDefaultVertexStyle();  
11527 - var appliedStyle = vertexStyle;  
11528 -  
11529 - if (model.isEdge(cell)) {  
11530 - defaultStyle = graph.stylesheet.getDefaultEdgeStyle();  
11531 - appliedStyle = edgeStyle;  
11532 - }  
11533 -  
11534 - removeStyles(result, defaultStyles, defaultStyle);  
11535 - applyStyle(commonStyle, result, cell, graphStyle);  
11536 - applyStyle(appliedStyle, result, cell, graphStyle);  
11537 -  
11538 - if (resolve) {  
11539 - result = this.postProcessCellStyle(cell, result);  
11540 - }  
11541 -  
11542 - return result;  
11543 - };  
11544 -  
11545 - graph.refresh();  
11546 - graph.getCellStyle = prev;  
11547 - graph.background = prevBg;  
11548 - graph.view.gridColor = prevGrid;  
11549 - }),  
11550 - );  
11551 -  
11552 - mxEvent.addListener(  
11553 - panel,  
11554 - "mouseleave",  
11555 - mxUtils.bind(this, function (evt) {  
11556 - graph.refresh();  
11557 - }),  
11558 - );  
11559 -  
11560 - // Workaround for broken cache in IE11  
11561 - if (!mxClient.IS_IE && !mxClient.IS_IE11) {  
11562 - this.format.cachedStyleEntries[index] = panel;  
11563 - }  
11564 - }  
11565 -  
11566 - entries.appendChild(panel);  
11567 - },  
11568 - );  
11569 -  
11570 - // Maximum palettes to switch the switcher  
11571 - var maxEntries = 10;  
11572 - var pageCount = Math.ceil(Editor.styles.length / maxEntries);  
11573 - this.format.currentStylePage =  
11574 - this.format.currentStylePage != null ? this.format.currentStylePage : 0;  
11575 - var dots = [];  
11576 -  
11577 - var addEntries = mxUtils.bind(this, function () {  
11578 - if (dots.length > 0) {  
11579 - dots[this.format.currentStylePage].style.background = "#84d7ff";  
11580 - }  
11581 -  
11582 - for (  
11583 - var i = this.format.currentStylePage * maxEntries;  
11584 - i <  
11585 - Math.min(  
11586 - (this.format.currentStylePage + 1) * maxEntries,  
11587 - Editor.styles.length  
11588 - );  
11589 - i++  
11590 - ) {  
11591 - var s = Editor.styles[i];  
11592 - addEntry(s.commonStyle, s.vertexStyle, s.edgeStyle, s.graph, i);  
11593 - }  
11594 - });  
11595 -  
11596 - var selectPage = mxUtils.bind(this, function (index) {  
11597 - if (index >= 0 && index < pageCount) {  
11598 - dots[this.format.currentStylePage].style.background = "transparent";  
11599 - entries.innerHTML = "";  
11600 - this.format.currentStylePage = index;  
11601 - addEntries();  
11602 - }  
11603 - });  
11604 -  
11605 - if (pageCount > 1) {  
11606 - // Selector  
11607 - var switcher = document.createElement("div");  
11608 - switcher.style.whiteSpace = "nowrap";  
11609 - switcher.style.position = "relative";  
11610 - switcher.style.textAlign = "center";  
11611 - switcher.style.paddingTop = "4px";  
11612 - switcher.style.width = "210px";  
11613 -  
11614 - div.style.paddingBottom = "8px";  
11615 -  
11616 - for (var i = 0; i < pageCount; i++) {  
11617 - var dot = document.createElement("div");  
11618 - dot.style.display = "inline-block";  
11619 - dot.style.width = "6px";  
11620 - dot.style.height = "6px";  
11621 - dot.style.marginLeft = "4px";  
11622 - dot.style.marginRight = "3px";  
11623 - dot.style.borderRadius = "3px";  
11624 - dot.style.cursor = "pointer";  
11625 - dot.style.background = "transparent";  
11626 - dot.style.border = "1px solid #b5b6b7";  
11627 -  
11628 - mxUtils.bind(this, function (index, elt) {  
11629 - mxEvent.addListener(  
11630 - dot,  
11631 - "click",  
11632 - mxUtils.bind(this, function () {  
11633 - selectPage(index);  
11634 - }),  
11635 - );  
11636 - })(i, dot);  
11637 -  
11638 - switcher.appendChild(dot);  
11639 - dots.push(dot);  
11640 - }  
11641 -  
11642 - div.appendChild(switcher);  
11643 - addEntries();  
11644 -  
11645 - if (pageCount < 15) {  
11646 - var left = document.createElement("div");  
11647 - left.style.position = "absolute";  
11648 - left.style.left = "0px";  
11649 - left.style.top = "0px";  
11650 - left.style.bottom = "0px";  
11651 - left.style.width = "24px";  
11652 - left.style.height = "24px";  
11653 - left.style.margin = "0px";  
11654 - left.style.cursor = "pointer";  
11655 - left.style.opacity = "0.5";  
11656 - left.style.backgroundRepeat = "no-repeat";  
11657 - left.style.backgroundPosition = "center center";  
11658 - left.style.backgroundSize = "24px 24px";  
11659 - left.style.backgroundImage = "url(" + Editor.previousImage + ")";  
11660 -  
11661 - if (Editor.isDarkMode()) {  
11662 - left.style.filter = "invert(100%)";  
11663 - }  
11664 -  
11665 - var right = left.cloneNode(false);  
11666 - right.style.backgroundImage = "url(" + Editor.nextImage + ")";  
11667 - right.style.left = "";  
11668 - right.style.right = "2px";  
11669 -  
11670 - switcher.appendChild(left);  
11671 - switcher.appendChild(right);  
11672 -  
11673 - mxEvent.addListener(  
11674 - left,  
11675 - "click",  
11676 - mxUtils.bind(this, function () {  
11677 - selectPage(mxUtils.mod(this.format.currentStylePage - 1, pageCount));  
11678 - }),  
11679 - );  
11680 -  
11681 - mxEvent.addListener(  
11682 - right,  
11683 - "click",  
11684 - mxUtils.bind(this, function () {  
11685 - selectPage(mxUtils.mod(this.format.currentStylePage + 1, pageCount));  
11686 - }),  
11687 - );  
11688 -  
11689 - // Hover state  
11690 - function addHoverState(elt) {  
11691 - mxEvent.addListener(elt, "mouseenter", function () {  
11692 - elt.style.opacity = "1";  
11693 - });  
11694 - mxEvent.addListener(elt, "mouseleave", function () {  
11695 - elt.style.opacity = "0.5";  
11696 - });  
11697 - }  
11698 -  
11699 - addHoverState(left);  
11700 - addHoverState(right);  
11701 - }  
11702 - } else {  
11703 - addEntries();  
11704 - }  
11705 -  
11706 - return div;  
11707 -};  
11708 -  
11709 -/**  
11710 - * Adds the label menu items to the given menu and parent.  
11711 - */  
11712 -DiagramStylePanel.prototype.destroy = function () {  
11713 - BaseFormatPanel.prototype.destroy.apply(this, arguments);  
11714 -  
11715 - if (this.darkModeChangedListener) {  
11716 - this.editorUi.removeListener(this.darkModeChangedListener);  
11717 - this.darkModeChangedListener = null;  
11718 - }  
11719 -};  
11720 -  
11721 -/**  
11722 - * Adds the label menu items to the given menu and parent.  
11723 - */  
11724 -DiagramFormatPanel = function (format, editorUi, container) {  
11725 - BaseFormatPanel.call(this, format, editorUi, container);  
11726 - this.init();  
11727 -};  
11728 -  
11729 -mxUtils.extend(DiagramFormatPanel, BaseFormatPanel);  
11730 -  
11731 -/**  
11732 - * Switch to disable page view.  
11733 - */  
11734 -DiagramFormatPanel.showPageView = true;  
11735 -  
11736 -/**  
11737 - * Specifies if the background image option should be shown. Default is true.  
11738 - */  
11739 -DiagramFormatPanel.prototype.showBackgroundImageOption = true;  
11740 -  
11741 -/**  
11742 - * Adds the label menu items to the given menu and parent.  
11743 - */  
11744 -DiagramFormatPanel.prototype.init = function () {  
11745 - var ui = this.editorUi;  
11746 - var editor = ui.editor;  
11747 - var graph = editor.graph;  
11748 -  
11749 - this.container.appendChild(this.addView(this.createPanel()));  
11750 -  
11751 - if (graph.isEnabled()) {  
11752 - this.container.appendChild(this.addOptions(this.createPanel()));  
11753 - this.container.appendChild(this.addPaperSize(this.createPanel()));  
11754 - this.container.appendChild(this.addStyleOps(this.createPanel()));  
11755 - }  
11756 -};  
11757 -  
11758 -/**  
11759 - * Adds the label menu items to the given menu and parent.  
11760 - */  
11761 -DiagramFormatPanel.prototype.addView = function (div) {  
11762 - var ui = this.editorUi;  
11763 - var editor = ui.editor;  
11764 - var graph = editor.graph;  
11765 -  
11766 - div.appendChild(this.createTitle(mxResources.get("view")));  
11767 -  
11768 - // Grid  
11769 - this.addGridOption(div);  
11770 -  
11771 - // Page View  
11772 - if (DiagramFormatPanel.showPageView) {  
11773 - div.appendChild(  
11774 - this.createOption(  
11775 - mxResources.get("pageView"),  
11776 - function () {  
11777 - return graph.pageVisible;  
11778 - },  
11779 - function (checked) {  
11780 - ui.actions.get("pageView").funct();  
11781 - },  
11782 - {  
11783 - install: function (apply) {  
11784 - this.listener = function () {  
11785 - apply(graph.pageVisible);  
11786 - };  
11787 -  
11788 - ui.addListener("pageViewChanged", this.listener);  
11789 - },  
11790 - destroy: function () {  
11791 - ui.removeListener(this.listener);  
11792 - },  
11793 - },  
11794 - ),  
11795 - );  
11796 - }  
11797 -  
11798 - if (graph.isEnabled()) {  
11799 - // Background  
11800 - var bg = this.createColorOption(  
11801 - mxResources.get("background"),  
11802 - function () {  
11803 - return graph.background;  
11804 - },  
11805 - function (color) {  
11806 - var change = new ChangePageSetup(ui, color);  
11807 - change.ignoreImage = color != null && color != mxConstants.NONE;  
11808 -  
11809 - graph.model.execute(change);  
11810 - },  
11811 - "#ffffff",  
11812 - {  
11813 - install: function (apply) {  
11814 - this.listener = function () {  
11815 - apply(graph.background);  
11816 - };  
11817 -  
11818 - ui.addListener("backgroundColorChanged", this.listener);  
11819 - },  
11820 - destroy: function () {  
11821 - ui.removeListener(this.listener);  
11822 - },  
11823 - },  
11824 - );  
11825 -  
11826 - if (this.showBackgroundImageOption) {  
11827 - var label = bg.getElementsByTagName("span")[0];  
11828 - label.style.display = "inline-block";  
11829 - label.style.textOverflow = "ellipsis";  
11830 - label.style.overflow = "hidden";  
11831 - label.style.maxWidth = "68px";  
11832 -  
11833 - if (mxClient.IS_FF) {  
11834 - label.style.marginTop = "1px";  
11835 - }  
11836 -  
11837 - var btn = mxUtils.button(mxResources.get("change"), function (evt) {  
11838 - ui.showBackgroundImageDialog(null, ui.editor.graph.backgroundImage);  
11839 - mxEvent.consume(evt);  
11840 - });  
11841 -  
11842 - btn.className = "geColorBtn";  
11843 - btn.style.position = "absolute";  
11844 - btn.style.marginTop = "-3px";  
11845 - btn.style.height = "22px";  
11846 - btn.style.left = "118px";  
11847 - btn.style.width = "56px";  
11848 -  
11849 - bg.appendChild(btn);  
11850 - }  
11851 -  
11852 - div.appendChild(bg);  
11853 - }  
11854 -  
11855 - return div;  
11856 -};  
11857 -  
11858 -/**  
11859 - * Adds the label menu items to the given menu and parent.  
11860 - */  
11861 -DiagramFormatPanel.prototype.addOptions = function (div) {  
11862 - var ui = this.editorUi;  
11863 - var editor = ui.editor;  
11864 - var graph = editor.graph;  
11865 -  
11866 - div.appendChild(this.createTitle(mxResources.get("options")));  
11867 -  
11868 - if (graph.isEnabled()) {  
11869 - // Connection arrows  
11870 - div.appendChild(  
11871 - this.createOption(  
11872 - mxResources.get("connectionArrows"),  
11873 - function () {  
11874 - return graph.connectionArrowsEnabled;  
11875 - },  
11876 - function (checked) {  
11877 - ui.actions.get("connectionArrows").funct();  
11878 - },  
11879 - {  
11880 - install: function (apply) {  
11881 - this.listener = function () {  
11882 - apply(graph.connectionArrowsEnabled);  
11883 - };  
11884 -  
11885 - ui.addListener("connectionArrowsChanged", this.listener);  
11886 - },  
11887 - destroy: function () {  
11888 - ui.removeListener(this.listener);  
11889 - },  
11890 - },  
11891 - ),  
11892 - );  
11893 -  
11894 - // Connection points  
11895 - div.appendChild(  
11896 - this.createOption(  
11897 - mxResources.get("connectionPoints"),  
11898 - function () {  
11899 - return graph.connectionHandler.isEnabled();  
11900 - },  
11901 - function (checked) {  
11902 - ui.actions.get("connectionPoints").funct();  
11903 - },  
11904 - {  
11905 - install: function (apply) {  
11906 - this.listener = function () {  
11907 - apply(graph.connectionHandler.isEnabled());  
11908 - };  
11909 -  
11910 - ui.addListener("connectionPointsChanged", this.listener);  
11911 - },  
11912 - destroy: function () {  
11913 - ui.removeListener(this.listener);  
11914 - },  
11915 - },  
11916 - ),  
11917 - );  
11918 -  
11919 - // Guides  
11920 - div.appendChild(  
11921 - this.createOption(  
11922 - mxResources.get("guides"),  
11923 - function () {  
11924 - return graph.graphHandler.guidesEnabled;  
11925 - },  
11926 - function (checked) {  
11927 - ui.actions.get("guides").funct();  
11928 - },  
11929 - {  
11930 - install: function (apply) {  
11931 - this.listener = function () {  
11932 - apply(graph.graphHandler.guidesEnabled);  
11933 - };  
11934 -  
11935 - ui.addListener("guidesEnabledChanged", this.listener);  
11936 - },  
11937 - destroy: function () {  
11938 - ui.removeListener(this.listener);  
11939 - },  
11940 - },  
11941 - ),  
11942 - );  
11943 - }  
11944 -  
11945 - return div;  
11946 -};  
11947 -  
11948 -/**  
11949 - *  
11950 - */  
11951 -DiagramFormatPanel.prototype.addGridOption = function (container) {  
11952 - var fPanel = this;  
11953 - var ui = this.editorUi;  
11954 - var graph = ui.editor.graph;  
11955 -  
11956 - var input = document.createElement("input");  
11957 - input.style.position = "absolute";  
11958 - input.style.textAlign = "right";  
11959 - input.style.width = "48px";  
11960 - input.style.marginTop = "-2px";  
11961 - input.style.height = "21px";  
11962 - input.style.border = "1px solid rgb(160, 160, 160)";  
11963 - input.style.borderRadius = "4px";  
11964 - input.style.boxSizing = "border-box";  
11965 - input.value = this.inUnit(graph.getGridSize()) + " " + this.getUnit();  
11966 -  
11967 - var stepper = this.createStepper(  
11968 - input,  
11969 - update,  
11970 - this.getUnitStep(),  
11971 - null,  
11972 - null,  
11973 - null,  
11974 - this.isFloatUnit(),  
11975 - );  
11976 - input.style.display = graph.isGridEnabled() ? "" : "none";  
11977 - stepper.style.display = input.style.display;  
11978 -  
11979 - mxEvent.addListener(input, "keydown", function (e) {  
11980 - if (e.keyCode == 13) {  
11981 - graph.container.focus();  
11982 - mxEvent.consume(e);  
11983 - } else if (e.keyCode == 27) {  
11984 - input.value = graph.getGridSize();  
11985 - graph.container.focus();  
11986 - mxEvent.consume(e);  
11987 - }  
11988 - });  
11989 -  
11990 - function update(evt) {  
11991 - var value = fPanel.isFloatUnit()  
11992 - ? parseFloat(input.value)  
11993 - : parseInt(input.value);  
11994 - value = fPanel.fromUnit(  
11995 - Math.max(fPanel.inUnit(1), isNaN(value) ? fPanel.inUnit(10) : value),  
11996 - );  
11997 -  
11998 - if (value != graph.getGridSize()) {  
11999 - mxGraph.prototype.gridSize = value;  
12000 - graph.setGridSize(value);  
12001 - }  
12002 -  
12003 - input.value = fPanel.inUnit(value) + " " + fPanel.getUnit();  
12004 - mxEvent.consume(evt);  
12005 - }  
12006 -  
12007 - mxEvent.addListener(input, "blur", update);  
12008 - mxEvent.addListener(input, "change", update);  
12009 -  
12010 - input.style.right = "78px";  
12011 - stepper.style.marginTop = "-17px";  
12012 - stepper.style.right = "66px";  
12013 -  
12014 - var panel = this.createColorOption(  
12015 - mxResources.get("grid"),  
12016 - function () {  
12017 - var color = graph.view.gridColor;  
12018 -  
12019 - return graph.isGridEnabled() ? color : null;  
12020 - },  
12021 - function (color) {  
12022 - var enabled = graph.isGridEnabled();  
12023 -  
12024 - if (color == mxConstants.NONE) {  
12025 - graph.setGridEnabled(false);  
12026 - } else {  
12027 - graph.setGridEnabled(true);  
12028 - ui.setGridColor(color);  
12029 - }  
12030 -  
12031 - input.style.display = graph.isGridEnabled() ? "" : "none";  
12032 - stepper.style.display = input.style.display;  
12033 -  
12034 - if (enabled != graph.isGridEnabled()) {  
12035 - graph.defaultGridEnabled = graph.isGridEnabled();  
12036 - ui.fireEvent(new mxEventObject("gridEnabledChanged"));  
12037 - }  
12038 - },  
12039 - Editor.isDarkMode()  
12040 - ? graph.view.defaultDarkGridColor  
12041 - : graph.view.defaultGridColor,  
12042 - {  
12043 - install: function (apply) {  
12044 - this.listener = function () {  
12045 - apply(graph.isGridEnabled() ? graph.view.gridColor : null);  
12046 - };  
12047 -  
12048 - ui.addListener("gridColorChanged", this.listener);  
12049 - ui.addListener("gridEnabledChanged", this.listener);  
12050 - },  
12051 - destroy: function () {  
12052 - ui.removeListener(this.listener);  
12053 - },  
12054 - },  
12055 - );  
12056 -  
12057 - panel.appendChild(input);  
12058 - panel.appendChild(stepper);  
12059 - container.appendChild(panel);  
12060 -};  
12061 -  
12062 -/**  
12063 - * Adds the label menu items to the given menu and parent.  
12064 - */  
12065 -DiagramFormatPanel.prototype.addDocumentProperties = function (div) {  
12066 - // Hook for subclassers  
12067 - var ui = this.editorUi;  
12068 - var editor = ui.editor;  
12069 - var graph = editor.graph;  
12070 -  
12071 - div.appendChild(this.createTitle(mxResources.get("options")));  
12072 -  
12073 - return div;  
12074 -};  
12075 -  
12076 -/**  
12077 - * Adds the label menu items to the given menu and parent.  
12078 - */  
12079 -DiagramFormatPanel.prototype.addPaperSize = function (div) {  
12080 - var ui = this.editorUi;  
12081 - var editor = ui.editor;  
12082 - var graph = editor.graph;  
12083 -  
12084 - div.appendChild(this.createTitle(mxResources.get("paperSize")));  
12085 -  
12086 - var accessor = PageSetupDialog.addPageFormatPanel(  
12087 - div,  
12088 - "formatpanel",  
12089 - graph.pageFormat,  
12090 - function (pageFormat) {  
12091 - if (  
12092 - graph.pageFormat == null ||  
12093 - graph.pageFormat.width != pageFormat.width ||  
12094 - graph.pageFormat.height != pageFormat.height  
12095 - ) {  
12096 - var change = new ChangePageSetup(ui, null, null, pageFormat);  
12097 - change.ignoreColor = true;  
12098 - change.ignoreImage = true;  
12099 -  
12100 - graph.model.execute(change);  
12101 - }  
12102 - },  
12103 - );  
12104 -  
12105 - this.addKeyHandler(accessor.widthInput, function () {  
12106 - accessor.set(graph.pageFormat);  
12107 - });  
12108 - this.addKeyHandler(accessor.heightInput, function () {  
12109 - accessor.set(graph.pageFormat);  
12110 - });  
12111 -  
12112 - var listener = function () {  
12113 - accessor.set(graph.pageFormat);  
12114 - };  
12115 -  
12116 - ui.addListener("pageFormatChanged", listener);  
12117 - this.listeners.push({  
12118 - destroy: function () {  
12119 - ui.removeListener(listener);  
12120 - },  
12121 - });  
12122 -  
12123 - graph.getModel().addListener(mxEvent.CHANGE, listener);  
12124 - this.listeners.push({  
12125 - destroy: function () {  
12126 - graph.getModel().removeListener(listener);  
12127 - },  
12128 - });  
12129 -  
12130 - return div;  
12131 -};  
12132 -  
12133 -/**  
12134 - * Adds the label menu items to the given menu and parent.  
12135 - */  
12136 -DiagramFormatPanel.prototype.addStyleOps = function (div) {  
12137 - this.addActions(div, ["editData"]);  
12138 - this.addActions(div, ["clearDefaultStyle"]);  
12139 -  
12140 - return div;  
12141 -};  
12142 -  
12143 -/**  
12144 - * Adds the label menu items to the given menu and parent.  
12145 - */  
12146 -DiagramFormatPanel.prototype.destroy = function () {  
12147 - BaseFormatPanel.prototype.destroy.apply(this, arguments);  
12148 -  
12149 - if (this.gridEnabledListener) {  
12150 - this.editorUi.removeListener(this.gridEnabledListener);  
12151 - this.gridEnabledListener = null;  
12152 - }  
12153 -};  
12154 -  
12155 -// TODO UseLayUi  
12156 -class UseLayUi {  
12157 -  
12158 - constructor() {  
12159 - }  
12160 -  
12161 - static isFunction = fn => {  
12162 - const result = Object.prototype.toString.call(fn)  
12163 - return result === '[object Function]' || result === '[object AsyncFunction]'  
12164 - }  
12165 -  
12166 - static dynamicAttr = (attr, value) => value ? `${attr}="${value}"` : ''  
12167 -  
12168 - /**  
12169 - * @description format data source to tree structure  
12170 - * @param {object[]} data - data source  
12171 - * @param {Function} [customSetValue = ((record) => ({ id: record.id, title: record.name }))] customSetValue - custom set value && need return value  
12172 - * @param {string} [idField = 'id'] idField - id field  
12173 - * @param {string} [titleField = 'name'] titleField - titleField field  
12174 - * @param {string} [childrenField = 'children'] childrenField - children field  
12175 - * @returns {object[]}  
12176 - */  
12177 - static formatTreeDataSource(data, customSetValue, idField = 'id', titleField = 'name', childrenField = 'children') {  
12178 - if (!Array.isArray(data) && !data.length) return []  
12179 - customSetValue = customSetValue || ((record) => ({ id: record[idField], title: record[titleField] }))  
12180 - const fn = (data) => {  
12181 - return data.reduce((prev, next = {}) => {  
12182 - let children = []  
12183 - if (next[childrenField] && next[childrenField].length) {  
12184 - children = fn(next.children)  
12185 - }  
12186 - return [...prev, { children, ...customSetValue(next) }]  
12187 - }, [])  
12188 - }  
12189 - return fn(data)  
12190 - }  
12191 -  
12192 - /**  
12193 - * @description 通过ID 找到对应节点  
12194 - * @param dataSource  
12195 - * @param value  
12196 - * @param findField  
12197 - * @param childrenField  
12198 - * @returns {any}  
12199 - */  
12200 - static findTreeObjectByField(dataSource, value, findField = 'id', childrenField = 'children') {  
12201 - const map = new Map()  
12202 -  
12203 - function find(array) {  
12204 - for (const item of array) {  
12205 - map.set(item[findField], item)  
12206 - if (map.has(item[value])) {  
12207 - break  
12208 - }  
12209 - if (item[childrenField] && Array.isArray(item[childrenField])) {  
12210 - find(item[childrenField])  
12211 - }  
12212 - }  
12213 - }  
12214 -  
12215 - if (Array.isArray(dataSource)) {  
12216 - find(dataSource)  
12217 - return map.get(value)  
12218 - }  
12219 - }  
12220 -  
12221 - /**  
12222 - * @description generator options template 生产下拉选项模板  
12223 - * @param options  
12224 - * @param {object[]} [dataSource] options.dataSource  
12225 - * @param {boolean} [addPlaceholderOption = true] options.addPlaceholderOption  
12226 - * @param {string} [labelField = 'name'] options.labelField  
12227 - * @param {string} [valueField = 'name'] options.valueField  
12228 - * @returns {*}  
12229 - */  
12230 - static generateOptionTemplate(options) {  
12231 - const { dataSource = [], addPlaceholderOption = true, labelField = 'name', valueField = 'id' } = options  
12232 - let { renderFn } = options  
12233 - renderFn = renderFn || ((record) => {  
12234 - if (typeof record === 'object') {  
12235 - return `<option value="${record[valueField]}" ${record.disabled ? 'disabled=""' : ''}>${record[labelField]}</option>`  
12236 - } else {  
12237 - return `<option value="${record}">${record}</option>`  
12238 - }  
12239 - })  
12240 - const optionsList = dataSource.map(renderFn)  
12241 - if (addPlaceholderOption) optionsList.unshift('<option value="">请选择</option>')  
12242 - return optionsList.join('')  
12243 - }  
12244 -  
12245 - /**  
12246 - * @description create single usage controls  
12247 - * @param {string} content  
12248 - */  
12249 - static createSingleUseFormItem(content, props = '') {  
12250 - return `  
12251 - <div class="layui-form" ${props}>  
12252 - ${content}  
12253 - </div>  
12254 - `  
12255 - }  
12256 -  
12257 - /**  
12258 - * @description 判断节点是否在某个节点之内  
12259 - * @param {HTMLElement} parentNode  
12260 - * @param {HTMLElement} childrenNode  
12261 - * @param {boolean} [containsItsOwn = false] containsItsOwn - 是否包含自身  
12262 - * @returns {boolean|*}  
12263 - */  
12264 - static isInNode(parentNode, childrenNode, containsItsOwn = false) {  
12265 - return parentNode === childrenNode  
12266 - ? containsItsOwn  
12267 - : parentNode.contains(childrenNode)  
12268 - }  
12269 -  
12270 - /**  
12271 - * @description create layui single select template  
12272 - * @param {string} [options.layFilter] options.layFilter  
12273 - * @param {string} [options.bindValueFiled] options.bindValueFiled  
12274 - * @param {string} [options.layVerify] options.layVerify  
12275 - * @param {string} [options.layVerType] options.layVerType  
12276 - * @param {Function} [options.renderFn] options.renderFn  
12277 - * @param {Array} [options.dataSource = []] options.dataSource  
12278 - * @param {string} [options.valueField = id] options.valueField  
12279 - * @param {string} [options.labelField = name] options.labelField - dataSource  
12280 - * @param {string} [options.label = 选择框] options.label - select label  
12281 - * @param {string} [options.className = ''] options.className - css class name  
12282 - * @param {Function} [options.onClick] options.onClick - select on click  
12283 - * @returns {string}  
12284 - */  
12285 - static createSelect(options) {  
12286 - const { form, jquery: $ } = layui  
12287 -  
12288 - const {  
12289 - elem,  
12290 - layFilter,  
12291 - bindValueFiled,  
12292 - layVerify,  
12293 - layVerType,  
12294 - renderFn,  
12295 - dataSource = [],  
12296 - valueField = 'id',  
12297 - labelField = 'name',  
12298 - label = '',  
12299 - className = '',  
12300 - onClick,  
12301 - singleUsage = true,  
12302 - } = options  
12303 -  
12304 - const formatDataSource = (dataSource) => {  
12305 - return dataSource.map(record => {  
12306 - return {  
12307 - value: record[valueField],  
12308 - label: record[labelField],  
12309 - }  
12310 - })  
12311 - }  
12312 -  
12313 - const getOptionList = (dataSource) => {  
12314 - if (renderFn && this.isFunction(renderFn)) {  
12315 - return dataSource.map(record => renderFn(record))  
12316 - }  
12317 - return formatDataSource(dataSource).map(record => {  
12318 - return `<option value="${record[valueField]}" ${record.disable ? 'disabled=""' : ''}>${record[labelField]}</option>`  
12319 - })  
12320 - }  
12321 -  
12322 - const generateOptionTemplate = (dataSource, addPlaceholderOption = true) => {  
12323 - const optionsList = getOptionList(dataSource)  
12324 - if (addPlaceholderOption) optionsList.unshift('<option value="">请选择</option>')  
12325 - return optionsList.join('')  
12326 - }  
12327 -  
12328 - if (layFilter) {  
12329 - form.on(`select(${layFilter})`, (data) => {  
12330 - if (onClick && this.isFunction(onClick)) {  
12331 - onClick(data)  
12332 - }  
12333 - })  
12334 - }  
12335 -  
12336 - let template = `  
12337 - <div class="layui-form-item ${className}">  
12338 - <label class="layui-form-label">${label}</label>  
12339 - <div class="layui-input-block">  
12340 - <select name="${bindValueFiled}" ${this.dynamicAttr('lay-filter', layFilter)} ${this.dynamicAttr('lay-verify', layVerify)} ${this.dynamicAttr('lay-verType', layVerType)}>  
12341 - ${generateOptionTemplate(dataSource)}  
12342 - </select>  
12343 - </div>  
12344 - </div>`  
12345 -  
12346 - const updateOptions = (dataSource) => {  
12347 - if (!elem) return  
12348 - const optionList = generateOptionTemplate(dataSource)  
12349 - $(elem).find('select').html(optionList)  
12350 - form.render('select', layFilter)  
12351 - }  
12352 -  
12353 - template = singleUsage ? UseLayUi.createSingleUseFormItem(template, '') : template  
12354 -  
12355 -  
12356 - function mount() {  
12357 - if (elem) {  
12358 - UseLayUi.nextTick(() => {  
12359 - $(elem).html(template)  
12360 - })  
12361 - return { template, updateOptions }  
12362 - }  
12363 - return template  
12364 - }  
12365 -  
12366 - return mount()  
12367 - }  
12368 -  
12369 - // TODO Tree Select  
12370 - /**  
12371 - * @description create a tree select controls  
12372 - * @param {string} [options.layFilter] options.layFilter  
12373 - * @param {string} [options.label] options.label  
12374 - * @param {object} [options.treeProps] options.treeProps  
12375 - * @param {HTMLDivElement} [options.elem] options.elem  
12376 - * @param {boolean} [options.singleUsage = true] options.singleUsage  
12377 - * @param {Function} [options.customSetTree = ((record) => ({ id: record.id, title: record.name }))] options.customSetTree  
12378 - * @param {boolean} [options.autoFormatDataSource = true] options.autoFormatDataSource  
12379 - * @param {string} [options.layVerify] options.layVerify  
12380 - * @param {string} [options.layVerType] options.layVerType  
12381 - * @param {Function} [options.treeProps.onReady] options.treeProps.onReady  
12382 - */  
12383 - static createTreeSelect(options) {  
12384 - const CLASS_NAME = 'things-kit-tree-select'  
12385 - const SELECT_CLS = 'things-kit-tree-select__tree'  
12386 - const { tree, jquery: $, form } = layui  
12387 -  
12388 - const {  
12389 - layFilter,  
12390 - label,  
12391 - treeProps = {},  
12392 - elem,  
12393 - className = '',  
12394 - singleUsage = true,  
12395 - customSetTree = undefined,  
12396 - autoFormatDataSource = true,  
12397 - labelField = 'name',  
12398 - valueField = 'id',  
12399 - childrenField = 'children',  
12400 - layVerify,  
12401 - layVerType,  
12402 - } = options  
12403 -  
12404 - let { data = [], click, onReady } = treeProps  
12405 -  
12406 - let template = `  
12407 - <div class="layui-form-item ${CLASS_NAME} ${className}">  
12408 - <label class="layui-form-label">${label}</label>  
12409 - <div class="layui-input-block">  
12410 - <div class="layui-unselect layui-form-select ${SELECT_CLS}">  
12411 - <div class="layui-select-title">  
12412 - <span class="layui-input layui-unselect tree-select__label">请选择</span>  
12413 - <input ${this.dynamicAttr('lay-verify', layVerify)} ${this.dynamicAttr('lay-verType', layVerType)} type="text" style="visibility: hidden; position: absolute; top: 0" name="${layFilter}">  
12414 - <i class="layui-edge"></i>  
12415 - </div>  
12416 - <dl class="layui-anim layui-anim-upbit">  
12417 - <dd>  
12418 - <ul class="tree-select__tree-mount"></ul>  
12419 - </dd>  
12420 - </dl>  
12421 - </div>  
12422 - </div>  
12423 - </div>`  
12424 -  
12425 - template = singleUsage ? UseLayUi.createSingleUseFormItem(template) : template  
12426 -  
12427 - /**  
12428 - * @description 设置下拉树值  
12429 - * @param {string} id - layui tree 树形结构 title字段  
12430 - * @param {string} title - layui tree 树形结构 id字段  
12431 - */  
12432 - function setValue({ id, title }) {  
12433 - $(elem)  
12434 - .find('.layui-form-select').removeClass('layui-form-selected').end()  
12435 - .find(".layui-select-title span").html(title).end()  
12436 - .find(`input[name='${layFilter}']`).val(id);  
12437 - }  
12438 -  
12439 - // init mount  
12440 - function mount() {  
12441 - // mount select container  
12442 - $(elem).html(template)  
12443 -  
12444 - // mount tree  
12445 - // UseLayUi.nextTick(() => {  
12446 - tree.render({  
12447 - ...treeProps,  
12448 - ...(autoFormatDataSource ? { data: UseLayUi.formatTreeDataSource(data, customSetTree, valueField, labelField, childrenField) } : {}),  
12449 - elem: $(elem).find('.tree-select__tree-mount'),  
12450 - click(node) {  
12451 - setValue(node.data)  
12452 - if (UseLayUi.isFunction(click)) click(node)  
12453 - },  
12454 - })  
12455 -  
12456 - // focus  
12457 - $(`.${SELECT_CLS}`).off('click')  
12458 - .on("click", ".layui-select-title", function (e) {  
12459 - $(document).find('.layui-form-select').removeClass('layui-form-selected')  
12460 - $(this).parents(`.${SELECT_CLS}`).toggleClass("layui-form-selected");  
12461 - layui.stope(e);  
12462 - })  
12463 - .on('click', '.layui-anim', (e) => {  
12464 - layui.stope(e)  
12465 - })  
12466 - .on("click", "dl i", function (e) {  
12467 - layui.stope(e);  
12468 - })  
12469 -  
12470 - // blur  
12471 - // $(document)  
12472 - // .on("click", function (e) {  
12473 - // const target = e.target  
12474 - // const parentNode = $(`.${CLASS_NAME} .tree-select__tree-mount`)  
12475 - // if (!parentNode) return  
12476 - // console.log($.contains(parentNode, target))  
12477 - // // const showClose = UseLayUi.isInNode(parentNode, target, true)  
12478 - // // if (showClose) return  
12479 - // // $(`.${ SELECT_CLS }`).removeClass("layui-form-selected")  
12480 - // });  
12481 -  
12482 - if (UseLayUi.isFunction(onReady)) {  
12483 - onReady(setValue)  
12484 - }  
12485 - // })  
12486 - form.render()  
12487 - }  
12488 -  
12489 - mount()  
12490 - }  
12491 -  
12492 - static createCheckBox(options) {  
12493 - const { jquery: $, form } = layui  
12494 - const CLASS_NAME = 'things-kit__checkbox'  
12495 - let {  
12496 - elem,  
12497 - singleUsage = true,  
12498 - layFilter = '',  
12499 - layVerify = '',  
12500 - label = '',  
12501 - laySkin = 'primary',  
12502 - dataSource = [],  
12503 - customSetValue,  
12504 - labelField = 'name',  
12505 - valueField = 'id',  
12506 - checkedField = 'checked',  
12507 - onChange,  
12508 - } = options  
12509 - customSetValue = customSetValue || ((record) => ({ value: record.id, title: record.name }))  
12510 - if (!Array.isArray(dataSource)) {  
12511 - dataSource = [dataSource]  
12512 - }  
12513 -  
12514 - function createOptions(dataSource) {  
12515 - return dataSource.map((record) => {  
12516 - return `<input  
12517 - type="checkbox" lay-skin="${laySkin}"  
12518 - ${UseLayUi.dynamicAttr('name', record[valueField])}  
12519 - ${UseLayUi.dynamicAttr('title', record[labelField])}  
12520 - ${UseLayUi.dynamicAttr('lay-filter', layFilter)}  
12521 - ${UseLayUi.dynamicAttr('lay-verify', layVerify)}  
12522 - ${UseLayUi.dynamicAttr('checked', record[checkedField])}  
12523 - >`  
12524 - })  
12525 - }  
12526 -  
12527 - let template = `  
12528 - <div class="layui-form-item ${CLASS_NAME}" >  
12529 - <label class="layui-form-label">${label}</label>  
12530 - <div class="layui-input-block">  
12531 - ${createOptions(dataSource).join('')}  
12532 - </div>  
12533 - </div>`  
12534 -  
12535 - template = singleUsage ? UseLayUi.createSingleUseFormItem(template) : template  
12536 -  
12537 - function mount() {  
12538 - if (!elem) return template  
12539 - $(elem).empty()  
12540 - $(elem).append(template)  
12541 - form.on(`checkbox(${layFilter})`, (data) => {  
12542 - onChange && (onChange(data))  
12543 - })  
12544 - form.render()  
12545 - }  
12546 -  
12547 - return mount()  
12548 - }  
12549 -  
12550 - /**  
12551 - * @description 创建树形组件  
12552 - * @param {object} options  
12553 - * @param {string | object} options.elem - 挂载节点  
12554 - * @param {object[]} [data] options.data - 数据源  
12555 - * @param {string} [id] options.id - 用于基础方法传参使用  
12556 - * @param {boolean} [showCheckbox = false] options.showCheckbox - 显示复选框  
12557 - * @param {boolean|string[]} [edit] options.edit - 是否开启节点操作  
12558 - * @param {boolean} [accordion = false] options.accordion - 手风琴  
12559 - * @param {boolean} [onlyIconControl = false] options.onlyIconControl - 仅允许左侧图标展开收缩  
12560 - * @param {boolean} [isJump = false] options.isJump - 跳转  
12561 - * @param {boolean} [showLine = true] options.showLine - 显示连接线  
12562 - * @param {object} [text] options.text - 自定义默认值  
12563 - * @param {string} [valueField = 'id'] options.valueField - 值字段  
12564 - * @param {string} [labelField = 'name'] options.labelField - 标签字段  
12565 - * @param {string} [childrenField = 'children'] options.childrenField - 后代节点字段  
12566 - * @param {Function} [customSetValue] options.customSetValue - 后代节点字段  
12567 - * @param {boolean} [autoFormatValue = true] options.autoFormatValue - 自动格式化值  
12568 - */  
12569 - static createTree(options = {}) {  
12570 - const { tree } = layui  
12571 - const {  
12572 - data = [],  
12573 - valueField = 'id',  
12574 - labelField = 'name',  
12575 - childrenField = 'children',  
12576 - customSetValue,  
12577 - autoFormatValue = true,  
12578 - } = options  
12579 - tree.render({  
12580 - ...options,  
12581 - data: autoFormatValue ? UseLayUi.formatTreeDataSource(data, customSetValue, valueField, labelField, childrenField) : data,  
12582 - })  
12583 - }  
12584 -  
12585 -  
12586 - static nextTick(fn) {  
12587 - new Promise((resolve) => {  
12588 - resolve()  
12589 - }).then(() => {  
12590 - fn()  
12591 - })  
12592 - }  
12593 -  
12594 - static msg(msg, options) {  
12595 - const { layer } = layui  
12596 - layer.msg(msg, options)  
12597 - }  
12598 -  
12599 - static successMsg(msg = '操作成功', options) {  
12600 - UseLayUi.msg(msg, { ...options, icon: 6 })  
12601 - }  
12602 -  
12603 - static errorMsg(msg = '操作失败', options) {  
12604 - UseLayUi.msg(msg, { ...options, icon: 5 })  
12605 - }  
12606 -  
12607 - static topMsg(msg, options, icon) {  
12608 - const { layer } = layui  
12609 - layer.msg(`<div style="padding: 20px; display: flex; align-items: center;"><i class="layui-layer-ico layui-layer-ico${icon}" style="width: 30px;height: 30px;"></i><span style="margin-left: 5px">${msg}</span></div>`, { ...options, type: 1, icon, time: 2000, })  
12610 - }  
12611 -  
12612 - static topSuccessMsg(msg = '操作成功', options) {  
12613 - this.topMsg(msg, options, 6)  
12614 - }  
12615 -  
12616 - static topErrorMsg(msg = '操作失败', options) {  
12617 - this.topMsg(msg, options, 5)  
12618 - }  
12619 -  
12620 - static topInfoMsg(msg = '提示', options) {  
12621 - this.topMsg(msg, options, 0)  
12622 - }  
12623 -}  
12624 -  
12625 -  
12626 -/**  
12627 - * @description use to function capture await throw error  
12628 - * @param promise  
12629 - * @param errorExt - Additional Information you can pass to the err object  
12630 - */  
12631 -function to(promise, errorExt) {  
12632 - return promise  
12633 - .then((data) => [null, data])  
12634 - .catch((err) => {  
12635 - if (errorExt) {  
12636 - const parsedError = Object.assign({}, err, errorExt)  
12637 - return [parsedError, undefined]  
12638 - }  
12639 - return [err, undefined]  
12640 - })  
12641 -}  
12642 -  
12643 -  
12644 -class EventCenter {  
12645 -  
12646 - /**  
12647 - * @description 调度中心  
12648 - * @type {Map<string, Function[]>}  
12649 - */  
12650 - eventStack  
12651 -  
12652 - /**  
12653 - * @description 实例化EventCenter  
12654 - */  
12655 - constructor() {  
12656 - this.eventStack = new Map()  
12657 - }  
12658 -  
12659 - /**  
12660 - * @description 监听事件  
12661 - * @param {string | number} eventName - 事件名  
12662 - * @param {Function} callback - 事件处理方法  
12663 - */  
12664 - on(eventName, callback) {  
12665 - if (this.eventStack.has(eventName)) {  
12666 - this.eventStack.get(eventName).push(callback)  
12667 - return  
12668 - }  
12669 - this.eventStack.set(eventName, [callback])  
12670 - }  
12671 -  
12672 - /**  
12673 - * @description 触发事件  
12674 - * @param {string | number} eventName - 事件名  
12675 - * @param {any} args - 参数  
12676 - */  
12677 - emit(eventName, ...args) {  
12678 - if (this.eventStack.has(eventName))  
12679 - this.eventStack.get(eventName).forEach(fn => fn(...args))  
12680 - }  
12681 -  
12682 - /**  
12683 - * @description 移除事件  
12684 - * @param {string} eventName - 时间名  
12685 - */  
12686 - off(eventName) {  
12687 - if (this.eventStack.has(eventName))  
12688 - this.eventStack.delete(eventName)  
12689 - }  
12690 -  
12691 - /**  
12692 - * @description 清除事件  
12693 - */  
12694 - clean(eventName) {  
12695 - this.eventStack.clear()  
12696 - }  
12697 -  
12698 -  
12699 -}  
12700 -  
12701 -class Ws {  
12702 - /**  
12703 - * @description url 连接地址  
12704 - */  
12705 - url  
12706 -  
12707 - /**  
12708 - * @description 协议  
12709 - */  
12710 - protocols  
12711 -  
12712 - /**  
12713 - * @description socket open时 拓展  
12714 - * @type {Function}  
12715 - * @param {Ws} instance - 实例  
12716 - */  
12717 - onopenCallback  
12718 -  
12719 - /**  
12720 - * @description socket error时 拓展  
12721 - * @type {Function}  
12722 - * @param {Ws} instance - 实例  
12723 - */  
12724 - onerrorCallback  
12725 -  
12726 - /**  
12727 - * @description socket close时 拓展  
12728 - * @type {Function}  
12729 - * @param {Ws} instance - 实例  
12730 - */  
12731 - oncloseCallback  
12732 -  
12733 - /**  
12734 - * @description socket message时 拓展  
12735 - * @type {Function}  
12736 - * @param {object} data - event.data message数据  
12737 - * @param {MessageEvent} event - event 事件对象  
12738 - * @param {Ws} instance - Ws 实例  
12739 - */  
12740 - onmessageCallback  
12741 -  
12742 - /**  
12743 - * @description socket 实例  
12744 - * @type {WebSocket}  
12745 - */  
12746 - ws  
12747 -  
12748 - /**  
12749 - * @description 重连标志  
12750 - * @type {boolean}  
12751 - */  
12752 - isReconnectionLoading = false  
12753 -  
12754 - /**  
12755 - * @description 重连定时器  
12756 - */  
12757 - timeId = null  
12758 -  
12759 - /**  
12760 - * @description 手动关闭标志位  
12761 - * @type {boolean}  
12762 - */  
12763 - isCustomClose = false  
12764 -  
12765 - /**  
12766 - * @description 消息队列 重新连接后会将之前断开期间发送的消息重新推送  
12767 - * @type {Array}  
12768 - */  
12769 - errorStack = []  
12770 -  
12771 - /**  
12772 - * @description 实例  
12773 - */  
12774 - static instance  
12775 -  
12776 - /**  
12777 - * @description 创建websocket实例  
12778 - * @param {string} option.url - 连接路径  
12779 - * @param {string} [option.protocols] option.protocols - 协议  
12780 - * @param {Function} [option.onopenCallback] option.onopenCallback - socket open时 拓展  
12781 - * @param {Function} [option.onerrorCallback] option.onerrorCallback - socket error时 拓展  
12782 - * @param {Function} [option.oncloseCallback] option.oncloseCallback - socket close时 拓展  
12783 - * @param {Function} [option.onmessageCallback] option.onmessageCallback - socket message时 拓展  
12784 - */  
12785 - constructor(option) {  
12786 - const { url, protocols, onopenCallback, onerrorCallback, oncloseCallback, onmessageCallback } = option  
12787 - if (!url) throw new Error('param url in Ws constructor is required')  
12788 - this.url = url  
12789 - this.protocols = protocols  
12790 - this.onopenCallback = onopenCallback  
12791 - this.onerrorCallback = onerrorCallback  
12792 - this.oncloseCallback = oncloseCallback  
12793 - this.onmessageCallback = onmessageCallback  
12794 - this.createWs()  
12795 - }  
12796 -  
12797 - /**  
12798 - * @description  
12799 - */  
12800 - createWs() {  
12801 - this.ws = new WebSocket(this.url, this.protocols)  
12802 - this.onopen()  
12803 - this.onerror()  
12804 - this.onclose()  
12805 - this.onmessage()  
12806 - }  
12807 -  
12808 - /**  
12809 - * @description 建立连接时  
12810 - */  
12811 - onopen() {  
12812 - this.ws.onopen = () => {  
12813 - this.errorStack.forEach(message => {  
12814 - this.send(message)  
12815 - })  
12816 - this.errorStack = []  
12817 - this.isReconnectionLoading = false  
12818 - if (typeof this.onopenCallback === 'function') this.onopenCallback(this)  
12819 - }  
12820 - }  
12821 -  
12822 - /**  
12823 - * @description 连接发生错误  
12824 - */  
12825 - onerror() {  
12826 - this.ws.onerror = (err) => {  
12827 - this.reconnection()  
12828 - this.isReconnectionLoading = false  
12829 - if (typeof this.onerrorCallback === 'function') this.onerrorCallback(this)  
12830 - }  
12831 - }  
12832 -  
12833 - /**  
12834 - * @description 连接断开时  
12835 - */  
12836 - onclose() {  
12837 - this.ws.onclose = () => {  
12838 - if (this.isCustomClose) return  
12839 -  
12840 - this.reconnection()  
12841 - this.isReconnectionLoading = false  
12842 -  
12843 - if (typeof this.oncloseCallback === 'function') this.oncloseCallback(this)  
12844 - }  
12845 - }  
12846 -  
12847 - /**  
12848 - * @description 接受消息  
12849 - */  
12850 - onmessage() {  
12851 - this.ws.onmessage = (event) => {  
12852 - try {  
12853 - const data = JSON.parse(event.data)  
12854 - if (typeof this.onmessageCallback === 'function') this.onmessageCallback(data, event, this)  
12855 -  
12856 - } catch (error) {  
12857 - // throw new Error(error)  
12858 - console.error(error)  
12859 - }  
12860 - }  
12861 - }  
12862 -  
12863 - /**  
12864 - * @description 断开重连  
12865 - */  
12866 - reconnection() {  
12867 - if (this.isReconnectionLoading) return  
12868 -  
12869 - this.isReconnectionLoading = true  
12870 - clearTimeout(this.timeId)  
12871 - this.timeId = setTimeout(() => {  
12872 - this.createWs()  
12873 - }, 60000)  
12874 - }  
12875 -  
12876 - /**  
12877 - * @description 发送消息  
12878 - */  
12879 - send(message) {  
12880 - if (!this.ws || this.ws.readyState !== 1) {  
12881 - this.errorStack.push(message)  
12882 - return  
12883 - }  
12884 -  
12885 - this.ws.send(message)  
12886 - }  
12887 -  
12888 - /**  
12889 - * @description 手动关闭  
12890 - */  
12891 - close() {  
12892 - this.isCustomClose = true  
12893 - this.ws.close()  
12894 - }  
12895 -  
12896 - /**  
12897 - * @description 手动开启  
12898 - */  
12899 - start() {  
12900 - this.isCustomClose = false  
12901 - this.reconnection()  
12902 - }  
12903 -  
12904 - /**  
12905 - * @description 销毁  
12906 - */  
12907 - destroy() {  
12908 - this.close()  
12909 - this.ws = null  
12910 - this.errorStack = null  
12911 - Ws.instance = null  
12912 - }  
12913 -  
12914 - /**  
12915 - * @description 单例模式  
12916 - * @param {string} option.url - 连接路径  
12917 - * @param {string} [option.protocols] option.protocols - 协议  
12918 - * @param {Function} [option.onopenCallback] option.onopenCallback - socket open时 拓展  
12919 - * @param {Function} [option.onerrorCallback] option.onerrorCallback - socket error时 拓展  
12920 - * @param {Function} [option.oncloseCallback] option.oncloseCallback - socket close时 拓展  
12921 - * @param {Function} [option.onmessageCallback] option.onmessageCallback - socket message时 拓展  
12922 - * @return {Ws} instance  
12923 - */  
12924 - static getInstance(option) {  
12925 - if (!this.instance) {  
12926 - this.instance = new Ws(option)  
12927 - }  
12928 - return this.instance  
12929 - }  
12930 -}  
12931 -  
12932 -/**  
12933 - * @description 切换页面时触发 /src/main/webapp/js/diagramly/Pages.js row: 461  
12934 - * @param editorUi  
12935 - * @param currentPage  
12936 - */  
12937 -function previewAction(editorUi, currentPage) {  
12938 - if (!editorUi.editor.graph.isLightboxView()) return  
12939 - DispatchCenter.getInstance(editorUi, currentPage)  
12940 -  
12941 - /**  
12942 - * @description 编辑模式下editor对象的editable为true  
12943 - * @param editorUi  
12944 - * @return {boolean}  
12945 - */  
12946 - function isPreviewMode(editorUi = {}) {  
12947 - const { editor: { editable } = {} } = editorUi  
12948 - return !!editable  
12949 - }  
12950 -}  
12951 -  
12952 -  
12953 -/**  
12954 - * @description 调度中心  
12955 - */  
12956 -class DispatchCenter {  
12957 -  
12958 - /**  
12959 - * @description 节点映射  
12960 - * @type {Map<string, Map<string, object>>}  
12961 - */  
12962 - nodeMapping  
12963 -  
12964 - /**  
12965 - * @description cmd ID 与 node 映射关系  
12966 - * @type {Map<number, string>}  
12967 - */  
12968 - cmdIdMapping = new Map()  
12969 -  
12970 - /**  
12971 - * @description  
12972 - */  
12973 - editorUi  
12974 -  
12975 - /**  
12976 - * @description 当前页信息  
12977 - */  
12978 - currentPage  
12979 -  
12980 - /**  
12981 - * @description 当前页中的所有cell  
12982 - */  
12983 - contentAllCell  
12984 -  
12985 - /**  
12986 - * @description 图源信息  
12987 - */  
12988 - graph  
12989 -  
12990 - /**  
12991 - * @description socket instance  
12992 - * @type {Ws}  
12993 - */  
12994 - socket  
12995 -  
12996 - /**  
12997 - * @description 事件总线  
12998 - * @type {EventCenter}  
12999 - */  
13000 - eventBus  
13001 -  
13002 - /**  
13003 - * @description 页面数据  
13004 - * @type {{dataSources: [], act: [], event: []}}  
13005 - */  
13006 - contentData  
13007 -  
13008 - /**  
13009 - * @description 处理数据源实例  
13010 - * @type {HandleDataSource}  
13011 - */  
13012 - dataSourceHandlerInstance  
13013 -  
13014 - /**  
13015 - * @description 处理数据动效实例  
13016 - * @type {HandleDynamicEffect}  
13017 - */  
13018 - dynamicEffectInstance  
13019 -  
13020 - /**  
13021 - * @description 处理数据交互实例  
13022 - * @type {HandleDataInteraction}  
13023 - */  
13024 - dataInteractionInstance  
13025 -  
13026 - /**  
13027 - * @description 更新队列  
13028 - * @type {UpdateQueue}  
13029 - */  
13030 - updateQueueInstance  
13031 -  
13032 - /**  
13033 - * @description cmd id  
13034 - */  
13035 - cmdIdPrimaryKey = 0  
13036 -  
13037 - /**  
13038 - * @description 当前实例  
13039 - * @type {DispatchCenter}  
13040 - */  
13041 - static instance  
13042 -  
13043 - /**  
13044 - * @description 原页面ID 原页面content id  
13045 - */  
13046 - static rawContentId  
13047 -  
13048 - /**  
13049 - * @description 判断事件监听器时候已经绑定过  
13050 - */  
13051 - static eventListenerIsExist = false  
13052 -  
13053 - static enumEventType = {  
13054 - DOWN: 'DOWN',  
13055 - UP: 'UP',  
13056 - SINGLE: 'SINGLE',  
13057 - DOUBLE: 'DOUBLE',  
13058 - }  
13059 -  
13060 - static enumDynamicEffectType = {  
13061 - DISPLAY: 'DISPLAY',  
13062 - FLASH: 'FLASH',  
13063 - ROTATE: 'ROTATE',  
13064 - SWITCH: 'SWITCH',  
13065 - }  
13066 -  
13067 - static enumPageType = {  
13068 - PAGE: 'PAGE',  
13069 - LINK: 'LINK',  
13070 - PROPS: 'PROPS',  
13071 - PARAMS_SETTING: 'PARAMS_SETTING'  
13072 - }  
13073 -  
13074 -  
13075 - constructor(editorUi, currentPage) {  
13076 - this.nodeMapping = new Map()  
13077 - this.editorUi = editorUi  
13078 - this.init(editorUi, currentPage)  
13079 - }  
13080 -  
13081 - /**  
13082 - * @description 初始化实例  
13083 - * @param editorUi  
13084 - * @param currentPage  
13085 - */  
13086 - async init(editorUi, currentPage) {  
13087 - this.createEventBus()  
13088 - this.saveContentInfo(editorUi, currentPage)  
13089 - this.connectSocket()  
13090 - await this.getContentDataNode()  
13091 - this.dataSourceHandlerInstance = new HandleDataSource(this)  
13092 - this.dataInteractionInstance = new HandleDataInteraction(this)  
13093 - this.dynamicEffectInstance = new HandleDynamicEffect(this)  
13094 - this.updateQueueInstance = new UpdateQueue(this)  
13095 - }  
13096 -  
13097 - /**  
13098 - * @description 建立socket连接  
13099 - */  
13100 - connectSocket() {  
13101 - Ws.instance?.destroy?.()  
13102 - this.socket = Ws.getInstance({ url: GLOBAL_WS_URL(), onmessageCallback: this.socketOnmessage })  
13103 - }  
13104 -  
13105 - /**  
13106 - * @description 处理webSocket消息  
13107 - * @param message  
13108 - * @param event  
13109 - * @param ws  
13110 - */  
13111 - socketOnmessage(message, event, ws) {  
13112 - const { subscriptionId, data } = message  
13113 - DispatchCenter.instance.publishEvent(subscriptionId, data, message, event, ws)  
13114 - }  
13115 -  
13116 - /**  
13117 - * @description 创建事件中心  
13118 - */  
13119 - createEventBus() {  
13120 - this.eventBus = new EventCenter()  
13121 - }  
13122 -  
13123 - /**  
13124 - * @description 保存部分页面信息到实例上  
13125 - * @param editorUi  
13126 - * @param currentPage  
13127 - */  
13128 - saveContentInfo(editorUi, currentPage) {  
13129 - const editor = editorUi.editor  
13130 - this.graph = editor.graph  
13131 - this.currentPage = currentPage  
13132 - this.contentAllCell = this.graph.getDefaultParent().children || []  
13133 - }  
13134 -  
13135 - /**  
13136 - * @description 获取页面绑定的节点信息  
13137 - */  
13138 - async getContentDataNode() {  
13139 - const { node: { id } = {} } = this.currentPage  
13140 - if (!id) return  
13141 - const [err, res] = await to(ConfigurationNodeApi.getConfigurationInfo('CONTENT', id))  
13142 - this.contentData = res  
13143 - }  
13144 -  
13145 - /**  
13146 - * @description 发送消息去获取实时数据  
13147 - */  
13148 - sendMessageToGetRealTimeData(message) {  
13149 - if (typeof message !== 'string') message = JSON.stringify(message)  
13150 - this.socket.send(message)  
13151 - }  
13152 -  
13153 - /**  
13154 - * @description 通过传入NodeId获取cmdId  
13155 - * @param nodeId  
13156 - * @return {number}  
13157 - */  
13158 - getCmdId(nodeId) {  
13159 - const cmdId = this.cmdIdPrimaryKey++  
13160 - this.cmdIdMapping.set(cmdId, nodeId)  
13161 - return cmdId  
13162 - }  
13163 -  
13164 - /**  
13165 - * @description 生成节点映射表  
13166 - * @param dataSources  
13167 - * @return {{cmdId: number, entityType: string, keys: *, scope: string, entityId: *}[]}  
13168 - */  
13169 - generatorDataSourceMapping(dataSources = []) {  
13170 - return dataSources.map((datum) => {  
13171 - const { deviceId, attr, nodeId, slaveDeviceId } = datum  
13172 - const cmdId = this.getCmdId(nodeId)  
13173 - const sendMsgTemplate = {  
13174 - entityType: "DEVICE",  
13175 - entityId: slaveDeviceId ? slaveDeviceId : deviceId,  
13176 - scope: "LATEST_TELEMETRY",  
13177 - cmdId,  
13178 - keys: attr,  
13179 - }  
13180 - this.subscribeDataSources(datum, cmdId, attr)  
13181 - return sendMsgTemplate  
13182 - })  
13183 - }  
13184 -  
13185 - /**  
13186 - * @description 分发事件  
13187 - */  
13188 - publishEvent(eventName, data, message, event, ws) {  
13189 - // data = data ? data : {}  
13190 - this.eventBus.emit(eventName, message, event, ws)  
13191 - // console.log(arguments)  
13192 - // Object.keys(data).forEach(() => {  
13193 - // this.eventBus.emit(eventName, message, event, ws)  
13194 - // })  
13195 - }  
13196 -  
13197 - /**  
13198 - * @description 订阅数据源  
13199 - * @param datum  
13200 - * @param eventName  
13201 - * @param key  
13202 - */  
13203 - subscribeDataSources(datum, eventName, key) {  
13204 - const node = this.contentAllCell.find(item => item.id === datum.nodeId)  
13205 - this.eventBus.on(eventName, (message) => {  
13206 - node && this.updatePage(() => {  
13207 - const { data } = message  
13208 - const [[timespan, value]] = data[key]  
13209 - node.setValue(value)  
13210 - }, node)  
13211 - })  
13212 - }  
13213 -  
13214 - /**  
13215 - * @description 更新页面  
13216 - * @param callback  
13217 - * @param cell  
13218 - */  
13219 - updatePage(callback, cell) {  
13220 - this.graph.getModel().beginUpdate()  
13221 - try {  
13222 - callback()  
13223 - this.graph.refresh(cell);  
13224 - } finally {  
13225 - this.graph.getModel().endUpdate()  
13226 - }  
13227 - }  
13228 -  
13229 -  
13230 - /**  
13231 - * @description 返回 DispatchCenter 实例 当contentID变化时重新创建实例  
13232 - * @param editorUi  
13233 - * @param currentPage  
13234 - * @return {*}  
13235 - */  
13236 - static getInstance(editorUi, currentPage = {}) {  
13237 - const { node: { id } = {} } = currentPage  
13238 - if (!id) return  
13239 - if (!DispatchCenter.instance || DispatchCenter.rawContentId !== id) {  
13240 - DispatchCenter.instance?.dynamicEffectInstance?.cleanSetInterval?.()  
13241 - DispatchCenter.instance?.updateQueueInstance?.cleanAllUpdateQueue?.()  
13242 - DispatchCenter.instance = new DispatchCenter(editorUi, currentPage)  
13243 - DispatchCenter.rawContentId = id  
13244 - }  
13245 -  
13246 - return DispatchCenter.instance  
13247 - }  
13248 -  
13249 -}  
13250 -  
13251 -class HandleDataSource {  
13252 -  
13253 - static enumConst = {  
13254 -  
13255 - /**  
13256 - * @description 聚合方式  
13257 - */  
13258 - AGG: 'agg',  
13259 -  
13260 - /**  
13261 - * @description 间隔方式  
13262 - */  
13263 - INTERVAL: 'interval',  
13264 -  
13265 - /**  
13266 - * @description 单位  
13267 - */  
13268 - UNIT: 'unit',  
13269 -  
13270 - /**  
13271 - * @description 开始时间  
13272 - */  
13273 - STARTTs: 'startTs',  
13274 -  
13275 - /**  
13276 - * @description 结束时间  
13277 - */  
13278 - ENDTs: 'endTs',  
13279 -  
13280 - /**  
13281 - * @description 范围  
13282 - */  
13283 - EFFECT_SCOPE: 'effectScope',  
13284 -  
13285 - /**  
13286 - * @description 绑定数据类型  
13287 - */  
13288 - DATA_TYPE: 'dataType'  
13289 - }  
13290 -  
13291 -  
13292 - static enumDataBindType = {  
13293 -  
13294 - /**  
13295 - * @description 历史  
13296 - */  
13297 - HISTORY: 'historyCmds',  
13298 -  
13299 - /**  
13300 - * @description 事实  
13301 - */  
13302 - REAL: 'tsSubCmds'  
13303 - }  
13304 -  
13305 - /**  
13306 - * @description 数据源节点映射  
13307 - * @type {Map<string, object>}  
13308 - */  
13309 - dataSourceNodeMapping = new Map()  
13310 -  
13311 - /**  
13312 - * @description 派发队列  
13313 - * @type {DispatchCenter}  
13314 - */  
13315 - DispatchInstance  
13316 -  
13317 - constructor(DispatchInstance) {  
13318 - this.DispatchInstance = DispatchInstance  
13319 - this.generatorCommonDataSourceMapping()  
13320 - this.generatorChartDataSourceMapping()  
13321 - }  
13322 -  
13323 - get graph() {  
13324 - return this.DispatchInstance.graph  
13325 - }  
13326 -  
13327 - /**  
13328 - * @description 普通数据源绑定列表  
13329 - */  
13330 - get commonDataSourceBindList() {  
13331 - return this.DispatchInstance.contentData?.dataSources?.filter(item => !item.additional && item.attr) || []  
13332 - }  
13333 -  
13334 - /**  
13335 - * @description 图表数据源绑定列表  
13336 - */  
13337 - get chartDataSourceBindList() {  
13338 - return this.DispatchInstance.contentData?.dataSources?.filter(item => item.additional) || []  
13339 - }  
13340 -  
13341 - get cmdIdMapping() {  
13342 - return this.DispatchInstance.cmdIdMapping  
13343 - }  
13344 -  
13345 - get basicAttr() {  
13346 - return Sidebar.prototype.enumCellBasicAttribute  
13347 - }  
13348 -  
13349 - get componentType() {  
13350 - return Sidebar.prototype.enumComponentType  
13351 - }  
13352 -  
13353 - get contentAllCell() {  
13354 - return this.graph.getDefaultParent().children || []  
13355 - }  
13356 -  
13357 - /**  
13358 - * @description 生成普通数据源绑定映射关系  
13359 - * @param dataSources  
13360 - * @return {{cmdId: number, entityType: string, keys: *, scope: string, entityId: *}[]}  
13361 - */  
13362 - generatorCommonDataSourceMapping() {  
13363 - const msg = this.commonDataSourceBindList.map((datum) => {  
13364 - const { deviceId, attr, nodeId, slaveDeviceId } = datum  
13365 - const cmdId = this.getCmdId(nodeId)  
13366 - const sendMsgTemplate = {  
13367 - entityType: "DEVICE",  
13368 - entityId: slaveDeviceId ? slaveDeviceId : deviceId,  
13369 - scope: "LATEST_TELEMETRY",  
13370 - cmdId,  
13371 - keys: attr,  
13372 - }  
13373 - this.dataSourceNodeMapping.set(nodeId, datum)  
13374 - this.subscribeEvent(cmdId, this.updateCommonDataSource.bind(this))  
13375 - return sendMsgTemplate  
13376 - })  
13377 - const { REAL } = HandleDataSource.enumDataBindType  
13378 - if (msg.length) this.sendMsg({ [REAL]: msg })  
13379 - }  
13380 -  
13381 -  
13382 - /**  
13383 - * @description 图表数据源绑定关系  
13384 - * @param {any[]} dataSource  
13385 - */  
13386 - generatorChartDataSourceMapping() {  
13387 - const realList = []  
13388 - const historyList = []  
13389 - const { HISTORY, REAL } = HandleDataSource.enumDataBindType  
13390 - const { STARTTs, ENDTs } = HandleDataSource.enumConst  
13391 - for (const item of this.chartDataSourceBindList) {  
13392 - const { additional = {}, deviceId, attr, nodeId, slaveDeviceId } = item  
13393 - if (!attr) continue  
13394 - const { agg, interval = 1000, dataType, effectScope = 0 } = additional  
13395 - const cmdId = this.getCmdId(nodeId)  
13396 - const template = {  
13397 - entityType: "DEVICE",  
13398 - entityId: slaveDeviceId ? slaveDeviceId : deviceId,  
13399 - cmdId,  
13400 - interval: Number(interval),  
13401 - agg,  
13402 - keys: attr,  
13403 - }  
13404 - let scope = isNaN(effectScope) ? 0 : Number(effectScope)  
13405 - if (dataType === HISTORY) {  
13406 - template[STARTTs] = Date.now() - scope  
13407 - template[ENDTs] = Date.now()  
13408 - historyList.push(template)  
13409 - this.subscribeEvent(cmdId, (message) => {  
13410 - this.updateHistoryDataSource(message, agg)  
13411 - })  
13412 - }  
13413 - else if (dataType === REAL) {  
13414 - template[STARTTs] = Date.now() - scope  
13415 - // template['timeWindow'] = interval  
13416 - realList.push(template)  
13417 - this.subscribeEvent(cmdId, (message) => {  
13418 - this.updateRealTimeDataSource(message, agg)  
13419 - })  
13420 - }  
13421 - this.dataSourceNodeMapping.set(nodeId, item)  
13422 - }  
13423 -  
13424 - if (historyList.length || realList.length) this.sendMsg({ [HISTORY]: historyList, [REAL]: realList })  
13425 - }  
13426 -  
13427 - /**  
13428 - * @description 订阅事件 绑定回调  
13429 - * @param eventName  
13430 - * @param callback  
13431 - */  
13432 - subscribeEvent(eventName, callback) {  
13433 - this.DispatchInstance.eventBus.on(eventName, callback)  
13434 - }  
13435 -  
13436 - /**  
13437 - * @description 更新变量值  
13438 - * @param {} message  
13439 - */  
13440 - updateCommonDataSource(message) {  
13441 - const { subscriptionId } = message  
13442 - const node = this.getNodeByCmdId(subscriptionId)  
13443 - const { attr } = this.getBindData(subscriptionId)  
13444 - node && this.updatePage(() => {  
13445 - const { data } = message  
13446 - const type = this.getComponentType(node)  
13447 - if (type === this.componentType.SWITCH) {  
13448 - this.handleSwitchComponent(message)  
13449 - return  
13450 - }  
13451 -  
13452 - if (type === this.componentType.PARAMS_SETTING_BUTTON) {  
13453 - this.handleParamSettingButton(message)  
13454 - return  
13455 - }  
13456 -  
13457 - if (type === this.componentType.IMAGE) {  
13458 - this.handleImageComponent(message)  
13459 - return  
13460 - }  
13461 -  
13462 - if (!data) return  
13463 - const [[timespan, value]] = data[attr]  
13464 - node.setValue(value)  
13465 - }, node)  
13466 - }  
13467 -  
13468 - /**  
13469 - * @description 处理switch 组件  
13470 - * @param {} message  
13471 - */  
13472 - handleSwitchComponent(message) {  
13473 - const { subscriptionId, data = {} } = message  
13474 - const node = this.getNodeByCmdId(subscriptionId)  
13475 - const { nodeId, attr } = this.getBindData(subscriptionId)  
13476 - const [[timespan, receiveValue] = []] = data[attr] || []  
13477 - const switchConfig = this.DispatchInstance.contentData.act.find(item => item.id === nodeId && item.type === 'SWITCH')  
13478 - const { condition = [] } = switchConfig || {}  
13479 - let reg = /image=[^;]+/g  
13480 - let flag = false  
13481 - const { SWITCH_STATE, SWITCH_VALUE, SWITCH_SEND_VALUE } = Sidebar.prototype.enumComponentType  
13482 - const { SWITCH_STATE_NONE } = Sidebar.prototype.enumComponentTypeValue  
13483 -  
13484 - const getSendValue = (type) => {  
13485 - return (condition.find(item => item.type !== type) || {}).value  
13486 - }  
13487 - for (const item of condition) {  
13488 - const { value, imagePath, type } = item || {}  
13489 - if (Number(receiveValue) === Number(value)) {  
13490 - flag = true  
13491 - this.updatePage(() => {  
13492 - const style = node.getStyle()  
13493 - const sendValue = getSendValue(type)  
13494 - node.setStyle(style.replace(reg, `image=${imagePath}`))  
13495 - node.setAttribute('label', '')  
13496 - node.setAttribute(SWITCH_VALUE, receiveValue)  
13497 - node.setAttribute(SWITCH_SEND_VALUE, sendValue)  
13498 - node.setAttribute(SWITCH_STATE, type)  
13499 - }, node)  
13500 - break  
13501 - }  
13502 - }  
13503 - if (!flag) {  
13504 - this.updatePage(() => {  
13505 - const style = node.getStyle()  
13506 - node.setStyle(style.replace(reg, `image=images/thingskit/not-standard-value.svg`))  
13507 - node.setAttribute('label', receiveValue)  
13508 - node.setAttribute(SWITCH_VALUE, receiveValue)  
13509 - node.setAttribute(SWITCH_STATE, SWITCH_STATE_NONE)  
13510 - }, node)  
13511 - }  
13512 -  
13513 - }  
13514 -  
13515 - handleParamSettingButton(message) {  
13516 - const { subscriptionId, data = {} } = message  
13517 - if (!data) return  
13518 - const node = this.getNodeByCmdId(subscriptionId)  
13519 - const { attr } = this.getBindData(subscriptionId)  
13520 - const [[timespan, receiveValue] = []] = data[attr] || []  
13521 - this.updatePage(() => {  
13522 - node.setAttribute('label', `<button class="param-setting-button">${receiveValue}</button>`)  
13523 - }, node)  
13524 - }  
13525 -  
13526 - handleImageComponent(message) {  
13527 - const { subscriptionId, data = {} } = message  
13528 - const node = this.getNodeByCmdId(subscriptionId)  
13529 - const { attr } = this.getBindData(subscriptionId)  
13530 - const [[timespan, receiveValue] = []] = data[attr] || []  
13531 - this.updatePage(() => {  
13532 - node.setAttribute('label', `<img class="basic-component__image" alt="图片" src="${receiveValue}" />`)  
13533 - }, node)  
13534 - }  
13535 -  
13536 - /**  
13537 - * @description 更新实时数据  
13538 - * @param {} message  
13539 - * @param {} agg 聚合方式  
13540 - */  
13541 - updateRealTimeDataSource(message, agg) {  
13542 - const { data = {}, subscriptionId } = message  
13543 - const node = this.getNodeByCmdId(subscriptionId)  
13544 - if (!node) return  
13545 - const enumConst = Sidebar.prototype.enumCellBasicAttribute  
13546 - const chartInstanceMap = Sidebar.prototype.chartsInstanceMapping  
13547 - const chartInstanceId = node.getAttribute(enumConst.CHART_INSTANCE_ID)  
13548 - const chartInstanceType = node.getAttribute(enumConst.COMPONENT_TYPE)  
13549 - const instance = chartInstanceMap.get(chartInstanceId)  
13550 - const { attr = [[]] } = this.getBindData(subscriptionId)  
13551 - const realDataList = data[attr] || []  
13552 -  
13553 - const action = agg === 'NONE' ? 'unshift' : 'push'  
13554 -  
13555 - // chart insstance 是否已经接受过一次消息推送  
13556 - const isActive = instance.isActive  
13557 - if (!isActive) {  
13558 - instance.isActive = true  
13559 - const chartOption = this.getChartComponentOption(chartInstanceType, { chartType: chartInstanceType, attr, dataList: realDataList, action, nodeId: node.id })  
13560 - instance.setOption(chartOption)  
13561 -  
13562 - } else {  
13563 - const oldOptions = instance.getOption()  
13564 - const options = this.getRealTimeUpdateChartOption(chartInstanceType, { oldOptions, dataList: realDataList })  
13565 - if (!instance) clearInterval(interval)  
13566 - instance && instance.setOption(options)  
13567 - }  
13568 - }  
13569 -  
13570 - /**  
13571 - * @description 更新历史数据  
13572 - */  
13573 - updateHistoryDataSource(message, agg) {  
13574 - const { data = {}, subscriptionId } = message  
13575 - const node = this.getNodeByCmdId(subscriptionId)  
13576 - if (!node) return  
13577 - const enumConst = Sidebar.prototype.enumCellBasicAttribute  
13578 - const chartInstanceMap = Sidebar.prototype.chartsInstanceMapping  
13579 - const chartInstanceId = node.getAttribute(enumConst.CHART_INSTANCE_ID)  
13580 - const chartInstanceType = node.getAttribute(enumConst.COMPONENT_TYPE)  
13581 - const instance = chartInstanceMap.get(chartInstanceId)  
13582 - const { attr = [[]] } = this.getBindData(subscriptionId)  
13583 - const historyDataList = data[attr] || []  
13584 - const showNumberOf = 4  
13585 - const action = agg === 'NONE' ? 'unshift' : 'push'  
13586 -  
13587 - const chartOption = this.getChartComponentOption(chartInstanceType, { dataList: historyDataList, attr, chartType: chartInstanceType, action })  
13588 -  
13589 - let interval  
13590 - // TODO 清除定时器  
13591 - function autoMove() {  
13592 - if (seriesValue.length <= 5) return  
13593 - interval = setInterval(() => {  
13594 - if (Number(chartOption.dataZoom[0].endValue) === seriesValue.length - 1) {  
13595 - chartOption.dataZoom[0].endValue = showNumberOf  
13596 - chartOption.dataZoom[0].startValue = 0  
13597 - } else {  
13598 - chartOption.dataZoom[0].endValue = chartOption.dataZoom[0].endValue + 1  
13599 - chartOption.dataZoom[0].startValue = chartOption.dataZoom[0].startValue + 1  
13600 - }  
13601 - if (!chartInstanceMap.has(chartInstanceId)) {  
13602 - clearInterval(interval)  
13603 - return  
13604 - }  
13605 - instance && instance.setOption(chartOption)  
13606 -  
13607 - }, 2000);  
13608 - }  
13609 -  
13610 - function stop() {  
13611 - clearInterval(interval)  
13612 - }  
13613 -  
13614 - function goMove() {  
13615 - autoMove()  
13616 - }  
13617 -  
13618 - instance.setOption(chartOption)  
13619 - // instance.on('mouseover', stop)  
13620 - // instance.on('mouseout', goMove)  
13621 - // autoMove()  
13622 - }  
13623 -  
13624 - getChartComponentOption(chartInstanceType, params) {  
13625 - const { LINE_CHART, BAR_CHART, DASHBOARD_CHART } = Sidebar.prototype.enumComponentType  
13626 - switch (chartInstanceType) {  
13627 - case LINE_CHART:  
13628 - return this.getBasicChartOption(Object.assign(params, { chartType: 'line' }))  
13629 - case BAR_CHART:  
13630 - return this.getBasicChartOption(Object.assign(params, { chartType: 'bar' }))  
13631 - case DASHBOARD_CHART:  
13632 - return this.getDashboardChartOption(params)  
13633 - default:  
13634 - return {}  
13635 - }  
13636 - }  
13637 -  
13638 - getRealTimeUpdateChartOption(chartInstanceType, params) {  
13639 - const { LINE_CHART, BAR_CHART, DASHBOARD_CHART } = Sidebar.prototype.enumComponentType  
13640 - switch (chartInstanceType) {  
13641 - case LINE_CHART:  
13642 - return this.getRealTimeUpdateBasicChartOption(params)  
13643 - case BAR_CHART:  
13644 - return this.getRealTimeUpdateBasicChartOption(params)  
13645 - case DASHBOARD_CHART:  
13646 - return this.getRealTimeUpdateDashboardChartOption(params)  
13647 - default:  
13648 - return {}  
13649 - }  
13650 - }  
13651 -  
13652 - /**  
13653 - *  
13654 - * @param {@} params  
13655 - * @returns  
13656 - */  
13657 - getBasicChartOption(params = { dataList: [], attr: '', chartType: 'bar', action }) {  
13658 - const { dataList = [], attr = '', chartType = 'bar', action } = params  
13659 -  
13660 - const xAxisData = []  
13661 - const seriesValue = []  
13662 -  
13663 - dataList.forEach(item => {  
13664 - const [timespan, value] = item  
13665 - xAxisData[action](new Date(Number(timespan)).toLocaleTimeString())  
13666 - seriesValue[action](Number(value))  
13667 - })  
13668 -  
13669 - return {  
13670 - title: {  
13671 - subtext: dataList.length ? '' : '暂无数据',  
13672 - x: 'center',  
13673 - y: 'center',  
13674 - itemGap: -20,  
13675 - subtextStyle: {  
13676 - fontSize: 16  
13677 - }  
13678 - },  
13679 - tooltip: {  
13680 - trigger: 'axis',  
13681 - axisPointer: {  
13682 - type: 'shadow'  
13683 - }  
13684 - },  
13685 - grid: {  
13686 - left: '3%',  
13687 - right: '3%',  
13688 - bottom: '3%',  
13689 - containLabel: true,  
13690 - },  
13691 - xAxis: {  
13692 - name: '时间',  
13693 - type: 'category',  
13694 - data: xAxisData,  
13695 - boundaryGap: true,  
13696 - axisLabel: {  
13697 - rotate: 70  
13698 - },  
13699 - axisPointer: {  
13700 - label: {  
13701 - formatter() {  
13702 - return attr  
13703 - }  
13704 - }  
13705 - }  
13706 - },  
13707 - yAxis: {  
13708 - type: 'value'  
13709 - },  
13710 - series: [  
13711 - {  
13712 - data: seriesValue,  
13713 - type: chartType,  
13714 - }  
13715 - ],  
13716 - dataZoom: [  
13717 - {  
13718 - show: true,  
13719 - type: 'inside'  
13720 - }  
13721 - ]  
13722 - }  
13723 - }  
13724 -  
13725 - getRealTimeUpdateBasicChartOption(params = { oldOptions: {}, dataList: [] }) {  
13726 - const { oldOptions, dataList } = params  
13727 - const xAxisData = oldOptions.xAxis[0].data || []  
13728 - const seriesValue = oldOptions.series[0].data || []  
13729 - const oldEndValue = Number(oldOptions.dataZoom[0].endValue) || 0  
13730 - const oldStartValue = Number(oldOptions.dataZoom[0].startValue) || 0  
13731 - const showNumberOf = 4  
13732 -  
13733 - for (let i = dataList.length - 1; i >= 0; i--) {  
13734 - const [timespan, value] = dataList[i]  
13735 - xAxisData.push(new Date(Number(timespan)).toLocaleTimeString())  
13736 - seriesValue.push(Number(value))  
13737 - }  
13738 -  
13739 - if (Number(oldOptions.dataZoom[0].endValue) === seriesValue.length - 1) {  
13740 - oldOptions.dataZoom[0].endValue = showNumberOf  
13741 - oldOptions.dataZoom[0].startValue = 0  
13742 - } else {  
13743 - oldOptions.dataZoom[0].endValue = oldOptions.dataZoom[0].endValue + 1  
13744 - oldOptions.dataZoom[0].startValue = oldOptions.dataZoom[0].startValue + 1  
13745 - }  
13746 -  
13747 - return {  
13748 - title: {  
13749 - subtext: ''  
13750 - },  
13751 - xAxis: {  
13752 - data: xAxisData  
13753 - },  
13754 - series: [  
13755 - {  
13756 - data: seriesValue  
13757 - }  
13758 - ],  
13759 - dataZoom: [  
13760 - {  
13761 - show: true,  
13762 - type: 'inside',  
13763 - }  
13764 - ]  
13765 - }  
13766 - }  
13767 -  
13768 - getDashboardChartOption(params = { dataList: [], nodeId }) {  
13769 - const { dataList = [], nodeId } = params  
13770 - const dataSource = this.DispatchInstance.contentData.dataSources.find(item => item.nodeId === nodeId) || {}  
13771 - const { additional: { unit = '°C' } = {} } = dataSource  
13772 -  
13773 - const [timespan, value] = dataList[0] || []  
13774 - return {  
13775 - series: [  
13776 - {  
13777 - type: 'gauge',  
13778 - center: ['50%', '60%'],  
13779 - radius: '100%',  
13780 - startAngle: 200,  
13781 - endAngle: -20,  
13782 - min: 0,  
13783 - max: 100,  
13784 - splitNumber: 10,  
13785 - itemStyle: {  
13786 - color: '#5479c6'  
13787 - // color: '#FFAB91'  
13788 - },  
13789 - progress: {  
13790 - show: true,  
13791 - width: 30  
13792 - },  
13793 - pointer: {  
13794 - show: false  
13795 - },  
13796 - axisLine: {  
13797 - lineStyle: {  
13798 - width: 30  
13799 - }  
13800 - },  
13801 - axisTick: {  
13802 - distance: 0,  
13803 - splitNumber: 5,  
13804 - lineStyle: {  
13805 - width: 2,  
13806 - color: '#999'  
13807 - }  
13808 - },  
13809 - splitLine: {  
13810 - distance: 0,  
13811 - length: 14,  
13812 - lineStyle: {  
13813 - width: 3,  
13814 - color: '#999'  
13815 - }  
13816 - },  
13817 - axisLabel: {  
13818 - distance: 35,  
13819 - color: '#999',  
13820 - fontSize: 20  
13821 - },  
13822 - anchor: {  
13823 - show: false  
13824 - },  
13825 - title: {  
13826 - show: false  
13827 - },  
13828 - detail: {  
13829 - valueAnimation: true,  
13830 - width: '60%',  
13831 - lineHeight: 40,  
13832 - borderRadius: 8,  
13833 - offsetCenter: [0, '-15%'],  
13834 - fontSize: 25,  
13835 - fontWeight: 'bolder',  
13836 - formatter: `{value} ${unit}`,  
13837 - color: 'auto'  
13838 - },  
13839 - data: [  
13840 - {  
13841 - value  
13842 - }  
13843 - ]  
13844 - },  
13845 - ]  
13846 - }  
13847 - }  
13848 -  
13849 - /**  
13850 - * @description 获取仪表盘配置  
13851 - */  
13852 - getRealTimeUpdateDashboardChartOption(params = { dataList: [] }) {  
13853 - const { dataList = [], oldOptions } = params  
13854 - const [timespan, value] = dataList[0] || []  
13855 - console.log(value)  
13856 - return {  
13857 - series: [  
13858 - {  
13859 - data: [  
13860 - {  
13861 - value  
13862 - }  
13863 - ]  
13864 - },  
13865 - ]  
13866 - }  
13867 - }  
13868 -  
13869 - /**  
13870 - * @description 获取绑定的数据  
13871 - * @param subscriptionId  
13872 - * @param actionType  
13873 - * @return {*}  
13874 - */  
13875 - getBindData(subscriptionId) {  
13876 - const nodeId = this.getNodeIdByCmdId(subscriptionId)  
13877 - const temp = this.dataSourceNodeMapping.get(nodeId) || {}  
13878 - return temp  
13879 - }  
13880 -  
13881 - /**  
13882 - * @description 获取cmdId  
13883 - * @param {string} nodeId  
13884 - * @returns  
13885 - */  
13886 - getCmdId(nodeId) {  
13887 - return this.DispatchInstance.getCmdId(nodeId)  
13888 - }  
13889 -  
13890 - /**  
13891 - * @description 通过cmdID获取节点id  
13892 - * @param subscriptionId  
13893 - * @return {string}  
13894 - */  
13895 - getNodeIdByCmdId(subscriptionId) {  
13896 - return this.DispatchInstance.cmdIdMapping.get(subscriptionId)  
13897 - }  
13898 -  
13899 - /**  
13900 - * @description 通过cmdID 获取节点  
13901 - * @param subscriptionId  
13902 - * @return {*}  
13903 - */  
13904 - getNodeByCmdId(subscriptionId) {  
13905 - const nodeId = this.getNodeIdByCmdId(subscriptionId)  
13906 - return this.contentAllCell.find(item => item.id === nodeId)  
13907 - }  
13908 -  
13909 - getComponentType(node) {  
13910 - return node.getAttribute(this.basicAttr.COMPONENT_TYPE)  
13911 - }  
13912 -  
13913 - /**  
13914 - * @description 发送socket 消息  
13915 - * @param {any} msg  
13916 - * @returns  
13917 - */  
13918 - sendMsg(msg) {  
13919 - return this.DispatchInstance.sendMessageToGetRealTimeData(msg)  
13920 - }  
13921 -  
13922 - updatePage(callback, cell) {  
13923 - return this.DispatchInstance.updatePage(callback, cell)  
13924 - }  
13925 -}  
13926 -  
13927 -class HandleDataInteraction {  
13928 - /**  
13929 - * @description 事件分发中心实例  
13930 - * @type {DispatchCenter}  
13931 - */  
13932 - DispatchInstance  
13933 -  
13934 - /**  
13935 - * @description 事件映射  
13936 - * @type {Map<>}  
13937 - */  
13938 - static eventMapping = new Map()  
13939 -  
13940 - constructor(DispatchInstance) {  
13941 - this.DispatchInstance = DispatchInstance  
13942 - HandleDataInteraction.eventMapping = new Map()  
13943 - this.init()  
13944 - }  
13945 -  
13946 - init() {  
13947 - this.generatorEventMapping()  
13948 - this.createGraphEventListener()  
13949 - }  
13950 -  
13951 - get eventMapping() {  
13952 - return HandleDataInteraction.eventMapping  
13953 - }  
13954 -  
13955 - /**  
13956 - * @description DispatchCenter 实例中保存的 graph 对象  
13957 - * @return {*}  
13958 - */  
13959 - get graph() {  
13960 - return this.DispatchInstance.graph  
13961 - }  
13962 -  
13963 - /**  
13964 - * @description DispatchCenter 实例中保存的 editorUi 对象  
13965 - * @return {*}  
13966 - */  
13967 - get editorUi() {  
13968 - return this.DispatchInstance.editorUi  
13969 - }  
13970 -  
13971 - /**  
13972 - * @description DispatchCenter 实例中保存的 contentAllCell 对象  
13973 - * @return {*}  
13974 - */  
13975 - get eventList() {  
13976 - const { event = [] } = this.DispatchInstance.contentData  
13977 - return event  
13978 - }  
13979 -  
13980 - /**  
13981 - * @description 获取页面数据  
13982 - */  
13983 - get contentData() {  
13984 - return DispatchCenter.instance.contentData  
13985 - }  
13986 -  
13987 - get contentAllCell() {  
13988 - return this.graph.getDefaultParent().children || []  
13989 - }  
13990 -  
13991 - /**  
13992 - * @description 事件映射  
13993 - */  
13994 - generatorEventMapping() {  
13995 - const event = this.eventList  
13996 - for (const item of event) {  
13997 - const { content, id: nodeId, enabled, type } = item  
13998 - if (!enabled) continue  
13999 - if (!this.eventMapping.has(nodeId)) this.eventMapping.set(nodeId, new Map())  
14000 - const temp = this.eventMapping.get(nodeId)  
14001 - temp.set(type, content)  
14002 - }  
14003 - }  
14004 -  
14005 - createGraphEventListener() {  
14006 - if (DispatchCenter.eventListenerIsExist) return  
14007 -  
14008 - const graphDblClick = this.graph.dblClick;  
14009 - this.graph.dblClick = (...args) => {  
14010 - this.handleDoubleClickEvent(...args)  
14011 - graphDblClick.apply(this.graph, args)  
14012 - }  
14013 -  
14014 - const graphClick = this.graph.click;  
14015 - this.graph.click = (...args) => {  
14016 - this.handleClickEvent(...args)  
14017 - graphClick.apply(this.graph, args)  
14018 - }  
14019 -  
14020 - const mouseDownEvent = this.throttle(this.handleMouseDownEvent)  
14021 - const mouseUpEvent = this.throttle(this.handleMouseUpEvent)  
14022 - const graphFireMouseEvent = this.graph.fireMouseEvent;  
14023 - this.graph.fireMouseEvent = (eventName, event, sender) => {  
14024 - if (eventName === mxEvent.MOUSE_DOWN) {  
14025 - // this.handleMouseDownEvent(eventName, event, sender)  
14026 - mouseDownEvent(eventName, event, sender)  
14027 - }  
14028 - if (eventName === mxEvent.MOUSE_UP) {  
14029 - mouseUpEvent(eventName, event, sender)  
14030 - // this.handleMouseUpEvent(eventName, event, sender)  
14031 - }  
14032 - graphFireMouseEvent.apply(this.graph, [eventName, event, sender]);  
14033 - };  
14034 -  
14035 - DispatchCenter.eventListenerIsExist = true  
14036 - }  
14037 -  
14038 - /**  
14039 - * @description 处理按下事件  
14040 - * @param eventName  
14041 - * @param event  
14042 - * @param sender  
14043 - */  
14044 - handleMouseDownEvent(eventName, event, sender) {  
14045 - const { state } = event  
14046 - if (!state) return  
14047 - const { cell = {} } = state  
14048 - const { id } = cell || {}  
14049 - const temp = this.eventMapping.get(id)  
14050 - if (temp && temp.has(DispatchCenter.enumEventType.DOWN)) {  
14051 - const content = temp.get(DispatchCenter.enumEventType.DOWN)  
14052 - this.sendInstruction(content.data)  
14053 - }  
14054 - }  
14055 -  
14056 - /**  
14057 - * @description 处理抬起事件  
14058 - * @param eventName  
14059 - * @param event  
14060 - * @param sender  
14061 - */  
14062 - handleMouseUpEvent(eventName, event, sender) {  
14063 - const { state } = event  
14064 - if (!state) return  
14065 - const { cell = {} } = state  
14066 - const { id } = cell || {}  
14067 - const temp = this.eventMapping.get(id)  
14068 - if (temp && temp.has(DispatchCenter.enumEventType.UP)) {  
14069 - const content = temp.get(DispatchCenter.enumEventType.UP)  
14070 - this.sendInstruction(content.data)  
14071 - }  
14072 - }  
14073 -  
14074 - /**  
14075 - * @description 鼠标单击事件事件  
14076 - * @param event  
14077 - */  
14078 - handleClickEvent(event) {  
14079 - const { state } = event  
14080 - if (!state) return  
14081 - const { cell = {} } = state  
14082 - const { id } = cell || {}  
14083 - const temp = this.eventMapping.get(id)  
14084 - if (temp && temp.has(DispatchCenter.enumEventType.SINGLE)) {  
14085 - const content = temp.get(DispatchCenter.enumEventType.SINGLE)  
14086 - const { type, value } = content  
14087 - if (type === DispatchCenter.enumPageType.PAGE && value) {  
14088 - this.jumpPage(value)  
14089 - } else if (type === DispatchCenter.enumPageType.LINK && value) {  
14090 - window.open(value)  
14091 - } else if (type === DispatchCenter.enumPageType.PARAMS_SETTING) {  
14092 - this.paramsSetting(id, content)  
14093 - }  
14094 - }  
14095 - }  
14096 -  
14097 - /**  
14098 - * @description 鼠标双击事件  
14099 - * @param event  
14100 - * @param cell  
14101 - */  
14102 - handleDoubleClickEvent(event, cell = {}) {  
14103 - if (!cell) return  
14104 - const { id } = cell  
14105 - const temp = this.eventMapping.get(id)  
14106 - if (temp && temp.has(DispatchCenter.enumEventType.DOUBLE)) {  
14107 - const content = temp.get(DispatchCenter.enumEventType.DOUBLE)  
14108 - const { type, value } = content  
14109 - if (type === DispatchCenter.enumPageType.PAGE && value) {  
14110 - this.jumpPage(value)  
14111 - } else if (type === DispatchCenter.enumPageType.LINK && value) {  
14112 - window.open(value)  
14113 - }  
14114 - }  
14115 - }  
14116 -  
14117 -  
14118 - /**  
14119 - * @description 下发指令  
14120 - * @param list  
14121 - */  
14122 - sendInstruction(list = []) {  
14123 - const queue = []  
14124 - const fn = async (way, deviceId, data) => {  
14125 - const [err, res = []] = await to(ConfigurationNodeApi.deviceIsOnLine(deviceId))  
14126 - const { value } = res[0] || {}  
14127 - if (value) {  
14128 - await to(ConfigurationNodeApi.sendInstruction(way, deviceId, data))  
14129 - } else {  
14130 - UseLayUi.errorMsg('设备不在线!')  
14131 - }  
14132 - }  
14133 - for (const item of list) {  
14134 - const { deviceId, slaveDeviceId, value, way } = item  
14135 - if (!value || !deviceId) continue  
14136 - const data = {  
14137 - method: "methodThingskit",  
14138 - params: JSON.parse(value),  
14139 - }  
14140 - if (deviceId) {  
14141 - queue.push(() => {  
14142 - fn(way, deviceId, data)  
14143 - })  
14144 - }  
14145 - // if (slaveDeviceId) {  
14146 - // queue.push(() => {  
14147 - // fn(way, slaveDeviceId, data)  
14148 - // })  
14149 - // } else if (deviceId) {  
14150 - // queue.push(() => {  
14151 - // fn(way, deviceId, data)  
14152 - // })  
14153 - // }  
14154 - }  
14155 -  
14156 - Promise.all(queue.map(fn => fn()))  
14157 - }  
14158 -  
14159 - throttle(fn, time = 1000) {  
14160 - let now = Date.now  
14161 - let oldTime = now()  
14162 - return (...args) => {  
14163 - let newTime = now()  
14164 - if (newTime - oldTime > time) {  
14165 - oldTime = now()  
14166 - fn.apply(this, args)  
14167 - }  
14168 - }  
14169 - }  
14170 -  
14171 - /**  
14172 - * @description 跳转页面  
14173 - */  
14174 - jumpPage(page) {  
14175 - try {  
14176 - this.editorUi.handleCustomLink(`data:page/id,${page}`)  
14177 - } catch (error) {  
14178 - throw error  
14179 - }  
14180 - }  
14181 -  
14182 - /**  
14183 - * @description 参数设置  
14184 - */  
14185 - paramsSetting(nodeId, content) {  
14186 - const { layer, jquery: $, form } = layui  
14187 - const { SWITCH_STATE, SWITCH_VALUE, SWITCH_SEND_VALUE, SWITCH, PARAMS_SETTING_BUTTON } = Sidebar.prototype.enumComponentType  
14188 - const { SWITCH_STATE_NONE } = Sidebar.prototype.enumComponentTypeValue  
14189 - const { COMPONENT_TYPE } = Sidebar.prototype.enumCellBasicAttribute  
14190 - const contentData = this.contentData  
14191 - const currentNode = this.contentAllCell.find(item => item.id === nodeId)  
14192 -  
14193 - const enumConst = {  
14194 - VALUE: 'value',  
14195 - ISSUED_WAY: 'way',  
14196 - ONE_WAY: 'oneway',  
14197 - TWO_WAY: 'twoway',  
14198 - ATTR_PLACEHOLDER: 'attrPlaceholder'  
14199 - }  
14200 -  
14201 - const enumActionEl = {  
14202 - CONTAINER: 'container',  
14203 - EDITOR: 'editor',  
14204 - ISSUED_WAY_FILTER: 'wayFilter'  
14205 -  
14206 - }  
14207 -  
14208 - function createContent() {  
14209 - return `  
14210 - <div>  
14211 - <div class="layui-form" lay-filter="${enumActionEl.ISSUED_WAY_FILTER}">  
14212 - <div class="layui-form-item">  
14213 - <label class="layui-form-label">下发值</label>  
14214 - <div class="layui-input-block">  
14215 - <input type="text" name="${enumConst.VALUE}" lay-verify="required" autocomplete="off" placeholder="请输入下发值" class="layui-input">  
14216 - </div>  
14217 - </div>  
14218 - </div>  
14219 - </div>`  
14220 - }  
14221 -  
14222 - function jsonParse(value) {  
14223 - try {  
14224 - return JSON.parse(value)  
14225 - } catch (error) {  
14226 - return {}  
14227 - }  
14228 - }  
14229 -  
14230 - function handleSwitchComponent() {  
14231 - const state = currentNode.getAttribute(SWITCH_STATE)  
14232 - const value = currentNode.getAttribute(SWITCH_SEND_VALUE)  
14233 - if (state === SWITCH_STATE_NONE) {  
14234 - return  
14235 - }  
14236 - layer.confirm('是否确认下发命令?', async function (index) {  
14237 - defaultHandler(value, () => layer.close(index))  
14238 - });  
14239 -  
14240 -  
14241 - }  
14242 -  
14243 - function replaceAttrPlaceholder(oldValue = {}, replaceAttr = '', replaceValue = '', newValue = {},) {  
14244 - if (typeof oldValue !== 'object') return newValue  
14245 -  
14246 - for (const key of Object.keys(oldValue)) {  
14247 - if (key === enumConst.ATTR_PLACEHOLDER) {  
14248 - newValue[replaceAttr] = replaceValue  
14249 - continue  
14250 - }  
14251 - if (typeof oldValue[key] === 'object') {  
14252 - newValue[key] = replaceAttrPlaceholder(oldValue[key], replaceAttr, replaceValue)  
14253 - continue  
14254 - }  
14255 - newValue[key] = oldValue[key]  
14256 - }  
14257 -  
14258 - return newValue  
14259 - }  
14260 -  
14261 - const submitThrottle = this.throttle(submit)  
14262 - async function submit(callback) {  
14263 - const { value } = form.val(enumActionEl.ISSUED_WAY_FILTER)  
14264 - defaultHandler(value, callback)  
14265 - }  
14266 -  
14267 - async function defaultHandler(value, callback) {  
14268 - let { deviceId, attr } = contentData.dataSources.find(item => item.nodeId === nodeId) || {}  
14269 - let { command, way } = content  
14270 - const validate = new Validate([  
14271 - { value, required: true, message: '下发值是必填项' },  
14272 - { value: deviceId, required: true, message: '未绑定设备' },  
14273 - { value: way, required: true, message: '未绑定指令下发方式(单向/双向)' },  
14274 - { value: command, required: true, message: '未设置下发命令' },  
14275 - { value: attr, required: true, message: '未绑定设备属性' },  
14276 - ])  
14277 - if (!validate.begin()) return  
14278 - if (typeof command === 'string') command = jsonParse(command)  
14279 - const data = replaceAttrPlaceholder(command, attr, value)  
14280 - const instructionData = {  
14281 - method: "methodThingskit",  
14282 - params: data,  
14283 - }  
14284 -  
14285 - const [err, res = []] = await to(ConfigurationNodeApi.deviceIsOnLine(deviceId))  
14286 - const { value: onlineFlag } = res[0] || {}  
14287 - if (onlineFlag) {  
14288 - const [err, res] = await to(ConfigurationNodeApi.sendInstruction(way, deviceId, instructionData))  
14289 - if (!err) {  
14290 - UseLayUi.topSuccessMsg('操作成功')  
14291 - callback && typeof callback === 'function' && callback()  
14292 - }  
14293 - } else {  
14294 - UseLayUi.topErrorMsg('设备不在线!')  
14295 - }  
14296 - }  
14297 -  
14298 - function createLayer() {  
14299 -  
14300 - layer.open({  
14301 - title: '参数设置',  
14302 - content: createContent(),  
14303 - area: '400px',  
14304 - btn: ["应用", "取消"],  
14305 - yes(index) {  
14306 - submitThrottle(() => {  
14307 - layer.close(index)  
14308 - })  
14309 - },  
14310 - but2(index, layero) {  
14311 -  
14312 - },  
14313 - async success(layero, index) {  
14314 - $('.layui-layer-setwin a').removeAttr('href')  
14315 - form.render()  
14316 - },  
14317 - })  
14318 - }  
14319 -  
14320 -  
14321 - function startProcess() {  
14322 - const componentType = currentNode.getAttribute(COMPONENT_TYPE)  
14323 - const handle = {  
14324 - [SWITCH]: handleSwitchComponent,  
14325 - [PARAMS_SETTING_BUTTON]: createLayer  
14326 - }  
14327 -  
14328 - try {  
14329 - handle[componentType]()  
14330 - } catch (error) {  
14331 -  
14332 - }  
14333 - }  
14334 - startProcess()  
14335 - }  
14336 -}  
14337 -  
14338 -/**  
14339 - * @description 处理数据动效  
14340 - */  
14341 -class HandleDynamicEffect {  
14342 -  
14343 - /**  
14344 - * @description 事件分发中心实例  
14345 - * @type {DispatchCenter}  
14346 - */  
14347 - DispatchInstance  
14348 -  
14349 - /**  
14350 - * @description 开启的数据动效  
14351 - * @type {any[]}  
14352 - */  
14353 - enableActList  
14354 -  
14355 - /**  
14356 - * @description 视频记录列表  
14357 - */  
14358 - videoRecordList  
14359 -  
14360 - /**  
14361 - * @description 动效节点映射  
14362 - * @type {Map<string, {display: boolean, value: Map<string, any>}>}  
14363 - */  
14364 - actNodeMapping = new Map()  
14365 -  
14366 - /**  
14367 - * @description clear setInterval  
14368 - */  
14369 - cleanSetInterval  
14370 -  
14371 - static enumConst = {  
14372 - MAX: 'max',  
14373 - MIN: 'min',  
14374 - }  
14375 -  
14376 - static enumActType = {  
14377 - FLASH: 'FLASH',  
14378 - DISPLAY: 'DISPLAY',  
14379 - ROTATE: 'ROTATE',  
14380 - IMAGE: 'IMAGE',  
14381 - RUNNING: 'RUNNING'  
14382 - }  
14383 -  
14384 - static enumDisplayType = {  
14385 - SHOW: 'show',  
14386 - HIDDEN: 'hidden',  
14387 - }  
14388 -  
14389 - static enumRunningType = {  
14390 - RUN: 'run',  
14391 - STOP: 'stop'  
14392 - }  
14393 -  
14394 - static enumVideoConst = {  
14395 - ORG_ID: 'orgId',  
14396 - RECORD_ID: 'id',  
14397 - VIDEO_URL: 'videoUrl',  
14398 - ACCESSMODE: 'accessMode',  
14399 - VIDEO_FLAG: 'videoComponentFlag'  
14400 - }  
14401 -  
14402 - static enumVarImageConst = {  
14403 -  
14404 - /**  
14405 - * @description 最小值  
14406 - */  
14407 - MIN: 'min',  
14408 -  
14409 - /**  
14410 - * @description 最大值  
14411 - */  
14412 - MAX: 'max',  
14413 -  
14414 - /**  
14415 - * @description 图片字段 key  
14416 - */  
14417 - IMAGE: 'image',  
14418 -  
14419 - /**  
14420 - * @description 颜色  
14421 - */  
14422 - COLOR: 'color',  
14423 -  
14424 - /**  
14425 - * @description 图片来源  
14426 - */  
14427 - IMAGE_ORIGIN: 'imageOrigin',  
14428 -  
14429 - /**  
14430 - * @description 图库图形类别  
14431 - */  
14432 - IMAGE_GALLERY_CATEGORY: 'category',  
14433 -  
14434 - /**  
14435 - * @description 图表图形路径  
14436 - */  
14437 - IMAGE_GALLERY_IMAGE_PATH: 'imagePath',  
14438 -  
14439 - /**  
14440 - * @description 默认图片 flag  
14441 - */  
14442 - DEFAULT_IMAGE_FLAG: 'defaultImageFlag'  
14443 - }  
14444 -  
14445 - static enumVideoAccessMode = {  
14446 - MANUAL_ENTER: 0,  
14447 - STREAMING: 1  
14448 - }  
14449 -  
14450 - constructor(DispatchInstance) {  
14451 - this.DispatchInstance = DispatchInstance  
14452 - this.init()  
14453 - }  
14454 -  
14455 - init() {  
14456 - this.getEnableActList()  
14457 - this.getVideoRecord()  
14458 - this.generatorMappingRelation()  
14459 - }  
14460 -  
14461 - get graph() {  
14462 - return this.DispatchInstance.graph  
14463 - }  
14464 -  
14465 - /**  
14466 - * @description 只更新一次的更新事件  
14467 - * @returns {*}  
14468 - */  
14469 - get insertOnceUpdateFn() {  
14470 - return this.DispatchInstance.updateQueueInstance.insertOnceUpdateFn.bind(this.DispatchInstance.updateQueueInstance)  
14471 - }  
14472 -  
14473 - /**  
14474 - * @description 将持续更新时间放入更新队列  
14475 - * @returns {*}  
14476 - */  
14477 - get insertContinueUpdateFn() {  
14478 - return this.DispatchInstance.updateQueueInstance.insertContinueUpdateFn.bind(this.DispatchInstance.updateQueueInstance)  
14479 - }  
14480 -  
14481 - /**  
14482 - * @description 从更新队列中删除更新  
14483 - * @returns {*}  
14484 - */  
14485 - get delUpdateFn() {  
14486 - return this.DispatchInstance.updateQueueInstance.delUpdateFn.bind(this.DispatchInstance.updateQueueInstance)  
14487 - }  
14488 -  
14489 - get contentAllCell() {  
14490 - return this.graph.getDefaultParent().children || []  
14491 - }  
14492 -  
14493 - /**  
14494 - * @description 筛选出视频数据源  
14495 - */  
14496 - getVideoRecord() {  
14497 - const { dataSources = [] } = this.DispatchInstance.contentData  
14498 - const { VIDEO_FLAG } = HandleDynamicEffect.enumVideoConst  
14499 - this.videoRecordList = dataSources.filter(item => item?.additional?.[VIDEO_FLAG])  
14500 - }  
14501 -  
14502 - /**  
14503 - * @description 获取已开启的数据动效  
14504 - */  
14505 - getEnableActList() {  
14506 - const { act = [] } = this.DispatchInstance.contentData  
14507 - // 过滤页面中没有的节点及未开启动效的节点  
14508 - this.enableActList = act.filter(item => this.contentAllCell.find(each => each.id === item.id) && item.enabled)  
14509 - // this.enableActList = act.filter(item => item.enabled)  
14510 - }  
14511 -  
14512 - /**  
14513 - * @description 生成映射关系 && 初始化推送消息  
14514 - */  
14515 - generatorMappingRelation() {  
14516 - this.videoPlay()  
14517 - const tsSubCmds = []  
14518 - this.enableActList.forEach(each => {  
14519 - const { id, type, attr, deviceId, slaveDeviceId } = each  
14520 -  
14521 - if (!this.actNodeMapping.has(id)) this.actNodeMapping.set(id, { display: true, value: new Map() })  
14522 - const temp = this.actNodeMapping.get(id)  
14523 - temp.value.set(type, each)  
14524 -  
14525 - const cmdId = this.DispatchInstance.getCmdId(id)  
14526 -  
14527 - tsSubCmds.push(this.generatorMessage(slaveDeviceId ? slaveDeviceId : deviceId, cmdId, attr))  
14528 -  
14529 - this.subscribeEvent(cmdId, this.dispatch(type))  
14530 - })  
14531 - if (tsSubCmds.length) this.sendMsg({ tsSubCmds })  
14532 - }  
14533 -  
14534 - /**  
14535 - * @description 推送消息  
14536 - * @param msg  
14537 - */  
14538 - sendMsg(msg) {  
14539 - this.DispatchInstance.sendMessageToGetRealTimeData(msg)  
14540 - }  
14541 -  
14542 - /**  
14543 - * @description 订阅事件 绑定回调  
14544 - * @param eventName  
14545 - * @param callback  
14546 - */  
14547 - subscribeEvent(eventName, callback) {  
14548 - this.DispatchInstance.eventBus.on(eventName, callback)  
14549 - }  
14550 -  
14551 - /**  
14552 - * @description 创建消息  
14553 - * @param deviceId  
14554 - * @param cmdId  
14555 - * @param attr  
14556 - * @return {{cmdId, entityType: string, keys, scope: string, entityId}}  
14557 - */  
14558 - generatorMessage(deviceId, cmdId, attr) {  
14559 - return {  
14560 - entityType: "DEVICE",  
14561 - entityId: deviceId,  
14562 - scope: "LATEST_TELEMETRY",  
14563 - cmdId,  
14564 - keys: attr,  
14565 - }  
14566 - }  
14567 -  
14568 - /**  
14569 - * @description 分发事件  
14570 - * @param type  
14571 - * @return Function  
14572 - */  
14573 - dispatch(type) {  
14574 - let invoke = () => {  
14575 - }  
14576 - switch (type) {  
14577 - case HandleDynamicEffect.enumActType.ROTATE:  
14578 - invoke = this.rotate.bind(this)  
14579 - break  
14580 - case HandleDynamicEffect.enumActType.DISPLAY:  
14581 - invoke = this.display.bind(this)  
14582 - break  
14583 - case HandleDynamicEffect.enumActType.FLASH:  
14584 - invoke = this.flash.bind(this)  
14585 - break  
14586 - case HandleDynamicEffect.enumActType.IMAGE:  
14587 - invoke = this.varImage.bind(this)  
14588 - break  
14589 - case HandleDynamicEffect.enumActType.RUNNING:  
14590 - invoke = this.running.bind(this)  
14591 - break  
14592 - }  
14593 - return invoke  
14594 - }  
14595 -  
14596 - /**  
14597 - * @description 旋转  
14598 - * @param message  
14599 - * @param attr  
14600 - */  
14601 - rotate(message) {  
14602 - const { subscriptionId, data } = message  
14603 - const node = this.getNodeByCmdId(subscriptionId)  
14604 - const key = node.id + DispatchCenter.enumDynamicEffectType.ROTATE  
14605 - if (!this.validatePriority(node.id)) {  
14606 - this.delUpdateFn(key)  
14607 - return  
14608 - }  
14609 - const { flag } = this.validate(subscriptionId, DispatchCenter.enumDynamicEffectType.ROTATE, data)  
14610 - let deg = 0  
14611 - const updateFn = () => {  
14612 - if (deg === 360) deg = 0  
14613 - deg += 20  
14614 - let style = node.getStyle()  
14615 - const reg = /rotation=(-?)\w+(;?)/g  
14616 - style = style.replace(reg, '')  
14617 - style += `rotation=${deg};`  
14618 - node.setStyle(style)  
14619 - this.graph.updateCellStyles(style, node)  
14620 - }  
14621 - if (!flag) {  
14622 - this.delUpdateFn(key)  
14623 - return  
14624 - }  
14625 - this.insertContinueUpdateFn(node, updateFn, key)  
14626 - }  
14627 -  
14628 - /**  
14629 - * @description 显示与隐藏  
14630 - * @param message  
14631 - * @param attr  
14632 - */  
14633 - display(message) {  
14634 - const { subscriptionId, data = {} } = message  
14635 - const { flag, condition } = this.validate(subscriptionId, HandleDynamicEffect.enumActType.DISPLAY, data)  
14636 - if (!flag) return  
14637 - const node = this.getNodeByCmdId(subscriptionId)  
14638 - let isShow = false  
14639 - if (condition.type === HandleDynamicEffect.enumDisplayType.SHOW) {  
14640 - isShow = true  
14641 - } else if (condition.type === HandleDynamicEffect.enumDisplayType.HIDDEN) {  
14642 - isShow = false  
14643 - }  
14644 - const updateFn = () => {  
14645 - if (!isShow) {  
14646 - Object.keys(HandleDynamicEffect.enumActType).forEach(key => {  
14647 - const delKey = node.id + key  
14648 - this.delUpdateFn(delKey)  
14649 - })  
14650 - const temp = this.actNodeMapping.get(node.id)  
14651 - temp.display = false  
14652 - } else {  
14653 - const temp = this.actNodeMapping.get(node.id)  
14654 - temp.display = true  
14655 - }  
14656 -  
14657 - node.setVisible(isShow)  
14658 - }  
14659 - this.insertOnceUpdateFn(node, updateFn)  
14660 - }  
14661 -  
14662 - /**  
14663 - * @description 闪烁  
14664 - * @param message  
14665 - * @param attr  
14666 - */  
14667 - flash(message) {  
14668 - const { subscriptionId, data } = message  
14669 - const node = this.getNodeByCmdId(subscriptionId)  
14670 - const key = node.id + DispatchCenter.enumDynamicEffectType.FLASH  
14671 - if (!this.validatePriority(node.id)) {  
14672 - this.delUpdateFn(key)  
14673 - return  
14674 - }  
14675 - const { flag, condition } = this.validate(subscriptionId, HandleDynamicEffect.enumActType.FLASH, data)  
14676 - let flashFlag = false  
14677 - const updateFn = () => {  
14678 - node.setVisible(flashFlag)  
14679 - flashFlag = !flashFlag  
14680 - }  
14681 - if (!flag) {  
14682 - flashFlag = true  
14683 - this.insertOnceUpdateFn(node, updateFn)  
14684 - this.delUpdateFn(key)  
14685 - return  
14686 - }  
14687 - this.insertContinueUpdateFn(node, updateFn, key)  
14688 - }  
14689 -  
14690 - /**  
14691 - * @description 处理变量图片  
14692 - */  
14693 - varImage(message) {  
14694 - const { subscriptionId, data } = message  
14695 - const node = this.getNodeByCmdId(subscriptionId)  
14696 - const { flag, condition } = this.validate(subscriptionId, HandleDynamicEffect.enumActType.IMAGE, data)  
14697 - if (flag && node) {  
14698 - const { imagePath } = condition  
14699 - this.insertOnceUpdateFn(  
14700 - node,  
14701 - () => {  
14702 - node.setStyle(`image;image=${imagePath};imageAspect=0;`)  
14703 - })  
14704 - } else if (!flag && node) {  
14705 - const { condition = [], attr } = this.getBindData(subscriptionId, HandleDynamicEffect.enumActType.IMAGE)  
14706 - const flag = HandleDynamicEffect.enumVarImageConst.DEFAULT_IMAGE_FLAG  
14707 - const defaultBindData = condition.find(item => item[flag])  
14708 - if (defaultBindData) {  
14709 - const { imagePath } = defaultBindData  
14710 - if (!imagePath) return  
14711 - this.insertOnceUpdateFn(  
14712 - node,  
14713 - () => {  
14714 - node.setStyle(`image;image=${imagePath};imageAspect=0;`)  
14715 - })  
14716 - }  
14717 - }  
14718 - }  
14719 -  
14720 - running(message) {  
14721 - const { subscriptionId, data = {} } = message  
14722 - const { flag, condition } = this.validate(subscriptionId, HandleDynamicEffect.enumActType.RUNNING, data)  
14723 - if (!flag) return  
14724 - const node = this.getNodeByCmdId(subscriptionId)  
14725 - let isRun = false  
14726 - if (condition.type === HandleDynamicEffect.enumRunningType.RUN) {  
14727 - isRun = true  
14728 - } else if (condition.type === HandleDynamicEffect.enumRunningType.STOP) {  
14729 - isRun = false  
14730 - }  
14731 -  
14732 - const updateFn = () => {  
14733 - const reg = /flowAnimation[^;]+/  
14734 - const style = node.getStyle()  
14735 - node.setStyle(style.replace(reg, `flowAnimation=${isRun ? 1 : 0}`))  
14736 - }  
14737 - this.insertOnceUpdateFn(node, updateFn)  
14738 - }  
14739 -  
14740 - /**  
14741 - * @description 播放视频  
14742 - */  
14743 - videoPlay() {  
14744 - const enumAccessMode = HandleDynamicEffect.enumVideoAccessMode  
14745 - const reg = /(?:.*)(?<=\.)/  
14746 - const graph = this.graph  
14747 - const createVideoTemplate = this.createVideoTemplate  
14748 - const videoPlayConfig = {  
14749 - controls: true,  
14750 - autoPlay: true,  
14751 - // bigPlayButton: true,  
14752 - // textTrackDisplay: false,  
14753 - // posterImage: false,  
14754 - // errorDisplay: false,  
14755 - }  
14756 - for (const record of this.videoRecordList) {  
14757 - const { additional = {}, nodeId } = record  
14758 - const { accessMode, videoUrl, id } = additional  
14759 - const cell = this.getCellByCellId(nodeId)  
14760 - if (!cell) continue  
14761 - if (Number(accessMode) === enumAccessMode.MANUAL_ENTER) {  
14762 - handleVideoPlay(videoPlayConfig, cell, videoUrl)  
14763 - } else {  
14764 - getStreamingVideoPlayUrl(id, nodeId)  
14765 - }  
14766 - }  
14767 -  
14768 - async function getStreamingVideoPlayUrl(id, cell) {  
14769 - const [err, res = {}] = await to(ConfigurationNodeApi.getStreamingVideoPlayUrl(id))  
14770 - const { url } = res?.data || {}  
14771 - if (!url) return  
14772 - handleVideoPlay({ ...videoPlayConfig, hls: { withCredentials: true } }, cell, url)  
14773 - }  
14774 -  
14775 - function handleVideoPlay(videoPlayConfig, cell, videoUrl) {  
14776 - if (!cell) return  
14777 - const { geometry = {} } = cell  
14778 - const { width, height } = geometry  
14779 - const idEl = getIdEl()  
14780 - graph.getModel().beginUpdate()  
14781 - try {  
14782 - let type  
14783 - if (videoUrl.replace(reg, '') === 'm3u8') type = 'application/x-mpegURL'  
14784 - const template = createVideoTemplate(idEl, width, height, videoUrl, type)  
14785 - cell.setAttribute('label', template)  
14786 - graph.refresh(cell);  
14787 - } finally {  
14788 - graph.getModel().endUpdate()  
14789 - videojs(idEl, videoPlayConfig, function () {  
14790 - this.play()  
14791 - })  
14792 - }  
14793 - }  
14794 -  
14795 - function getIdEl() {  
14796 - return `video-play__${Date.now()}`  
14797 - }  
14798 - }  
14799 -  
14800 -  
14801 - createVideoTemplate(idEl, width, height, videoUrl, videoType = 'video/mp4') {  
14802 - const poster = `${Proxy_Prefix}/images/youtube.png`  
14803 - const template = `<video id="${idEl}" class="video-js" controls preload="auto" muted="muted" width="${width}" height="${height}" poster="${poster}" data-setup='{}'>  
14804 - <source src="${videoUrl}" type="${videoType}">  
14805 - <p class="vjs-no-js">  
14806 - 要查看此视频,请启用JavaScript,并考虑升级web浏览器.  
14807 - </p>  
14808 - </video>`  
14809 - return template  
14810 - }  
14811 - /**  
14812 - * @description 获取cell 通过cell id  
14813 - */  
14814 - getCellByCellId(id) {  
14815 - const allCell = this.contentAllCell || []  
14816 - return allCell.find(item => item.id === id)  
14817 - }  
14818 -  
14819 -  
14820 - /**  
14821 - * @description 验证是否满足条件列表中的任意一条  
14822 - * @param subscriptionId  
14823 - * @param type  
14824 - * @param value  
14825 - * @return {{flag: boolean, condition: {}}}  
14826 - */  
14827 - validate(subscriptionId, type, value) {  
14828 - const { condition = [], attr } = this.getBindData(subscriptionId, type)  
14829 - const result = { condition: {}, flag: false }  
14830 - for (let i = 0; i < condition.length; i++) {  
14831 - const { min, max } = condition[i]  
14832 - const [timespan, realValue] = value[attr][0]  
14833 - result.flag = this.isExistInArea(min, max, realValue)  
14834 - if (result.flag) {  
14835 - result.condition = condition[i]  
14836 - break  
14837 - }  
14838 - }  
14839 - return result  
14840 - }  
14841 -  
14842 - /**  
14843 - * @description 判断一个数是否在区间范围内  
14844 - * @param min 最小值  
14845 - * @param max 最大值  
14846 - * @param value 值  
14847 - * @return {boolean}  
14848 - */  
14849 - isExistInArea(min, max, value) {  
14850 - return Number(value) >= Number(min) && Number(value) <= Number(max)  
14851 - }  
14852 -  
14853 - /**  
14854 - * @description 获取绑定的数据  
14855 - * @param subscriptionId  
14856 - * @param actionType  
14857 - * @return {*}  
14858 - */  
14859 - getBindData(subscriptionId, actionType) {  
14860 - const nodeId = this.getNodeIdByCmdId(subscriptionId)  
14861 - const temp = this.actNodeMapping.get(nodeId)  
14862 - return temp.value.get(actionType)  
14863 - }  
14864 -  
14865 - /**  
14866 - * @description 通过cmdID获取节点id  
14867 - * @param subscriptionId  
14868 - * @return {string}  
14869 - */  
14870 - getNodeIdByCmdId(subscriptionId) {  
14871 - return this.DispatchInstance.cmdIdMapping.get(subscriptionId)  
14872 - }  
14873 -  
14874 - /**  
14875 - * @description 通过cmdID 获取节点  
14876 - * @param subscriptionId  
14877 - * @return {*}  
14878 - */  
14879 - getNodeByCmdId(subscriptionId) {  
14880 - const nodeId = this.getNodeIdByCmdId(subscriptionId)  
14881 - return this.contentAllCell.find(item => item.id === nodeId)  
14882 - }  
14883 -  
14884 - /**  
14885 - * @description 验证数据动效优先级 显示隐藏优先级最高  
14886 - * @param {string} nodeId  
14887 - * @returns  
14888 - */  
14889 - validatePriority(nodeId) {  
14890 - return this.actNodeMapping.get(nodeId).display  
14891 - }  
14892 -  
14893 -}  
14894 -  
14895 -class UpdateQueue {  
14896 -  
14897 - /**  
14898 - * @description 图实例  
14899 - */  
14900 - graph  
14901 -  
14902 - /**  
14903 - * @description 更新队列  
14904 - * @type { Map<number, {cell: any, fn: Function, key: string}[]> }  
14905 - */  
14906 - updateQueueMapping = new Map()  
14907 -  
14908 - /**  
14909 - * @description 时间队列  
14910 - * @type { Map<number, Function> }  
14911 - */  
14912 - timeQueue = new Map()  
14913 -  
14914 - constructor(DispatchCenterInstance) {  
14915 - this.graph = DispatchCenterInstance.graph  
14916 - window.timeMap = this.timeQueue  
14917 - }  
14918 -  
14919 - /**  
14920 - * @description 创建更新队列  
14921 - * @param {number} time  
14922 - */  
14923 - createUpdateQueue(time) {  
14924 - const callback = () => {  
14925 - this.graph.getModel().beginUpdate()  
14926 - try {  
14927 - const updateQueue = this.updateQueueMapping.get(time)  
14928 - updateQueue.forEach(each => {  
14929 - const { cell: updateCell, fn: updateFn } = each  
14930 - updateFn()  
14931 - this.graph.refresh(updateCell);  
14932 - })  
14933 - } finally {  
14934 - this.graph.getModel().endUpdate()  
14935 - }  
14936 - }  
14937 - const cleanFn = RAFSetInterval(callback, time)  
14938 - this.timeQueue.set(time, cleanFn)  
14939 - }  
14940 -  
14941 - createIntervalQueue(time, callback) {  
14942 - const cleanFn = RAFSetInterval(callback, time)  
14943 - this.timeQueue.set(time, cleanFn)  
14944 - }  
14945 -  
14946 - /**  
14947 - * @description 持续更新  
14948 - * @param cell 更新cell  
14949 - * @param fn 更新方法  
14950 - * @param key key  
14951 - * @param time 间隔事时间  
14952 - */  
14953 - insertContinueUpdateFn(cell, fn, key, time = 100) {  
14954 - if (!this.updateQueueMapping.has(time)) {  
14955 - this.updateQueueMapping.set(time, [])  
14956 - }  
14957 - if (!this.timeQueue.get(time)) {  
14958 - this.createUpdateQueue(time)  
14959 - }  
14960 - if (this.updateQueueMapping.get(time).find(item => item.key === key)) {  
14961 - return  
14962 - }  
14963 - this.updateQueueMapping.get(time).push({ cell, fn, key })  
14964 - }  
14965 -  
14966 - /**  
14967 - * @description 只更新一次  
14968 - * @param cell 更新cell  
14969 - * @param fn 更新方法  
14970 - */  
14971 - insertOnceUpdateFn(cell, fn) {  
14972 - this.graph.getModel().beginUpdate()  
14973 - try {  
14974 - fn()  
14975 - this.graph.refresh(cell);  
14976 - } finally {  
14977 - this.graph.getModel().endUpdate()  
14978 - }  
14979 - }  
14980 -  
14981 - /**  
14982 - * @description 从更新队列中移除不再更新的事件  
14983 - * @param key  
14984 - * @param time  
14985 - */  
14986 - delUpdateFn(key, time = 100) {  
14987 - let temp = this.updateQueueMapping.get(time)  
14988 - if (temp) {  
14989 - const index = temp.findIndex(item => item.key === key)  
14990 - if (~index) {  
14991 - temp.splice(index, 1)  
14992 - if (!temp.length) {  
14993 - const cleanFn = this.timeQueue.get(time)  
14994 - cleanFn()  
14995 - this.timeQueue.delete(time)  
14996 - }  
14997 - }  
14998 - }  
14999 - }  
15000 -  
15001 - /**  
15002 - * @description 清楚所有更新队列  
15003 - */  
15004 - cleanAllUpdateQueue() {  
15005 - this.timeQueue.forEach(cleanFn => {  
15006 - cleanFn()  
15007 - })  
15008 - }  
15009 -}  
15010 -  
15011 -class RAFSetTimeoutImp {  
15012 - constructor(callback, time = 0) {  
15013 - this.callback = callback;  
15014 - this.time = time;  
15015 - this.now = Date.now;  
15016 - this.current = this.now();  
15017 - this.old = this.now();  
15018 - const fn = () => {  
15019 - if (this.current - this.old > this.time) {  
15020 - this.callback();  
15021 - this.old = this.now();  
15022 - this.clean();  
15023 - return;  
15024 - }  
15025 - this.current = this.now();  
15026 - this.instance = window.requestAnimationFrame(fn);  
15027 - };  
15028 - this.instance = window.requestAnimationFrame(fn);  
15029 - }  
15030 -  
15031 - clean() {  
15032 - window.cancelAnimationFrame(this.instance);  
15033 - this.instance = null;  
15034 - }  
15035 -}  
15036 -  
15037 -function RAFSetTimeout(callback, time) {  
15038 - const instance = new RAFSetTimeoutImp(callback, time);  
15039 - return instance.clean.bind(instance);  
15040 -}  
15041 -  
15042 -class RAFSetIntervalImp {  
15043 - constructor(callback, time = 0) {  
15044 - this.callback = callback;  
15045 - this.time = time;  
15046 - this.now = Date.now;  
15047 - this.current = this.now();  
15048 - this.old = this.now();  
15049 - const fn = () => {  
15050 - if (this.current - this.old > this.time) {  
15051 - this.callback();  
15052 - this.old = this.now();  
15053 - }  
15054 - this.current = this.now();  
15055 - this.instance = window.requestAnimationFrame(fn);  
15056 - };  
15057 - this.instance = window.requestAnimationFrame(fn);  
15058 - }  
15059 -  
15060 - clean() {  
15061 - window.cancelAnimationFrame(this.instance);  
15062 - this.instance = null  
15063 - }  
15064 -}  
15065 -  
15066 -function RAFSetInterval(callback, time) {  
15067 - const instance = new RAFSetIntervalImp(callback, time);  
15068 - return instance.clean.bind(instance);  
15069 -}  
15070 -  
15071 -  
15072 -class Validate {  
15073 - /**  
15074 - * @description  
15075 - * @type {{value: any, message: string, required?: boolean, validator?: any}[]} list  
15076 - */  
15077 - list = []  
15078 -  
15079 - /**  
15080 - * @description  
15081 - * @param {{value: any, message: string, required?: boolean, validator?: any}[]} ruleList  
15082 - */  
15083 - constructor(ruleList = []) {  
15084 - this.list = ruleList  
15085 - }  
15086 -  
15087 - /**  
15088 - * @description 设置规则  
15089 - * @param {{value: any, message: string, required?: boolean, validator?: any}} rule  
15090 - */  
15091 - set(rule) {  
15092 - this.list.push(rule)  
15093 - }  
15094 -  
15095 - begin() {  
15096 - for (const rule of this.list) {  
15097 - const { required, value, message, validator } = rule  
15098 - if (required && !value) {  
15099 - UseLayUi.topErrorMsg(message)  
15100 - return false  
15101 - }  
15102 - }  
15103 - return true  
15104 - }  
15105 -}  
@@ -22,26 +22,26 @@ @@ -22,26 +22,26 @@
22 <meta name="mobile-web-app-capable" content="yes"> 22 <meta name="mobile-web-app-capable" content="yes">
23 <meta name="theme-color" content="#d89000"> 23 <meta name="theme-color" content="#d89000">
24 24
25 - <link rel="stylesheet" href="./js/plugin/layui/css/layui.css?v=1663582316568"> 25 + <link rel="stylesheet" href="./js/plugin/layui/css/layui.css?v=1664184574262">
26 26
27 <!-- load configure file --> 27 <!-- load configure file -->
28 - <script src="./js/config/config.js?v=1663582316568"></script> 28 + <script src="./js/config/config.js?v=1664184574262"></script>
29 29
30 <!-- crypto-js --> 30 <!-- crypto-js -->
31 - <script src="./js/plugin/crypto-js/crypto-js.js?v=1663582316568"></script> 31 + <script src="./js/plugin/crypto-js/crypto-js.js?v=1664184574262"></script>
32 32
33 <!-- storage persistent --> 33 <!-- storage persistent -->
34 - <script src="./js/const/persistentStorage.js?v=1663582316568"></script> 34 + <script src="./js/const/persistentStorage.js?v=1664184574262"></script>
35 <!-- Global const --> 35 <!-- Global const -->
36 - <script src="./js/const/const.js?v=1663582316568"></script> 36 + <script src="./js/const/const.js?v=1664184574262"></script>
37 37
38 <!-- Axios --> 38 <!-- Axios -->
39 - <script src="./js/plugin/axios/axios.min.js?v=1663582316568"></script>  
40 - <script src="./js/plugin/axios/DefHttp.js?v=1663582316568"></script>  
41 - <script src="./js/api/index.js?v=1663582316568"></script> 39 + <script src="./js/plugin/axios/axios.min.js?v=1664184574262"></script>
  40 + <script src="./js/plugin/axios/DefHttp.js?v=1664184574262"></script>
  41 + <script src="./js/api/index.js?v=1664184574262"></script>
42 42
43 <!-- load script --> 43 <!-- load script -->
44 - <script src="./js/config/loadScript.js?v=1663582316568"></script> 44 + <script src="./js/config/loadScript.js?v=1664184574262"></script>
45 45
46 <!-- act editor --> 46 <!-- act editor -->
47 <!-- <script src="https://oss.yuntengcloud.com/iotdocs/thingskit-scada/ace.js"></script> --> 47 <!-- <script src="https://oss.yuntengcloud.com/iotdocs/thingskit-scada/ace.js"></script> -->
@@ -54,7 +54,7 @@ @@ -54,7 +54,7 @@
54 <!-- <script src="https://vjs.zencdn.net/7.10.2/video.min.js"></script> --> 54 <!-- <script src="https://vjs.zencdn.net/7.10.2/video.min.js"></script> -->
55 <!-- <script src="https://oss.yuntengcloud.com/iotdocs/thingskit-scada/video.min.js"></script> --> 55 <!-- <script src="https://oss.yuntengcloud.com/iotdocs/thingskit-scada/video.min.js"></script> -->
56 56
57 - <script src="./js/plugin/layui/layui.js?v=1663582316568"></script> 57 + <script src="./js/plugin/layui/layui.js?v=1664184574262"></script>
58 <!-- <link rel="stylesheet" href="https://cdnjs.loli.net/ajax/libs/layui/2.6.8/css/layui.min.css" 58 <!-- <link rel="stylesheet" href="https://cdnjs.loli.net/ajax/libs/layui/2.6.8/css/layui.min.css"
59 integrity="sha512-iQBJbsNHXUcgEIgWThd2dr8tOdKPvICwqjPEZYY81z3eMya44A5MiAqfWSCh+Ee1YzNYkdrI982Qhwgr8LEYOQ==" 59 integrity="sha512-iQBJbsNHXUcgEIgWThd2dr8tOdKPvICwqjPEZYY81z3eMya44A5MiAqfWSCh+Ee1YzNYkdrI982Qhwgr8LEYOQ=="
60 crossorigin="anonymous" referrerpolicy="no-referrer" /> 60 crossorigin="anonymous" referrerpolicy="no-referrer" />
@@ -63,7 +63,7 @@ @@ -63,7 +63,7 @@
63 crossorigin="anonymous" referrerpolicy="no-referrer"></script> --> 63 crossorigin="anonymous" referrerpolicy="no-referrer"></script> -->
64 64
65 <!-- 引入修改样式 --> 65 <!-- 引入修改样式 -->
66 - <link rel="stylesheet" href="./styles/formatChange.css?v=1663582316568"> 66 + <link rel="stylesheet" href="./styles/formatChange.css?v=1664184574262">
67 67
68 <script type="text/javascript"> 68 <script type="text/javascript">
69 /** 69 /**
@@ -306,7 +306,7 @@ @@ -306,7 +306,7 @@
306 var supportedDomain = (hostName.substring(hostName.length - 8, hostName.length) === '.draw.io') || 306 var supportedDomain = (hostName.substring(hostName.length - 8, hostName.length) === '.draw.io') ||
307 (hostName.substring(hostName.length - 13, hostName.length) === '.diagrams.net'); 307 (hostName.substring(hostName.length - 13, hostName.length) === '.diagrams.net');
308 308
309 - const releaseVersion = '1663582316568' 309 + const releaseVersion = '1664184574262'
310 const appMinSrc = Enable_OSS ? `${OSS_Prefix}app.min.js?v=${releaseVersion}` : `js/app.min.js?v=${releaseVersion}` 310 const appMinSrc = Enable_OSS ? `${OSS_Prefix}app.min.js?v=${releaseVersion}` : `js/app.min.js?v=${releaseVersion}`
311 function loadAppJS() { 311 function loadAppJS() {
312 mxscript(appMinSrc, function () { 312 mxscript(appMinSrc, function () {