Views

Views are used to define the visual appearance of the various artefacts (which template to use for Nodes/Ports, CSS classes, etc)
and event registration. If you want to read about defining connectivity rules, see the Data Model documentation.

Views are provided as an argument to the render method of an instance of the Toolkit, in which you specify the visual
appearance and behaviour of UI artefacts representing your data.

Example

This example is an edited View from the Database Visualizer example application.

toolkit.render({view:{// we have two node types - 'table' and 'view'. nodes:{"table":{// we use 'tmplTable' to render tablestemplate:"tmplTable"},"view":{// and 'tmplView' to render viewstemplate:"tmplView",events:{// when you click a view Node, we alert its id.click:function(params){alert("click on view "+params.node.id);}}}},edges:{// common appearance of all edges"common":{connector:"StateMachine",paintStyle:{lineWidth:2,strokeStyle:"#CCC"}},// a 1:1 relationship"1:1":{parent:"common",// declared 'common' as its parent.overlays:[["Label",{label:"1",location:0.1}],["Label",{label:"1",location:0.9}]]},"1:N":{parent:"common",overlays:[["Label",{label:"1",location:0.1}],["Label",{label:"N",location:0.9}]]}},ports:{// a table has an arbitrary number of columns; it is a table's columns that actually connect to other tables, not a table itself."column":{// use 'tmplColumn' to render a Port of type 'column'template:"tmplColumn",// the appearance of the endpoint on a columnendpoint:["Dot",{radius:7}],// anchor locations on a columnanchor:["Left","Right"],// the type of edge that will be created from this port by default when the user drags a connectionedgeType:"common"}}}});

Mapping Types

An instance of the Toolkit has the concept of a typeFunction - a function that, when
given the data corresponding to some Node, Port, Edge or Group, returns the object's type (as a string). The type returned
by this function is what is used as the key into a View.

Default Types

For each of Nodes, Ports and Edges, you can provide a default definition, using the key "default":

Default Edge Type

Definition Inheritance

Any Node, Port, Edge or Group definition can declare a parent definition. The resulting definition consists of the parent's
entries, with the child's entries merged on top. An example:

{...view:{nodes:{"common":{events:{"click":function(params){console.log("Click on node",params.node);}}},bigNode:{parent:"common",template:"tmplBigNode"},smallNode:{parent:"common",template:"tmplSmallNode"}}},...}

Here, we have defined a common click handler on the parent definition, and then defined templates for each Node type
in their own definitions.

Nodes

There are two node types defined in the example above - table and view. They each have a single entry that defines the
template to use to render a node of this type. The value for this parameter must be the id of some client side
template in the format that is appropriate for the template engine you are using. See below for a discussion of
templates.

In addition, the view Node declares an event handler for Node clicks. There are many different events to which
you can subscribe; these are discussed below.

Supported Parameters

[parent] ID of a Node definition from which this definition should inherit properties.

[dragOptions] JS object containing options for drag behaviour for nodes of the given type. The allowed values in this object are anything that the underlying drag library - Katavorio supports. Common uses of per-node dragOptions are such things as setting handles for dragging, or specifying a filter for which parts of an element should not be able to initiate a drag.

Edges

In the Database Visualizer, an edge maps the concept of a relationship between two tables. This View shows three
entries in the edges section. The first, common, contains directives that are common to all of the different
relationships.

The second and third entries - 1:1 and 1:N - are concrete edge types, defining a 1:1 and a 1:N relationship
respectively. Notice how they both declare their parent to be common, so they derive the styling directives from
that type. Then each one declares two overlays that are unique to itself.

There is no limit to the depth of inheritance supported, but multiple inheritance is not supported. It may have
occurred to you that we said each of the two concrete edge types declares two overlays that are unique to itself,
but in fact that is not the case: they both share the "1" overlay positioned at 0.1. So with no limit on inheritance
we could have actually defined some other abstract type:

Ports

This View shows one type of Port - a column. Recall from the data model discussion that a Node has one implicit
Port (itself), and an arbitrary number of other Ports. In the case of the Database Visualizer, a Node represents a
table, and a Port represents a column. The table's "implicit" Port is not used in the Database Visualizer application.
In the Flowchart Builder, each object type's implicit Port is used when the object is the target of some Edge.

As with Nodes, Ports can be associated with a template for rendering. they do no have to be - in some cases, you will
want to use an Endpoint to represent a Port, and in others you'll want to use a DOM element. If you're using DOM elements
and your application supports the dynamic addition of new Ports - as in the case of the
Database Visualizer when the user adds a new column to a table - then you need to provide the Toolkit with a
separate template to use to render the Port (as opposed to rendering the Ports inside of each Node's template).

The concept of Ports is synonymous with the concept of Endpoints in jsPlumb. Valid values for a Port definition are
anything that is valid on a jsPlumb.addEndpoint or jsPlumb.makeSource call: essentially, a description of the
appearance and behaviour of the endpoints associated with the Port. Here we are using a Dot endpoint of radius 7,
and instructing the Toolkit to use a dynamic anchor with Left and Right locations.

Specifying Endpoints vs DOM elements

When jsPlumb encounters a jtk-port element in a template, it knows that you wish to use an Endpoint to show the Port,
as opposed to using a DOM element. If, though, you add a Port programmatically to some Node, and you wish to show that
as an Endpoint, you need to tell jsPlumb, in the appropriate Port definition:

view:{...ports:{"someEndpointPort":{isEndpoint:true...}}}

Limiting Connections

A Port may support an arbitrary number of Edges. You can limit this with the maxConnections argument in the Port
definition, but note that you would ideally set this in the Toolkit's model rather than in a View, as
setting it here will set it only for the current renderer.

The default maximum - which is jsPlumb's default - maximum is 1 Edge. A value of -1 means there is no upper limit.

Edge Type

Notice in the column Port there is an edgeType parameter. This tells the Toolkit what type of Edge to
create when a new connection is dragged from the Port. In this example we are using the type common, because
when the user drags a new relationship between two tables we do not yet know the cardinality of the relationship.
The Database Visualizer subscribes to the edgeAdded event from the Toolkit and prompts the user to specify the
cardinality of the new Edge; the Edge is then assigned the appropriate type.

Dragging Connections

As mentioned above, a Port is synonymous with the concept of an Endpoint in jsPlumb. By default, Endpoints in
jsPlumb do not have mouse support enabled. You need to indicate whether or not the Endpoint should be allowed to be
the source and/or target of connections created with the mouse through the use of the isSource/isTarget parameters.

Supported Parameters

[parent] ID of a Port definition from which this definition should inherit properties.

template ID of the template to use to render the Node

[edgeType] Type of Edge to create when a new connection is dragged from the Port

[maxConnections] Defaults to 1. The maximum number of connections the Port allows. Set to -1 to allow unlimited connections.

[isSource=false] If true, indicates the Port can be a source for Edges dragged with the mouse.

[isTarget=false] If true, indicates the Port can be a target for Edges dragged with the mouse.

[isEndpoint=false] Instructs jsPlumb that any Ports of this type that are programmatically added to a Node should result in the addition of an Endpoint to the UI. Defaults to false, meaning that Ports added programmatically configure the entire element as a source or target.

Groups

The Database Visualizer does not make use of the concept of Groups. For a full discussion on Groups, including how to
map them inside Views, take a look at this page.

Events

Each type of object in the View supports declarative registration of events, through the inclusion of an events
member in the appropriate definition. The list of supported events is as follows:

click

dblclick

mouseover

mouseout

mousedown

mouseup

contextmenu

view:{nodes:{someNodeType:{events:{click:function(params){// params.toolkit is the Toolkit instance// params.renderer is the Surface widget// params.e is the original mouse event // params.node is the Toolkit Node// params.el is the element from the DOM representing the Node}}}},edges:{someEdgeType:{events:{mouseover:function(params){// params.toolkit is the Toolkit instance// params.renderer is the Surface widget// params.e is the original mouse event// params.edge is the Toolkit Edge// params.connection is a jsPlumb Connection object.console.dir(params.edge,params.connection);}}}},ports:{somePortType:{events:{mousedown:function(params){// params.toolkit is the Toolkit instance// params.renderer is the Surface widget// params.e is the original mouse event// params.port is the Toolkit Port// params.endpoint is a jsPlumb Endpoint objectconsole.dir(params.port,params.endpoint);}}}}}

Interceptors

Interceptors are jsPlumb events that can be used to cancel some proposed activity. jsPlumb currently supports two of
these:

beforeDrop Called when the user has attempted to drop a connection. Returning anything other than true aborts the connection.

beforeDetach Called when the user has attempted to detach a connection. Returning anything other than true aborts the detachment of the connection.

You can map these in the View by including an interceptors object. They are only supported on Port definitions, as
they are functionality that is handled by the underlying Endpoints.

An example:

vartk=jsPlumbToolkit.newInstance();tk.render({container:"foo",view:{...ports:{"default":{template:"tmplFoo",interceptors:{beforeDrop:function(params){// returning anything but true will cause the connection to be aborted.},beforeDetach:function(params){// returning anything but true will cause the detach to be aborted.}}}}}});

Preconfigured Parameters

Note Preconfigured parameters are known to break 2-way data binding when using the Toolkit with AngularJS,
because the data object passed to the template is a copy of the original. To switch off preconfigured parameters,
set enhancedview:false in your render call.

You may have a template that you'd like to reuse for a collection of nodes, with slight variations between each.
Consider this example:

This template draws SVG rectangles, of any given size, with arbitrary fill and stroke, and possibly rotated. Let's say
we're creating an application in which there are two types of rectangle shapes: big red ones, and little yellow ones.
In our View we can define custom parameters for each of these node types, which will be mixed in with the node's
data when it comes time to render:

So the foo entry in bigRed would completely overwrite the foo entry from base; the two are not merged
together. smallYellow does not have foo entry and therefore inherits it from base.

Note Preconfigured parameters operate at the view level only: they are not written into your data model. So you
cannot use this mechanism to provide parameters that you will subsequently update (such as the w/h parameters that the
Flowchart Builder demo uses: if provided via the preconfigured parameters mechanism the UI would initially render
correctly, but if the w/h values were updated, the template would not re-render. In the Flowchart Builder, the solution
is to provide the w/h in the data model).

Switching off Preconfigured Parameters

As mentioned above, there are some cases in which you cannot use preconfigured parameters. One such known case is
when you are using AngularJS and you're taking advantage of the two-way data binding provided by its template engine.
Preconfigured parameters (and function parameters, discussed below), cause a copy of the original data to be created,
which then breaks Angular's two-way binding. A copy is created because the only other option is to copy the
preconfigured parameters into the original data, which is almost certainly not what you want, given that they are a
view concern.

To switch off preconfigured parameters and function parameters, set the enhancedView flag on your render call
to false:

Function Parameters

Note Function parameters are known to break 2-way data binding when using the Toolkit with AngularJS, because
the data object passed to the template is a copy of the original. To switch off function parameters,
set enhancedView:false in your render call.

By default you can provide values in definitions as functions. These will be given the backing data for the object
being rendered. An example definition: