流程圖控件GoJS教程:驗證方式(下)
GoJS是一款功能強大,快速且輕量級的流程圖控件,可幫助你在JavaScript 和HTML5 Canvas程序中創(chuàng)建流程圖,且極大地簡化您的JavaScript / Canvas 程序。
常規(guī)鏈接驗證
在某些情況下,您的應用程序的語義將導致有效鏈接目標集以某種方式取決于節(jié)點數(shù)據(jù)(即,鏈接從其開始的節(jié)點和端口以及可能的目標節(jié)點/端口)只能使用代碼來實現(xiàn):謂詞函數(shù)。
您可以通過設置LinkingBaseTool.linkValidation或Node.linkValidation來實現(xiàn)此類特定于域的驗證。這些謂詞(如果提供)將為鏈接工具考慮的每對端口調用。如果謂詞返回false,則可能無法建立鏈接。在LinkingTool或RelinkingTool上設置屬性會使謂詞應用于所有鏈接操作,而在Node上設置屬性僅適用于涉及該節(jié)點的鏈接操作。根據(jù)上述屬性,只有在所有標準鏈接檢查均通過的情況下,才調用謂詞。
在此示例中,存在三種不同顏色的節(jié)點。該LinkingTool和RelinkingTool自定義為使用的功能,sameColor以確保鏈接只有相同顏色的連接節(jié)點。鼠標向下拖動并在橢圓上拖動(光標變?yōu)椤爸羔槨保?,開始繪制新鏈接。您將看到,唯一允許的鏈接目標是相同顏色的節(jié)點,這些節(jié)點尚未從同一節(jié)點進行鏈接。
diagram.nodeTemplate = $(go.Node, "Auto", $(go.Shape, "Ellipse", { cursor: "pointer", portId: "", fromLinkable: true, toLinkable: true }, new go.Binding("fill", "color")), $(go.TextBlock, { stroke: "white", margin: 3 }, new go.Binding("text", "key")) ); diagram.linkTemplate = $(go.Link, { curve: go.Link.Bezier, relinkableFrom: true, relinkableTo: true }, $(go.Shape, { strokeWidth: 2 }, new go.Binding("stroke", "fromNode", function(n) { return n.data.color; }) .ofObject()), $(go.Shape, { toArrow: "Standard", stroke: null}, new go.Binding("fill", "fromNode", function(n) { return n.data.color; }) .ofObject()) ); // this predicate is true if both nodes have the same color function sameColor(fromnode, fromport, tonode, toport) { return fromnode.data.color === tonode.data.color; // this could look at the fromport.fill and toport.fill instead, // assuming that the ports are Shapes, which they are because portID was set on them, // and that there is a data Binding on the Shape.fill } // only allow new links between ports of the same color diagram.toolManager.linkingTool.linkValidation = sameColor; // only allow reconnecting an existing link to a port of the same color diagram.toolManager.relinkingTool.linkValidation = sameColor; var nodeDataArray = [ { key: "Red1", color: "red" }, { key: "Blue1", color: "blue" }, { key: "Green1", color: "green" }, { key: "Green2", color: "green" }, { key: "Red2", color: "red" }, { key: "Blue2", color: "blue" }, { key: "Red3", color: "red" }, { key: "Green3", color: "green" }, { key: "Blue3", color: "blue" } ]; var linkDataArray = [ // initially no links ]; diagram.model = new go.GraphLinksModel(nodeDataArray, linkDataArray);
為了強調顏色限制,鏈接的顏色綁定到“ from”節(jié)點數(shù)據(jù)。
限制與節(jié)點連接的鏈接總數(shù)
可以通過設置GraphObject.toMaxLinks來限制進入端口的鏈接數(shù)。同樣,可以通過設置GraphObject.fromMaxLinks來限制從端口出來的鏈接數(shù)。但是,如果要限制與端口連接的鏈接總數(shù),而不管它們是進入端口還是離開端口,該怎么辦?這樣的約束只能通過鏈接驗證謂詞來實現(xiàn)。
當要限制任一方向上與每個端口連接的鏈路總數(shù)時,可以使用此Node.linkValidation謂詞:
$(go.Node, . . ., { linkValidation: function(fromnode, fromport, tonode, toport) { // total number of links connecting with a port is limited to 1: return fromnode.findLinksConnected(fromport.portId).count + tonode.findLinksConnected(toport.portId).count < 1; } }, . . .當想要限制任一方向的鏈接總數(shù),并為一個節(jié)點的所有端口連接時,可以使用此Node.linkValidation謂詞:
$(go.Node, . . ., { linkValidation: function(fromnode, fromport, tonode, toport) { // total number of links connecting with all ports of a node is limited to 1: return fromnode.linksConnected.count + tonode.linksConnected.count < 1; } }, . . .
分組驗證
當要限制用戶可以添加到特定組的節(jié)點的類型時,可以將謂詞實現(xiàn)為CommandHandler.memberValidation或Group.memberValidation屬性。在CommandHandler上設置屬性會使謂詞應用于所有組,而在Group上設置屬性僅適用于該組。
在此示例中,samePrefix謂詞用于確定是否可以將節(jié)點放入組中。嘗試將左側的簡單文本節(jié)點拖到右側的任一組中。僅當將節(jié)點放到高亮“綠色”的組上時,該節(jié)點才被添加為該組的成員。您可以通過移動組以查看文本節(jié)點是否也移動來進行驗證。
// this predicate is true if both node data keys start with the same letter function samePrefix(group, node) { if (group === null) return true; // when maybe dropping a node in the background if (node instanceof go.Group) return false; // don't add Groups to Groups return group.data.key.charAt(0) === node.data.key.charAt(0); }; diagram.nodeTemplate = $(go.Node, new go.Binding("location", "loc", go.Point.parse), $(go.TextBlock, new go.Binding("text", "key")) ); diagram.groupTemplate = $(go.Group, "Vertical", { // only allow those simple nodes that have the same data key prefix: memberValidation: samePrefix, // don't need to define handlers on member Nodes and Links handlesDragDropForMembers: true, // support highlighting of Groups when allowing a drop to add a member mouseDragEnter: function(e, grp, prev) { // this will call samePrefix; it is true if any node has the same key prefix if (grp.canAddMembers(grp.diagram.selection)) { var shape = grp.findObject("SHAPE"); if (shape) shape.fill = "green"; grp.diagram.currentCursor = ""; } else { grp.diagram.currentCursor = "not-allowed"; } }, mouseDragLeave: function(e, grp, next) { var shape = grp.findObject("SHAPE"); if (shape) shape.fill = "rgba(128,128,128,0.33)"; grp.diagram.currentCursor = ""; }, // actually add permitted new members when a drop occurs mouseDrop: function(e, grp) { if (grp.canAddMembers(grp.diagram.selection)) { // this will only add nodes with the same key prefix grp.addMembers(grp.diagram.selection, true); } else { // and otherwise cancel the drop grp.diagram.currentTool.doCancel(); } } }, // make sure all Groups are behind all regular Nodes { layerName: "Background" }, new go.Binding("location", "loc", go.Point.parse), $(go.TextBlock, { alignment: go.Spot.Left, font: "Bold 12pt Sans-Serif" }, new go.Binding("text", "key")), $(go.Shape, { name: "SHAPE", width: 100, height: 100, fill: "rgba(128,128,128,0.33)" }) ); diagram.mouseDrop = function(e) { // dropping in diagram background removes nodes from any group diagram.commandHandler.addTopLevelParts(diagram.selection, true); }; var nodeDataArray = [ { key: "A group", isGroup: true, loc: "100 10" }, { key: "B group", isGroup: true, loc: "100 140" }, { key: "A1", loc: "10 30" }, // can be added to "A" group { key: "A2", loc: "10 60" }, { key: "B1", loc: "10 90" }, // can be added to "B" group { key: "B2", loc: "10 120" }, { key: "C1", loc: "10 150" } // cannot be added to either group ]; diagram.model = new go.GraphLinksModel(nodeDataArray, []);
這些組是固定大小的組-它們不使用Placeholder。因此,當將節(jié)點放入其中時,該組不會自動調整自身大小以包圍其成員節(jié)點。但這在將節(jié)點拖出組時也是有好處的。
拖動已經是組成員的節(jié)點時,也會調用驗證謂詞。您可以看到將節(jié)點放入其現(xiàn)有的包含組是如何可接受的。當將其拖動到組的外部到圖的背景中時,謂詞將以null作為“組”參數(shù)被調用。
在此示例中,將節(jié)點放到圖的背景中而不是放到一個組中總是可以的。如果要禁止在后臺拖放,可以myDiagram.currentTool.doCancel() 在Diagram.mouseDrop事件處理程序中調用。如果要在后臺拖動過程中顯示反饋,則可以實現(xiàn)一個set 的Diagram.mouseDragOver事件處理程序 myDiagram.currentCursor = "not-allowed"。當在“組”中拖動時,此行為將類似于上面實現(xiàn)的行為。
文字編輯驗證
您還可以限制用戶在對TextBlock進行就地文本編輯時輸入的文本。首先,要完全啟用任何編輯,您需要將TextBlock.editable設置為true。零件中可能有許多TextBlock,但是您可能希望將文本編輯限制為特定的TextBlock。
通常,用戶可以輸入什么文字沒有限制。如果要提供斷言以在用戶完成編輯時批準輸入,請設置TextEditingTool.textValidation或TextBlock.textValidation屬性。在TextEditingTool上設置屬性會使謂詞應用于所有TextBlock,而在TextBlock上設置屬性僅應用于該文本對象。
// this predicate is true if the new string has at least three characters // and has a vowel in it function okName(textblock, oldstr, newstr) { return newstr.length >= 3 && /[aeiouy]/i.test(newstr); }; diagram.nodeTemplate = $(go.Node, "Auto", $(go.Shape, { fill: "lightyellow" }), $(go.Panel, "Vertical", { margin: 3 }, $(go.TextBlock, { editable: true }, // no validation predicate new go.Binding("text", "text1")), $(go.TextBlock, { editable: true, isMultiline: false, // don't allow embedded newlines textValidation: okName }, // new string must be an OK name new go.Binding("text", "text2")) ) ); var nodeDataArray = [ { key: 1, text1: "Hello", text2: "Dolly!" }, { key: 2, text1: "Goodbye", text2: "Mr. Chips" } ]; diagram.model = new go.GraphLinksModel(nodeDataArray, []);
請注意,如何編輯頂部的TextBlock如何接受不帶任何元音的文本,但是底部的TextBlock不接受它,而是使文本編輯器處于打開狀態(tài)。
如果要在文本編輯完成后執(zhí)行代碼,請通過調用Diagram.addDiagramListener來實現(xiàn)“ TextEdited” DiagramEvent偵聽器。
====================================================
有關產品的最新消息和最新資訊,歡迎掃描關注下方微信公眾號