documentationfor yFiles for HTML 2.6

Supported User Interactions

yFiles for HTML offers a wide array of predefined actions, not only for commonly used editor functionality (such as clipboard support, or zooming), but also actions specific to editing graphs. Most kinds of interaction in the following sections are the result of a specific input mode handling input events, usually because they are child input modes of GraphEditorInputMode or GraphViewerInputMode. These child input modes are available on GraphEditorInputMode and GraphViewerInputMode as properties with the same name as the respective input mode. A few interactions are also supported directly by GraphComponent, even without any input mode. Naturally, every interaction that exists to actually change the graph is only supported with GraphEditorInputMode, not GraphViewerInputMode.

Unless otherwise stated, all user interactions which support mouse gestures support touch gestures as well.

One frequent type of customization is to change the gesture for an interaction. This is usually done with a property whose name ends in Recognizer and whose type is a function that takes an Object and an EventArgs instance and returns a boolean value. event recognizers thus are essentially a predicate that matches on certain events. You can write them manually, but there are also predefined event recognizers for many common events, such as mouse button presses and modifier keys.

You can also easily combine event recognizers using appropriate helper methods:

Creating a combined event recognizer
const ctrlClick = EventRecognizers.createAndRecognizer(
  KeyEventRecognizers.CTRL_IS_DOWN,
  MouseEventRecognizers.LEFT_CLICK
)

Zooming, Panning, and Scrolling

Exploring the graph is often performed by panning the viewport and zooming. These are the most common types of interactions and are present in nearly every application. From a technical perspective both interactions move and resize the viewport. Zooming is handled by GraphComponent, while panning is handled by MoveViewportInputMode. Once the graph exceeds the current viewport, scrollbars appear which are handled by GraphComponent again.

The default gesture for zooming is simply turning the mouse wheel. If your application needs to use the mouse wheel for scrolling the viewport instead, you can configure this with the mouseWheelBehavior property, which has three major modes:

MouseWheelBehaviors.NONE
Turning the mouse wheel will do nothing.
MouseWheelBehaviors.ZOOM
Turning the mouse wheel or pinching on a touchpad will zoom the viewport. This is the default.
MouseWheelBehaviors.SCROLL
Turning the mouse wheel will scroll the viewport vertically, and horizontally when turning the mouse wheel while pressing the Shift key. No modifier key is required if bidirectional wheel events are available (e.g. touchpad or two-axis mouse wheel).

ZOOM and SCROLL can be combined as well, in which case scrolling is the default behavior when turning the mouse wheel and zooming happens when the mouseWheelZoomEventRecognizer is satisfied (default: Ctrl) and turning the mouse wheel.

On touchpads, this combination enables bidirectional panning with two fingers and pinch zooming:

Setting the combined zoom and scroll mouse wheel behavior
graphComponent.mouseWheelBehavior = MouseWheelBehaviors.ZOOM | MouseWheelBehaviors.SCROLL

Furthermore, you can combine those values with the special value ONLY_WHEN_FOCUSED to specify that the mouse wheel should only do anything when the GraphComponent currently has the focus.

Panning the viewport with GraphViewerInputMode is done by holding the left mouse button and dragging. With GraphEditorInputMode the Ctrl key has to be pressed as well to distinguish the gesture from edge creation and marquee or lasso selection. Common adjustments to the panning gesture are as follows:

MoveViewportInputMode.pressedRecognizer
Changes the mouse interaction to start the panning gesture.
MoveViewportInputMode.dragCursor
Changes the mouse cursor to show during the gesture.

You can turn off panning completely by disabling the MoveViewportInputMode via its enabled property.

Turning off panning the viewport
graphEditorInputMode.moveViewportInputMode.enabled = false

To make GraphEditorInputMode work like GraphViewerInputMode regarding panning and marquee selection, change the recognizer back to just a mouse drag and disable marquee selection entirely:

graphEditorInputMode.moveViewportInputMode.pressedRecognizer = MouseEventRecognizers.LEFT_DOWN
graphEditorInputMode.marqueeSelectionInputMode.enabled = false

With the horizontalScrollBarPolicy and verticalScrollBarPolicy properties you can configure the scrollbars on the GraphComponent to be always or never visible, or shown only when needed, which is the default.

Zooming and panning via multi-touch gestures is also supported by default. To pan the viewport, simply touch the screen and maintain contact as you move it around. To zoom, touch the screen with two fingers and make a pinching motion to zoom out and a stretching motion to zoom in. Common adjustments to the panning and zooming gesture are as follows:

MoveViewportInputMode.primaryDownRecognizer
Changes the interaction to start the move viewport gesture.
MoveViewportInputMode.secondaryDownRecognizer
Changes the interaction to start the pinch gesture.
MoveViewportInputMode.allowPinchZoom
Turns the zooming gesture using two touch pointers on or off.

Advanced customization of zoom and scrolling features is discussed in the section Restricting the Viewport, as well as Customizing Canvas Navigation.

Creating Nodes

Creating nodes is one of the basic user interactions provided by GraphEditorInputMode. By default a new node is created simply when left-clicking or tapping on an empty area in the canvas.

Node creation can be turned off via GraphEditorInputMode’s allowCreateNode property. Further customization options for node creation are discussed in detail in Customizing Creating Nodes.

Nodes can also be created with Drag and Drop.

Creating Edges

Creating edges is another basic interaction provided by GraphEditorInputMode. By default, starting a drag with the left mouse button on an unselected node will start edge creation. Simply releasing the mouse button over another node creates the edge. When using a touch device, the edge creation is started in a similar fashion by a long press on the source node, and then dragging the touch pointer to the target node and releasing it.

Bends can be introduced into the edge during creation by releasing the mouse button or touch pointer at an empty location in the canvas. Subsequent bends can be added by clicking or tapping on empty canvas locations. Right-clicking or long pressing a second touch pointer will undo the most recent bend and, if no bends are left, cancel edge creation altogether.

GraphEditorInputMode’s child input mode CreateEdgeInputMode allows you to customize edge creation in various ways via a number of properties:

CreateEdgeInputMode.allowCreateBend
Allows to turn off adding bends during edge creation. Note that to disallow creating bends entirely bend creation for existing edges must be disabled, too.
CreateEdgeInputMode.edgeDefaults
The defaults for newly-created edges, most notably their style. This works the same as setting defaults for new edges on a graph.
CreateEdgeInputMode.allowSelfloops
Whether self-loops, i.e. an edge that connects a node with itself, can be created.
CreateEdgeInputMode.validBeginCursor
The mouse cursor to show when edge creation can start. This is usually when hovering over an unselected node.
CreateEdgeInputMode.validBendCursor
The mouse cursor to show when a bend can be added. This is usually when the mouse pointer is over an empty part of the canvas during edge creation.
CreateEdgeInputMode.validEndCursor
The mouse cursor to show when edge creation can finish. This is usually when hovering over a possible target node during edge creation.

Creating edges is supported by the following auxiliary interaction concepts:

You can turn off edge creation by disabling the CreateEdgeInputMode via its enabled property or with GraphEditorInputMode’s allowCreateEdge property. Further customization options for edge creation are discussed in detail in Customizing Creating Edges.

Created edges can also be reconnected to other nodes. However, this is not enabled in the default configuration. This is described in detail in Customizing Reconnecting Edges.

Adding and Editing Labels

GraphEditorInputMode supports adding labels to graph items interactively. The default keyboard shortcut is F2, it will open a text area to edit the label for the currently selected item. The newly entered text can then be committed using Enter ↵, in which case it will become the label of the respective item. Changing an existing label can be done with F2 as well. Label editing can be canceled with Esc, in which case either no label is added, or the edited label isn’t changed.

GraphEditorInputMode offers a few simple ways to customize label editing and adding:

GraphEditorInputMode.labelEditableItems
The types of items that labels can be edited for. This can be either NODE, EDGE, or both.
GraphEditorInputMode.allowAddLabel
Specifies whether labels can be added to graph items by pressing Shift ⇧+F2 (or F2 on items that don’t already have labels).
GraphEditorInputMode.allowEditLabel
Specifies whether labels can be edited by pressing F2. When turned off, this also affects adding a label by pressing F2.
GraphEditorInputMode.autoRemoveEmptyLabels
Specifies whether labels with an empty text are automatically removed or not. Sometimes labels show more than just their text (e.g. an icon) in which case the empty text may actually be intentional.

Further customization options for label editing are discussed in detail in Customizing Adding and Editing Labels.

Creating Bends

Interactively designing an edge path can be done by creating bends, another of the basic graph structure-related interactions GraphEditorInputMode provides. Bends can be created during edge creation, but if the edge path after creation isn’t satisfactory they can also be added later. By default, the gesture to add a bend is to simply press the left mouse button on an edge path and drag. This will split the edge segment at the drag point and introduce a bend that will be placed where the mouse button is released.

You can be turn off bend creation on GraphEditorInputMode via its allowCreateBend property.

Creating bends is supported by the following auxiliary interaction concepts:

Deleting Items

All items in the graph can not only be created, but also removed again as well. By default selected items can be deleted by pressing Del. Deleting an item will also delete associated other items, such as labels or incident edges when a node is deleted.

GraphEditorInputMode has two properties for easy control of what can be deleted:

GraphEditorInputMode.deletableItems
The types of items that can be deleted. Note that dependent items will be deleted regardless of this setting, e.g. incident edges or labels when deleting a node.
GraphEditorInputMode.deletablePredicate
A predicate that controls what items can be deleted. This allows finer control than just the item type above.

Further customization options for deleting items are discussed in detail in Customizing Deleting Items.

Moving Items

GraphEditorInputMode offers the ability to reposition items by dragging them. By default this is done by pressing the left mouse button on a selected item and dragging the mouse. Releasing the mouse button again will finalize the new position of the item.

Moving a node
interaction move

GraphEditorInputMode handles moving items through two child input modes: MoveInputMode which handles moving all items except labels, and MoveLabelInputMode, which handles moving labels. Labels are handled differently since they are only allowed to move to certain positions (as defined by their label model) which are indicated as a visual aid as well. Common adjustments to item moving are as follows:

GraphEditorInputMode.movableItems
Specifies the types of items that can be moved.
MoveInputMode.pressedRecognizer
Changes the mouse interaction to start a moving gesture.
MoveInputMode.pressedRecognizerTouch
Changes the touch interaction to start a moving gesture.
MoveInputMode.moveCursor
Changes the mouse cursor to show during the move.

Further customization options for moving items are discussed in detail in Customizing Moving Items.

Moving items is supported by the following auxiliary interaction concepts:

  • Grouping: Moving a child node of a group node will resize the surrounding group node accordingly. Nodes can be moved in or out of group nodes by holding the Shift ⇧ key during a move.
  • Orthogonal Edge Editing: When moving nodes, incident edges will stay orthogonal.
  • Snapping

Resizing Nodes

By default GraphEditorInputMode will show a set of handles for selected items. For nodes these are eight handles on the sides and corners which can be used to resize the node by dragging the handles with the mouse.

Resize handles around a node
interaction resize

Since resizing nodes is done via handles, adjusting the behavior can be done with GraphEditorInputMode’s showHandleItems property. This is also the place where resizing nodes can be turned off completely by setting a value that does not include NODE.

Turning off interactive node resizing
graphEditorInputMode.showHandleItems = GraphItemTypes.ALL & ~GraphItemTypes.NODE

Further customization is possible via GraphEditorInputMode’s child input mode HandleInputMode which is discussed in more detail in Customizing Resizing Nodes.

Resizing nodes is supported by the following auxiliary interaction concepts:

Grouping

Graphs in yFiles for HTML support nesting nodes in so-called group nodes, as described in the introduction to the graph model. GraphEditorInputMode allows to interactively create and handle those as well.

Grouping-related features are disabled by default on GraphEditorInputMode and have to be enabled as the following code snippet shows.

Turning on grouping-related features
graphEditorInputMode.allowGroupingOperations = true

Grouping
A group node with several children
Moving child nodes resizes the group node accordingly

By default, selected nodes can be grouped in a newly created group node by pressing Ctrl+G. The selected nodes can also be removed from a group by pressing Ctrl+U.

When ungrouping nodes, they will still appear on top of the group node, but are no longer part of that group node. This may not immediately be evident because the group node will still be underneath the nodes, but the difference is apparent when moving the nodes afterwards.

Selected group nodes can also be resized to fit their contents by pressing Ctrl+Shift ⇧+G. Furthermore, nodes can be moved to another group node (or simply out of their current group) by holding the Shift ⇧ key during a move.

GraphEditorInputMode offers a number of properties to configure grouping features and behavior:

GraphEditorInputMode.allowGroupingOperations
Enables or disables all grouping-related interaction features. They can be further configured with the other properties below. This property is disabled by default. When disabled, the other properties below have no effect.
GraphEditorInputMode.allowGroupSelection
Enables or disables the group selection shortcut Ctrl+G.
GraphEditorInputMode.allowUngroupSelection
Enables or disables the ungroup selection shortcut Ctrl+U.
GraphEditorInputMode.allowAdjustGroupNodeSize
Enables or disables the adjust group node size shortcut Ctrl+Shift ⇧+G.

In addition to these features, you can collapse and expand groups if folding is enabled.

Keyboard Input

Many interactive features that GraphEditorInputMode provides can be accessed via keyboard shortcuts, some of which are already mentioned shortly in the other sections. Keyboard shortcuts for nearly all predefined operations are part of their respective Commands. Central to handling them is KeyboardInputMode, which both GraphEditorInputMode and GraphViewerInputMode have as a child input mode. KeyboardInputMode allows to add custom actions with custom shortcuts and manages the input and action maps of GraphComponent accordingly which is discussed in Custom Command Bindings.

While tying a keyboard shortcut to a certain command is done in KeyboardInputMode, the actual implementation for that command often resides elsewhere. In this case it is usually GraphEditorInputMode that handles most commands.

Another feature is keyboard navigation and selection, which is handled by the child input mode NavigationInputMode by both GraphEditorInputMode and GraphViewerInputMode. It allows you to navigate between nodes with the arrow keys. Selecting nodes in a certain direction can be done with Shift ⇧+arrow keys and Ctrl+arrow keys moves the focus in a certain direction.

Mouse Clicks

GraphEditorInputMode and GraphViewerInputMode support notifications for left and right mouse clicks and double clicks on items. This is a convenience extension provided on top of the lower-level click events provided by ClickInputMode. ClickInputMode, however, can still be useful if you want to handle clicks regardless of whether they happen on an item or not.

There are no special events on GraphEditorInputMode, GraphViewerInputMode, or ClickInputMode which report middle mouse clicks. Instead you have to use the Clicked or the DoubleClicked event and check by means of its arguments if the middle button has triggered the event.

Both GraphEditorInputMode and GraphViewerInputMode handle clicks on items in the same way. If an item is clicked, it will be focused and selected, in that order. The behavior of clicks can be adjusted with a few properties on either GraphEditorInputMode or GraphViewerInputMode, and their child input mode ClickInputMode:

GraphViewerInputMode.clickableItems
GraphEditorInputMode.clickableItems
The type of items that should be clickable. If an item is not clickable no events will be raised for that item and no default actions (focus and selection) will be taken.
ClickInputMode.doubleClickPolicy
How single clicks are reported when they are part of a double click. By default, two single click events followed by a double click event are raised.

Since clicking and selection are closely related, the properties that relate to both clicking and selection are discussed in Selection.

Further customization options for click handling are discussed in detail in Customizing Mouse Clicks.

Touch Gestures

When using touch devices, tapping the screen is processed in a similar fashion as mouse left-click events. The default gestures that are available with tapping are creating nodes and selecting items.

Despite its name, property GraphEditorInputMode.clickableItems will control the item types for which taps are handled as well. Acordingly, the GraphEditorInputMode or GraphViewerInputMode will dispatch an ItemClicked event for tapped items.

A more general handling of tap events is achieved with the low-level events on the TapInputMode which is a sub mode of both GraphEditorInputMode or GraphViewerInputMode.

There are also other more complex gestures with touch input, such as:

Further customization options for touch handling are discussed in detail in Customizing Touch Gestures.

Selection

GraphComponent manages a set of selected items, as described in Selection, Focus, and Highlight. Both GraphEditorInputMode and GraphViewerInputMode offer support for interactively managing this selection. Selected items are used for many commands and interactions, such as clipboard commands, or deleting items.

A selection of two nodes with their labels and an edge. The third node and second edge are not selected.
interaction selection1

Items can be selected in both GraphEditorInputMode and GraphViewerInputMode by simply left-clicking them. Selected items are highlighted with an item-specific selection indicator (e.g. a rectangle around a selected node).

When using a touch device, tapping on the device is equal to left-clicking in regards to selection. This means that in the following section, everything that is described as working with clicking will also work with tapping.

Selection in general and click selection in particular can be configured on GraphEditorInputMode and GraphViewerInputMode with a few properties:

GraphViewerInputMode.selectableItems
GraphEditorInputMode.selectableItems
The types of items that can be selected (via any method).
GraphViewerInputMode.selectablePredicate
GraphEditorInputMode.selectablePredicate
A predicate that controls what items can be selected. This allows finer control than just the item type above.
GraphViewerInputMode.clickSelectableItems
GraphEditorInputMode.clickSelectableItems
The types of items that can be selected by clicking them.

clickSelectableItems can only constrain selectableItems further.

Multiple items can easily be selected at once with marquee selection or lasso selection. Both selection modes work by holding the left mouse button on an empty canvas area and dragging the mouse or long press and drag using touch devices. Marquee selection will show a rectangular area in which all items will be selected when the mouse button / touch pointer is released. Lasso selection will show a freehand path within which all items will be selected when the mouse button / touch pointer is released.

There is also a shortcut for selecting all items, Ctrl+A, as well as for deselecting all items again, Ctrl+Shift ⇧+A.

Bulk selection interactions
Marquee selection
Lasso selection

Lasso selection is disabled by default, in favor of marquee selection. However, you can simply enable the lassoSelectionInputMode on GraphViewerInputMode or GraphEditorInputMode. By default lasso selection takes precedence over marquee selection (via the respective priorities of the input modes), so enabling the lassoSelectionInputMode is enough to switch from marquee to lasso selection.

marqueeSelectableItems is an additional property that specifically controls what items can be selected by marquee or lasso selection.

You can customize marquee and lasso selection on GraphViewerInputMode and GraphEditorInputMode and their child input modes MarqueeSelectionInputMode and LassoSelectionInputMode:

GraphViewerInputMode.marqueeSelectableItems
GraphEditorInputMode.marqueeSelectableItems
The types of items that can be selected via marquee or lasso selection.
MarqueeSelectionInputMode.marqueeCursor
The mouse cursor to use during the marquee selection gesture.
MarqueeSelectionInputMode.pressedRecognizer
MarqueeSelectionInputMode.pressedRecognizerTouch
Changes the interaction to start marquee selection.
LassoSelectionInputMode.lassoCursor
The mouse cursor to use during the lasso selection gesture.
LassoSelectionInputMode.validEndCursor
The mouse cursor to use when hovering over the end point for the gesture (by default this is where the gesture started).
LassoSelectionInputMode.prepareRecognizer
LassoSelectionInputMode.prepareRecognizerTouch
Changes the interaction to start lasso selection.

Marquee and lasso selection are available in GraphViewerInputMode, but disabled by default. You can enable either by setting the enabled property on GraphViewerInputMode’s marqueeSelectionInputMode or lassoSelectionInputMode. When enabled, both use Shift ⇧+drag as their default gesture to not clash with panning.

To select multiple items with more than one selection gesture, you can hold down the Ctrl key. Newly selected items will then be added to the selection instead of replacing it. This works with all selection interactions, be it click, marquee, or lasso selection.

Click selection also offers two other features: detail selection and cyclic selection. Detail selection can be used to explicitly select the topmost item under the mouse pointer, regardless of the current hit testing order. For example, by default when clicking a node the node will be selected, even when clicking on its label that is on top of the node. With detail selection, which by default uses Shift ⇧+click you can select the label when clicking it.

The clickHitTestOrder and doubleClickHitTestOrder properties determine by means of the item type which one will be considered when clicked or double-clicked if there are multiple items at a given location.

Cyclic selection on the other hand allows you to cycle through all possible hits at the click location by pressing the Alt key during the click. So, to stay with our example of a single node with a label on top of it, performing cyclic selection will first select the node, Alt-clicking the same location again will select the label. Now, if the node was in a group node, the selection order with cyclic selection would be node, group node, label, because the group node is below its child node and thus also exists at the click location.

Further customization options for click selection, as well as marquee and lasso selection are discussed in Customizing Selection. How the selection indicator’s visualization can be customized is explained in Styling Selection, Focus, and Highlight.

Focus

Similar to selection there is also the concept of a focused item. This item, usually a node, is shown with a dotted border and in many cases is also selected at the same time. Like selection, this focused item is supported by both GraphEditorInputMode and GraphViewerInputMode

Focus indicator on a node
interaction focus

The focused item is represented by GraphComponent’s currentItem property and is changed by clicking on a node or creating a new node via clicking on the canvas.

The focus indicator can serve two main purposes. It can be used to highlight a single item, e.g. in applications where the graph can’t be edited, but a single node can be selected for further information. The other purpose is selecting nodes one by one with the keyboard. The focus indicator can be moved by holding the Ctrl key and pressing an arrow key. Pressing Ctrl+Space will then select or de-select the focused node. This works similar to selecting files in many graphical file managers, e.g. Windows Explorer.

You can control what items can be focused interactively by changing the focusableItems property. To disable focusing an item completely, this property can be set to NONE.

How the focus indicator’s visualization can be customized is explained in Styling Selection, Focus, and Highlight.

Tooltips

Tooltips are small snippets of text shown when hovering the mouse pointer over a control. Usually, they explain in more detail what the control does. yFiles for HTML supports tooltips for all graph items with both GraphEditorInputMode and GraphViewerInputMode.

Tooltip on a node
interaction tooltip

How tooltips can be configured and set up is discussed in detail in Customizing Tooltips.

Context Menus

Right-clicking an item can show a context menu with both GraphEditorInputMode and GraphViewerInputMode. A different context menu can also be shown when right-clicking an empty canvas area.

A context menu on a node
interaction context menu

How a context menu can be configured and set up is discussed in detail in Customizing Context Menus.

Drag and Drop

GraphEditorInputMode supports drag and drop gestures as well, or rather, the drop part of the gesture. Drag and drop enables you to conveniently create applications that use a “palette” of items which can be dragged onto the canvas to create graph items.

Creating a node via drag and drop
interaction drag drop

You can drag elements from within the HTML document into a GraphComponent and drop them there. For nodes, labels, and ports this is handled by GraphEditorInputMode’s child input modes NodeDropInputMode, LabelDropInputMode, and PortDropInputMode, respectively. Since drag and drop functionality is usually different for each application (if needed at all), this mode is disabled by default.

With startDrag arbitrary HTML elements can be registered for a drag operation. By default, when the drag operation ends on a GraphComponent a new node will be created that is a copy of the dragged node.

This feature highly depends on the application implementation and requirements, so any further configuration and customization (including how to drag and drop your own data) is discussed in detail in Customizing Drag and Drop.

Drag and drop is supported by the following auxiliary interaction concepts:

Clipboard

GraphEditorInputMode provides support for the usual clipboard commands: Copy, Cut, and Paste. GraphViewerInputMode on the other hand, only provides support for Copy (as it cannot alter the graph). These commands also have the usual shortcuts:

Command Shortcuts
CopyCtrl+C, Ctrl+Ins
CutCtrl+X, Shift ⇧+Del
PasteCtrl+V, Shift ⇧+Ins

The Copy and Cut operations are applied to the selected items. Cut can be thought of as a combined Copy and Delete. This has some implications, e.g. when cutting a node that has incident edges, only the selected node will end up in the clipboard, but since cutting deletes the item from the graph, the connected edges will simply be removed.

There is another command, Duplicate, which can be thought of as a combined Copy-Paste command, except it doesn’t modify the clipboard. You can duplicate the selected items simply by pressing Ctrl+D. Since this is also a clipboard operation, the cases described above apply, e.g. when duplicating an edge with only one connected node.

There are a few easy customizations for the clipboard provided on GraphViewerInputMode and GraphEditorInputMode:

GraphViewerInputMode.allowClipboardOperations
Enables or disables copying items.
GraphEditorInputMode.allowClipboardOperations
Enables or disables support for Cut, Copy, Paste, and Duplicate.
GraphEditorInputMode.allowPaste
Enables or disables pasting items.
GraphEditorInputMode.pasteSelectableItems
The types of items that should be selected after pasting.
GraphEditorInputMode.pasteDelta
The geometric offset between the mouse location and the location where the items should be pasted.
GraphEditorInputMode.allowDuplicate
Enables or disables duplicating items.

The GraphClipboard class offers another option:

GraphClipboard.copyItems
The types of items that can be copied and pasted.

The clipboard can be extensively customized in nearly all aspects, which is described in Customizing the Clipboard.

Undo and Redo

yFiles for HTML offers comprehensive support for undoing and redoing graph modifications. Everything that can be changed on a graph can be undone too. Such modifications can be single changes, e.g. adding a node, or composite changes where many items change at once, e.g. moving multiple items. There is no limit to how many operations can be undone, except available memory.

Keyboard shortcuts for Undo and Redo are provided by GraphEditorInputMode. Undo uses Ctrl+Z, and Redo can be invoked with Ctrl+Y.

Undo and Redo support is disabled by default. To turn it on you need to enable it on the graph setting undoEngineEnabled to true:

Enabling undo support on a graph
graph.undoEngineEnabled = true

Undo and Redo support on GraphEditorInputMode is automatically available when the underlying graph supports it and can be turned off using the allowUndoOperations property.

Changes that can be undone include both interactive and programmatic changes. This is useful when creating custom interactions that modify the graph, which can be undone by the user the same way as interactive changes.

You can extend Undo and Redo support to your own operations or data if needed, and extensively customize it as well. This is described in detail in Customizing Undo and Redo.

Snapping

When creating, moving, or resizing elements, snapping can provide so-called snap lines that capture the mouse pointer when near them. This makes it easy to align items, have nodes share the same size, etc.

Snapping (here for moving a node) provides numerous snap lines to align graph items
interaction snapping

Snapping is not turned on by default and consists of two different parts: snapping all items except labels, and snapping labels. To enable snapping, you need to set a GraphSnapContext on GraphEditorInputMode’s snapContext property as well as a LabelSnapContext on GraphEditorInputMode’s labelSnapContext property:

Enabling snapping
graphEditorInputMode.snapContext = new GraphSnapContext()
graphEditorInputMode.labelSnapContext = new LabelSnapContext()

Snapping is supported by the following interactions:

There are a few different snap lines, some of which are only active with certain interactions:

Border and center snap lines

Snap line at the border of a node
Snap line in the center of a node

These snap lines appear at the borders and centers of nodes and make it easy to align centers or a particular border of several nodes when moving or resizing them. Labels will also snap to those snap lines for label models that allow free movement.

Same size snap lines

Snap line showing a matching width and height with other nodes.
interaction snapping size

These snap lines appear during resizing nodes when the width or height of the resized node matches the width or height of another node.

Same distance snap lines

Snapping a node so that is has the same distance as the other two
Snapping a node between two nodes so that it has the same distance to both of them

These are snap lines that appear when moving nodes to indicate that the distance between the moved node and an adjacent node matches the distance between two other nodes on the same line. This provides an easy way to create graphs that look regular without having to configure a grid.

Grid snapping

Snapping a node between two grid points
Snapping a node onto a grid point

yFiles for HTML also supports a grid, which enables snapping items to points at regular intervals. Grid snapping not only works for moving or resizing nodes, but also for creating edges and adding and moving bends.

Grid snapping has to be enabled explicitly by creating a suitable GridInfo object and activating grid snapping for various items on the GraphSnapContext:

const gridInfo = new GridInfo()
snapContext.nodeGridConstraintProvider = new GridConstraintProvider(gridInfo)
snapContext.bendGridConstraintProvider = new GridConstraintProvider(gridInfo)
snapContext.portGridConstraintProvider = new GridConstraintProvider(gridInfo)

Enabling grid snapping does not mean that the GraphComponent shows any grid visualization. You have to do that in addition:

graphComponent.backgroundGroup.addChild(
  new GridVisualCreator(gridInfo),
  ICanvasObjectDescriptor.ALWAYS_DIRTY_INSTANCE
)

How to configure and customize snapping is described in detail in Customizing Snapping.

Orthogonal Edge Editing

Orthogonal edge editing is a feature in GraphEditorInputMode that forces edge paths to only have right angles. While snapping gives some help to create and maintain orthogonal edge paths, it’s still time-consuming and unnecessary effort to do so manually when yFiles for HTML offers integrated support for most editing gestures to keep edges orthogonal. (Note that this doesn’t mean that it’s a decision between snapping or orthogonal edge editing — both features work very well together.)

A graph with orthogonal edges
interaction orthogonal

Orthogonal edge editing is disabled by default. To enable it, you have to set an OrthogonalEdgeEditingContext on GraphEditorInputMode’s orthogonalEdgeEditingContext property:

graphEditorInputMode.orthogonalEdgeEditingContext = new OrthogonalEdgeEditingContext()

Orthogonal edge editing is an interactive feature that affects interactive creation and modification of graph elements. If you instead want to programmatically make all edges in a graph orthogonal, the more appropriate approach is an edge routing algorithm. Of course, the two features can both be used in the same application without a problem.

Orthogonal edge editing modifies a number of interactions so that edges stay orthogonal:

Edge creation, naturally, now only creates orthogonal edges. When starting an edge creation gesture, the rough direction in which the mouse is moved first will determine the direction of the first edge segment. If the mouse pointer is not moved exactly orthogonal, a bend will also be shown so that the edge ends at the mouse pointer. Since the first segment direction is not always the correct one on the first try, you can press Space to toggle between the two possible orientations as long as no explicit bend has been created yet.

Different orientations of the first segment during orthogonal edge creation

Adding bends during edge creation is still done with the same gesture, except that implicit bends are also added whenever the current edge segment would not be orthogonal (as can be seen in the figures above).

Creating bends works rather differently when using orthogonal edge editing. Normally when creating a bend the gesture will, well, create a bend. However, with orthogonal edge editing this would always destroy the edge’s orthogonality. The best way to picture bend creation with orthogonal edge editing is actually to see it not as creating bends, but moving edge segments.

Moving edge segments
Start of drag
After finishing the drag

In case of the first or last edge segment the segment cannot move. Instead, a part of that segment is split off when dragging:

Moving the first or last edge segment
Start of drag
After finishing the drag

When dragging a segment so it coincides with another segment (essentially the reverse of the situation shown above), the bends that lie on straight line segments will automatically be removed. This is easier to achieve with snapping.

Deleting bends has special support to keep edges orthogonal by also removing one or two adjacent bends. This can be turned off individually with GraphEditorInputMode’s orthogonalBendRemoval property.

Removing bends
The bend to remove
Removing the bend without support for orthogonal edge editing will just remove that single bend and thus create a sloped segment
Removing the bend with support for orthogonal edge editing removes adjacent bends as well to keep the edge orthogonal

Moving items, most notably nodes, will also keep edges orthogonal. When nodes are moved an incident segment and bend will move with them to keep that segment orthogonal. If there is no adjacent bend, the edge will be broken up in a similar way as when dragging the edge segment itself.

Moving a node
Before the move
After the move

When bends are moved, their incident edge segments will stay orthogonal as well by moving adjacent bends appropriately. If an incident segment is the first or last segment, it will be broken up in a similar manner to moving that segment.

Resizing nodes acts very similar to moving nodes because the end points of incident edges change in a very similar way.