How to make LineH to be port as a whole?

Please, take a look at the following diagram:

There is an element above and line below. The elements like that one could be more and they can be above and below the line. I put the port at the bottom of element and want to connect to the line. Of course, I could put ports on the line and make the connection in that way. But, is there a way to not to put the ports on the line, but make the line to be port without additional small rectangles. I’d like to draw the lines from elements above and below and connect them directly to the line as is.

Perhaps you want to implement a custom Link class such as the one in Network Configuration.

Thank you. I’ve found that sample as well.

One more question - could diagram have more than one link template?

http://gojs.net/latest/intro/templateMaps.html

Based on network sample, I’ve got the following:

If you are wondering about the multi-segmented link route, you’ll need to debug that, because clearly the Network sample does not show that kind of routing unless there is no straight vertical line from the port to the horizontal bar node.

I don’t understand where’s the mistake.

What I need except of HTML and JS to show the issue on https://codepen.io? I suppose I need to reference GoJS files, but how can I do that?

The complete code is here:

var black = "black";
var myDiagram;

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

    myDiagram = $(go.Diagram, "myDiagramDiv",
    {
        initialContentAlignment: go.Spot.Center,
        allowDrop: true,
        "undoManager.isEnabled": true,
        "linkingTool.direction": go.LinkingTool.ForwardsOnly
    });

    myDiagram.requestUpdate();

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

    myDiagram.linkTemplate =
        $(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 })
        );

    // 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"
            }
        ];
    }

    var image1Template =
      $(go.Node, "Vertical", nodeStyle(),
        $(go.Picture, "Images/ElectricalElements/Cell_1.svg"),
        $(go.Shape, "Rectangle",
          {
              portId: "", fill: "black", desiredSize: new go.Size(3, 3), alignment: new go.Spot(0.13, 0),
              fromLinkable: true, fromSpot: go.Spot.TopBottomSides, toSpot: go.Spot.TopBottomSides,
              cursor: "pointer"
          })
      );

    var image2Template =
      $(go.Node, "Vertical", nodeStyle(),
        $(go.Picture, "Images/ElectricalElements/Cell_2.svg"),
        $(go.Shape, "Rectangle",
          {
              portId: "", fill: "black", desiredSize: new go.Size(3, 3), alignment: new go.Spot(0.26, 0),
              fromLinkable: true, fromSpot: go.Spot.TopBottomSides, toSpot: go.Spot.TopBottomSides,
              cursor: "pointer"
          })
      );

    var hBarTemplate =
      $(go.Node,
        new go.Binding("location", "location", go.Point.parse).makeTwoWay(go.Point.stringify),
        {
            // 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"
                  }))
        },
        $(go.Shape, "Rectangle",
          {
              name: "SHAPE",
              fill: "black", stroke: null, strokeWidth: 0,
              width: 50, height: 4,
              minSize: new go.Size(50, 4),
              maxSize: new go.Size(Infinity, 4)
          },
          new go.Binding("desiredSize", "size", go.Size.parse).makeTwoWay(go.Size.stringify),
          new go.Binding("fill"),
          { portId: "", toLinkable: true })
      );

    // add the templates created above to myDiagram and palette
    myDiagram.nodeTemplateMap.add("image1", image1Template);
    myDiagram.nodeTemplateMap.add("image2", image2Template);
    myDiagram.nodeTemplateMap.add("hBar", hBarTemplate);

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

    palette.model.nodeDataArray = [
      { category: "image1" },
      { category: "image2" },
      { category: "hBar" }
    ];

    // continually update the diagram
    loop();
}

// 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);
        //}
    });
    myDiagram.skipsUndoManager = oldskip;
}

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

Category names are case sensitive.

Aaaaaaaa!

Thank you.

By the way, I’ve already posted the issue to codepen.io.