Absolute Layout

This is an example of how to use the Absolute Layout to display a dataset. This layout reads element positions from the backing data of Nodes.

Absolute Layout Demo


    "dependencies": {
        "font-awesome": "^4.7.0",
        "jsplumbtoolkit": "file:../../jsplumbtoolkit.tgz"


Page Setup

<link href="//" rel="stylesheet">
<link href="node_modules/font-awesome/css/font-awesome.min.css" rel="stylesheet">
<link rel="stylesheet" href="node_modules/jsplumbtoolkit/dist/css/jsplumbtoolkit-defaults.css">
<link rel="stylesheet" href="node_modules/jsplumbtoolkit/dist/css/jsplumbtoolkit-demo.css">
<link rel="stylesheet" href="app.css">

Font Awesome, Bootstrap, jsplumbtoolkit-demo.css, and app.css are used for this demo and are not jsPlumb Toolkit requirements. jsplumbtoolkit-defaults.css is recommended for all apps using the Toolkit, at least when you first start to build your app. This stylesheet contains sane defaults for the various widgets in the Toolkit.

<script src="node_modules/jsplumbtoolkit/dist/js/jsplumbtoolkit.js"></script>
<script src="app.js"></script>

We import jsplumbtoolkit.js from node_modules (it was listed in package.json). app.js contains the demo code; it is discussed on this page.



This demonstration uses a single template to render its nodes:

<script type="jtk" id="tmplNode">
  <div style="width:${w}px;height:${h}px;">
    <div class="name">
      <div class="delete" title="Click to delete">
        <i class="fa fa-times"></i>
    <div class="connect"></div>
    <jtk-source filter=".connect"></jtk-source>

This template uses the jtk-source and jtk-target elements to enable connectivity via the mouse. The jtk-source element has a filter attribute that specifies that connections may be dragged only from the element with classname "connect".


Data Loading

This is the data used by this demonstration:

var data = {
  "nodes": [
    { "id": "window1", "name": "1", "left": 50, "top": 50 },
    { "id": "window2", "name": "2", "left": 250, "top": 50 },
    { "id": "window3", "name": "3", "left": 450, "top": 50 },
    { "id": "window4", "name": "4", "left": 50, "top": 250 },
    { "id": "window5", "name": "5", "left": 250, "top": 250 },
    { "id": "window6", "name": "6", "left": 450, "top": 250 },
    { "id": "window7", "name": "7", "left": 50, "top": 450 }
  "edges": [
    { "source": "window1", "target": "window3" },
    { "source": "window1", "target": "window4" },
    { "source": "window3", "target": "window5" },
    { "source": "window5", "target": "window2" },
    { "source": "window4", "target": "window6" },
    { "source": "window6", "target": "window2" }

The data is loaded by this call:

toolkit.load({type: "json", data: data})

The load function takes an optional type parameter that indicates the format of the data you are loading. If not supplied - as is the case here - it defaults to "json", which refers to the Toolkit's default Graph JSON syntax.

Note also here that we have wired up the zoomToFit function from the Surface to the load method's onload callback.



The view for this demonstration consists solely of a mapping of the default Node type to a template:

var view = {
  nodes: {
    "default": {
      template: "tmplNode"

This is a very simple View. All of the specifications for appearance are made through the jsPlumb parameter in the render call.



This is the call that sets up the UI:

  container: canvasElement,
  view: view,
  layout: { type: "Absolute" },
  miniview: {
    container: miniviewElement
  lassoFilter: ".controls, .controls *, .miniview, .miniview *",
  events: {
    canvasClick: function (e) {
    modeChanged: function (mode) {
      jsPlumb.removeClass(jsPlumb.getSelector("[mode]"), "selected-mode");
      jsPlumb.addClass(jsPlumb.getSelector("[mode='" + mode + "']"), "selected-mode");
  jsPlumb: {
      Endpoint: "Blank",
      Connector: [ "StateMachine", { cssClass: "connectorClass", hoverClass: "connectorHoverClass" } ],
      PaintStyle: { lineWidth: 1, strokeStyle: '#89bcde' },
      HoverPaintStyle: { strokeStyle: "orange" },
      Overlays: [
          [ "Arrow", { fillStyle: "#09098e", width: 10, length: 10, location: 1 } ]

Here's an explanation of what the various parameters mean:

  • id

This is an optional parameter that assigns an ID to this particular Surface widget - the Toolkit supports an arbitrary number of Surfaces viewing the same dataset. If you assign an ID to a Surface you can subsequently retrieve it via toolkitInstance.getRenderer("someID").

  • container

This identifies the element into which you wish the Toolkit to render.

  • view

These are the Node, Port and Edge definitions for this renderer.

  • layout

Parameters for the layout. Here we specify an Absolute layout

  • miniview

The miniview options provide the the element to convert into a miniview. You can also provide an element ID here.

  • lassoFilter

This selector specifies elements on which a mousedown should not cause the selection lasso to begin. In this demonstration we exclude the buttons in the top left and the miniview.

  • events

We listen for two events:

canvasClick - a click somewhere on the widget's whitespace. Then we clear the Toolkit's current selection.

modeChanged - Surface's mode has changed (either "select" or "pan"). We update the state of the buttons.

  • jsPlumb

Recall that the Surface widget is backed by an instance of jsPlumb. This parameter sets the Defaults for that object.


Selecting Nodes

Lasso selection is enabled by default on the Surface widget. To activate the lasso, click the pencil icon in the toolbar:

Lasso Select Mode

The code that listens to clicks on this icon is as follows:

// pan mode/select mode
jsPlumb.on(".controls", "tap", "[mode]", function () {

The tap listener extracts the desired mode from the button that was clicked and sets it on the renderer. This causes a modeChanged event to be fired, which is picked up by the modeChanged event listener in the View.

Note that here we could have used a click listener, but tap works better for mobile devices.

Lasso Operation

The lasso works in two ways: when you drag from left to right, any node that intersects your lasso will be selected. When you drag from right to left, only nodes that are enclosed by your lasso will be selected.

Exiting Select Mode

The Surface widget automatically exits select mode once the user has selected something. In this application we also listen to clicks on the whitespace in the widget and switch back to pan mode when we detect one. This is the events argument to the render call:

events: {
  canvasClick: function (e) {

clearSelection clears the current selection and switches back to Pan mode.


Adding New Nodes

In this demonstration, new Nodes are dragged onto the canvas from a sidebar.

Drag Nodes From Sidebar

This is configured with the following code:

  droppables: jsPlumb.getSelector("#nodePalette li"),
  dragOptions: {
    zIndex: 50000,
    cursor: "move",
    clone: true
  dataGenerator: function () {
    return { name: jsPlumbUtil.uuid().substring(1, 4) };

For a detailed discussion of this functionality, see this page.


Deleting Nodes

Single Node

Clicking the X button in this demonstration deletes the current node.

jsPlumb.on("#canvas", "tap", ".delete *", function (e) {
  var info = toolkit.getObjectInfo(this);