# Buttons

For your convenience we have defined several Panels for common uses. These include "Button", "TreeExpanderButton", "SubGraphExpanderButton", "PanelExpanderButton", and "ContextMenuButton".

These predefined panels can be used as if they were Panel-derived classes in calls to GraphObject.make. They are implemented as simple visual trees of GraphObjects in Panels, with pre-set properties and event handlers.

You can see a copy of their definitions in this file: Buttons.js.

See samples that make use of buttons in the samples index. In addition, see the Checkboxes extension for an example of using "CheckBoxButton".

## General Buttons

The most general kind of predefined Panel is "Button".

      diagram.initialContentAlignment = go.Spot.Center;

      diagram.nodeTemplate =
        $(go.Node, "Auto",
          { locationSpot: go.Spot.Center },
          $(go.Shape, "Rectangle",
            { fill: "gold" }),
          $(go.Panel, "Vertical",
            { margin: 3 },
            $("Button",
              { margin: 2,
                click: incrementCounter },
              $(go.TextBlock, "Click me!")),
            $(go.TextBlock,
              new go.Binding("text", "clickCount",
                             function(c) { return "Clicked " + c + " times."; }))
          )
        );

      function incrementCounter(e, obj) {
        var node = obj.part;
        var data = node.data;
        if (data) {
          node.diagram.startTransaction("clicked");
          var old = data.clickCount;
          data.clickCount++;
          node.diagram.model.raiseDataChanged(data, "clickCount", old, data.clickCount);
          node.diagram.commitTransaction("clicked");
        }
      }

      diagram.model = new go.GraphLinksModel(
        [ { clickCount: 0 } ]);

## TreeExpanderButtons

It is common to want to expand and collapse subtrees. It is easy to let the user control this by adding an instance of the "TreeExpanderButton" to your node template.

      diagram.initialContentAlignment = go.Spot.Center;

      diagram.nodeTemplate =
        $(go.Node, "Spot",
          $(go.Panel, "Auto",
            $(go.Shape, "Rectangle",
              { fill: "gold" }),
            $(go.TextBlock, "Click small button\nto collapse/expand subtree",
              { margin: 5 })
          ),
          $("TreeExpanderButton",
            { alignment: go.Spot.Bottom, alignmentFocus: go.Spot.Top },
            { visible: true })
        );

      diagram.layout = $(go.TreeLayout, { angle: 90 });

      diagram.model = new go.GraphLinksModel(
        [ { key: 1 },
          { key: 2 } ],
        [ { from: 1, to: 2 } ] );

## SubGraphExpanderButtons

It is also common to want to expand and collapse groups containing subgraphs. You can let the user control this by adding an instance of the "SubGraphExpanderButton" to your group template.

      diagram.initialContentAlignment = go.Spot.Center;

      diagram.groupTemplate =
        $(go.Group, "Auto",
          $(go.Shape, "Rectangle",
            { fill: "gold" }),
          $(go.Panel, "Vertical",
            { margin: 5,
              defaultAlignment: go.Spot.Left },
            $(go.Panel, "Horizontal",
              $("SubGraphExpanderButton",
                { margin: new go.Margin(0, 3, 5, 0) }),
              $(go.TextBlock, "Group")
            ),
            $(go.Placeholder)
          )
        );

      diagram.model = new go.GraphLinksModel(
        [ { key: 0, isGroup: true },
          { key: 1, group: 0 },
          { key: 2, group: 0 },
          { key: 3, group: 0 } ] );

## PanelExpanderButtons

It is common to want to expand and collapse a piece of a node, thereby showing or hiding details that are sometimes not needed. It is easy to let the user control this by adding an instance of the "PanelExpanderButton" to your node template. The second argument to GraphObject.make should be a string that names the element in the node whose GraphObject.visible property you want the button to toggle.

      diagram.initialContentAlignment = go.Spot.Center;

      diagram.nodeTemplate =
        $(go.Node, "Auto",
          $(go.Shape,
            { fill: "gold" }),
          $(go.Panel, "Table",
            { defaultAlignment: go.Spot.Top, defaultColumnSeparatorStroke: "black" },
            $(go.Panel, "Table",
              { column: 0 },
              $(go.TextBlock, "List 1",
                { column: 0, margin: new go.Margin(3, 3, 0, 3),
                  font: "bold 12pt sans-serif" }),
              $("PanelExpanderButton", "LIST1",
                { column: 1 }),
              $(go.Panel, "Vertical",
                { name: "LIST1", row: 1, column: 0, columnSpan: 2 },
                new go.Binding("itemArray", "list1"))
            ),
            $(go.Panel, "Table",
              { column: 1 },
              $(go.TextBlock, "List 2",
                { column: 0, margin: new go.Margin(3, 3, 0, 3),
                  font: "bold 12pt sans-serif" }),
              $("PanelExpanderButton", "LIST2",
                { column: 1 }),
              $(go.Panel, "Vertical",
                { name: "LIST2", row: 1, column: 0, columnSpan: 2 },
                new go.Binding("itemArray", "list2"))
            )
          )
        );

      diagram.model = new go.GraphLinksModel([
        {
          key: 1,
          list1: [ "one", "two", "three", "four", "five" ],
          list2: [ "first", "second", "third", "fourth" ]
        }
      ]);

## ContextMenuButtons

Although you can implement context menus in any way you choose, it is common to use the predefined "ContextMenuButton".

      diagram.initialContentAlignment = go.Spot.Center;

      diagram.nodeTemplate =
        $(go.Node, "Auto",
          $(go.Shape, "Rectangle",
            { fill: "gold" }),
          $(go.TextBlock, "Use ContextMenu!",
            { margin: 5 })
        );

      diagram.nodeTemplate.contextMenu =
        $(go.Adornment, "Vertical",
          $("ContextMenuButton",
            $(go.TextBlock, "Shift Left"),
            { click: function(e, obj) { shiftNode(obj, -20); } }),
          $("ContextMenuButton",
            $(go.TextBlock, "Shift Right"),
            { click: function(e, obj) { shiftNode(obj, +20); } })
        );

      function shiftNode(obj, dist) {
        var adorn = obj.part;
        var node = adorn.adornedPart;
        node.diagram.startTransaction("Shift");
        var pos = node.location.copy();
        pos.x += dist;
        node.location = pos;
        node.diagram.commitTransaction("Shift");
      }

      diagram.model = new go.GraphLinksModel(
        [ { key: 1 } ] );

For an example of defining context menus using HTML, see the Custom ContextMenu sample.

## Button Definitions

The implementation of all predefined buttons is provided in Buttons.js in the Extensions directory. You may wish to copy and adapt these definitions when creating your own buttons.

Those definitions might not be an up-to-date description of the actual standard button implementations that are in GoJS and used by GraphObject.make.

Note that the definitions of those buttons makes use of the GraphObject.defineBuilder static function. That extends the behavior of GraphObject.make to allow the creation of fairly complex visual trees by name with optional arguments. You can find the definitions of various kinds of controls throughout the samples and extensions, such as at:

- Buttons.js
- HyperlinkText.js
- ScrollingTable.js
- AutoRepeatButton