In this design each swimlane is implemented by a Group, and all lanes are inside a "Pool" Group. Each lane Group has its own Group.layout, which in this case is a LayeredDigraphLayout. Each pool Group has its own custom GridLayout that arranges all of its lanes in a vertical stack. That custom layout makes sure all of the pool's lanes have the same length. If you don't want each lane/group to have its own layout, you could use set the lane group's Group.layout to null and set the pool group's Group.layout to an instance of SwimLaneLayout, shown at Swim Lane Layout.

When dragging nodes note that the nodes are limited to stay within the lanes. This is implemented by a custom Part.dragComputation function, here named stayInGroup. Hold down the Shift key while dragging simple nodes to move the selection to another lane. Lane groups cannot be moved between pool groups.

A Group (i.e. swimlane) is movable but not copyable. When the user moves a lane up or down the lanes automatically re-order. You can prevent lanes from being moved and thus re-ordered by setting Group.movable to false.

Each Group is collapsible. The previous breadth of that lane is saved in the savedBreadth property, to be restored when expanded.

When a Group/lane is selected, its custom Part.resizeAdornmentTemplate gives it a broad resize handle at the bottom of the Group and a broad resize handle at the right side of the Group. This allows the user to resize the "breadth" of the selected lane as well as the "length" of all of the lanes. However, the custom ResizingTool prevents the lane from being too narrow to hold the Group.placeholder that represents the subgraph, and it prevents the lane from being too short to hold any of the contents of the lanes. Each Group/lane is also has a GraphObject.minSize to keep it from being too narrow even if there are no member Parts at all.

A different sample has its swim lanes horizontally oriented: Swim Lanes (horizontal).

Diagram Model saved in JSON format:

GoJS Features in this sample

Table Panels

The "Table" Panel, Panel.Table, arranges objects in rows and columns. Each object in a Table Panel is put into the cell indexed by the value of GraphObject.row and GraphObject.column. The panel will look at the rows and columns for all of the objects in the panel to determine how many rows and columns the table should have. More information can be found in the GoJS Intro.

Related samples

Grid Layouts

This predefined layout is used for placing Nodes in a grid-like arrangement. Nodes can be ordered, spaced apart, and wrapped as needed. This Layout ignores any Links connecting the nodes being laid out. More information can be found in the GoJS Intro.

Related samples

Layered Digraph Layout

This predefined layout is used for placing Nodes of a general directed graph in layers (rows or columns). This is more general than TreeLayout, as it does not require that the graph be tree-structured. More information can be found in the GoJS Intro.

Related samples

Custom Layouts

GoJS allows for the creation of custom layouts to meet specific needs.

There are also many layouts that are extensions -- not predefined in the go.js or go-debug.js library, but available as source code in one of the three extension directories, with some documentation and corresponding samples. More information can be found in the GoJS Intro.

Related samples


The Group class is used to treat a collection of Nodes and Links as if they were a single Node. Those nodes and links are members of the group; together they constitute a subgraph.

A subgraph is not another Diagram, so there is no separate HTML Div element for the subgraph of a group. All of the Parts that are members of a Group belong to the same Diagram as the Group. There can be links between member nodes and nodes outside of the group as well as links between the group itself and other nodes. There can even be links between member nodes and the containing group itself.

More information can be found in the GoJS Intro.

Related samples


Tools handle all input events, such as mouse and keyboard interactions, in a Diagram. There are many kinds of predefined Tool classes that implement all of the common operations that users do.

For flexibility and simplicity, all input events are canonicalized as InputEvents and redirected by the diagram to go to the Diagram.currentTool. By default the Diagram.currentTool is an instance of ToolManager held as the Diagram.toolManager. The ToolManager implements support for all mode-less tools. The ToolManager is responsible for finding another tool that is ready to run and then making it the new current tool. This causes the new tool to process all of the input events (mouse, keyboard, and touch) until the tool decides that it is finished, at which time the diagram's current tool reverts back to the Diagram.defaultTool, which is normally the ToolManager, again.

More information can be found in the GoJS Intro.

Related samples


GoJS defines several Panels for common uses. These include "Button", "TreeExpanderButton", "SubGraphExpanderButton", "PanelExpanderButton", "ContextMenuButton", and "CheckBoxButton". "ContextMenuButton"s are typically used inside of "ContextMenu" Panels; "CheckBoxButton"s are used in the implementation of "CheckBox" Panels.

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.

More information can be found in the GoJS Intro.

Related samples