Path Tracing

This is an example of the Toolkit's ability to trace an overlay along the shortest path from one Node to another.

Path Tracing

This page gives you an in-depth look at how the application is put together.

Page Setup

CSS
  • Font Awesome 4.0.3 Used for all the iconography. Not a Toolkit requirement.
  • jsPlumbToolkit-defaults.css 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.
  • jsPlumbToolkit-demo.css Common styles for the demonstration pages. Not a Toolkit requirement.
  • app.css Styles specific to this demo.
JS
  • jsPlumb-x.x.x.js
  • jsPlumbToolkit-x.x.x.js
  • app.js Application specific JS.

TOP


Toolkit Setup

var toolkit = jsPlumbToolkit.newInstance();

TOP


Templates

The app uses a single template, with the default ID:

<script type="jtk" id="jtk-template-default">
    <div>
        <div class="name">
            <span>${name}</span>
        </div>
    </div>
</script>

TOP

Data Loading

Data for this application is randomly generated from a demo support class:

var data = jsPlumbToolkitDemoSupport.randomGraph(5, 10);

toolkit.load({
  data: data
});

TOP


View

In the View, we configure the appearance of Edges and Nodes, and we also handle node clicks to instigate path traversals. See below for a discussion of how path traversals are handler.

 var view = {
     edges: {
         "default": {
             paintStyle: { lineWidth: 1, strokeStyle: '#89bcde' },
             overlays: [
                 ["Arrow", { fillStyle: "#89bcde", width: 10, length: 10, location:1 } ]
             ]
         },
         "bidirectional":{
             overlays: [
                 ["Arrow", { fillStyle: "#89bcde", width: 10, length: 10, location:0, direction:-1 } ]
             ]
         }
     },
     nodes:{
         "default":{
             events: {
                 tap:function(params) {
                     // on node click...
                     if (source == null) {
                         //... either set the current path source. here we also add a class
                         // so you can see its selected.
                         source = params;
                         jsPlumb.addClass(source.el, "jtk-animate-source");
                     }
                     else {
                         // ...or trace a path from the current source to the clicked node.
                         var traced = renderer.tracePath({
                             source:source.node,
                             target:params.node,
                             overlay:["Diamond", {
                                 width:15,
                                 length:15,
                                 fillStyle: "#89bcde"
                             }],
                             options: {
                                 speed: 250
                             }
                         });
                         // cleanup the source for the next one.
                         jsPlumb.removeClass(source.el, "jtk-animate-source");
                         source = null;

                         if (!traced) {
                             alert("No path found!");
                         }
                     }
                 }
             }
         }
     }
 };

Rendering

var renderer = toolkit.load({type: "json", data: data}).render({
    container: canvasElement,
    view:view,
    layout: {
        type: "Spring",
        padding:[ 30, 30 ]
    },
    miniview: {
        container: miniviewElement
    },
    lassoFilter: ".controls, .controls *, .miniview, .miniview *",
    events: {
        canvasClick: function (e) {
            toolkit.clearSelection();
        },
        modeChanged: function (mode) {
            jsPlumb.removeClass(jsPlumb.getSelector("[mode]"), "selected-mode");
            jsPlumb.addClass(jsPlumb.getSelector("[mode='" + mode + "']"), "selected-mode");
        }
    },
    jsPlumb: {
        Anchor:"Continuous",
        Connector: [ "StateMachine", { cssClass: "connectorClass", hoverClass: "connectorHoverClass" } ],
        Endpoint: "Blank"
    }
});

The meaning of each parameter is as follows:

  • container The element into which to render. You can also provide an element ID here.
  • view Mappings from Node/Edge/Port types to their visual representation/behaviour.
  • layout We use a Spring layout in this demonstration.
  • jsPlumb Defaults for the Surface's backing instance of jsPlumb.
  • miniview Tthe element to turn into a Miniview. You can also provide an element ID here.
  • events Provides event handler for events on the Surface. Here we listen for clicks and we clear the current selection, as well as events that tell us the Surface's mode has changed.
  • lassoFilter A Selector identifying which elements should not respond to the lasso's start drag event.

TOP


Path Tracing

Path tracing is handled in two stages:

  • when a user taps a node and no previous node has been selected, that node becomes the source
  • when a user taps a node and there is already a source selected, the path is computed and traversed.

The tap event is captured and handled inside the view:

tap:function(params) {
 // on node click...
 if (source == null) {
     //... either set the current path source. here we also add a class
     // so you can see its selected.
     source = params;
     jsPlumb.addClass(source.el, "jtk-animate-source");
 }
 else {
     // ...or trace a path from the current source to the clicked node.
     var traced = renderer.tracePath({
         source:source.node,
         target:params.node,
         overlay:["Diamond", {
             width:15,
             length:15,
             fillStyle: "#89bcde"
         }],
         options: {
             speed: 250
         }
     });

     // cleanup the source for the next one.
     jsPlumb.removeClass(source.el, "jtk-animate-source");
     source = null;

     if (!traced) {
         alert("No path found!");
     }
 }
}

The key piece of code here is the call to tracePath on the renderer:

var traced = renderer.tracePath({
     source:source.node,
     target:params.node,
     overlay:["Diamond", {
         width:15,
         length:15
     }],
     options: {
         speed: 250
     }
 });

The meaning of each parameter is:

  • source Either a Node, Node ID, or a DOM element to use as the path source
  • target Either a Node, Node ID, or a DOM element to use as the path target
  • overlay An Overlay specification in the standard format used by the Community edition of jsPlumb.
  • options Options for the path traversal. For a discussion of these, see here