基于Web实现网络拓扑图

想想好像好久没用写博客了! 由于最近想跳槽了(ps:尽管公司挽留,提出一些异与往常的挽留“制度”,But确实已经死心了) ,发现前一段时间一些做Hadoop,和Spark同事时常来请教网络拓扑图的有关问题,由于当时确实比较忙,没时间帮着一起分析,表示歉意!

先前整理过份简单的Demo 但是不详细  基于Web实现在线绘画拓扑图[GraphEditor]

首先呢这里是要详述的几个要点:(我用图是直接显示了~) (当然这套UI模块是后期改动的~重点不在这里)        [备案:后续使用文档]

显示拓扑图

基于Web实现网络拓扑图

基于Web实现网络拓扑图

其次呢是一些后期加上去的代码,我想既然用了网络拓扑图,后期的可塑性应该是很强的,部分都是后续需求加上去的!

基于Web实现网络拓扑图

基于Web实现网络拓扑图

基于Web实现网络拓扑图

基于Web实现网络拓扑图

言归正传,看完一些简单的流程图,我想都大概知道他的基本用途,和后期的塑造价值

一些简单的用途比如:做大数据Hadoop,Spark是的个个服务器之间的关系,以及关系流程图的描述; 大型企业的负载集群管理的关系以及流程图,安全管理,OA企业人士管理.....多事不可缺少的素材!

主要JQ代码模块:

基于Web实现网络拓扑图

上面的一些常量是一些属性!

用于绑定一些菜单信息

编辑保存

(主要文件:mxClient.js , Editor.js ,Graph.js,Shapes.js,EditorUi.js,Actions.js,Menus.js,Sidebar.js,                 Toolbar.js,Dialogs.js,jscolor.js )

核心文件代码如下:

EditorUi.js

基于Web实现网络拓扑图

基于Web实现网络拓扑图

1 /** 2 *$id:Action 。JS,V 2015-3-23 3 *$author Dana丶Li$ 4 */ 5 /** 6 * 构建了一种新的图形编辑器 7 * 编辑管理 实现方法管理 8 */ 9 EditorUi = function(editor, container) 10 { 11 this.editor = editor || new Editor(); 12 this.container = container || document.body; 13 var graph =http://www.likecs.com/ editor.graph; 14 //禁用滚动条 15 this.container.style.overflow = \'hidden\'; 16 17 var textEditing = mxUtils.bind(this, function(evt) 18 { 19 if (evt == null) 20 { 21 evt =http://www.likecs.com/ window.event; 22 } 23 24 if (this.isSelectionAllowed(evt)) 25 { 26 return true; 27 } 28 29 return graph.isEditing() || this.dialog != null; 30 }); 31 32 //禁用文本选择而不是编辑没有对话框可见 33 if (this.container ==http://www.likecs.com/ document.body) 34 { 35 document.onselectstart =http://www.likecs.com/ textEditing; 36 document.onmousedown =http://www.likecs.com/ textEditing; 37 } 38 39 //使用内置的上下文菜单编辑时 40 if (mxClient.IS_IE && document.documentMode != 9) 41 { 42 mxEvent.addListener(this.container, \'contextmenu\', textEditing); 43 } 44 else 45 { 46 this.container.oncontextmenu =http://www.likecs.com/ textEditing; 47 } 48 49 //图像预fetches子菜单 50 new Image().src =http://www.likecs.com/ mxPopupMenu.prototype.submenuImage; 51 52 //预取连接图像 53 if (mxConnectionHandler.prototype.connectImage != null) 54 { 55 new Image().src =http://www.likecs.com/ mxConnectionHandler.prototype.connectImage.src; 56 } 57 58 //创建用户界面 59 this.actions = new Actions(this); 60 this.menus = new Menus(this); 61 this.createDivs(); 62 this.refresh(); 63 this.createUi(); 64 65 //contains the given the inside main图审小组 66 graph.init(this.diagramContainer); 67 graph.refresh(); 68 69 //使容器的滚动条和设置光标样式 70 graph.container.setAttribute(\'tabindex\', \'0\'); 71 graph.container.style.overflow = (touchStyle) ? \'hidden\' : \'auto\'; 72 graph.container.style.cursor = \'default\'; 73 graph.container.style.backgroundImage = \'url(\' + IMAGE_PATH + \'/grid.gif)\'; 74 graph.container.focus(); 75 76 //保持图形容器集中在鼠标按下 77 var graphFireMouseEvent =http://www.likecs.com/ graph.fireMouseEvent; 78 graph.fireMouseEvent = function(evtName, me, sender) 79 { 80 if (evtName ==http://www.likecs.com/ mxEvent.MOUSE_DOWN) 81 { 82 this.container.focus(); 83 } 84 85 graphFireMouseEvent.apply(this, arguments); 86 }; 87 88 //在鼠标经过时自动扩展配置 89 graph.panningHandler.autoExpand = true; 90 91 //对上下文菜单 92 graph.panningHandler.factoryMethod = mxUtils.bind(this, function(menu, cell, evt) 93 { 94 this.menus.createPopupMenu(menu, cell, evt); 95 }); 96 97 //初始化轮廓 98 editor.outline.init(this.outlineContainer); 99 100 //隐藏菜单 101 var md = (mxClient.IS_TOUCH) ? \'touchstart\' : \'mousedown\'; 102 mxEvent.addListener(document, md, mxUtils.bind(this, function(evt) 103 { 104 graph.panningHandler.hideMenu(); 105 })); 106 107 //增加了手势操作(缩放) 108 if (mxClient.IS_TOUCH) 109 { 110 mxEvent.addListener(graph.container, \'gesturechange\', 111 mxUtils.bind(this, function(evt) 112 { 113 graph.view.getDrawPane().setAttribute(\'transform\', \'scale(\' + evt.scale + \')\'); 114 graph.view.getOverlayPane().style.visibility = \'hidden\'; 115 }) 116 ); 117 118 mxEvent.addListener(graph.container, \'gestureend\', 119 mxUtils.bind(this, function(evt) 120 { 121 graph.view.getDrawPane().removeAttribute(\'transform\'); 122 graph.zoomToCenter = true; 123 graph.zoom(evt.scale); 124 graph.view.getOverlayPane().style.visibility = \'visible\'; 125 }) 126 ); 127 } 128 129 // Create handler for key events 130 var keyHandler = this.createKeyHandler(editor); 131 132 // Getter for key handler 133 this.getKeyHandler = function() 134 { 135 return keyHandler; 136 }; 137 138 // Shows dialog if changes are lost 139 window.onbeforeunload = function() 140 { 141 if (editor.modified) 142 { 143 //return mxResources.get(\'allChangesLost\'); 144 } 145 }; 146 147 // Updates the editor UI after the window has been resized 148 mxEvent.addListener(window, \'resize\', mxUtils.bind(this, function() 149 { 150 this.refresh(); 151 graph.sizeDidChange(); 152 this.editor.outline.update(false); 153 this.editor.outline.outline.sizeDidChange(); 154 })); 155 156 // Updates action and menu states 157 this.init(); 158 this.open(); 159 }; 160 161 /** 162 * Specifies the size of the split bar. 163 */ 164 EditorUi.prototype.splitSize = (mxClient.IS_TOUCH) ? 16 : 8; 165 166 /** 167 * Specifies the height of the menubar. Default is 34. 168 */ 169 EditorUi.prototype.menubarHeight = 34; 170 171 /** 172 * Specifies the height of the toolbar. Default is 46. 173 */ 174 EditorUi.prototype.toolbarHeight = 46; 175 176 /** 177 * Specifies the height of the footer. Default is 28. 178 */ 179 EditorUi.prototype.footerHeight = 28; 180 181 /** 182 * Specifies the position of the horizontal split bar. Default is 190. 183 */ 184 EditorUi.prototype.hsplitPosition = 190; 185 186 /** 187 * Specifies the position of the vertical split bar. Default is 190. 188 */ 189 EditorUi.prototype.vsplitPosition = 190; 190 191 /** 192 * Installs the listeners to update the action states. 193 */ 194 EditorUi.prototype.init = function() 195 { 196 // Updates action states 197 this.addUndoListener(); 198 this.addSelectionListener(); 199 200 // Overrides clipboard to update paste action state 201 var paste = this.actions.get(\'paste\'); 202 203 var updatePaste = function() 204 { 205 paste.setEnabled(!mxClipboard.isEmpty()); 206 }; 207 208 var mxClipboardCut =http://www.likecs.com/ mxClipboard.cut; 209 mxClipboard.cut = function() 210 { 211 mxClipboardCut.apply(this, arguments); 212 updatePaste(); 213 }; 214 215 var mxClipboardCopy =http://www.likecs.com/ mxClipboard.copy; 216 mxClipboard.copy = function() 217 { 218 mxClipboardCopy.apply(this, arguments); 219 updatePaste(); 220 }; 221 }; 222 223 /** 224 * Hook for allowing selection and context menu for certain events. 225 */ 226 EditorUi.prototype.isSelectionAllowed = function(evt) 227 { 228 return false; 229 }; 230 231 /** 232 * Opens the current diagram via the window.opener if one exists. 233 */ 234 EditorUi.prototype.open = function() 235 { 236 // Cross-domain window access is not allowed in FF, so if we 237 // were opened from another domain then this will fail. 238 try 239 { 240 if (window.opener != null && window.opener.openFile != null) 241 { 242 window.opener.openFile.setConsumer(mxUtils.bind(this, function(xml, filename) 243 { 244 try 245 { 246 var doc =http://www.likecs.com/ mxUtils.parseXml(xml); 247 this.editor.setGraphXml(doc.documentElement); 248 this.editor.modified = false; 249 this.editor.undoManager.clear(); 250 251 if (filename != null) 252 { 253 this.editor.filename =http://www.likecs.com/ filename; 254 } 255 } 256 catch (e) 257 { 258 mxUtils.alert(mxResources.get(\'invalidOrMissingFile\') + \': \' + e.message); 259 } 260 })); 261 } 262 } 263 catch(e) 264 { 265 // ignore 266 } 267 }; 268 269 /** 270 * 在给定的文件名保存当前图。 271 */ 272 EditorUi.prototype.save = function() 273 { 274 var xml = mxUtils.getXml(this.editor.getGraphXml()); 275 //火狐浏览器 276 //if (navigator.userAgent.indexOf(\'Firefox\') >= 0){ 277 //} 278 xml="<mxGraphModel grid=\"0\" guides=\"1\" tooltips=\"1\" connect=\"1\" fold=\"1\" page=\"0\" pageScale=\"1\" pageWidth=\"826\" pageHeight=\"1169\">"+xml+"</mxGraphModel>" 279 280 //将xml代码保存至服务器文件 281 $.post($("#path").val()+"/SaveToXmlServlet",{"tp":$("#mapTp").val(),"xml":xml,"type":"set"},function(text){ 282 if(text=="0"){ 283 alert("保存失败!"); 284 } 285 }); 286 }; 287 288 /** 289 * 返回一个拷贝没有状态这个编辑器的URL。 290 */ 291 EditorUi.prototype.getUrl = function(pathname) 292 { 293 var href = (pathname != null) ? pathname : window.location.pathname; 294 var parms = (pathname.indexOf(\'?\') > 0) ? 1 : 0; 295 296 // Removes template URL parameter for new blank diagram 297 for (var key in urlParams) 298 { 299 if (parms == 0) 300 { 301 href += \'?\'; 302 } 303 else 304 { 305 href += \'&\'; 306 } 307 308 href += key + \'=\' + urlParams[key]; 309 parms++; 310 } 311 312 return href; 313 }; 314 315 /** 316 * 更新的撤销/重做项的状态。 317 */ 318 EditorUi.prototype.addUndoListener = function() 319 { 320 var undo = this.actions.get(\'undo\'); 321 var redo = this.actions.get(\'redo\'); 322 323 var undoMgr = this.editor.undoManager; 324 325 var undoListener = function() 326 { 327 undo.setEnabled(undoMgr.canUndo()); 328 redo.setEnabled(undoMgr.canRedo()); 329 }; 330 331 undoMgr.addListener(mxEvent.ADD, undoListener); 332 undoMgr.addListener(mxEvent.UNDO, undoListener); 333 undoMgr.addListener(mxEvent.REDO, undoListener); 334 undoMgr.addListener(mxEvent.CLEAR, undoListener); 335 336 // Updates the button states once 337 undoListener(); 338 }; 339 340 /** 341 * Updates the states of the given toolbar items based on the selection. 342 */ 343 EditorUi.prototype.addSelectionListener = function() 344 { 345 var selectionListener = mxUtils.bind(this, function() 346 { 347 var graph = this.editor.graph; 348 var selected = !graph.isSelectionEmpty(); 349 var vertexSelected = false; 350 var edgeSelected = false; 351 352 var cells =http://www.likecs.com/ graph.getSelectionCells(); 353 354 if (cells != null) 355 { 356 for (var i = 0; i < cells.length; i++) 357 { 358 var cell =http://www.likecs.com/ cells[i]; 359 360 if (graph.getModel().isEdge(cell)) 361 { 362 edgeSelected = true; 363 } 364 365 if (graph.getModel().isVertex(cell)) 366 { 367 vertexSelected = true; 368 } 369 370 if (edgeSelected && vertexSelected) 371 { 372 break; 373 } 374 } 375 } 376 377 // 更新动作状态 378 var actions = [\'cut\', \'copy\', \'delete\', \'duplicate\', \'bold\', \'italic\', \'style\', \'fillColor\', 379 \'gradientColor\', \'underline\', \'fontColor\', \'strokeColor\', \'backgroundColor\', 380 \'borderColor\', \'toFront\', \'toBack\', \'dashed\', \'rounded\', \'shadow\', \'rotate\', 381 \'autosize\']; 382 383 for (var i = 0; i < actions.length; i++) 384 { 385 this.actions.get(actions[i]).setEnabled(selected); 386 } 387 388 this.actions.get(\'rotation\').setEnabled(vertexSelected); 389 this.actions.get(\'group\').setEnabled(graph.getSelectionCount() > 1); 390 this.actions.get(\'ungroup\').setEnabled(graph.getSelectionCount() == 1 && 391 graph.getModel().getChildCount(graph.getSelectionCell()) > 0); 392 var oneVertexSelected = vertexSelected && graph.getSelectionCount() == 1; 393 this.actions.get(\'removeFromGroup\').setEnabled(oneVertexSelected && 394 graph.getModel().isVertex(graph.getModel().getParent(graph.getSelectionCell()))); 395 396 //更新菜单状态 397 var menus = [\'fontFamily\', \'fontSize\', \'alignment\', \'position\', \'text\', \'format\', 398 \'arrange\', \'linewidth\', \'spacing\', \'gradient\']; 399 400 for (var i = 0; i < menus.length; i++) 401 { 402 this.menus.get(menus[i]).setEnabled(selected); 403 } 404 405 menus = [\'line\', \'lineend\', \'linestart\']; 406 407 for (var i = 0; i < menus.length; i++) 408 { 409 this.menus.get(menus[i]).setEnabled(edgeSelected); 410 } 411 412 this.actions.get(\'setAsDefaultEdge\').setEnabled(edgeSelected); 413 414 this.menus.get(\'align\').setEnabled(graph.getSelectionCount() > 1); 415 this.menus.get(\'direction\').setEnabled(vertexSelected || (edgeSelected && 416 graph.isLoop(graph.view.getState(graph.getSelectionCell())))); 417 this.menus.get(\'navigation\').setEnabled(graph.foldingEnabled && ((graph.view.currentRoot != null) || 418 (graph.getSelectionCount() == 1 && graph.isValidRoot(graph.getSelectionCell())))); 419 this.actions.get(\'home\').setEnabled(graph.view.currentRoot != null); 420 this.actions.get(\'exitGroup\').setEnabled(graph.view.currentRoot != null); 421 var groupEnabled = graph.getSelectionCount() == 1 && graph.isValidRoot(graph.getSelectionCell()); 422 this.actions.get(\'enterGroup\').setEnabled(groupEnabled); 423 this.actions.get(\'expand\').setEnabled(groupEnabled); 424 this.actions.get(\'collapse\').setEnabled(groupEnabled); 425 this.actions.get(\'editLink\').setEnabled(graph.getSelectionCount() == 1); 426 this.actions.get(\'openLink\').setEnabled(graph.getSelectionCount() == 1 && 427 graph.getLinkForCell(graph.getSelectionCell()) != null); 428 }); 429 430 this.editor.graph.getSelectionModel().addListener(mxEvent.CHANGE, selectionListener); 431 selectionListener(); 432 }; 433 434 /** 435 * Refreshes the viewport. 436 */ 437 EditorUi.prototype.refresh = function() 438 { 439 var quirks = mxClient.IS_IE && (document.documentMode == null || document.documentMode == 5); 440 var w = this.container.clientWidth; 441 var h = this.container.clientHeight; 442 443 if (this.container ==http://www.likecs.com/ document.body) 444 { 445 w = document.body.clientWidth || document.documentElement.clientWidth; 446 h = (quirks) ? document.body.clientHeight || document.documentElement.clientHeight : document.documentElement.clientHeight; 447 } 448 449 var effHsplitPosition = Math.max(0, Math.min(this.hsplitPosition, w - this.splitSize - 20)); 450 var effVsplitPosition = Math.max(0, Math.min(this.vsplitPosition, h - this.menubarHeight - this.toolbarHeight - this.footerHeight - this.splitSize - 1)); 451 452 this.menubarContainer.style.height = this.menubarHeight + \'px\'; 453 this.toolbarContainer.style.top = this.menubarHeight + \'px\'; 454 this.toolbarContainer.style.height = this.toolbarHeight + \'px\'; 455 this.sidebarContainer.style.top = (this.menubarHeight + this.toolbarHeight) + \'px\'; 456 this.sidebarContainer.style.width = effHsplitPosition + \'px\'; 457 this.outlineContainer.style.width = effHsplitPosition + \'px\'; 458 this.outlineContainer.style.height = effVsplitPosition + \'px\'; 459 this.outlineContainer.style.bottom = this.footerHeight + \'px\'; 460 this.diagramContainer.style.left = (effHsplitPosition + this.splitSize) + \'px\'; 461 this.diagramContainer.style.top = this.sidebarContainer.style.top; 462 this.footerContainer.style.height = this.footerHeight + \'px\'; 463 this.hsplit.style.top = this.sidebarContainer.style.top; 464 this.hsplit.style.bottom = this.outlineContainer.style.bottom; 465 this.hsplit.style.left = effHsplitPosition + \'px\'; 466 this.vsplit.style.width = this.sidebarContainer.style.width; 467 this.vsplit.style.bottom = (effVsplitPosition + this.footerHeight) + \'px\'; 468 469 if (quirks) 470 { 471 this.menubarContainer.style.width = w + \'px\'; 472 this.toolbarContainer.style.width = this.menubarContainer.style.width; 473 var sidebarHeight = (h - effVsplitPosition - this.splitSize - this.footerHeight - this.menubarHeight - this.toolbarHeight); 474 this.sidebarContainer.style.height = sidebarHeight + \'px\'; 475 this.diagramContainer.style.width = (w - effHsplitPosition - this.splitSize) + \'px\'; 476 var diagramHeight = (h - this.footerHeight - this.menubarHeight - this.toolbarHeight); 477 this.diagramContainer.style.height = diagramHeight + \'px\'; 478 this.footerContainer.style.width = this.menubarContainer.style.width; 479 this.hsplit.style.height = diagramHeight + \'px\'; 480 } 481 else 482 { 483 this.sidebarContainer.style.bottom = (effVsplitPosition + this.splitSize + this.footerHeight) + \'px\'; 484 this.diagramContainer.style.bottom = this.outlineContainer.style.bottom; 485 } 486 }; 487 488 /** 489 * Creates the required containers. 490 */ 491 EditorUi.prototype.createDivs = function() 492 { 493 this.menubarContainer = this.createDiv(\'geMenubarContainer\'); 494 this.toolbarContainer = this.createDiv(\'geToolbarContainer\'); 495 this.sidebarContainer = this.createDiv(\'geSidebarContainer\'); 496 this.outlineContainer = this.createDiv(\'geOutlineContainer\'); 497 this.diagramContainer = this.createDiv(\'geDiagramContainer\'); 498 this.footerContainer = this.createDiv(\'geFooterContainer\'); 499 this.hsplit = this.createDiv(\'geHsplit\'); 500 this.vsplit = this.createDiv(\'geVsplit\'); 501 502 // Sets static style for containers 503 this.menubarContainer.style.top = \'0px\'; 504 this.menubarContainer.style.left = \'0px\'; 505 this.menubarContainer.style.right = \'0px\'; 506 this.toolbarContainer.style.left = \'0px\'; 507 this.toolbarContainer.style.right = \'0px\'; 508 this.sidebarContainer.style.left = \'0px\'; 509 this.outlineContainer.style.left = \'0px\'; 510 this.diagramContainer.style.right = \'0px\'; 511 this.footerContainer.style.left = \'0px\'; 512 this.footerContainer.style.right = \'0px\'; 513 this.footerContainer.style.bottom = \'0px\'; 514 this.vsplit.style.left = \'0px\'; 515 this.vsplit.style.height = this.splitSize + \'px\'; 516 this.hsplit.style.width = this.splitSize + \'px\'; 517 }; 518 519 /** 520 * Creates the required containers. 521 */ 522 EditorUi.prototype.createUi = function() 523 { 524 // Creates menubar 525 this.menubar = this.menus.createMenubar(this.createDiv(\'geMenubar\')); 526 this.menubarContainer.appendChild(this.menubar.container); 527 528 // Creates toolbar 529 this.toolbar = this.createToolbar(this.createDiv(\'geToolbar\')); 530 this.toolbarContainer.appendChild(this.toolbar.container); 531 532 // Creates the sidebar 533 this.sidebar = this.createSidebar(this.sidebarContainer); 534 535 // Creates the footer 536 this.footerContainer.appendChild(this.createFooter()); 537 538 // Adds status bar in menubar 539 this.statusContainer = this.createStatusContainer(); 540 541 // Connects the status bar to the editor status 542 this.editor.addListener(\'statusChanged\', mxUtils.bind(this, function() 543 { 544 this.setStatusText(this.editor.getStatus()); 545 })); 546 547 this.setStatusText(this.editor.getStatus()); 548 this.menubar.container.appendChild(this.statusContainer); 549 550 // Inserts into DOM 551 this.container.appendChild(this.menubarContainer); 552 this.container.appendChild(this.toolbarContainer); 553 this.container.appendChild(this.sidebarContainer); 554 this.container.appendChild(this.outlineContainer); 555 this.container.appendChild(this.diagramContainer); 556 this.container.appendChild(this.footerContainer); 557 this.container.appendChild(this.hsplit); 558 this.container.appendChild(this.vsplit); 559 560 // HSplit 561 this.addSplitHandler(this.hsplit, true, 0, mxUtils.bind(this, function(value) 562 { 563 this.hsplitPosition =http://www.likecs.com/ value; 564 this.refresh(); 565 this.editor.graph.sizeDidChange(); 566 this.editor.outline.update(false); 567 this.editor.outline.outline.sizeDidChange(); 568 })); 569 570 // VSplit 571 this.addSplitHandler(this.vsplit, false, this.footerHeight, mxUtils.bind(this, function(value) 572 { 573 this.vsplitPosition =http://www.likecs.com/ value; 574 this.refresh(); 575 this.editor.outline.update(false); 576 this.editor.outline.outline.sizeDidChange(); 577 })); 578 }; 579 580 /** 581 * Creates a new toolbar for the given container. 582 */ 583 EditorUi.prototype.createStatusContainer = function() 584 { 585 var container = document.createElement(\'a\'); 586 container.className = \'geItem geStatus\'; 587 588 return container; 589 }; 590 591 /** 592 * Creates a new toolbar for the given container. 593 */ 594 EditorUi.prototype.setStatusText = function(value) 595 { 596 this.statusContainer.innerHTML =http://www.likecs.com/ value; 597 }; 598 599 /** 600 * Creates a new toolbar for the given container. 601 */ 602 EditorUi.prototype.createToolbar = function(container) 603 { 604 return new Toolbar(this, container); 605 }; 606 607 /** 608 * Creates a new sidebar for the given container. 609 */ 610 EditorUi.prototype.createSidebar = function(container) 611 { 612 return new Sidebar(this, container); 613 }; 614 615 /** 616 * Creates and returns a new footer. 617 */ 618 EditorUi.prototype.createFooter = function() 619 { 620 return this.createDiv(\'geFooter\'); 621 }; 622 623 /** 624 * Creates the actual toolbar for the toolbar container. 625 */ 626 EditorUi.prototype.createDiv = function(classname) 627 { 628 var elt = document.createElement(\'div\'); 629 elt.className =http://www.likecs.com/ classname; 630 631 return elt; 632 }; 633 634 /** 635 * Updates the states of the given undo/redo items. 636 */ 637 EditorUi.prototype.addSplitHandler = function(elt, horizontal, dx, onChange) 638 { 639 var start = null; 640 var initial = null; 641 642 function getValue() 643 { 644 return parseInt(((horizontal) ? elt.style.left : elt.style.bottom)); 645 } 646 647 var md = (mxClient.IS_TOUCH) ? \'touchstart\' : \'mousedown\'; 648 var mm = (mxClient.IS_TOUCH) ? \'touchmove\' : \'mousemove\'; 649 var mu = (mxClient.IS_TOUCH) ? \'touchend\' : \'mouseup\'; 650 651 mxEvent.addListener(elt, md, function(evt) 652 { 653 start = new mxPoint(mxEvent.getClientX(evt), mxEvent.getClientY(evt)); 654 initial =http://www.likecs.com/ getValue(); 655 mxEvent.consume(evt); 656 }); 657 658 function moveHandler(evt) 659 { 660 if (start != null) 661 { 662 var pt = new mxPoint(mxEvent.getClientX(evt), mxEvent.getClientY(evt)); 663 onChange(Math.max(0, initial + ((horizontal) ? (pt.x - start.x) : (start.y - pt.y)) - dx)); 664 mxEvent.consume(evt); 665 } 666 } 667 668 mxEvent.addListener(document, mm, moveHandler); 669 670 mxEvent.addListener(document, mu, function(evt) 671 { 672 moveHandler(evt); 673 start = null; 674 initial = null; 675 }); 676 }; 677 678 /** 679 * Displays a print dialog. 680 */ 681 EditorUi.prototype.showDialog = function(elt, w, h, modal, closable, onClose) 682 { 683 this.hideDialog(); 684 this.dialog = new Dialog(this, elt, w, (mxClient.IS_VML) ? h - 12 : h, modal, closable, onClose); 685 }; 686 687 /** 688 * Displays a print dialog. 689 */ 690 EditorUi.prototype.hideDialog = function() 691 { 692 if (this.dialog != null) 693 { 694 this.dialog.close(); 695 this.dialog = null; 696 this.editor.graph.container.focus(); 697 } 698 }; 699 700 /** 701 * Adds the label menu items to the given menu and parent. 702 */ 703 EditorUi.prototype.openFile = function() 704 { 705 // Closes dialog after open 706 window.openFile = new OpenFile(mxUtils.bind(this, function() 707 { 708 this.hideDialog(); 709 })); 710 711 // Removes openFile if dialog is closed 712 this.showDialog(new OpenDialog(this).container, 300, 180, true, true, function() 713 { 714 window.openFile = null; 715 }); 716 }; 717 718 /** 719 * Adds the label menu items to the given menu and parent. 720 */ 721 EditorUi.prototype.saveFile = function(forceDialog) 722 { 723 if (!forceDialog && this.editor.filename != null) 724 { 725 this.save(this.editor.getOrCreateFilename()); 726 } 727 else 728 { 729 this.showDialog(new SaveDialog(this).container, 300, 100, true, true); 730 } 731 }; 732 733 /** 734 * Executes the given layout. 735 */ 736 EditorUi.prototype.executeLayout = function(layout, animate, ignoreChildCount) 737 { 738 var graph = this.editor.graph; 739 var cell =http://www.likecs.com/ graph.getSelectionCell(); 740 741 graph.getModel().beginUpdate(); 742 try 743 { 744 layout.execute(graph.getDefaultParent(), cell); 745 } 746 catch (e) 747 { 748 throw e; 749 } 750 finally 751 { 752 // Animates the changes in the graph model except 753 // for Camino, where animation is too slow 754 if (animate && navigator.userAgent.indexOf(\'Camino\') < 0) 755 { 756 // New API for animating graph layout results asynchronously 757 var morph = new mxMorphing(graph); 758 morph.addListener(mxEvent.DONE, mxUtils.bind(this, function() 759 { 760 graph.getModel().endUpdate(); 761 })); 762 763 morph.startAnimation(); 764 } 765 else 766 { 767 graph.getModel().endUpdate(); 768 } 769 } 770 }; 771 772 /** 773 * Creates the keyboard event handler for the current graph and history. 774 */ 775 EditorUi.prototype.createKeyHandler = function(editor) 776 { 777 var graph = this.editor.graph; 778 var keyHandler = new mxKeyHandler(graph); 779 780 // Routes command-key to control-key on Mac 781 keyHandler.isControlDown = function(evt) 782 { 783 return mxEvent.isControlDown(evt) || (mxClient.IS_MAC && evt.metaKey); 784 }; 785 786 // Helper function to move cells with the cursor keys 787 function nudge(keyCode) 788 { 789 if (!graph.isSelectionEmpty()) 790 { 791 var dx = 0; 792 var dy = 0; 793 794 if (keyCode == 37) 795 { 796 dx = -1; 797 } 798 else if (keyCode == 38) 799 { 800 dy = -1; 801 } 802 else if (keyCode == 39) 803 { 804 dx = 1; 805 } 806 else if (keyCode == 40) 807 { 808 dy = 1; 809 } 810 811 graph.moveCells(graph.getSelectionCells(), dx, dy); 812 graph.scrollCellVisible(graph.getSelectionCell()); 813 } 814 }; 815 816 // Binds keystrokes to actions 817 var bindAction = mxUtils.bind(this, function(code, control, key, shift) 818 { 819 var action = this.actions.get(key); 820 821 if (action != null) 822 { 823 var f = function() 824 { 825 if (action.enabled) 826 { 827 action.funct(); 828 } 829 }; 830 831 if (control) 832 { 833 if (shift) 834 { 835 keyHandler.bindControlShiftKey(code, f); 836 } 837 else 838 { 839 keyHandler.bindControlKey(code, f); 840 } 841 } 842 else 843 { 844 if (shift) 845 { 846 keyHandler.bindShiftKey(code, f); 847 } 848 else 849 { 850 keyHandler.bindKey(code, f); 851 } 852 } 853 } 854 }); 855 856 var ui = this; 857 var keyHandleEscape =http://www.likecs.com/ keyHandler.escape; 858 keyHandler.escape = function(evt) 859 { 860 ui.hideDialog(); 861 keyHandleEscape.apply(this, arguments); 862 }; 863 864 // Ignores enter keystroke. Remove this line if you want the 865 // enter keystroke to stop editing. 866 keyHandler.enter = function() {}; 867 keyHandler.bindKey(8, function() { graph.foldCells(true); }); // Backspace 868 keyHandler.bindKey(13, function() { graph.foldCells(false); }); // Enter 869 keyHandler.bindKey(33, function() { graph.exitGroup(); }); // Page Up 870 keyHandler.bindKey(34, function() { graph.enterGroup(); }); // Page Down 871 keyHandler.bindKey(36, function() { graph.home(); }); // Home 872 keyHandler.bindKey(35, function() { graph.refresh(); }); // End 873 keyHandler.bindKey(37, function() { nudge(37); }); // Left arrow 874 keyHandler.bindKey(38, function() { nudge(38); }); // Up arrow 875 keyHandler.bindKey(39, function() { nudge(39); }); // Right arrow 876 keyHandler.bindKey(40, function() { nudge(40); }); // Down arrow 877 keyHandler.bindKey(113, function() { graph.startEditingAtCell(); }); 878 bindAction(46, false, \'delete\'); // Delete 879 bindAction(82, true, \'rotate\'); // Ctrl+R 880 bindAction(83, true, \'save\'); // Ctrl+S 881 bindAction(83, true, \'saveAs\', true); // Ctrl+Shift+S 882 bindAction(107, false, \'zoomIn\'); // Add 883 bindAction(109, false, \'zoomOut\'); // Subtract 884 bindAction(65, true, \'selectAll\'); // Ctrl+A 885 bindAction(86, true, \'selectVertices\', true); // Ctrl+Shift+V 886 bindAction(69, true, \'selectEdges\', true); // Ctrl+Shift+E 887 bindAction(69, true, \'export\'); // Ctrl+Shift+E 888 bindAction(66, true, \'toBack\'); // Ctrl+B 889 bindAction(70, true, \'toFront\'); // Ctrl+F 890 bindAction(68, true, \'duplicate\'); // Ctrl+D 891 bindAction(90, true, \'undo\'); // Ctrl+Z 892 bindAction(89, true, \'redo\'); // Ctrl+Y 893 bindAction(88, true, \'cut\'); // Ctrl+X 894 bindAction(67, true, \'copy\'); // Ctrl+C 895 bindAction(81, true, \'connect\'); // Ctrl+Q 896 bindAction(86, true, \'paste\'); // Ctrl+V 897 bindAction(71, true, \'group\'); // Ctrl+G 898 bindAction(71, true, \'grid\', true); // Ctrl+Shift+G 899 bindAction(85, true, \'ungroup\'); // Ctrl+U 900 bindAction(112, false, \'about\'); // F1 901 902 return keyHandler; 903 };

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zgfdpp.html