UI / Surface Widget

Surface Widget

The Surface widget is an 'infinite pan' canvas that does not use scrollbars. To pan the canvas, the user drags using the left mouse button, or, on touch devices, by dragging a single touch.

Panning is normally enabled, but a Surface can be initialized with panning disabled by setting enablePan to false:

var surface = toolkit.render({
  container:"someElement",
  enablePan:false
});

You can also disable a Surface entirely via the setMode method:

surface.setMode(Surface.DISABLED);

It's a fairly common use case that there be some set of elements in your canvas on which a drag should not cause a pan to occur. To handle this, the Surface has the panFilter parameter. This is either a String that is a CSS selector representing elements that should allow a pan to begin, or a Function from which you should return true if you would like a pan to begin.

CSS Selector Filter
let surface = toolkit.render({
  container:"someElement",
  panFilter:".someClassName"
});
Function filter
let surface = toolkit.render({
  container:"someElement",
  panFilter:function(eventTarget) {
    return someLogic(eventTarget);
  }
});

The Surface draws a 'nudge' bar on each edge, which the user can click on to pan the canvas by a small distance in the given direction, or click and hold for continuous panning in that direction.

The default distance moved by a click (or a tick, when held continuously) is 50 pixels. This can be set on the render call:

let surface = toolkit.render({
  ...
  panDistance:25
  ...
});

You can do this via CSS, since each pan button has the class jtk-surface-pan. You can also do this via a parameter on the render call:

var surface = toolkit.render({
  ...
  enablePanButtons:false
  ...
});

TOP


The default behaviour of the Surface is to support zooming via the mouse wheel, or on touch devices, via pinch to zoom.

Constructor parameters

These parameters can be passed in as part of the render call to a Toolkit instance:

  • enableWheelZoom Defaults to true. Whether or not zooming with the mouse wheel is enabled.
  • wheelFilter Optional CSS selector representing elements that should not respond to wheel zoom. Defaults to empty.
  • wheelZoomMetaKey Defaults to false. If true, the wheel zoom only fires when Ctrl (or CMD on Mac) is pressed and the wheel is rotated.
  • wheelReverse Defaults to false. If true, the zoom direction is reversed: wheel up zooms out, and wheel down zooms in.

Zoom Methods

There are a few helper methods for zooming exposed on the Surface.

zoomToFit(options)

Zooms the display so that all tracked elements fit inside the viewport (including invisible nodes). This method will also increase the zoom if necessary in order that the content fills the 90% of the shortest axis of the viewport.

The most basic call you can make is this:

surface.zoomToFit();

zoomToFit supports a number of parameters:

  • fill A decimal indicating how much of the viewport to fill with the zoomed content. Defaults to 0.9.
  • padding Padding to leave around all elements. Default is 20 pixels.
  • onComplete Optional function to call on operation complete (centering may be animated).
  • onStep Optional function to call on operation step (centering may be animated).
  • doNotAnimate By default, the centering content step does not use animation (this parameter is set to true). This is due to this method being used most often to initially setup a UI.
  • doNotZoomIfVisible Defaults to false. If true, no action is taken if the content is currently all visible.
  • doNotFirePanEvent Defaults to false. If true, a pan event will not be fired.

An example showing the Surface animating the content until it fits 80% of the viewport and then popping up an alert:

surface.zoomToFit({
  fill:0.8,
  doNotAnimate:false,
  onComplete:function() { alert("done!"); }
});

To zoom to show only visible nodes, see zoomToVisible.

zoomToFitIfNecessary(options)

Works like zoomToFit but if all tracked elements are currently visible does not adjust the zoom.

surface.zoomToFitIfNecessary();

All of the parameters supported by zoomToFit are supported by zoomToFitIfNecessary.

zoomToBackground(options)

If a background was set, zooms the widget such that the entire background is visible.

surface.zoomToBackground({
  onComplete:function() { alert("done!"); }
});

This method also supports onStep and doNotAnimate.

zoomToSelection(options)

Zoom to either the current selected set of nodes in the Toolkit (defaults to the current selection filling 90% of the shortest axis in the viewport):

surface.zoomToSelection();

or provide a Selection of your own to which to zoom:

surface.zoomToSelection({
  fill:0.8,
  selection:some Toolkit Selection
});

To find our more about Selections, see here.

This method also supports an optional filter function, which is used to create a Selection by running it through the Toolkit's filter method. For instance, this is how you could create what the zoomToVisible method (described below) does:

surface.zoomToSelection({
  filter:function(obj) { return obj.objectType === "Node" && surface.isVisible(obj); }
});

Zooms to display all the currently visible nodes. All animation options are supported by this method - it is a wrapper around zoomToSelection in which we first create a selection representing all the visible nodes.

This method is to zoomToVisible as zoomToFitIfNecessary is to zoomToFit - the content will be centered, but the zoom level will be changed only if all of the currently visible nodes are not visible in the viewport.

setZoom(value)

Sets the current zoom level. This must be a positive decimal number. If it is outside of the current zoom range, it will be clamped to the zoom range.

surface.setZoom(0.5);

Here we have set the zoom to 50%.

nudgeZoom(amount)

Nudges the current zoom level by some value (negative or positive).

// nudge the zoom by 5% 
surface.nudgeZoom(0.05);

// nudge the zoom by -15%
surface.nudgeZoom(-0.15);
setZoomRange(range, doNotClamp)

Sets the current zoom range. By default, this method checks if the current zoom is within the new range, and if it is not then setZoom is called, which will cause the zoom to be clamped to an allowed value in the new range. You can disable this by passing true for doNotClamp.

surface.setZoomRange(0.5, 2);

here we have set the zoom range to be 50% minimum, 200% maximum. If the current zoom was outside of this range, it was clamped to be within.

Let's set the zoom to 2, the top of our current range, and then adjust the zoom range without affecting the widget's zoom:

surface.setZoom(2);
surface.setZoomRange([0.5, 1], true);

TOP


Clamping

Pan Movement

By default, the Surface will clamp movement when panning so that some content is always visible. This can be overridden:

var surface = toolkit.render({
  ...
  clamp:false,
  ...
});

Zoom Movement

It is also default behaviour to clamp the movement of the canvas when the user zooms such that some content is always visible. Without this, it's quite easy for a user to accidentally zoom in such a way that all of the content disappears (consider the case that the canvas is zoomed out a long way and the user then zooms in on some whitespace that is a long way from any content).

As with pan clamping, you can also switch off zoom clamping if you wish:

var surface = toolkit.render({
  ...
  clampZoom:false,
  ...
});

Background

This is discussed below, but a brief mention should be made of the fact that you can also tell the Surface to clamp movement such that part of the background is always visible:

var surface = toolkit.render({
  ...
  clampToBackground:false,
  ...
});

TOP


Positioning

Several methods are available to assist you with positioning the Surface canvas. These are discussed in greater detail in the API documentation:

  • centerOn(node)

Takes a node as argument and positions the Surface canvas such that the given node is at the center in both axes.

  • centerOnHorizontally(node)

Takes a node as argument and positions the Surface canvas such that the given node is at the center in the X axis.

  • centerOnVertically(node)

Takes a node as argument and positions the Surface canvas such that the given node is at the center in the Y axis.

  • centerContent()

Centers the content in the viewport (without altering the zoom, so the content may still extend past the viewport bounds).

  • pan(x, y)

Pans the canvas by a given amount in X and Y.

  • positionElementAt(el, x, y)

Positions a DOM element at a given X,Y on the canvas, in canvas coordinates (meaning it takes into account the current zoom and pan). This is not intended for use with elements the Surface is managing: it is designed to be used with elements such as pop-ups that you may wish to position relative to the content in your canvas.

  • positionElementAtEventLocation(el, event)

Positions a DOM element at the apparent canvas location corresponding to the page location given by some event. This is not intended for use with elements the Surface is managing: it is designed to be used with elements such as pop-ups that you may wish to position relative to the content in your canvas.

  • positionElementAtPageLocation(el, x, y)

Positions a DOM element at the apparent canvas location corresponding to the given page location. This is not intended for use with elements the Surface is managing: it is designed to be used with elements such as pop-ups that you may wish to position relative to the content in your canvas.

TOP


Dragging

By default, any nodes rendered by a Surface will be initialized to be draggable. This can be overridden:

var surface = toolkit.render({
  ...
  elementsDraggable:false,
  ...
});

Drag Options

You can provide a set of options that will be applied to every node when it is made draggable:

var surface = toolkit.render({
  ...
  dragOptions:{
    grid:[20,20]
  },
  ...
});

Valid values for the contents of dragOptions are any valid parameters in Katavorio, the drag library used by jsPlumb.

TOP


Selecting nodes

Nodes managed by a Surface widget may be "selected" at any point in time programmatically via the associated Toolkit instance. When a node is selected, the Surface is informed, and its DOM element is assigned the class jtk-surface-selected-element.

You can also select nodes using the mouse, with a "lasso". To switch into this mode, call setMode:

surface.setMode(Surface.SELECT);

Lasso Behaviour

The lasso works in one of two ways: when the mouse is travelling from left to right, any node that intersects the lasso will be selected. When travelling from right to left, however, only nodes that are fully enclosed by the lasso will be selected.

Lasso Start Filter

You may need to specify one or more elements on which a mousedown should not cause the selection lasso to activate. You can do that with the lassoFilter parameter:

var surface = toolkit.render({
  ...
  lassoFilter:".delete, .add"
  ...
});

Here we tell the Surface that a mousedown on any element having the class delete or add should not cause the lasso to activate - perhaps they are classes assigned to buttons that fire actions in our UI. The format of lassoFilter is any valid CSS selector string.

Lasso Select Filter

There is also a finer-grained means of controlling which nodes should be selected by the lasso - the lassoSelectionFilter function. This can be specified in the render call:

var surface = toolkit.render({
  ...
  lassoSelectionFilter:function(node) {
    return node.data.foo != null;
  }
});

The function is given node objects, and is considered to accept the node if anything other than a boolean false value is returned. In this example, then, we reject nodes whose foo value is null.

You can update this function at runtime, in two ways. First, directly via the setLassoSelectionFilter method:

surface.setLassoSelectionFilter(function(node) {
  return node.data.foo === "bar";
});

...you can also provide a selection filter as an option to the third argument of a setMode call:

surface.setMode("select", null, {
  lassoSelectionFilter:function(node) {
    return node.data.foo < Math.PI;
  }
});

Exiting Select Mode

Ordinarily, the Surface will jump back into Pan mode from Select mode after some nodes have been selected, but this behaviour can be overridden, using the autoExitSelectMode flag:

var surface = toolkit.render({
  ...
  autoExitSelectMode:false
  ...
});

TOP


Events

Event listeners can be bound to the Surface widget in one of three ways:

  • via the bind method
  • in the events parameter to a render call on an instance of the Toolkit
  • in the individual node, Port and Edge definitions in the view parameter to a render call.

The full list of bindable events is below.

Bind

var surface = toolkitInstance.render({
  container:"someElement",
  ...
});
surface.bind("canvasClick", function(e) {
  console.log("click on the canvas");
});
surface.bind("nodeAdded", function(params) {
 
});

Suspending Events

You can suspend/enable events from the Surface widget with this method:

surface.setSuspendEvents(true);

You can also wrap the underlying Toolkit's batch command (which runs a series of operations without making any rendering changes) with the Surface widget's batch command:

surface.batch(function() {
  toolkit.addNode({id:"foo"});
  toolkit.addNode({id:"bar"});
  toolkit.addNode({source:"foo", target:"bar"});
});

This is equivalent to:

surface.setSuspendEvents(true);
toolkit.batch(function() {
  toolkit.addNode({id:"foo"});
  toolkit.addNode({id:"bar"});
  toolkit.addNode({source:"foo", target:"bar"});
});
surface.setSuspendEvents(false);

Events Parameter

You can provide a set of event listeners via the events parameter on a render call:

var surface = toolkitInstance.render({
  container:"someElement",
  ...
  events:{
    "canvasClick":function(e) {
      console.log("click on the canvas");
    },
    "nodeAdded":function(params) {
  
    }
  }
});

Each of these entries is equivalent to first instantiating the Surface and then calling bind on it:

var surface = toolkitInstance.render({
  container:"someElement",
  ...
});
surface.bind("canvasClick", function(e) {
  console.log("click on the canvas");
});
surface.bind("nodeAdded", function(params) {
 
});

View Events

Each entry in the nodes, groups, ports or edges section of the view you pass to a render call can also specify a list of events. The advantage to doing this is that you can be very granular in your event registrations, limiting listeners to objects of some specific type as you need to. The disadvantage is of course more complexity in configuring everything.

Here's a simple example showing two node types, one of which declares a dblclick listener:

var surface = toolkitInstance.render({
  container:"someElement",
  view:{
    nodes:{
      "type_a":{
        template:"TypeA"
      },
      "type_b":{
        template:"TypeB",
        events:{
          dblclick:function(node) {
            console.log("double click on node " + node.id);
          }
        }
      }
    }
  }
});
View Event Inheritance

If you have a type declared that extends some other type, it will inherit the parent type's listeners. But if your subtype declares some event listener, that listener will override the parent's listener for the given event, if one is present. For example:

var surface = toolkitInstance.render({
  container:"someElement",
  view:{
    nodes:{
      "type_a":{
        template:"TypeA",
        events:{
          dblclick:function(node) {
            console.log("type A double click");
          }
        }
      },
      "type_b":{
        parent:"type_a",
        events:{
          dblclick:function(node) {
            console.log("type B double click");
          }
        }
      }
    }
  }
});

A click on a node of type type_b will produce a single line in the console: "type B double click".

Subscribable Events in Views

This is the full list of events to which you can subscribe in a View definition:

  • click - Notification that a click event occurred
  • tap - A synthesized click event that normalises click behaviour between touch and mouse devices
  • dblclick - Notification that a double click event occurred
  • mouseover - Notification the mouse entered the object
  • mouseout - Notification the mouse left the object
  • mousedown - Notification a mouse button was pressed on the object
  • mouseup - Notification a mouse button was released
  • contextmenu - Notification that a context menu event occurred on a node. This typically means a right click.

Each of these callback functions is given a JS object, the contents of which differs between Edges and node/Ports.

Node Callback Parameters
{
  el:Element, 
  node:Node, 
  e:Event
}
Port Callback Parameters
{
  el:Element, 
  node:Port, 
  e:Event
}
Edge Callback Parameters
{
  connection:Connection, 
  edge:Edge, 
  e:Event,
  toolkit:jsPlumbToolkitInstance,
  renderer:AbstractRenderer
}

List of Events

EventDescriptionParameters
nodeAddedThis is a notification that a new node has been added to the UI.
  • node The Tookit node object. The node's id is available via the `id` property.
  • data The underlying node data.
  • el The DOM element corresponding to the node.
nodeRendered This is a notification that a node has been rendered to the DOM: it is only fired if you create a Surface for an instance of the Toolkit that already contains some data. You can use this event in the same way as you would use `nodeAdded`: to attach behaviour to the node.
  • node The Tookit node object. The node's id is available via the `id` property.
  • data The underlying node data.
  • el The DOM element corresponding to the node.
nodeRemoved This is a notification that a node has been removed.
  • nodeThe node that was removed.
nodeMoveStart Notification that a given node has just begun to be dragged.
  • node The node that has begun moving.
  • domEl The associated DOM Element.
  • el DOM element, wrapped in a selector for the underlying library.
  • elementId ID of the associated DOM element. This is not necessarily the same as the node's ID.
  • pos Array of [left,top] denoting the node's new position (in pixels).
nodeMoveEnd Notification that a given node has ceased movement.
  • node The node that just finished moving.
  • domEl The associated DOM Element.
  • el DOM element, wrapped in a selector for the underlying library.
  • elementId ID of the associated DOM element. This is not necessarily the same as the node's ID.
  • pos Array of [left,top] denoting the node's new position (in pixels).
edgeAdded Notification that a new Edge was established, either programmatically or by the user. Note that this is different from the `nodeRemoved` event described below, which is fired __only__ when the Edge is removed through user intervention in the UI.
  • sourceNodeId ID of the source node
  • sourcePortId ID of the Port on the source node. May be null.
  • targetNodeId ID of the target node
  • targetPortId ID of the Port on the target node. May be null.
  • type Type of the Edge. Default is `"default"`, but the vast majority of applications will set Edge types.
  • source Source object - either a node or a Port.
  • target Target object - either a node or a Port.
  • sourceId Full ID of the source object: if source is a node then this is just a node id; otherwise it is in the form nodeId.PortId.
  • targetId Full ID of the target object: if target is a node then this is just a node id; otherwise it is in the form nodeId.PortId.
  • edge Toolkit Edge object
  • addedByMouse A Boolean which, if true, indicates the Edge was added through user interaction with the UI, rather than programmatically.
edgeRemoved Notification that an Edge was removed. This event is fired only when the Edge was removed through user interaction with the UI, not when an Edge was removed programmatically.
  • sourceNodeId ID of the source node
  • sourcePortId ID of the Port on the source node. May be null.
  • targetNodeId ID of the target node
  • targetPortId ID of the Port on the target node. May be null.
  • type Type of the Edge. Default is `"default"`, but the vast majority of applications will set Edge types.
  • source Source object - either a node or a Port.
  • target Target object - either a node or a Port.
  • sourceId Full ID of the source object: if source is a node then this is just a node id; otherwise it is in the form nodeId.PortId.
  • targetId Full ID of the target object: if target is a node then this is just a node id; otherwise it is in the form nodeId.PortId.
  • edge Toolkit Edge object
portAdded Notification that a new Port has been added to some node.
  • node node to which the Port has been added.
  • port Port that was added.
  • nodeEl DOM element for the node.
  • portEl DOM element for the Port.
portRemoved Notification that a Port has been removed from some node.
  • node node from which the Port was removed.
  • port Port that was removed.
  • nodeEl DOM element for the node.
  • portEl DOM element for the Port.
anchorChanged Notification that the anchor position related to some Port has changed. This event is not something that the majority of applications will need to care about.
  • portId ID of the Port related to the anchor whose position has changed. May be null.
  • nodeId ID of the node related to the anchor whose position has changed.
  • portType Type of the related Port. May be null (if portId is null this will of course be null).
  • node node related to the anchor.
  • port Port related to the anchor. May be null.
  • endpoint Related jsPlumb Endpoint.
  • anchor jsPlumb Anchor.
modeChanged Notification that the Surface's mode has changed.
  • newModeId The id of the new mode. mode may be `"pan"`, `"select"` or `"disabled"`.
objectRepainted Notification that some Toolkit object was repainted.
  • obj Object that was repainted - a node or a Port.
  • id Object's id.
  • type Object's type.
  • el Related DOM element.
pan Notification that the Surface has been panned
  • x New X location of the Surface
  • y New Y location of the Surface
  • z Current zoom
  • event Event that caused the pan
zoom Notification that the Surface has been zoomed
  • x New X location of the Surface
  • y New Y location of the Surface
  • z Current zoom
  • event Event that caused the zoom
canvasClick Notification that the canvas background was clicked.
  • evt Associated mouse event
canvasDblClick Notification that the canvas background was double-clicked.
  • evt Associated mouse event
relayout Notification that the layout associated with some Surface performed a full relayout.
click Click event on a node or Port.
  • node The Tookit node object. The node's id is available via the `id` property.
  • port Toolkit Port object, if the event occurred on a Port.
  • el The DOM element corresponding to the node or Port.
  • e The original mouse event.
click Tap event on a node or Port.
  • node The Tookit node object. The node's id is available via the `id` property.
  • port Toolkit Port object, if the event occurred on a Port.
  • el The DOM element corresponding to the node or Port.
  • e The original mouse event.
dblclick Double click event on a node or Port.
  • node The Tookit node object. The node's id is available via the `id` property.
  • port Toolkit Port object, if the event occurred on a Port.
  • el The DOM element corresponding to the node or Port.
  • e The original mouse event.
contextmenu Context menu event on a node or Port.
  • node The Tookit node object. The node's id is available via the `id` property.
  • port Toolkit Port object, if the event occurred on a Port.
  • el The DOM element corresponding to the node or Port.
  • e The original mouse event.
mousedown Mouse down event on a node or Port.
  • node The Tookit node object. The node's id is available via the `id` property.
  • port Toolkit Port object, if the event occurred on a Port.
  • el The DOM element corresponding to the node or Port.
  • e The original mouse event.
mouseup Mouse up event on a node or Port.
  • node The Tookit node object. The node's id is available via the `id` property.
  • port Toolkit Port object, if the event occurred on a Port.
  • el The DOM element corresponding to the node or Port.
  • e The original mouse event.
mouseover Mouse enter event on a node or Port.
  • node The Tookit node object. The node's id is available via the `id` property.
  • port Toolkit Port object, if the event occurred on a Port.
  • el The DOM element corresponding to the node or Port.
  • e The original mouse event.
mouseout Mouse out event on a node or Port.
  • node The Tookit node object. The node's id is available via the `id` property.
  • port Toolkit Port object, if the event occurred on a Port.
  • el The DOM element corresponding to the node or Port.
  • e The original mouse event.
mouseover Mouse over event on a node or Port.
  • node The Tookit node object. The node's id is available via the `id` property.
  • port Toolkit Port object, if the event occurred on a Port.
  • el The DOM element corresponding to the node or Port.
  • e The original mouse event.
mousemove Mouse move event on a node or Port.
  • node The Tookit node object. The node's id is available via the `id` property.
  • port Toolkit Port object, if the event occurred on a Port.
  • el The DOM element corresponding to the node or Port.
  • e The original mouse event.

TOP


Background Images

Single Background Image

To display a single image as the background of the Surface widget:

var toolkit = jsPlumbToolkit.newInstance();
var surface = toolkit.render({
  container:"someElement",
  background:{
    url:"./myBackground.png"
  }
});

Tiled Background Image

You can use a tiled image as your background - you need to provide a url pattern, the number of available zoom levels, the tile size, and the width and height of the full image:

To display a single image as the background of the Surface widget:

var toolkit = jsPlumbToolkit.newInstance();
var surface = toolkit.render({
  container:"someElement",
  background:{
    type:"tiled",
    url:"tiles/{z}/tile_{x}_{y}.png",
    tileSize:[750,750],
    width:10000,
    height:6000,
    maxZoom:3
  }
});
Tiled Background Pattern URL

The URL you supply for a tiled background should have a placeholder for each of zoom, x and y, as in the example above. Tiles are zero-indexed, so, for example, the top left tile at zoom level 0 would, in the previous example, generate this url:

tiles/0/tile_0_0.png

The Surface does not support the concept of a "continuous world", in which tiles with negative indices may be requested.

Clamping to the background image

Depending on your use case, you may wish to force the Surface to clamp the pan/zoom such that some portion of the background image is always visible. You do this by setting the clampToBackground parameter on a render call:

var toolkit = jsPlumbToolkit.newInstance();
var surface = toolkit.render({
  container:"someElement",
  clampToBackground:true,
  background:{
    url:"myBackground.png"
  }
});

Zooming to the background image

If you wish to zoom out to the point that the entire background image is visible:

var toolkit = jsPlumbToolkit.newInstance();
var surface = toolkit.render({ ... });
surface.zoomToBackground();

[top]


Saving/Restoring State

The Surface widget supports writing/reading its current state to/from local storage. For some applications this is useful, but keep in mind that this is local to the current browser.

State handle

You can provide a state handle to the render call that instantiates a Surface widget:

var surface = toolkitInstance.render({
    ...
    stateHandle:"myAppSurface"
    ...
});

Saving State

To save the current state, call saveState:

surface.saveState();

You can optionally provide a handle to override the one that you provided to the constructor:

surface.saveState("someSpecialCondition");

Restoring State

At the time of writing, restoreState restores only the positions of the elements in the Surface.

surface.restoreState();

As with saveState, you can optionally provide a handle to override the default:

surface.restoreState("someSpecialCondition");

Clearing State

If you wish to clear out the state from local storage for some Surface, you can:

surface.clearState();

again, with an optional handle:

surface.clearState("someSpecialCondition");

TOP


Appearance

It is recommended that you use the view to configure the appearance of your UI, but should you wish to provide some defaults to the underlying jsPlumb instance, you can do so via the jsPlumb parameter:

var surface = toolkit.render({
  ...
  jsPlumb:{
    Anchor:"Center",
    Connector:[ "StateMachine", { curviness:50 } ]
  }
});

Valid values for this object are anything that is a valid jsPlumb default

TOP


This is a full list of CSS classes used by the Surface widget.

CSS

ClassDescription
jtk-surfaceAssigned to an element that is acting as a Surface widget.
jtk-surface-canvasAssigned to the work area of a Surface widget. This canvas element will have been created automatically by the Surface and is not normally something you will need to style. If you do attach some styles, you should be careful to ensure that this element always has `position:relative;` set.
jtk-surface-lassoAssigned to the "lasso" element used when selecting elements in a Surface using the mouse.
jtk-surface-panAssigned to all of the pan buttons in a Surface, regardless of which direction they control.
jtk-surface-pan-topAssigned to the pan button that appears on the top edge of the Surface.
jtk-surface-pan-leftAssigned to the pan button that appears on the topleft edge of the Surface.
jtk-surface-pan-rightAssigned to the pan button that appears on the right edge of the Surface.
jtk-surface-pan-bottomAssigned to the pan button that appears on the bottom edge of the Surface.
jtk-surface-selected-elementAssigned to any element that is part of some Surface's current selection.
jtk-lassoAssigned to the selection lasso element

TOP


Miscellaneous

Consuming Right Click

The default behaviour is to consume any right-click events. This is good when your app is in production, and really annoying when you're in the middle of development. To suppress this behaviour, set consumeRightClick:

var surface = toolkit.render({
  ...
  consumeRightClick:false
  ...
});

TOP