如何根据模块模式重构JS函数?

时间:2017-08-08 08:11:16

标签: javascript

我有2个JS文件。

1)第一个是主要的一个,它是根据模块模式组织的。它看起来如下:

"use strict";

var SchemaEditor = (function () {

    /* Private members */
    var black = "black";
    var transparent = "transparent";
    var sd = {
        mode: "pointer", // Set to default mode. Alternatives are "node" and "link", for adding a new node or a new link respectively.
        itemType: "pointer", // Set when user clicks on a node or link button.
        nodeCounter: {}
    };
    var myDiagram;
    var $ = go.GraphObject.make;

    /* Private methods */
    // update the diagram every 250 milliseconds
    function loop() {
        setTimeout(function () { updateStates(); loop(); }, 250);
    }

    // update the value and appearance of each node according to its type and input values
    function updateStates() {
        var oldskip = myDiagram.skipsUndoManager;
        myDiagram.skipsUndoManager = true;
        // do all "input" nodes first
        myDiagram.nodes.each(function (node) {
            if (node.category === "input") {
                doInput(node);
            }
        });
        // now we can do all other kinds of nodes
        myDiagram.nodes.each(function (node) {
            switch (node.category) {
                case "image1": doImage1(node); break;
                case "image2": doImage2(node); break;
                case "image3": doImage3(node); break;
                case "image4": doImage4(node); break;
                case "image5": doImage5(node); break;
                case "image6": doImage6(node); break;
                case "image7": doImage7(node); break;
                case "image8": doImage8(node); break;
                case "image9": doImage9(node); break;
                case "image10": doImage10(node); break;
                case "table": doTable(node); break;
                case "hBar": dohBar(node); break;
            }
        });
        myDiagram.skipsUndoManager = oldskip;
    }

    // update nodes by the specific function for its type
    // determine the color of links coming out of this node based on those coming in and node type
    function doImage1(node) {
        // assume there is just one input link
        // we just need to update the node's Shape.fill
        node.linksConnected.each(function (link) { node.findObject("NODESHAPE1").fill = link.findObject("SHAPE").stroke; });
    }

    function doImage2(node) {
        // assume there is just one input link
        // we just need to update the node's Shape.fill
        node.linksConnected.each(function (link) { node.findObject("NODESHAPE1").fill = link.findObject("SHAPE").stroke; });
    }

    function doImage3(node) {
        // assume there is just one input link
        // we just need to update the node's Shape.fill
        node.linksConnected.each(function (link) { node.findObject("NODESHAPE1").fill = link.findObject("SHAPE").stroke; });
    }

    function doImage4(node) {
        // assume there is just one input link
        // we just need to update the node's Shape.fill
        node.linksConnected.each(function (link) { node.findObject("NODESHAPE1").fill = link.findObject("SHAPE").stroke; });
    }

    function doImage5(node) {
        // assume there is just one input link
        // we just need to update the node's Shape.fill
        node.linksConnected.each(function (link) { node.findObject("NODESHAPE1").fill = link.findObject("SHAPE").stroke; });
    }

    function doImage6(node) {
        // assume there is just one input link
        // we just need to update the node's Shape.fill
        node.linksConnected.each(function (link) { node.findObject("NODESHAPE1").fill = link.findObject("SHAPE").stroke; });
    }

    function doImage7(node) {
        // assume there is just one input link
        // we just need to update the node's Shape.fill
        node.linksConnected.each(function (link) { node.findObject("NODESHAPE1").fill = link.findObject("SHAPE").stroke; });
    }

    function doImage8(node) {
        // assume there is just one input link
        // we just need to update the node's Shape.fill
        node.linksConnected.each(function (link) { node.findObject("NODESHAPE1").fill = link.findObject("SHAPE").stroke; });
    }

    function doImage9(node) {
        // assume there is just one input link
        // we just need to update the node's Shape.fill
        node.linksConnected.each(function (link) { node.findObject("NODESHAPE1").fill = link.findObject("SHAPE").stroke; });
    }

    function doImage10(node) {
        // assume there is just one input link
        // we just need to update the node's Shape.fill
        node.linksConnected.each(function (link) { node.findObject("NODESHAPE1").fill = link.findObject("SHAPE").stroke; });
    }

    function doTable(node) {
        // assume there is just one input link
        // we just need to update the node's Shape.fill
        node.linksConnected.each(function (link) { node.findObject("NODESHAPE1").fill = link.findObject("SHAPE").stroke; });
    }

    function dohBar(node) {
        // assume there is just one input link
        // we just need to update the node's Shape.fill
        node.linksConnected.each(function (link) { node.findObject("NODESHAPE1").fill = link.findObject("SHAPE").stroke; });
    }

    function BarLink() {
        go.Link.call(this);
    }
    go.Diagram.inherit(BarLink, go.Link);

    /** @override */
    BarLink.prototype.getLinkPoint = function (node, port, spot, from, ortho, othernode, otherport) {
        if (node.category === "hBar") {
            var op = go.Link.prototype.getLinkPoint.call(this, othernode, otherport, this.computeSpot(!from), !from, ortho, node, port);
            var r = new go.Rect(port.getDocumentPoint(go.Spot.TopLeft),
                                port.getDocumentPoint(go.Spot.BottomRight));
            var y = (op.y > r.centerY) ? r.bottom : r.top;
            if (op.x < r.left) return new go.Point(r.left, y);
            if (op.x > r.right) return new go.Point(r.right, y);
            return new go.Point(op.x, y);
        } else {
            return go.Link.prototype.getLinkPoint.call(this, node, port, spot, from, ortho, othernode, otherport);
        }
    };

    /** @override */
    BarLink.prototype.getLinkDirection = function (node, port, linkpoint, spot, from, ortho, othernode, otherport) {
        var p = port.getDocumentPoint(go.Spot.Center);
        var op = otherport.getDocumentPoint(go.Spot.Center);
        var below = op.y > p.y;
        return below ? 90 : 270;
    };
    // end BarLink class

    var setMode = function (mode, itemType) {
        myDiagram.startTransaction();
        sd.mode = mode;
        sd.itemType = itemType;
        if (mode === "link") {
            if (itemType === 'default') {
                if (document.getElementById("defaultMode").classList.contains('non-pushed')) {
                    document.getElementById("defaultMode").classList.remove('non-pushed');
                    document.getElementById("defaultMode").classList.add('pushed');
                    document.getElementById("orthoMode").classList.add('non-pushed');
                    document.getElementById("cornerMode").classList.add('non-pushed');
                }
            }
            if (itemType === 'ortho') {
                if (document.getElementById("orthoMode").classList.contains('non-pushed')) {
                    document.getElementById("orthoMode").classList.remove('non-pushed');
                    document.getElementById("orthoMode").classList.add('pushed');
                    document.getElementById("defaultMode").classList.add('non-pushed');
                    document.getElementById("cornerMode").classList.add('non-pushed');
                }
            }
            if (itemType === 'corner') {
                if (document.getElementById("cornerMode").classList.contains('non-pushed')) {
                    document.getElementById("cornerMode").classList.remove('non-pushed');
                    document.getElementById("cornerMode").classList.add('pushed');
                    document.getElementById("defaultMode").classList.add('non-pushed');
                    document.getElementById("orthoMode").classList.add('non-pushed');
                }
            }
            myDiagram.allowLink = true;
            myDiagram.nodes.each(function (n) { n.port.cursor = "pointer"; });
        }
        myDiagram.commitTransaction("mode changed");
    };

    // save a model to and load a model from JSON text, displayed below the Diagram
    var save = function () {
        document.getElementById("mySavedModel").value = myDiagram.model.toJson();
        myDiagram.isModified = false;
    };

    var load = function () {
        myDiagram.model = go.Model.fromJson(document.getElementById("mySavedModel").value);
    };

    function addLinkTemplateMaps() {
        // creates relinkable Links that will avoid crossing Nodes when possible and will jump over other Links in their paths
        myDiagram.linkTemplateMap.add("default",
            $(go.Link,
            {
                relinkableFrom: true, relinkableTo: true,
                selectionAdorned: false, // Links are not adorned when selected so that their color remains visible.
                shadowOffset: new go.Point(0, 0), shadowBlur: 5, shadowColor: "black"
            },
            new go.Binding("isShadowed", "isSelected").ofObject(),
            $(go.Shape,
                { name: "SHAPE", strokeWidth: 2, stroke: black })));

        myDiagram.linkTemplateMap.add("corner",
          $(go.Link,
            { reshapable: true, resegmentable: true, routing: go.Link.AvoidsNodes },
            new go.Binding("points").makeTwoWay(), // TwoWay Binding of Link.points
            $(go.Shape)
          ));

        myDiagram.linkTemplateMap.add("ortho",
            $(BarLink, // subclass defined below
                {
                    routing: go.Link.Orthogonal,
                    relinkableFrom: true,
                    relinkableTo: true,
                    toPortChanged: function (link, oldport, newport) {
                        if (newport instanceof go.Shape) link.path.stroke = newport.fill;
                    }
                },
                $(go.Shape,
                { strokeWidth: 2 })
            ));
    };

    var initSchemaEditor = function () {
        myDiagram = $(go.Diagram, "myDiagramDiv",
        {
            initialContentAlignment: go.Spot.Center,
            allowDrop: true, // Nodes from the Palette can be dropped into the Diagram
            "undoManager.isEnabled": true,
            "grid.visible": true,

            "linkingTool.portGravity": 0, // no snapping while drawing new links
            "linkingTool.doActivate": function () {
                // change the curve of the LinkingTool.temporaryLink
                this.temporaryLink.curve = (sd.itemType === "default") ? go.Link.Normal : go.Link.Orthogonal;
                go.LinkingTool.prototype.doActivate.call(this);
            },
            // override the link creation process
            "linkingTool.insertLink": function (fromnode, fromport, tonode, toport) {
                // to control what kind of Link is created,
                // change the LinkingTool.archetypeLinkData's category
                myDiagram.model.setCategoryForLinkData(this.archetypeLinkData, sd.itemType);
                // also change the text indicating the condition, which the user can edit
                this.archetypeLinkData.text = sd.itemType;
                return go.LinkingTool.prototype.insertLink.call(this, fromnode, fromport, tonode, toport);
            },

            "clickCreatingTool.archetypeNodeData": {}, // enable ClickCreatingTool
            "clickCreatingTool.isDoubleClick": false, // operates on a single click in background
            "clickCreatingTool.canStart": function () { // but only in "node" creation mode
                return sd.mode === "node" && go.ClickCreatingTool.prototype.canStart.call(this);
            },
            "clickCreatingTool.insertPart": function (loc) { // customize the data for the new node
                sd.nodeCounter[sd.itemType] += 1;
                var newNodeId = sd.itemType + sd.nodeCounter[sd.itemType];
                this.archetypeNodeData = {
                    key: newNodeId,
                    category: sd.itemType,
                    label: newNodeId
                };
                return go.ClickCreatingTool.prototype.insertPart.call(this, loc);
            }
        });

        myDiagram.requestUpdate();

        // when the document is modified, add a "*" to the title and enable the "Save" button
        myDiagram.addDiagramListener("Modified", function (e) {
            var button = document.getElementById("saveModel");
            if (button) button.disabled = !myDiagram.isModified;
            var idx = document.title.indexOf("*");
            if (myDiagram.isModified) {
                if (idx < 0) document.title += "*";
            } else {
                if (idx >= 0) document.title = document.title.substr(0, idx);
            }
        });

        myDiagram.model =
          $(go.GraphLinksModel,
            {
                linkFromPortIdProperty: "fromPort", // required information:
                linkToPortIdProperty: "toPort" // identifies data property names
            });

        addLinkTemplateMaps();

        loadNodes();

        myDiagram.nodeTemplateMap.add("image1", image1Template);
        myDiagram.nodeTemplateMap.add("image2", image2Template);
        myDiagram.nodeTemplateMap.add("image3", image3Template);
        myDiagram.nodeTemplateMap.add("image4", image4Template);
        myDiagram.nodeTemplateMap.add("image5", image5Template);
        myDiagram.nodeTemplateMap.add("image6", image6Template);
        myDiagram.nodeTemplateMap.add("image7", image7Template);
        myDiagram.nodeTemplateMap.add("image8", image8Template);
        myDiagram.nodeTemplateMap.add("image9", image9Template);
        myDiagram.nodeTemplateMap.add("image10", image10Template);
        myDiagram.nodeTemplateMap.add("table", tableTemplate);
        myDiagram.nodeTemplateMap.add("hBar", hBarTemplate);

        var palette = new go.Palette("palette"); // create a new Palette in the HTML DIV element "palette"

        // share the template map with the Palette
        palette.nodeTemplateMap = myDiagram.nodeTemplateMap;
        //palette.groupTemplateMap = myDiagram.groupTemplateMap;

        palette.model.nodeDataArray = [
            { category: "image1" },
            { category: "image2" },
            { category: "image3" },
            { category: "image4" },
            { category: "image5" },
            { category: "image6" },
            { category: "image7" },
            { category: "image8" },
            { category: "image9" },
            { category: "image10" },
            { category: "table" },
            { category: "hBar" }
        ];

        myDiagram.addDiagramListener("ExternalObjectsDropped", function (e) {
            if (myDiagram.currentTool instanceof go.TextEditingTool) {
                myDiagram.currentTool.acceptText(go.TextEditingTool.LostFocus);
            }
            myDiagram.commandHandler.ungroupSelection();
            jQuery.ajax({
                type: "GET",
                url: '/Home/GetRandomObjectProperties'
            }).done(function (data) {
                // loop through selection to find table node and populate properties
                myDiagram.selection.each(function (p) {
                    if (p instanceof go.Node && p.category === "table") {
                        var nodedata = p.data;
                        var properties = data.map(function (item) {
                            return { "property_name": item.Item1.toString(), "property_value": item.Item2.toString() };
                        });
                        myDiagram.model.setDataProperty(nodedata, "properties", properties);
                        return;
                    }
                });
            });
        });

        // load the initial diagram
        load();

        // continually update the diagram
        loop();
    };

    /* Public methods */
    return {
        initSchemaEditor: initSchemaEditor,
        setMode: setMode,
        save: save,
        load: load
    };
})();

2)第二个JS文件没有按照模块模式进行组织,它看起来如下:

"use strict";

var sharedToolTip;
var image1Template;
var image2Template;
var image3Template;
var image4Template;
var image5Template;
var image6Template;
var image7Template;
var image8Template;
var image9Template;
var image10Template;
var tableTemplate;
var hBarTemplate;

function loadNodes() {
    var $ = go.GraphObject.make;

    // node template helpers
    sharedToolTip =
        $(go.Adornment, "Auto",
            $(go.Shape, "RoundedRectangle", { fill: "lightyellow" }),
            $(go.TextBlock, { margin: 2 },
                new go.Binding("text", "", function (d) { return d.category; })));

    // define some common property settings
    function nodeStyle() {
        return [
            new go.Binding("location", "loc", go.Point.parse).makeTwoWay(go.Point.stringify),
            new go.Binding("isShadowed", "isSelected").ofObject(),
            {
                selectionAdorned: false,
                shadowOffset: new go.Point(0, 0),
                shadowBlur: 15,
                shadowColor: "blue",
                toolTip: sharedToolTip
            }
        ];
    }

    function portStyle0(input) {
        return {
            desiredSize: new go.Size(3, 3),
            fill: "black",
            fromLinkable: !input,
            toLinkable: input,
            cursor: "pointer"
        };
    }

    function portStyle1() {
        return {
            desiredSize: new go.Size(3, 3),
            fill: "black",
            toLinkable: true,
            cursor: "pointer",
            fromLinkable: true,
            fromSpot: go.Spot.TopBottomSides,
            toSpot: go.Spot.TopBottomSides
        };
    }

    image1Template =
      $(go.Node, "Vertical", nodeStyle(),
        $(go.Picture, "Images/ElectricalElements/Cell_1.svg"),
        $(go.Shape, "Rectangle", portStyle1(),
          { portId: "", alignment: new go.Spot(0.18, 0) })
      );

    image2Template =
      $(go.Node, "Vertical", nodeStyle(),
        $(go.Picture, "Images/ElectricalElements/Cell_2.svg"),
        $(go.Shape, "Rectangle", portStyle1(),
          { portId: "", alignment: new go.Spot(0.33, 0) })
      );

    image3Template =
      $(go.Node, "Vertical", nodeStyle(),
        $(go.Picture, "Images/ElectricalElements/GTU.svg"),
        $(go.Shape, "Rectangle", portStyle1(),
          { portId: "", alignment: new go.Spot(0.215, 0) })
      );

    image4Template =
        $(go.Node, "Vertical", nodeStyle(),
        $(go.Shape, "Rectangle", portStyle0(false),
            { portId: "1", alignment: new go.Spot(0.125, 0) }),
        $(go.Picture, "Images/ElectricalElements/Sec_1.svg"),
        $(go.Shape, "Rectangle", portStyle1(),
            { portId: "2", alignment: new go.Spot(0.125, 0) })
        );

    image5Template =
        $(go.Node, "Vertical", nodeStyle(),
        $(go.Shape, "Rectangle", portStyle0(true),
            { portId: "3", alignment: new go.Spot(0.523, 0) }),
        $(go.Picture, "Images/ElectricalElements/Sec_2.svg"),
        $(go.Shape, "Rectangle", portStyle1(),
            { portId: "4", alignment: new go.Spot(0.523, 0) })
        );

    image6Template =
      $(go.Node, "Vertical", nodeStyle(),
        $(go.Shape, "Rectangle", portStyle0(true),
          { portId: "", alignment: new go.Spot(0.12, 0) }),
        $(go.Picture, "Images/ElectricalElements/Sec_3.svg"),
        $(go.Shape, "Rectangle", portStyle1(),
          { portId: "", alignment: new go.Spot(0.12, 0) })
      );

    image7Template =
      $(go.Node, "Vertical", nodeStyle(),
        $(go.Picture, "Images/ElectricalElements/Tr_1.svg"),
        $(go.Shape, "Rectangle", portStyle1(),
          { portId: "", alignment: new go.Spot(0.42, 0) })
      );

    image8Template =
        $(go.Node, "Vertical", nodeStyle(),
        $(go.Shape, "Rectangle", portStyle1(),
            { portId: "", alignment: new go.Spot(0.59, 0) }),
        $(go.Picture, "Images/ElectricalElements/Tr_2.svg")
        );

    image9Template =
        $(go.Node, "Vertical", nodeStyle(),
            {
                resizable: true,
                resizeObjectName: "SHAPE", selectionObjectName: "SHAPE"
            },
        $(go.Shape, "Rectangle",
            {
                name: "SHAPE",
                fill: transparent,
                width: 60,
                height: 40,
                stroke: black,
                strokeWidth: 1,
                strokeDashArray: [5, 5]
            },
          new go.Binding("desiredSize", "size", go.Size.parse).makeTwoWay(go.Size.stringify))
        );

    image10Template =
      $(go.Node, "Vertical", nodeStyle(),
        $(go.TextBlock,
        {
            text: "text",
            editable: true,
            isMultiline: true
        },
        new go.Binding("text", "text").makeTwoWay())
      );

    tableTemplate =
        $(go.Node, go.Panel.Auto, nodeStyle(),
        $(go.Shape, { fill: "white", stroke: "gray", strokeWidth: 1 }),
        { movable: true },
        new go.Binding("location", "loc", go.Point.parse).makeTwoWay(go.Point.stringify),
        $(go.Panel, "Table",
            new go.Binding("itemArray", "properties"),
            {
                defaultAlignment: go.Spot.Left,
                defaultColumnSeparatorStroke: "black",
                itemTemplate:
                    $(go.Panel, "TableRow",
                        $(go.TextBlock, new go.Binding("text", "property_name"),
                        { column: 0, margin: 1, font: "bold 7pt sans-serif" }),
                        $(go.TextBlock, new go.Binding("text", "property_value"),
                        { column: 1, margin: 1 })
                    )
            },
            $(go.Panel, "TableRow",
                { isPanelMain: true },
                $(go.TextBlock, "Name",
                { column: 0, margin: new go.Margin(1, 1, 0, 1), font: "bold 7pt sans-serif" }),
                $(go.TextBlock, "Value",
                { column: 1, margin: new go.Margin(1, 1, 0, 1), font: "bold 7pt sans-serif" })
            ),
            $(go.RowColumnDefinition,
            { row: 0, background: "lightgray" }),
            $(go.RowColumnDefinition,
            { row: 1, separatorStroke: "black" })
        )
    );

    hBarTemplate =
      $(go.Node,
        new go.Binding("location", "location", go.Point.parse).makeTwoWay(go.Point.stringify),
        {
            layerName: "Background",
            // special resizing: just at the ends
            resizable: true, resizeObjectName: "SHAPE",
            resizeAdornmentTemplate:
              $(go.Adornment, "Spot",
                $(go.Placeholder),
                $(go.Shape, // left resize handle
                  {
                      alignment: go.Spot.Left, cursor: "col-resize",
                      desiredSize: new go.Size(6, 6), fill: "lightblue", stroke: "dodgerblue"
                  }),
                $(go.Shape, // right resize handle
                  {
                      alignment: go.Spot.Right, cursor: "col-resize",
                      desiredSize: new go.Size(6, 6), fill: "lightblue", stroke: "dodgerblue"
                  })),
            rotatable: true
        },
        $(go.Shape, "Rectangle",
          {
              name: "SHAPE",
              fill: "black", stroke: null, strokeWidth: 0,
              width: 60, height: 5,
              minSize: new go.Size(50, 5),
              maxSize: new go.Size(Infinity, 5)
          },
          new go.Binding("desiredSize", "size", go.Size.parse).makeTwoWay(go.Size.stringify),
          new go.Binding("fill"),
          { portId: "", toLinkable: true })
      );
};

我从主JS文件中的第二个JS文件调用函数loadNodes,它可以工作。

但是,当我尝试根据模块模式组织第二个JS文件时,它停止了工作。

我尝试了以下内容:

1)主文件:

...

NodeRepository.loadNodes();

myDiagram.nodeTemplateMap.add("image1", NodeRepository.image1Template);
myDiagram.nodeTemplateMap.add("image2", NodeRepository.image2Template);
myDiagram.nodeTemplateMap.add("image3", NodeRepository.image3Template);
myDiagram.nodeTemplateMap.add("image4", NodeRepository.image4Template);
myDiagram.nodeTemplateMap.add("image5", NodeRepository.image5Template);
myDiagram.nodeTemplateMap.add("image6", NodeRepository.image6Template);
myDiagram.nodeTemplateMap.add("image7", NodeRepository.image7Template);
myDiagram.nodeTemplateMap.add("image8", NodeRepository.image8Template);
myDiagram.nodeTemplateMap.add("image9", NodeRepository.image9Template);
myDiagram.nodeTemplateMap.add("image10", NodeRepository.image10Template);
myDiagram.nodeTemplateMap.add("table", NodeRepository.tableTemplate);
myDiagram.nodeTemplateMap.add("hBar", NodeRepository.hBarTemplate);

...

2)第二个文件:

"use strict";

var NodeRepository = (function () {
    var sharedToolTip;
    var image1Template;
    var image2Template;
    var image3Template;
    var image4Template;
    var image5Template;
    var image6Template;
    var image7Template;
    var image8Template;
    var image9Template;
    var image10Template;
    var tableTemplate;
    var hBarTemplate;

    function loadNodes() {
        var $ = go.GraphObject.make;
        ...
    };

    return {
        image1Template: image1Template,
        image2Template: image2Template,
        image3Template: image3Template,
        image4Template: image4Template,
        image5Template: image5Template,
        image6Template: image6Template,
        image7Template: image7Template,
        image8Template: image8Template,
        image9Template: image9Template,
        image10Template: image10Template,
        tableTemplate: tableTemplate,
        hBarTemplate: hBarTemplate,
        loadNodes: loadNodes
    };
})();

我做错了什么?

1 个答案:

答案 0 :(得分:0)

这就是我的所作所为:

"use strict";

var NodeRepository = (function () {

    var sharedToolTip;
    var image1Template;
    var image2Template;
    var image3Template;
    var image4Template;
    var image5Template;
    var image6Template;
    var image7Template;
    var image8Template;
    var image9Template;
    var image10Template;
    var tableTemplate;
    var hBarTemplate;

    function image1Public() {
        return image1Template;
    }
    function image2Public() {
        return image2Template;
    }
    function image3Public() {
        return image3Template;
    }
    function image4Public() {
        return image4Template;
    }
    function image5Public() {
        return image5Template;
    }
    function image6Public() {
        return image6Template;
    }
    function image7Public() {
        return image7Template;
    }
    function image8Public() {
        return image8Template;
    }
    function image9Public() {
        return image9Template;
    }
    function image10Public() {
        return image10Template;
    }
    function image11Public() {
        return tableTemplate;
    }
    function image12Public() {
        return hBarTemplate;
    }

    function loadNodes() {
        var $ = go.GraphObject.make;

        // node template helpers
        sharedToolTip =
            $(go.Adornment, "Auto",
                $(go.Shape, "RoundedRectangle", { fill: "lightyellow" }),
                $(go.TextBlock, { margin: 2 },
                    new go.Binding("text", "", function (d) { return d.category; })));

        // define some common property settings
        function nodeStyle() {
            return [
                new go.Binding("location", "loc", go.Point.parse).makeTwoWay(go.Point.stringify),
                new go.Binding("isShadowed", "isSelected").ofObject(),
                {
                    selectionAdorned: false,
                    shadowOffset: new go.Point(0, 0),
                    shadowBlur: 15,
                    shadowColor: "blue",
                    toolTip: sharedToolTip
                }
            ];
        }

        function portStyle0(input) {
            return {
                desiredSize: new go.Size(3, 3),
                fill: "black",
                fromLinkable: !input,
                toLinkable: input,
                cursor: "pointer"
            };
        }

        function portStyle1() {
            return {
                desiredSize: new go.Size(3, 3),
                fill: "black",
                toLinkable: true,
                cursor: "pointer",
                fromLinkable: true,
                fromSpot: go.Spot.TopBottomSides,
                toSpot: go.Spot.TopBottomSides
            };
        }

        image1Template =
          $(go.Node, "Vertical", nodeStyle(),
            $(go.Picture, "Images/ElectricalElements/Cell_1.svg"),
            $(go.Shape, "Rectangle", portStyle1(),
              { portId: "", alignment: new go.Spot(0.18, 0) })
          );

        image2Template =
          $(go.Node, "Vertical", nodeStyle(),
            $(go.Picture, "Images/ElectricalElements/Cell_2.svg"),
            $(go.Shape, "Rectangle", portStyle1(),
              { portId: "", alignment: new go.Spot(0.33, 0) })
          );

        image3Template =
          $(go.Node, "Vertical", nodeStyle(),
            $(go.Picture, "Images/ElectricalElements/GTU.svg"),
            $(go.Shape, "Rectangle", portStyle1(),
              { portId: "", alignment: new go.Spot(0.215, 0) })
          );

        image4Template =
            $(go.Node, "Vertical", nodeStyle(),
            $(go.Shape, "Rectangle", portStyle0(false),
                { portId: "1", alignment: new go.Spot(0.125, 0) }),
            $(go.Picture, "Images/ElectricalElements/Sec_1.svg"),
            $(go.Shape, "Rectangle", portStyle1(),
                { portId: "2", alignment: new go.Spot(0.125, 0) })
            );

        image5Template =
            $(go.Node, "Vertical", nodeStyle(),
            $(go.Shape, "Rectangle", portStyle0(true),
                { portId: "3", alignment: new go.Spot(0.523, 0) }),
            $(go.Picture, "Images/ElectricalElements/Sec_2.svg"),
            $(go.Shape, "Rectangle", portStyle1(),
                { portId: "4", alignment: new go.Spot(0.523, 0) })
            );

        image6Template =
          $(go.Node, "Vertical", nodeStyle(),
            $(go.Shape, "Rectangle", portStyle0(true),
              { portId: "", alignment: new go.Spot(0.12, 0) }),
            $(go.Picture, "Images/ElectricalElements/Sec_3.svg"),
            $(go.Shape, "Rectangle", portStyle1(),
              { portId: "", alignment: new go.Spot(0.12, 0) })
          );

        image7Template =
          $(go.Node, "Vertical", nodeStyle(),
            $(go.Picture, "Images/ElectricalElements/Tr_1.svg"),
            $(go.Shape, "Rectangle", portStyle1(),
              { portId: "", alignment: new go.Spot(0.42, 0) })
          );

        image8Template =
            $(go.Node, "Vertical", nodeStyle(),
            $(go.Shape, "Rectangle", portStyle1(),
                { portId: "", alignment: new go.Spot(0.59, 0) }),
            $(go.Picture, "Images/ElectricalElements/Tr_2.svg")
            );

        image9Template =
            $(go.Node, "Vertical", nodeStyle(),
                {
                    resizable: true,
                    resizeObjectName: "SHAPE", selectionObjectName: "SHAPE"
                },
            $(go.Shape, "Rectangle",
                {
                    name: "SHAPE",
                    fill: transparent,
                    width: 60,
                    height: 40,
                    stroke: black,
                    strokeWidth: 1,
                    strokeDashArray: [5, 5]
                },
              new go.Binding("desiredSize", "size", go.Size.parse).makeTwoWay(go.Size.stringify))
            );

        image10Template =
          $(go.Node, "Vertical", nodeStyle(),
            $(go.TextBlock,
            {
                text: "text",
                editable: true,
                isMultiline: true
            },
            new go.Binding("text", "text").makeTwoWay())
          );

        tableTemplate =
            $(go.Node, go.Panel.Auto, nodeStyle(),
            $(go.Shape, { fill: "white", stroke: "gray", strokeWidth: 1 }),
            { movable: true },
            new go.Binding("location", "loc", go.Point.parse).makeTwoWay(go.Point.stringify),
            $(go.Panel, "Table",
                new go.Binding("itemArray", "properties"),
                {
                    defaultAlignment: go.Spot.Left,
                    defaultColumnSeparatorStroke: "black",
                    itemTemplate:
                        $(go.Panel, "TableRow",
                            $(go.TextBlock, new go.Binding("text", "property_name"),
                            { column: 0, margin: 1, font: "bold 7pt sans-serif" }),
                            $(go.TextBlock, new go.Binding("text", "property_value"),
                            { column: 1, margin: 1 })
                        )
                },
                $(go.Panel, "TableRow",
                    { isPanelMain: true },
                    $(go.TextBlock, "Name",
                    { column: 0, margin: new go.Margin(1, 1, 0, 1), font: "bold 7pt sans-serif" }),
                    $(go.TextBlock, "Value",
                    { column: 1, margin: new go.Margin(1, 1, 0, 1), font: "bold 7pt sans-serif" })
                ),
                $(go.RowColumnDefinition,
                { row: 0, background: "lightgray" }),
                $(go.RowColumnDefinition,
                { row: 1, separatorStroke: "black" })
            )
        );

        hBarTemplate =
          $(go.Node,
            new go.Binding("location", "location", go.Point.parse).makeTwoWay(go.Point.stringify),
            {
                layerName: "Background",
                // special resizing: just at the ends
                resizable: true, resizeObjectName: "SHAPE",
                resizeAdornmentTemplate:
                  $(go.Adornment, "Spot",
                    $(go.Placeholder),
                    $(go.Shape, // left resize handle
                      {
                          alignment: go.Spot.Left, cursor: "col-resize",
                          desiredSize: new go.Size(6, 6), fill: "lightblue", stroke: "dodgerblue"
                      }),
                    $(go.Shape, // right resize handle
                      {
                          alignment: go.Spot.Right, cursor: "col-resize",
                          desiredSize: new go.Size(6, 6), fill: "lightblue", stroke: "dodgerblue"
                      })),
                rotatable: true
            },
            $(go.Shape, "Rectangle",
              {
                  name: "SHAPE",
                  fill: "black", stroke: null, strokeWidth: 0,
                  width: 60, height: 5,
                  minSize: new go.Size(50, 5),
                  maxSize: new go.Size(Infinity, 5)
              },
              new go.Binding("desiredSize", "size", go.Size.parse).makeTwoWay(go.Size.stringify),
              new go.Binding("fill"),
              { portId: "", toLinkable: true })
          );
    };

    return {
        image1Public: image1Public,
        image2Public: image2Public,
        image3Public: image3Public,
        image4Public: image4Public,
        image5Public: image5Public,
        image6Public: image6Public,
        image7Public: image7Public,
        image8Public: image8Public,
        image9Public: image9Public,
        image10Public: image10Public,
        image11Public: image11Public,
        image12Public: image12Public,
        loadNodes: loadNodes
    };

})();