GoJS组织结构图2
- <!DOCTYPE html>
- <html>
- <head>
- <meta charset="UTF-8">
- <title>组织结构图</title>
- <meta name="description" content="An organization chart editor -- edit details and change relationships." />
- <meta name="viewport" content="width=device-width, initial-scale=1">
- <!-- Copyright - by Northwoods Software Corporation. -->
- <style>
- .inspector {
- display: inline-block;
- font: bold 14px helvetica, sans-serif;
- background-color: #;
- /* Grey 900 */
- color: #F5F5F5;
- /* Grey 100 */
- cursor: default;
- }
- .inspector table {
- border-collapse: separate;
- border-spacing: 2px;
- }
- .inspector td,
- th {
- padding: 2px;
- }
- .inspector input {
- background-color: #;
- /* Grey 800 */
- color: #F5F5F5;
- /* Grey 100 */
- font: bold 12px helvetica, sans-serif;
- border: 0px;
- padding: 2px;
- }
- .inspector input:disabled {
- background-color: #BDBDBD;
- /* Grey 400 */
- color: #;
- /* Grey 700 */
- }
- .inspector select {
- background-color: #;
- }
- </style>
- <script src="https://cdnjs.cloudflare.com/ajax/libs/gojs/1.8.13/go-debug.js"></script>
- <!-- this is only for the GoJS Samples framework -->
- </head>
- <body onload="init()">
- <div id="sample">
- <div id="myDiagramDiv" style="background-color: #34343C; border: solid 1px black; height: 570px;"></div>
- <p>
- <button id="zoomToFit">Zoom to Fit</button>
- <button id="centerRoot">Center on root</button>
- </p>
- <div>
- <div id="myInspector">
- </div>
- </div>
- <p>
- This editable organizational chart sample color-codes the Nodes according to the tree level in the hierarchy.
- </p>
- <p>
- Double click on a node in order to add a person or the diagram background to add a new boss. Double clicking the diagram
- uses the
- <a>ClickCreatingTool</a>
- with a custom
- <a>ClickCreatingTool.insertPart</a> to scroll to the new node and start editing the
- <a>TextBlock</a> for its name .
- </p>
- <p>
- Drag a node onto another in order to change relationships. You can also draw a link from a node's background to other nodes
- that have no "boss". Links can also be relinked to change relationships. Right-click or tap-hold a Node to bring up
- a context menu which allows you to:
- <ul>
- <li>Vacate Position - remove the information specfic to the current person in that role</li>
- <li>Remove Role - removes the role entirely and reparents any children</li>
- <li>Remove Department - removes the role and the whole subtree</li>
- </ul>
- Deleting a Node or Link will orphan the child Nodes and generate a new tree. A custom SelectionDeleting
- <a>DiagramEvent</a> listener will clear out the boss info when the parent is removed.
- </p>
- <p>
- Select a node to edit/update node data values. This sample uses the
- <a href="../extensions/dataInspector.html">Data Inspector</a> extension to display and modify Part data.
- </p>
- <p>
- To learn how to build an org chart from scratch with GoJS, see the
- <a href="../learn/index.html">Getting Started tutorial</a>.
- </p>
- <p>
- If you want to have some "assistant" nodes on the side, above the regular reports, see the
- <a href="orgChartAssistants.html">Org Chart Assistants</a> sample, which is a copy of this sample that uses a custom
- <a>TreeLayout</a> to position "assistants" that way.
- </p>
- <div>
- <div>
- <button id="SaveButton" onclick="save()">Save</button>
- <button onclick="load()">Load</button>
- Diagram Model saved in JSON format:
- </div>
- <textarea id="mySavedModel" style="width:100%; height:270px;">
- { "class": "go.TreeModel",
- "nodeDataArray": [
- {"key":, "name":"中心主题"}
- ]
- }
- </textarea>
- </div>
- </div>
- </body>
- <script id="code">
- function init() {
- if (window.goSamples) goSamples(); // init for these samples -- you don't need to call this
- var $ = go.GraphObject.make; //GraphObject是所有图形基类,这里简洁定义模板,$太敏感,为避免与jQuery冲突,此处使用ds
- //图表由节点、文字、线、箭头组成。
- myDiagram =
- $(go.Diagram, "myDiagramDiv", // must be the ID or reference to div
- {
- "initialContentAlignment": go.Spot.Center, // 将图表在画布中居中显示
- maxSelectionCount: , // 一次允许选择一个部件,
- //"isReadOnly": true, // 只读
- "allowZoom": true, //画布缩放
- //"InitialLayoutCompleted":loadDiagramProperties这是函数名, //一个DiagramEvent侦听器
- //鼠标滚轮事件放大和缩小,而不是向上和向下滚动
- "toolManager.mouseWheelBehavior": go.ToolManager.WheelZoom,
- "undoManager.isEnabled": true, // 操作支持Ctrl-Z撤销、Ctrl-Y重做
- validCycle: go.Diagram.CycleDestinationTree, // make sure users can only create trees
- //"clickCreatingTool.archetypeNodeData": { // 默认单根节点,这段代码允许多根节点,双击背景创建新的根节点
- // name: "(自由节点)"
- //},
- "clickCreatingTool.insertPart": function (loc) { // scroll to the new node
- var node = go.ClickCreatingTool.prototype.insertPart.call(this, loc);
- if (node !== null) {
- this.diagram.select(node);
- this.diagram.commandHandler.scrollToPart(node);
- this.diagram.commandHandler.editTextBlock(node.findObject("NAMETB"));
- }
- return node;
- },
- layout:
- $(go.TreeLayout,
- {
- treeStyle: go.TreeLayout.StyleLastParents,
- arrangement: go.TreeLayout.ArrangementHorizontal,
- // properties for most of the tree:
- angle: ,
- layerSpacing: ,
- // properties for the "last parents":
- alternateAngle: ,
- alternateLayerSpacing: ,
- alternateAlignment: go.TreeLayout.AlignmentBus,
- alternateNodeSpacing:
- })
- });
- // 当文档被修改时,在标题中添加“*”并启用“Save”按钮
- myDiagram.addDiagramListener("Modified", function (e) {
- var button = document.getElementById("SaveButton");
- if (button) button.disabled = !myDiagram.isModified;
- var idx = document.title.indexOf("*");
- if (myDiagram.isModified) {
- if (idx < ) document.title += "*";
- } else {
- if (idx >= ) document.title = document.title.substr(, idx);
- }
- });
- // manage boss info manually when a node or link is deleted from the diagram
- myDiagram.addDiagramListener("SelectionDeleting", function (e) {
- var part = e.subject.first(); // e.subject is the myDiagram.selection collection,
- // so we'll get the first since we know we only have one selection
- myDiagram.startTransaction("clear boss");
- if (part instanceof go.Node) {
- var it = part.findTreeChildrenNodes(); // find all child nodes
- while (it.next()) { // now iterate through them and clear out the boss information
- var child = it.value;
- var bossText = child.findObject("boss"); // since the boss TextBlock is named, we can access it by name
- if (bossText === null) return;
- bossText.text = "";
- }
- } else if (part instanceof go.Link) {
- var child = part.toNode;
- var bossText = child.findObject("boss"); // since the boss TextBlock is named, we can access it by name
- if (bossText === null) return;
- bossText.text = "";
- }
- myDiagram.commitTransaction("clear boss");
- });
- var levelColors = ["#AC193D", "#2672EC", "#8C0095", "#5133AB",
- "#008299", "#D24726", "#008A00", "#094AB2"];
- // override TreeLayout.commitNodes to also modify the background brush based on the tree depth level
- myDiagram.layout.commitNodes = function () {
- go.TreeLayout.prototype.commitNodes.call(myDiagram.layout); // do the standard behavior
- // then go through all of the vertexes and set their corresponding node's Shape.fill
- // to a brush dependent on the TreeVertex.level value
- myDiagram.layout.network.vertexes.each(function (v) {
- if (v.node) {
- var level = v.level % (levelColors.length);
- var color = levelColors[level];
- var shape = v.node.findObject("SHAPE");
- if (shape) shape.stroke = $(go.Brush, "Linear", { : color, : go.Brush.lightenBy(color, 0.05), start: go.Spot.Left, end: go.Spot.Right });
- }
- });
- };
- // when a node is double-clicked, add a child to it
- function createNode(e, obj) {
- //拿到节点的对象,后面要拿什么值就直接拿
- var clicked = obj.part;
- if (clicked !== null) {
- var thisemp = clicked.data;
- myDiagram.startTransaction("createNode");
- var newemp = {
- name: "(新节点)",
- parent: thisemp.key
- };
- //console.log(thisemp.key);
- console.log(myDiagram.model.toJson());
- myDiagram.model.addNodeData(newemp);
- myDiagram.commitTransaction("createNode");
- }
- }
- // this is used to determine feedback during drags
- function mayWorkFor(node1, node2) {
- if (!(node1 instanceof go.Node)) return false; // must be a Node
- if (node1 === node2) return false; // cannot work for yourself
- if (node2.isInTreeOf(node1)) return false; // cannot work for someone who works for you
- return true;
- }
- // 为大多数文本块提供通用样式
- // Some of these values may be overridden in a particular TextBlock.某些值可能在特定的文本块中被覆盖
- function textStyle() {
- //strokez颜色,添加textAlign: "center"好像效果可能是被覆盖了
- return { font: "9pt Segoe UI,sans-serif", stroke: "white" };
- }
- // This converter is used by the Picture.
- function findHeadShot(key) {
- if (key < || key > ) return "images/HSnopic.jpg"; // There are only 16 images on the server
- return "images/HS" + key + ".jpg"
- }
- // define the Node template 定义节点模板 描述如何构建每个节点
- myDiagram.nodeTemplate =
- $(go.Node, "Auto",//形状自动填充适合 与css设置width:auto同样效果
- //{ doubleClick: createNode },
- { // handle dragging a Node onto a Node to (maybe) change the reporting relationship
- mouseDragEnter: function (e, node, prev) {
- var diagram = node.diagram;
- var selnode = diagram.selection.first();
- if (!mayWorkFor(selnode, node)) return;
- var shape = node.findObject("SHAPE");
- if (shape) {
- shape._prevFill = shape.fill; // remember the original brush
- shape.fill = "darkred";
- }
- },
- mouseDragLeave: function (e, node, next) {
- var shape = node.findObject("SHAPE");
- if (shape && shape._prevFill) {
- shape.fill = shape._prevFill; // restore the original brush
- }
- },
- mouseDrop: function (e, node) {
- var diagram = node.diagram;
- var selnode = diagram.selection.first(); // assume just one Node in selection
- if (mayWorkFor(selnode, node)) {
- // find any existing link into the selected node
- var link = selnode.findTreeParentLink();
- if (link !== null) { // 重新连接所有已有连接
- link.fromNode = node;
- } else { // 新建连接
- diagram.toolManager.linkingTool.insertLink(node, node.port, selnode, selnode.port);
- }
- }
- }
- },
- // for sorting, have the Node.text be the data.name
- new go.Binding("text", "name"),
- // bind the Part.layerName to control the Node's layer depending on whether it isSelected
- new go.Binding("layerName", "isSelected", function (sel) { return sel ? "Foreground" : ""; }).ofObject(),
- //设置节点形状:长方形
- $(go.Shape, "Rectangle",
- {
- name: "SHAPE", fill: "#333333", stroke: 'white', strokeWidth: 3.5,
- // set the port properties: 是否可连接fromLinkable、toLinkable
- portId: "", fromLinkable: false, toLinkable: false, cursor: "pointer"
- }),
- // Panel 有不同的类型,每个类型表示一种布局,通过不同的坐标系统排列
- $(go.Panel, "Horizontal",
- // 定义文本显示框
- $(go.Panel, "Table",
- {
- minSize: new go.Size(, NaN),
- maxSize: new go.Size(, NaN),
- margin: new go.Margin(),//设置文本和边框距离
- defaultAlignment: go.Spot.Center
- },
- $(go.RowColumnDefinition, { column: , width: }),
- // 设置文本节点
- $(go.TextBlock, textStyle(), // the name
- {
- row: , column: , columnSpan: ,
- font: "12pt Segoe UI,sans-serif",
- editable: true, isMultiline: false,// editable文本是否可编辑
- minSize: new go.Size(, )
- },
- //将节点数据nodeDataArray.name与text建立联系
- new go.Binding("text", "name").makeTwoWay())
- ) // end Table Panel
- ) // end Horizontal Panel
- ); // end Node
- // 选中的节点显示用于添加子节点的按钮
- myDiagram.nodeTemplate.selectionAdornmentTemplate =
- $(go.Adornment, "Spot",
- $(go.Panel, "Auto",
- $(go.Placeholder, {
- margin: new go.Margin(, -, , )
- })
- ),
- // 所选节点的删除按钮
- $("Button", {
- alignment: go.Spot.Right,
- alignmentFocus: go.Spot.Left,
- click: function (e, obj) {
- var node = obj.part.adornedPart;
- //console.log(node.data.key);
- if (node !== null) {
- myDiagram.startTransaction("remove dept");
- // 删除单个节点myDiagram.model.removeNodeData(node.data)只要能拿到node.data对象就能删除了;
- //删除整个子树,包括节点本身
- myDiagram.removeParts(node.findTreeParts());
- myDiagram.commitTransaction("remove dept");
- }
- }
- // 定义装饰中此按钮的单击行为
- },
- $(go.TextBlock, "-", // 按钮的内容
- {
- font: "bold 8pt sans-serif"
- })
- ),
- // 所选节点的新增按钮
- $("Button", {
- alignment: go.Spot.Right,
- alignmentFocus: go.Spot.Right,
- click: createNode
- },
- $(go.TextBlock, "+", // 按钮的内容
- {
- font: "bold 8pt sans-serif"
- })
- )
- );
- //监听键盘事件
- myDiagram.commandHandler.doKeyDown = function () {
- var e = myDiagram.lastInput;
- var control = e.control || e.meta;
- var key = e.key;
- console.log('key' + key);//Tab和Enter键好像这里取到的名字是空
- if (control && (key === 'Z' || key === 'Y')) {
- console.log('Ctrl+Z/Y');
- };
- // 取消Del/Backspace删除键的命令关联:
- //if (key === 'Del' || key === 'Backspace') return;
- go.CommandHandler.prototype.doKeyDown.call(this);
- };
- // 设置线条和箭头,是否允许拖动连接relinkableFrom,relinkableTo
- myDiagram.linkTemplate =
- $(go.Link, go.Link.Orthogonal,
- { corner: , relinkableFrom: false, relinkableTo: false },
- $(go.Shape, { strokeWidth: 1.5, stroke: "#F5F5F5" })); // the link shape
- // 拖拽框选功能
- myDiagram.toolManager.dragSelectingTool.box =
- $(go.Part,
- { layerName: "Tool", selectable: true },
- $(go.Shape,
- { name: "SHAPE", fill: null, stroke: "chartreuse", strokeWidth: }));
- // read in the JSON-format data from the "mySavedModel" element
- load();
- // support editing the properties of the selected person in HTML
- if (window.Inspector) myInspector = new Inspector("myInspector", myDiagram,
- {
- properties: {
- "key": { readOnly: true },
- "comments": {}
- }
- });
- // Setup zoom to fit button
- document.getElementById('zoomToFit').addEventListener('click', function () {
- myDiagram.commandHandler.zoomToFit();
- });
- document.getElementById('centerRoot').addEventListener('click', function () {
- myDiagram.scale = ;
- myDiagram.commandHandler.scrollToPart(myDiagram.findNodeForKey());
- });
- } // end init
- // Show the diagram's model in JSON format
- function save() {
- document.getElementById("mySavedModel").value = myDiagram.model.toJson();
- myDiagram.isModified = false;
- }
- function load() {
- // model中的数据每一个js对象都代表着一个相应的模型图中的元素
- myDiagram.model = go.Model.fromJson(document.getElementById("mySavedModel").value);
- // make sure new data keys are unique positive integers
- var lastkey = ;
- myDiagram.model.makeUniqueKeyFunction = function (model, data) {
- var k = data.key || lastkey;
- while (model.findNodeDataForKey(k)) k++;
- data.key = lastkey = k;
- return k;
- };
- }
- "use strict";//严格模式,在开发中使用严格模式能帮助我们早发现错误
- function Inspector(divid, diagram, options) {
- var mainDiv = document.getElementById(divid);
- mainDiv.className = "inspector";
- mainDiv.innerHTML = "";
- this._div = mainDiv;
- this._diagram = diagram;
- this._inspectedProperties = {};
- this._multipleProperties = {};
- // Either a GoJS Part or a simple data object, such as Model.modelData
- this.inspectedObject = null;
- // Inspector options defaults:
- this.includesOwnProperties = true;
- this.declaredProperties = {};
- this.inspectsSelection = true;
- this.propertyModified = null;
- this.multipleSelection = false;
- this.showAllProperties = false;
- this.showSize = ;
- if (options !== undefined) {
- if (options["includesOwnProperties"] !== undefined) this.includesOwnProperties = options["includesOwnProperties"];
- if (options["properties"] !== undefined) this.declaredProperties = options["properties"];
- if (options["inspectSelection"] !== undefined) this.inspectsSelection = options["inspectSelection"];
- if (options["propertyModified"] !== undefined) this.propertyModified = options["propertyModified"];
- if (options['multipleSelection'] !== undefined) this.multipleSelection = options['multipleSelection'];
- if (options['showAllProperties'] !== undefined) this.showAllProperties = options['showAllProperties'];
- if (options['showSize'] !== undefined) this.showSize = options['showSize'];
- }
- var self = this;
- diagram.addModelChangedListener(function (e) {
- if (e.isTransactionFinished) self.inspectObject();
- });
- if (this.inspectsSelection) {
- diagram.addDiagramListener("ChangedSelection", function (e) { self.inspectObject(); });
- }
- }
- // Some static predicates to use with the "show" property.
- Inspector.showIfNode = function (part) { return part instanceof go.Node };
- Inspector.showIfLink = function (part) { return part instanceof go.Link };
- Inspector.showIfGroup = function (part) { return part instanceof go.Group };
- // Only show the property if its present. Useful for "key" which will be shown on Nodes and Groups, but normally not on Links
- Inspector.showIfPresent = function (data, propname) {
- if (data instanceof go.Part) data = data.data;
- return typeof data === "object" && data[propname] !== undefined;
- };
- /**
- * Update the HTML state of this Inspector given the properties of the {@link #inspectedObject}.
- * @param {Object} object is an optional argument, used when {@link #inspectSelection} is false to
- * set {@link #inspectedObject} and show and edit that object's properties.
- */
- Inspector.prototype.inspectObject = function (object) {
- var inspectedObject = null;
- var inspectedObjects = null;
- if (object === null) return;
- if (object === undefined) {
- if (this.inspectsSelection) {
- if (this.multipleSelection) { // gets the selection if multiple selection is true
- inspectedObjects = this._diagram.selection;
- } else { // otherwise grab the first object
- inspectedObject = this._diagram.selection.first();
- }
- } else { // if there is a single inspected object
- inspectedObject = this.inspectedObject;
- }
- } else { // if object was passed in as a parameter
- inspectedObject = object;
- }
- if (inspectedObjects && inspectedObjects.count === ) {
- inspectedObject = inspectedObjects.first();
- }
- if (inspectedObjects && inspectedObjects.count <= ) {
- inspectedObjects = null;
- }
- // single object or no objects
- if (!inspectedObjects || !this.multipleSelection) {
- if (inspectedObject === null) {
- this.inspectedObject = inspectedObject;
- this.updateAllHTML();
- return;
- }
- this.inspectedObject = inspectedObject;
- if (this.inspectObject === null) return;
- var mainDiv = this._div;
- mainDiv.innerHTML = '';
- // use either the Part.data or the object itself (for model.modelData)
- var data = (inspectedObject instanceof go.Part) ? inspectedObject.data : inspectedObject;
- if (!data) return;
- // Build table:
- var table = document.createElement('table');
- var tbody = document.createElement('tbody');
- this._inspectedProperties = {};
- this.tabIndex = ;
- var declaredProperties = this.declaredProperties;
- // Go through all the properties passed in to the inspector and show them, if appropriate:
- for (var name in declaredProperties) {
- var desc = declaredProperties[name];
- if (!this.canShowProperty(name, desc, inspectedObject)) continue;
- var val = this.findValue(name, desc, data);
- tbody.appendChild(this.buildPropertyRow(name, val));
- }
- // Go through all the properties on the model data and show them, if appropriate:
- if (this.includesOwnProperties) {
- for (var k in data) {
- if (k === '__gohashid') continue; // skip internal GoJS hash property
- if (this._inspectedProperties[k]) continue; // already exists
- if (declaredProperties[k] && !this.canShowProperty(k, declaredProperties[k], inspectedObject)) continue;
- tbody.appendChild(this.buildPropertyRow(k, data[k]));
- }
- }
- table.appendChild(tbody);
- mainDiv.appendChild(table);
- } else { // multiple objects selected
- var mainDiv = this._div;
- mainDiv.innerHTML = '';
- var shared = new go.Map(); // for properties that the nodes have in common
- var properties = new go.Map(); // for adding properties
- var all = new go.Map(); // used later to prevent changing properties when unneeded
- var it = inspectedObjects.iterator;
- // Build table:
- var table = document.createElement('table');
- var tbody = document.createElement('tbody');
- this._inspectedProperties = {};
- this.tabIndex = ;
- var declaredProperties = this.declaredProperties;
- it.next();
- inspectedObject = it.value;
- this.inspectedObject = inspectedObject;
- var data = (inspectedObject instanceof go.Part) ? inspectedObject.data : inspectedObject;
- if (data) { // initial pass to set shared and all
- // Go through all the properties passed in to the inspector and add them to the map, if appropriate:
- for (var name in declaredProperties) {
- var desc = declaredProperties[name];
- if (!this.canShowProperty(name, desc, inspectedObject)) continue;
- var val = this.findValue(name, desc, data);
- if (val === '' && desc && desc.type === 'checkbox') {
- shared.add(name, false);
- all.add(name, false);
- } else {
- shared.add(name, val);
- all.add(name, val);
- }
- }
- // Go through all the properties on the model data and add them to the map, if appropriate:
- if (this.includesOwnProperties) {
- for (var k in data) {
- if (k === '__gohashid') continue; // skip internal GoJS hash property
- if (this._inspectedProperties[k]) continue; // already exists
- if (declaredProperties[k] && !this.canShowProperty(k, declaredProperties[k], inspectedObject)) continue;
- shared.add(k, data[k]);
- all.add(k, data[k]);
- }
- }
- }
- var nodecount = ;
- while (it.next() && (this.showSize < || nodecount <= this.showSize)) { // grabs all the properties from the other selected objects
- properties.clear();
- inspectedObject = it.value;
- if (inspectedObject) {
- // use either the Part.data or the object itself (for model.modelData)
- data = (inspectedObject instanceof go.Part) ? inspectedObject.data : inspectedObject;
- if (data) {
- // Go through all the properties passed in to the inspector and add them to properties to add, if appropriate:
- for (var name in declaredProperties) {
- var desc = declaredProperties[name];
- if (!this.canShowProperty(name, desc, inspectedObject)) continue;
- var val = this.findValue(name, desc, data);
- if (val === '' && desc && desc.type === 'checkbox') {
- properties.add(name, false);
- } else {
- properties.add(name, val);
- }
- }
- // Go through all the properties on the model data and add them to properties to add, if appropriate:
- if (this.includesOwnProperties) {
- for (var k in data) {
- if (k === '__gohashid') continue; // skip internal GoJS hash property
- if (this._inspectedProperties[k]) continue; // already exists
- if (declaredProperties[k] && !this.canShowProperty(k, declaredProperties[k], inspectedObject)) continue;
- properties.add(k, data[k]);
- }
- }
- }
- }
- if (!this.showAllProperties) {
- // Cleans up shared map with properties that aren't shared between the selected objects
- // Also adds properties to the add and shared maps if applicable
- var addIt = shared.iterator;
- var toRemove = [];
- while (addIt.next()) {
- if (properties.has(addIt.key)) {
- var newVal = all.get(addIt.key) + '|' + properties.get(addIt.key);
- all.set(addIt.key, newVal);
- if ((declaredProperties[addIt.key] && declaredProperties[addIt.key].type !== 'color'
- && declaredProperties[addIt.key].type !== 'checkbox' && declaredProperties[addIt.key].type !== 'select')
- || !declaredProperties[addIt.key]) { // for non-string properties i.e color
- newVal = shared.get(addIt.key) + '|' + properties.get(addIt.key);
- shared.set(addIt.key, newVal);
- }
- } else { // toRemove array since addIt is still iterating
- toRemove.push(addIt.key);
- }
- }
- for (var i = ; i < toRemove.length; i++) { // removes anything that doesn't showAllPropertiess
- shared.remove(toRemove[i]);
- all.remove(toRemove[i]);
- }
- } else {
- // Adds missing properties to all with the correct amount of seperators
- var addIt = properties.iterator;
- while (addIt.next()) {
- if (all.has(addIt.key)) {
- if ((declaredProperties[addIt.key] && declaredProperties[addIt.key].type !== 'color'
- && declaredProperties[addIt.key].type !== 'checkbox' && declaredProperties[addIt.key].type !== 'select')
- || !declaredProperties[addIt.key]) { // for non-string properties i.e color
- var newVal = all.get(addIt.key) + '|' + properties.get(addIt.key);
- all.set(addIt.key, newVal);
- }
- } else {
- var newVal = '';
- for (var i = ; i < nodecount - ; i++) newVal += '|';
- newVal += properties.get(addIt.key);
- all.set(addIt.key, newVal);
- }
- }
- // Adds bars in case properties is not in all
- addIt = all.iterator;
- while (addIt.next()) {
- if (!properties.has(addIt.key)) {
- if ((declaredProperties[addIt.key] && declaredProperties[addIt.key].type !== 'color'
- && declaredProperties[addIt.key].type !== 'checkbox' && declaredProperties[addIt.key].type !== 'select')
- || !declaredProperties[addIt.key]) { // for non-string properties i.e color
- var newVal = all.get(addIt.key) + '|';
- all.set(addIt.key, newVal);
- }
- }
- }
- }
- nodecount++;
- }
- // builds the table property rows and sets multipleProperties to help with updateall
- var mapIt;
- if (!this.showAllProperties) mapIt = shared.iterator;
- else mapIt = all.iterator;
- while (mapIt.next()) {
- tbody.appendChild(this.buildPropertyRow(mapIt.key, mapIt.value)); // shows the properties that are allowed
- }
- table.appendChild(tbody);
- mainDiv.appendChild(table);
- var allIt = all.iterator;
- while (allIt.next()) {
- this._multipleProperties[allIt.key] = allIt.value; // used for updateall to know which properties to change
- }
- }
- };
- /**
- * @ignore
- * This predicate should be false if the given property should not be shown.
- * Normally it only checks the value of "show" on the property descriptor.
- * The default value is true.
- * @param {string} propertyName the property name
- * @param {Object} propertyDesc the property descriptor
- * @param {Object} inspectedObject the data object
- * @return {boolean} whether a particular property should be shown in this Inspector
- */
- Inspector.prototype.canShowProperty = function (propertyName, propertyDesc, inspectedObject) {
- if (propertyDesc.show === false) return false;
- // if "show" is a predicate, make sure it passes or do not show this property
- if (typeof propertyDesc.show === "function") return propertyDesc.show(inspectedObject, propertyName);
- return true;
- }
- /**
- * @ignore
- * This predicate should be false if the given property should not be editable by the user.
- * Normally it only checks the value of "readOnly" on the property descriptor.
- * The default value is true.
- * @param {string} propertyName the property name
- * @param {Object} propertyDesc the property descriptor
- * @param {Object} inspectedObject the data object
- * @return {boolean} whether a particular property should be shown in this Inspector
- */
- Inspector.prototype.canEditProperty = function (propertyName, propertyDesc, inspectedObject) {
- if (this._diagram.isReadOnly || this._diagram.isModelReadOnly) return false;
- // assume property values that are functions of Objects cannot be edited
- var data = (inspectedObject instanceof go.Part) ? inspectedObject.data : inspectedObject;
- var valtype = typeof data[propertyName];
- if (valtype === "function") return false;
- if (propertyDesc) {
- if (propertyDesc.readOnly === true) return false;
- // if "readOnly" is a predicate, make sure it passes or do not show this property
- if (typeof propertyDesc.readOnly === "function") return !propertyDesc.readOnly(inspectedObject, propertyName);
- }
- return true;
- }
- /**
- * @ignore
- * @param {any} propName
- * @param {any} propDesc
- * @param {any} data
- * @return {any}
- */
- Inspector.prototype.findValue = function (propName, propDesc, data) {
- var val = '';
- if (propDesc && propDesc.defaultValue !== undefined) val = propDesc.defaultValue;
- if (data[propName] !== undefined) val = data[propName];
- if (val === undefined) return '';
- return val;
- }
- /**
- * @ignore
- * This sets this._inspectedProperties[propertyName] and creates the HTML table row:
- * <tr>
- * <td>propertyName</td>
- * <td><input value=propertyValue /></td>
- * </tr>
- * @param {string} propertyName the property name
- * @param {*} propertyValue the property value
- * @return the table row
- */
- Inspector.prototype.buildPropertyRow = function (propertyName, propertyValue) {
- var mainDiv = this._div;
- var tr = document.createElement("tr");
- var td1 = document.createElement("td");
- td1.textContent = propertyName;
- tr.appendChild(td1);
- var td2 = document.createElement("td");
- var decProp = this.declaredProperties[propertyName];
- var input = null;
- var self = this;
- function updateall() { self.updateAllProperties(); }
- if (decProp && decProp.type === "select") {
- input = document.createElement("select");
- this.updateSelect(decProp, input, propertyName, propertyValue);
- input.addEventListener("change", updateall);
- } else {
- input = document.createElement("input");
- input.value = this.convertToString(propertyValue);
- if (decProp) {
- var t = decProp.type;
- if (t !== 'string' && t !== 'number' && t !== 'boolean' &&
- t !== 'arrayofnumber' && t !== 'point' && t !== 'size' &&
- t !== 'rect' && t !== 'spot' && t !== 'margin') {
- input.setAttribute("type", decProp.type);
- }
- if (decProp.type === "color") {
- if (input.type === "color") {
- input.value = this.convertToColor(propertyValue);
- // input.addEventListener("input", updateall);
- input.addEventListener("change", updateall);
- }
- } if (decProp.type === "checkbox") {
- input.checked = !!propertyValue;
- input.addEventListener("change", updateall);
- }
- }
- if (input.type !== "color") input.addEventListener("blur", updateall);
- }
- if (input) {
- input.tabIndex = this.tabIndex++;
- input.disabled = !this.canEditProperty(propertyName, decProp, this.inspectedObject);
- td2.appendChild(input);
- }
- tr.appendChild(td2);
- this._inspectedProperties[propertyName] = input;
- return tr;
- };
- /**
- * @ignore
- * HTML5 color input will only take hex,
- * so var HTML5 canvas convert the color into hex format.
- * This converts "rgb(255, 0, 0)" into "#FF0000", etc.
- * @param {string} propertyValue
- * @return {string}
- */
- Inspector.prototype.convertToColor = function (propertyValue) {
- var ctx = document.createElement("canvas").getContext("2d");
- ctx.fillStyle = propertyValue;
- return ctx.fillStyle;
- };
- /**
- * @ignore
- * @param {string}
- * @return {Array.<number>}
- */
- Inspector.prototype.convertToArrayOfNumber = function (propertyValue) {
- if (propertyValue === "null") return null;
- var split = propertyValue.split(' ');
- var arr = [];
- for (var i = ; i < split.length; i++) {
- var str = split[i];
- if (!str) continue;
- arr.push(parseFloat(str));
- }
- return arr;
- };
- /**
- * @ignore
- * @param {*}
- * @return {string}
- */
- Inspector.prototype.convertToString = function (x) {
- if (x === undefined) return "undefined";
- if (x === null) return "null";
- if (x instanceof go.Point) return go.Point.stringify(x);
- if (x instanceof go.Size) return go.Size.stringify(x);
- if (x instanceof go.Rect) return go.Rect.stringify(x);
- if (x instanceof go.Spot) return go.Spot.stringify(x);
- if (x instanceof go.Margin) return go.Margin.stringify(x);
- if (x instanceof go.List) return this.convertToString(x.toArray());
- if (Array.isArray(x)) {
- var str = "";
- for (var i = ; i < x.length; i++) {
- if (i > ) str += " ";
- var v = x[i];
- str += this.convertToString(v);
- }
- return str;
- }
- return x.toString();
- };
- /**
- * @ignore
- * Update all of the HTML in this Inspector.
- */
- Inspector.prototype.updateAllHTML = function () {
- var inspectedProps = this._inspectedProperties;
- var diagram = this._diagram;
- var isPart = this.inspectedObject instanceof go.Part;
- var data = isPart ? this.inspectedObject.data : this.inspectedObject;
- if (!data) { // clear out all of the fields
- for (var name in inspectedProps) {
- var input = inspectedProps[name];
- if (input instanceof HTMLSelectElement) {
- input.innerHTML = "";
- } else if (input.type === "color") {
- input.value = "#000000";
- } else if (input.type === "checkbox") {
- input.checked = false;
- } else {
- input.value = "";
- }
- }
- } else {
- for (var name in inspectedProps) {
- var input = inspectedProps[name];
- var propertyValue = data[name];
- if (input instanceof HTMLSelectElement) {
- var decProp = this.declaredProperties[name];
- this.updateSelect(decProp, input, name, propertyValue);
- } else if (input.type === "color") {
- input.value = this.convertToColor(propertyValue);
- } else if (input.type === "checkbox") {
- input.checked = !!propertyValue;
- } else {
- input.value = this.convertToString(propertyValue);
- }
- }
- }
- }
- /**
- * @ignore
- * Update an HTMLSelectElement with an appropriate list of choices, given the propertyName
- */
- Inspector.prototype.updateSelect = function (decProp, select, propertyName, propertyValue) {
- select.innerHTML = ""; // clear out anything that was there
- var choices = decProp.choices;
- if (typeof choices === "function") choices = choices(this.inspectedObject, propertyName);
- if (!Array.isArray(choices)) choices = [];
- decProp.choicesArray = choices; // remember list of actual choice values (not strings)
- for (var i = ; i < choices.length; i++) {
- var choice = choices[i];
- var opt = document.createElement("option");
- opt.text = this.convertToString(choice);
- select.add(opt, null);
- }
- select.value = this.convertToString(propertyValue);
- }
- /**
- * @ignore
- * Update all of the data properties of {@link #inspectedObject} according to the
- * current values held in the HTML input elements.
- */
- Inspector.prototype.updateAllProperties = function () {
- var inspectedProps = this._inspectedProperties;
- var diagram = this._diagram;
- if (diagram.selection.count === || !this.multipleSelection) { // single object update
- var isPart = this.inspectedObject instanceof go.Part;
- var data = isPart ? this.inspectedObject.data : this.inspectedObject;
- if (!data) return; // must not try to update data when there's no data!
- diagram.startTransaction('set all properties');
- for (var name in inspectedProps) {
- var input = inspectedProps[name];
- var value = input.value;
- // don't update "readOnly" data properties
- var decProp = this.declaredProperties[name];
- if (!this.canEditProperty(name, decProp, this.inspectedObject)) continue;
- // If it's a boolean, or if its previous value was boolean,
- // parse the value to be a boolean and then update the input.value to match
- var type = '';
- if (decProp !== undefined && decProp.type !== undefined) {
- type = decProp.type;
- }
- if (type === '') {
- var oldval = data[name];
- if (typeof oldval === 'boolean') type = 'boolean'; // infer boolean
- else if (typeof oldval === 'number') type = 'number';
- else if (oldval instanceof go.Point) type = 'point';
- else if (oldval instanceof go.Size) type = 'size';
- else if (oldval instanceof go.Rect) type = 'rect';
- else if (oldval instanceof go.Spot) type = 'spot';
- else if (oldval instanceof go.Margin) type = 'margin';
- }
- // convert to specific type, if needed
- switch (type) {
- case 'boolean': value = !(value === false || value === 'false' || value === ''); break;
- case 'number': value = parseFloat(value); break;
- case 'arrayofnumber': value = this.convertToArrayOfNumber(value); break;
- case 'point': value = go.Point.parse(value); break;
- case 'size': value = go.Size.parse(value); break;
- case 'rect': value = go.Rect.parse(value); break;
- case 'spot': value = go.Spot.parse(value); break;
- case 'margin': value = go.Margin.parse(value); break;
- case 'checkbox': value = input.checked; break;
- case 'select': value = decProp.choicesArray[input.selectedIndex]; break;
- }
- // in case parsed to be different, such as in the case of boolean values,
- // the value shown should match the actual value
- input.value = value;
- // modify the data object in an undo-able fashion
- diagram.model.setDataProperty(data, name, value);
- // notify any listener
- if (this.propertyModified !== null) this.propertyModified(name, value, this);
- }
- diagram.commitTransaction('set all properties');
- } else { // selection object update
- diagram.startTransaction('set all properties');
- for (var name in inspectedProps) {
- var input = inspectedProps[name];
- var value = input.value;
- var arr1 = value.split('|');
- var arr2 = [];
- if (this._multipleProperties[name]) {
- // don't split if it is union and its checkbox type
- if (this.declaredProperties[name] && this.declaredProperties[name].type === 'checkbox' && this.showAllProperties) {
- arr2.push(this._multipleProperties[name]);
- } else {
- arr2 = this._multipleProperties[name].toString().split('|');
- }
- }
- var it = diagram.selection.iterator;
- var change = false;
- if (this.declaredProperties[name] && this.declaredProperties[name].type === 'checkbox') change = true; // always change checkbox
- if (arr1.length < arr2.length // i.e Alpha|Beta -> Alpha procs the change
- && (!this.declaredProperties[name] // from and to links
- || !(this.declaredProperties[name] // do not change color checkbox and choices due to them always having less
- && (this.declaredProperties[name].type === 'color' || this.declaredProperties[name].type === 'checkbox' || this.declaredProperties[name].type === 'choices')))) {
- change = true;
- } else { // standard detection in change in properties
- for (var j = ; j < arr1.length && j < arr2.length; j++) {
- if (!(arr1[j] === arr2[j])
- && !(this.declaredProperties[name] && this.declaredProperties[name].type === 'color' && arr1[j].toLowerCase() === arr2[j].toLowerCase())) {
- change = true;
- }
- }
- }
- if (change) { // only change properties it needs to change instead all of them
- for (var i = ; i < diagram.selection.count; i++) {
- it.next();
- var isPart = it.value instanceof go.Part;
- var data = isPart ? it.value.data : it.value;
- if (data) { // ignores the selected node if there is no data
- if (i < arr1.length) value = arr1[i];
- else value = arr1[];
- // don't update "readOnly" data properties
- var decProp = this.declaredProperties[name];
- if (!this.canEditProperty(name, decProp, it.value)) continue;
- // If it's a boolean, or if its previous value was boolean,
- // parse the value to be a boolean and then update the input.value to match
- var type = '';
- if (decProp !== undefined && decProp.type !== undefined) {
- type = decProp.type;
- }
- if (type === '') {
- var oldval = data[name];
- if (typeof oldval === 'boolean') type = 'boolean'; // infer boolean
- else if (typeof oldval === 'number') type = 'number';
- else if (oldval instanceof go.Point) type = 'point';
- else if (oldval instanceof go.Size) type = 'size';
- else if (oldval instanceof go.Rect) type = 'rect';
- else if (oldval instanceof go.Spot) type = 'spot';
- else if (oldval instanceof go.Margin) type = 'margin';
- }
- // convert to specific type, if needed
- switch (type) {
- case 'boolean': value = !(value === false || value === 'false' || value === ''); break;
- case 'number': value = parseFloat(value); break;
- case 'arrayofnumber': value = this.convertToArrayOfNumber(value); break;
- case 'point': value = go.Point.parse(value); break;
- case 'size': value = go.Size.parse(value); break;
- case 'rect': value = go.Rect.parse(value); break;
- case 'spot': value = go.Spot.parse(value); break;
- case 'margin': value = go.Margin.parse(value); break;
- case 'checkbox': value = input.checked; break;
- case 'select': value = decProp.choicesArray[input.selectedIndex]; break;
- }
- // in case parsed to be different, such as in the case of boolean values,
- // the value shown should match the actual value
- input.value = value;
- // modify the data object in an undo-able fashion
- diagram.model.setDataProperty(data, name, value);
- // notify any listener
- if (this.propertyModified !== null) this.propertyModified(name, value, this);
- }
- }
- }
- }
- diagram.commitTransaction('set all properties');
- }
- };
- </script>
- </html>
参考 学习文档 https://liuxiaofan.com/2018/03/16/3521.html
GoJS组织结构图2的更多相关文章
- GoJS组织结构图
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- GoJS 友情链接
目前GoJS官网是学习gojs的最佳选择 GOJS简单示例 GoJS API学习 GoJS组织结构图2 mind map思维导图 组织结构图 GoJS实例1 GoJS实例2 GoJS实例3 GoJS实 ...
- GoJS超详细入门(插件使用无非:引包、初始化、配参数(json)、引数据(json)四步)
GoJS超详细入门(插件使用无非:引包.初始化.配参数(json).引数据(json)四步) 一.总结 一句话总结:插件使用无非:引包.初始化.配参数(json).引数据(json)四步. 1.goj ...
- gojs绘流程图
引用:http://www.tuicool.com/articles/eEruaqu http://www.open-open.com/lib/view/open1435023502544.html ...
- GoJS使用
1. 先学习官网的这篇Get Started with GoJS教程入门,了解GoJS基础知识: 2. 浏览GoJS各个示例(Samples.Intro),找到契合自己业务需要的某个或者某几个例子,然 ...
- Web功能之组织结构图
前提:由于项目需要显示组织结构图的形式 工具:VS2010 项目:ASP.NET 自带的web项目 (带模板页) 插件:OrgChart(依赖:OrgChart.dll).JOrgChart 不多说 ...
- 模仿Word中组织结构图的特点生成流程图
//基本原理: // 1. 从下往上计算位置 // 2. 模仿Word中组织结构图的特点 //调用代码: Tree<string> tree = new Tree<string> ...
- asp.net 组织结构图控件
记得之前做项目的时候客户需要看一个组织结构图,从而了解一下公司的概况,本来自己之前没有做过这方面的控件,只好找度娘,出于对项目的完美,网上很多控件画面感比较渣,后来只能在这些个中挑个比较好的来做,先看 ...
- GoJS研究,简单图表制作。
话不多说,先上图 我在这个中加入了缩略图.鼠标放大缩小等功能. <!doctype html> <html> <head> <title>Flowcha ...
随机推荐
- acm数论之旅---扩展欧几里得算法
度娘百科说: 首先, ax+by = gcd(a, b) 这个公式肯定有解 (( •̀∀•́ )她说根据数论中的相关定理可以证明,反正我信了) 所以 ax+by = gcd(a, b) * k 也肯定 ...
- numpy.eye() 生成对角矩阵
numpy.eye(N,M=None, k=0, dtype=<type 'float'>) 关注第一个第三个参数就行了 第一个参数:输出方阵(行数=列数)的规模,即行数或列数 第三个参数 ...
- es 搜索功能简介
DSL 语法介绍 语法 范围 /_search 集群上搜索所有的索引 /index1/_search index1 /index1,index2/_search index1和index2 /inde ...
- 【转】获取Jenkins构建时Git Change Log
原文:https://www.jianshu.com/p/513ab6915dbd 在基于Jenkins进行CI持续集成的工作,在构建后上传蒲公英时想将本次版本的git commit信息同步到蒲公英的 ...
- LeetCode中等题(三)
题目一: 反转从位置 m 到 n 的链表.请使用一趟扫描完成反转. 说明:1 ≤ m ≤ n ≤ 链表长度. 示例: 输入: 1->2->3->4->5->NULL, m ...
- HDU 1372 Knight Moves(bfs)
嗯... 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1372 这是一道很典型的bfs,跟马走日字一个道理,然后用dir数组确定骑士可以走的几个方向, ...
- HD Tune检查硬盘各参数的含义
01 =Read Error Rate / (底层)数据读取错误率指从磁盘表面读取数据时发生的硬件读取错误的比率,Raw值对于不同的厂商有着不同的体系,单纯看做1个十进制数字是没有任何意义的.以上为W ...
- 扒网站工具 HTTrack Website Copier
下载地址:http://www.pc6.com/softview/SoftView_30936.html 作者:匿名用户 链接:https://www.zhihu.com/question/34188 ...
- java课后问题解答
1.当有多个嵌套的try…catch…finally时,要特别注意finally的执行时机 答:当有多层嵌套的finally时,异常在不同的层次抛出 ,在不同的位 置抛出,可能会导致不同的finall ...
- el-dialog 如何自定义大小样式
使用属性:custom-class 然后在css中根据这个类型编写指定的样式即可(比如宽高) 举例: