Summary

jsPlumb allows you to connect elements on the screen with "plumbing", using a Canvas element when supported, and Google's ExplorerCanvas script to support older browsers.

It can be used with jQuery, MooTools or YUI3 (or another library of your choice if you feel like implementing a plugin for it). Required versions are as follows:

jQuery

MooTools

YUI3

For Canvas support in IE you also need to include Google's ExplorerCanvas script.

jsPlumb 1.2.6 has been tested on the following browsers:

Changes since version 1.2.5

These issues have been resolved:

Imports

jQuery

<script type="text/javascript" src="http://explorercanvas.googlecode.com/svn/trunk/excanvas.js"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.0/jquery.min.js"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.13/jquery-ui.min.js"></script>
<script type="text/javascript" src="PATH_TO/jquery.jsPlumb-1.2.6-all-min.js "></script>

MooTools

<script type="text/javascript" src="http://explorercanvas.googlecode.com/svn/trunk/excanvas.js"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/mootools/1.3.2/mootools-yui-compressed.js"></script>
<script type="text/javascript" src="PATH_TO_MOO_TOOLS_MORE_1_3_2_1"></script>
<script type="text/javascript" src="PATH_TO/mootools.jsPlumb-1.2.6-all-min.js "></script>

YUI3

<script type="text/javascript" src="http://explorercanvas.googlecode.com/svn/trunk/excanvas.js"></script>
<script type="text/javascript" src="http://yui.yahooapis.com/3.3.0/build/simpleyui/simpleyui-min.js"></script>
<script type="text/javascript" src="PATH_TO/yui.jsPlumb-1.2.6-all-min.js "></script>

Initializing jsPlumb

You should not start making calls to jsPlumb until the DOM has been initialized - perhaps no surprises there. With YUI, though, the asynchronous nature of the script loading process means that you are not guaranteed that jsPlumb is ready as soon as the DOM is. To handle this, you should bind to the "ready" event on jsPlumb (or the instance of jsPlumb you are working with):
jsPlumb.bind("ready", function() {
...	
		
// your jsPlumb related init code goes here

...

});						
			

For jQuery and MooTools you should not actually need to do this; by the time the DOM ready event is fired in each of those libraries you can be sure all the JS we need has been loaded. But in terms of explicitly calling out that you are waiting for jsPlumb, it seems like a good practice to bind to the "ready" event.

If you bind to the "ready" event after jsPlumb has already been initialized, your callback will be executed immediately.

Unloading jsPlumb

jsPlumb offers a method you can call when your page is unloading. You should do this to insure against memory leaks. You configure it like this:
<body onunload="jsPlumb.unload();">

...

</body>

jsPlumb Basic Concepts

jsPlumb provides two ways of establishing connections between elements: programmatically, via Javascript, and interactively, with drag and drop. To support this, jsPlumb has these five core concepts:

Programmatic API

This section discusses Connections made programmatically.

The most simple connection you can make looks like this:
jsPlumb.connect({source:'element1', target:'element2'});
In this example we have created a Connection from 'element1' to 'element2'. Everything has a default value in jsPlumb and does not necessarily need to be supplied, so in this example, behind the scenes jsPlumb used default values for all of these things: Default values are discussed in detail in the Defaults section below.

The Basic Examples section below contains many more examples of how to create simple Connections.

Draggable Connections

To support draggable Connections, you are required to first create Endpoints, as it is Endpoints that the user drags to create new Connections. Endpoints are created by making an addEndpoint call, passing in the target element's id and an options object. There are quite a few things that can be set on the options object; all of these parameters are optional. Here's a simple example of how to create an Endpoint:
var endpointOptions = { isSource:true, isTarget:true };
var endpoint = jsPlumb.addEndpoint('elementId', endpointOptions);
This Endpoint will act as a source and target for new Connections, and will use the jsPlumb defaults for its own appearance and that of any Connections that are drawn from it.

Tip: use the three-argument addEndpoint method for common data

One thing that happens quite often is that you have an Endpoint whose appearance and behaviour is largely the same between usages on different elements, with just a few differences.
var exampleGreyEndpointOptions = {
	endpoint:"Rectangle",
	paintStyle:{ width:25, height:21, fillStyle:'#666' },
	isSource:true,
	connectorStyle : { strokeStyle:"#666" },
	isTarget:true
};
Notice there is no 'anchor' set. Here we apply it to two elements, at a different location in each:
jsPlumb.addEndpoint('element1', { anchor:"BottomCenter" }, exampleGreyEndpointOptions)); 

jsPlumb.addEndpoint('element2', { anchor:"TopCenter" }, exampleGreyEndpointOptions));

Here's an example of specifying that you want an Arrow overlay halfway along any Connection dragged from this Endpoint:

var exampleGreyEndpointOptions = {
	endpoint:"Rectangle",
	paintStyle:{ width:25, height:21, fillStyle:'#666' },
	isSource:true,
	connectorStyle : { strokeStyle:"#666" },
	isTarget:true,
	connectorOverlays: [ [ "Arrow", { location:0.5 } ] ]
};
This is an Endpoint that moves around the element it is attached to dependent on the location of other elements in the connections it is attached to (a 'dynamic' anchor):
var exampleGreyEndpointOptions = {
	endpoint:"Rectangle",
	paintStyle:{ width:25, height:21, fillStyle:'#666' },
	isSource:true,
	connectorStyle : { strokeStyle:"#666" },
	isTarget:true,
	connectorOverlays: [ [ "Arrow", { location:0.5 } ] ]
	anchor:[ "TopCenter","RightMiddle","BottomCenter","LeftMiddle" ]
};

Drag Options

These are options that will be passed through to the supporting library's drag API. jsPlumb passes everything you supply here through, inserting wrapping functions if necessary for the various lifecycle events that jsPlumb needs to know about. So if, for example, you pass a function to be called when dragging starts, jsPlumb will wrap that function with a function that does what jsPlumb needs to do, then call yours.

At the time of writing, jsPlumb supports jQuery, MooTools and YUI3, and each of those libraries uses different terminology. In addition, jQuery's API is more fully featured, providing easy support for setting the zIndex and opacity of elements being dragged, as well as the 'scope' for a drag/drop (allowing you to specify more than one type of drag/drop pair), and hover classes for when a draggable is on the move or over a droppable. If you're using jQuery you can of course just supply these values on the dragOptions; to make it easier, jsPlumb's MooTools and YUI3 adapters recognize these options and add appropriate callbacks for you.

Given that the options here are library-specific, and they are all well-documented, we're going to discuss just the three drag options that behave the same way in both (see below for hoverClass):

For more information about drag options, take a look at the jQuery, MooTools, or YUI3 docs.

NOTE: there is an issue in Chrome that affects the 'cursor' argument to drag options in jQuery. See these links:

http://forum.jquery.com/topic/draggable-cursor-option-does-not-work
http://forum.jquery.com/topic/chrome-text-select-cursor-on-drag

You should put something like this at the top of your JS to avoid it (perhaps not something so drastic as a document-wide override):
document.onselectstart = function () { return false; };

Drop Options

Drop options are treated by jsPlumb in the same way as drag options - they are passed through to the underlying library. MooTools does not have drop options like jQuery and YUI3 do; droppable functionality in MooTools is actually implemented by the Drag.Move class - the one used to initialise a draggable. But when you setup an Endpoint in jsPlumb you should ignore that fact, and treat droppables like you would in jQuery or YUI3. jsPlumb wires everything up for you under the hood.

There are two jQuery droppable options that jsPlumb treats as shortcuts in MooTools and YUI3, for the sake of consistency:

For more information about drop options when using jQuery, see here.

Scope

jsPlumb borrowed the concept of 'scope' from jQuery's drag/drop implementation: the notion of which draggables can be dropped on which droppables. In jsPlumb you can provide a 'scope' entry when creating an Endpoint. Here's the example grey Endpoint example with 'scope' added:
var exampleGreyEndpointOptions = {
	endpoint:"Rectangle",
	paintStyle:{ width:25, height:21, fillStyle:"#666" },
	isSource:true,
	connectionStyle : { strokeStyle:"#666" },
	isTarget:true,
	scope:"exampleGreyConnection"
};
If you do not provide a 'scope' entry, jsPlumb uses a default scope. Its value is accessible through this method:
jsPlumb.getDefaultScope();
If you want to change it for some reason you can do so with this method:
jsPlumb.setDefaultScope("mySpecialDefaultScope");
You can also, should you want to, provide the scope value separately on the drag/drop options, like this:
var exampleGreyEndpointOptions = {
	endpoint:"Rectangle",
	painStyle:{ width:25, height:21, fillStyle:'#666' },
	isSource:true,
	connectionStyle : { strokeStyle:"#666" },
	isTarget:true,
	dragOptions:{ scope:"dragScope" },
	dropOptions:{ scope:"dropScope" }
};

Multiple jsPlumb instances

jsPlumb is registered on the browser's Window by default, providing one static instance for the whole page to use. Should you need to, though, you can instantiate independent instances of jsPlumb, using the getInstance method, for example:
var firstInstance = jsPlumb.getInstance();
The variable 'firstInstance' can now be treated exactly as you would treat the 'jsPlumb' variable - you can set defaults, call the connect method, whatever:
firstInstance.Defaults.Connector = [ "Bezier", 150 ];
firstInstance.Defaults.Container = "container1";
firstInstance.Defaults.Anchors = [ "TopCenter", "BottomCenter" ];

firstInstance.connect({source:'element1', target:'element2', scope:'someScope'});
getInstance optionally takes an object that provides the defaults:
var secondInstance = jsPlumb.getInstance({
	PaintStyle:{lineWidth:3, strokeStyle:color3},
	Connector:[ "Bezier", 30 ],
	Endpoint:[ "Dot", {radius:5} ],
	EndpointStyle : { fillStyle: color3  },
	Anchor : [ 0.5, 0.5, 1, 1 ],
	Container:"container2"
});

secondInstance.connect({source:'element4', target:'element3', scope:'someScope'});
Notice the container directives that are set on the defaults. This tells jsPlumb to draw everything inside the container with the given id, giving you cleaner separation between instances. While not actually required in order to make multiple instances work together, you might find it easier. Using this concept you can, for example, drag an entire drawing area around as one.

Automatic Repaint

jsPlumb attaches a listener to the browser window and automatically repaints every connection when a window resize event occurs. You can disable this functionality, if you want to, with the following call:
jsPlumb.setAutomaticRepaint(false);
You can also provide your own function for jsPlumb to execute instead of its default behaviour:
var repaint = function() {
	// do some things, perhaps, and then...
	jsPlumb.repaintEverything();
};

jsPlumb.setRepaintFunction(repaint);
Notice the call to repaintEverything() here - a useful method.

Another example:

var repaint = function() {
	// completely start over
	jsPlumb.detachEverything();
	// paint all your connections
};

jsPlumb.setRepaintFunction(repaint);

jsPlumb.connect Options

These are the options you can specify on a call to the connect method, to establish a Connection programmatically:

jsPlumb.addEndpoint Options

The simplest addEndpoint call looks like this:

jsPlumb.addEndpoint(someEndpoint);
but you will almost always want to use the two argument method:
jsPlumb.addEndpoint(someEndpoint, { parameters } );

These are the options you can specify on a call to the addEndpoint method, to setup a UI for drag and drop Connections:

jsPlumb.detach Options

Both the jsPlumb object and also individual elements have a method called 'detach'. The jsPlumb.detach method is more versatile and allows you to specify elements, element ids, endpoint uuids or Endpoint objects, whereas the detach method on individual elements can only take the id of some element, or that element's selector. This documentation refers to the jsPlumb.detach method. It has several similarities with the connect method discussed above.

These are the options you can specify on a call to jsPlumb.detach. You don't need to supply them all: jsPlumb needs either [connection], [source,target] or [sourceEndpoint, targetEndpoint] or uuids.

Defaults

The easiest way to set a look and feel for your plumbing is to override the defaults that jsPlumb uses. If you do not do this you are forced to provide your overridden values on every call. Every argument to the connect and addEndpoint methods has an associated default value in jsPlumb.

The defaults that ship with jsPlumb are stored in jsPlumb.Defaults, which is a Javascript object. Valid entries, and their initial values, are:
Anchor : null,
Anchors : [ null, null ],
BackgroundPaintStyle : null,
Connector : null,
Container : null,
DragOptions : {},
DropOptions : {},
Endpoint : null,
Endpoints : [ null, null ],
EndpointStyle : { fillStyle : null },
EndpointStyles : [ null, null ],
EndpointHoverStyle : null,
EndpointHoverStyles : [ null, null ],
HoverPaintStyle : null,
LabelStyle : { fillStyle : "rgba(0,0,0,0)", color : "black" },
LogEnabled : true,
MaxConnections : null,
PaintStyle : { lineWidth : 10, strokeStyle : 'red' },
Scope : "_jsPlumb_DefaultScope"

Note that in EndpointStyle, the default fillStyle is 'null'. This instructs jsPlumb to use the strokeStyle from the attached connector to fill the endpoint.

Note also that you can specify either or both (or neither) of 'EndpointStyle' and 'EndpointStyles'. This allows you to specify a different end point for each end of a connection. 'Endpoint' and 'Endpoints' use the same concept. jsPlumb will look first in the individual endpoint/endpoint style arrays, and then fall back to the single default version.

you can override these defaults by including this in a script somewhere:
jsPlumb.Defaults.PaintStyle = {
	lineWidth:13,
	strokeStyle: 'rgba(200,0,0,100)'
}

jsPlumb.Defaults.DragOptions = { cursor: 'crosshair' };

jsPlumb.Default.Endpoints = [ [ "Dot", 7 ], [ "Dot", 11 ] ];

jsPlumb.Defaults.EndpointStyles = [{ fillStyle:'#225588' }, { fillStyle:'#558822' }];
after the jsPlumb script has been loaded of course! Here we have specified the following default behaviour:

Anchors

An Anchor models the notion of where on an element a Connector should connect. jsPlumb has nine default anchor locations you can use to specify where the Connectors connect to elements: these are the four corners of an element, the center of the element, and the midpoint of each edge of the element. Each of these string representations is just a wrapper around the underlying array-based syntax, for example:

jsPlumb.connect({...., anchor:"BottomCenter", ... }); 
is identical to:
jsPlumb.connect({...., anchor:[0.5, 1, 0, 1], ... }); 

Dynamic Anchors

These are Anchors that can be positioned in one of a number of locations, choosing the one that is most appropriate each time something moves or is painted in the UI.

There is no special syntax to creating a DynamicAnchor; you just provide an array of individual Anchor specifications, eg:

var dynamicAnchors = [ [ 0.2, 0, 0, -1 ],  [ 1, 0.2, 1, 0 ], 
			   [ 0.8, 1, 0, 1 ], [ 0, 0.8, -1, 0 ] ];


You can then use that anchor as you would any other. But note that you cannot share dynamic anchors between connections: dynamic anchors maintain state about the connection they belong to, so if you share one amongst two or more connections you will get unexpected results.

Default Dynamic Anchor

jsPlumb provides a 'default' dynamic anchor that chooses from TopCenter, RightMiddle, BottomCenter and LeftMiddle:
var aDefaultDynamicAnchor = "AutoDefault";

Location Selection

The initial implementation of the algorithm that decides which location to choose just calculates which location is closest to the center of the other element in the connection. It is possible that future versions of jsPlumb could support more sophisticated choice algorithms, if the need arose.

Draggable Connections

Dynamic Anchors and Draggable Connections can interoperate: jsPlumb locks the position of a dynamic anchor when you start to drag a connection from it, and unlocks it once the connection is either established or abandoned. At that point you may see the position of the dynamic anchor change, as jsPlumb optimises the connection.

You can see this behaviour in the draggable connections demonstration, when you drag a connection from the blue endpoint on window 1 to the blue endpoint on window 3 - the connection is established and then window 1's blue endpoint jumps down to a location that is closer to window 3.

Connectors

Connectors are the lines that actually join elements of the UI. jsPlumb has three connector implementations - a straight line, a Bezier curve, and "flowchart" connectors. The default connector is the Bezier curve. jsPlumb attaches the CSS class _jsPlumb_connector to the canvas elements that it generates for connectors.

You optionally specify a Connector by setting the 'connector' property on a call to jsPlumb.connect or jsPlumb.addEndpoint(s). If you do not supply a value for 'connector', the default will be used (see defaults).

To specify a Connector there are two syntaxes you can use:

1. Specify the Connector by name. jsPlumb will create a Connector of that type, using its default options

jsPlumb.connect({
	...
	connector:"Straight",
	...
});
						
2. Specify the Connector by an array of [ name, options ]. jsPlumb will create a Connector of type 'name', and pass in the given options to the connector's constructor
jsPlumb.connect({
	...
	connector:[ "Flowchart", { minStubLength:45 } ],
	...
});
						

Each Connector type supports different (or zero) constructor arguments. These are described below.

Bezier Connector

The Bezier Connector provides a cubic Bezier path between the two endpoints. It supports a single constructor argument:

curviness - Optional; defaults to 150. This defines the distance in pixels that the Bezier's control points are situated from the anchor points. This does not mean that your connector will pass through a point at this distance from your curve. It is a hint to how you want the curve to travel. Rather than discuss Bezier curves at length here, because they are a complex topic, we refer you to Wikipedia.

Straight Connector

The Straight Connector draws a straight line between the two endpoints. No constructor arguments are supported; use the endpointStyle argument to a connect or addEndpoint call to control the appearance of one of these Connectors.

Flowchart Connector

This type of Connector draws a connection that consists of a series of vertical or horizontal segments - the classic flowchart look. A single constructor argument is supported:

minStubLength - this is the minimum length, in pixels, of the initial stub that emanates from an Endpoint. This parameter is optional, and defaults to 30 pixels.

Overlays

Overlays are UI elements that are painted onto connections, such as labels or arrows. jsPlumb comes with four defaults:

The last two are actually just configured instances of the generic Arrow overlay (see examples).

You can specify one or more overlays either when making a call to jsPlumb.connect, or when calling jsPlumb.addEndpoint. The two cases are discussed below:

1. Specifying one or more overlays on a jsPlumb.connect call. In this example we'll create an Arrow with the default options for an Arrow, and a label with the text "foo":
jsPlumb.connect({
	...
	overlays:[ 
		"Arrow", 
		[ "Label", { label:"foo", location:0.25 } ]
	],
	...
});			
This connection will have an arrow located halfway along it, and the label "foo" one quarter of the way along.

2. Specifying one or more overlays on a jsPlumb.addEndpoint call. Note in this example that we use the parameter 'connectorOverlays' and not 'overlays' as in the last example. This is because 'overlays' will one day be used to support Endpoint Overlays:
jsPlumb.addEndpoint("someDiv", {
	...
	connectorOverlays:[ 
		[ "Arrow", { width:10, length:30, location:1 } ], 
		[ "Label", { label:"foo" } ]
	],
	...
});			
This connection will have a 10x30 Arrow located right at the head of the connection, and the label "foo" located at the halfway point.

Arrow Overlay

This overlay draws an arrow, using four points: the head and two tail points, and a 'foldback' point, which permits the tail of the arrow to be indented. Available constructor arguments for this Overlay are

PlainArrow Overlay

This is just a specialized instance of Arrow in which jsPlumb hardcodes 'foldback' to 1, meaning the tail of the Arrow is a flat edge. All of the constructor parameters from Arrow apply for PlainArrow.

Diamond Overlay

This is a specialized instance of Arrow in which jsPlumb hardcodes 'foldback' to 2, meaning the Arrow turns into a Diamond. All of the constructor parameters from Arrow apply for PlainArrow.

Label Overlay

This provides a text label to decorate Connectors with. The available constructor arguments are:

Endpoints

An Endpoint is the UI component that marks the location of an Anchor, ie. the place where a Connector joins an element. jsPlumb comes with three Endpoint implementations - Dot, Rectangle and Image. You optionally specify Endpoint properties using the endpoint parameter in a call to either jsPlumb.connect or jsPlumb.addEndpoint. The two ways you can specify an Endpoint are similar to that used for Connectors:

1. Specify an Endpoint by name:

jsPlumb.connect({
	...
	endpoint:"Dot",
	...
});
2. Specify an Endpoint by [ name, options ]:
jsPlumb.addEndpoint("someDiv", {
	...
	endpoint:[ "Dot", { radius:67 } ],
	...					
});					
The three available Endpoint types, and their constructor arguments, are as follows:

Dot Endpoint

This draws a dot. Example:

{ 
...
endpoint: ["Dot", {radius:34} ];
...
}
Here we created a dot with a radius of 34 pixels. You do not need to supply the radius though - if you omit it, jsPlumb will assign a default of 10 pixels. Note that you can also supply the radius in the endpointStyle object.

In the endpointStyle option of a connect call, you can set two values that this will pick up:


Rectangle Endpoint

Draws a rectangle. Example:

{
...
endpoint:[ "Rectangle", {width:34, height:10} ];
...
}
Here we created a rectangle of size 34x10. If you omit the size when you create a Rectangle, jsPlumb will use defaults of 20x20. Just like with the Dot endpoint, you can also provide this information in the endpointStyle.

In the endpointStyle you can set the following for this:


Image Endpoint

Draws an image from a given URL. Example:

{
...
endpoint:[ "Image", {url:"http://myserver.com/images/endpoint.png"} ];
...
}
This creates an Image endpoint with the image at the given url. You do not need to provide dimensions. jsPlumb will figure that out for you.

Endpoint Operations

These are the methods supported by the Endpoint class:

Endpoint UUIDs

Each Endpoint can have a UUID associated with it; these can be used to establish Connections and also to retrieve Endpoints from jsPlumb. To assign a UUID to an Endpoint you can do one of two things: Once you have an Endpoint that has a UUID assigned, you can retrieve it from jsPlumb:
var e = jsPlumb.getEndpoint("abcdefg");
...and you can also use the UUIDs to connect Endpoints:
jsPlumb.connect({uuids:["abcdefg", "hijklmn"});

Gradients

The Canvas element supports gradients, and jsPlumb can take advantage of this when painting your Connectors and/or Endpoints. Note: this does NOT WORK in IE, because we use ExplorerCanvas in IE and ExplorerCanvas does not support gradients.

There are two types of gradients available in Canvas - a 'linear' gradient, which consists of colored lines all going in one direction, and a 'radial' gradient, which consists of colored circles emanating from one circle to another. Because of their basic shape, jsPlumb supports only linear gradients for Connectors. But for Endpoints, jsPlumb supports both linear and radial gradients.

Connector gradients

To specify a linear gradient to use in a Connector, you must add a gradient object to your Connector's paintStyle, for instance:
jsPlumb.connect({
	source : "window2",
	target : "window3",
	paintStyle:{
		gradient:{
			stops:[[0,"green"], [1,"red"]]
		},
		lineWidth:15
	}
});
Here we have connected window2 to window3 with a 15 pixel wide connector that has a gradient from green to red.

Notice the gradient object and the stops list inside it - the gradient consists of an arbitrary number of these "color stops". Each color stop is comprised of two values - [position, color]. Position must be a decimal value between 0 and 1 (inclusive), and indicates where the color stop is situated as a fraction of the length of the entire gradient. Valid values for the colors in the stops list are the same as those that are valid for strokeStyle when describing a color.

As mentioned, the stops list can hold an arbitrary number of entries. Here's an example of a gradient that goes from red to blue to green, and back again through blue to red:

jsPlumb.connect({
	source : 'window2',
	target : 'window3',
	paintStyle : {
		gradient:{
			stops:[[0,'red'], [0.33,'blue'], [0.66,'green'], [0.33,'blue'], [1,'red']]
		},
		lineWidth : 15
	}
});
Note: jsPlumb uses ExplorerCanvas for IE, which does not support gradients. On IE, jsPlumb will simply ignore the gradient directive so it is best to ensure you also supply a strokeStyle in your paintStyle object, to give jsPlumb something to fall back on. If you do not supply a strokeStyle your Connectors will be painted black. The previous example might look like this, for instance:
jsPlumb.connect({
	source : 'window2',
	target : 'window3',
	paintStyle:{
		strokeStyle:'red',
		gradient:{
			stops:[[0,'red'], [0.33,'blue'], [0.66,'green'], [0.33,'blue'], [1,'red']]
		},
		lineWidth:15
	}
});
Notice the strokeStyle:'red' directive at the beginning of the parameter list in paintStyle.

Endpoint gradients

Endpoint gradients are specified using the same syntax as Connector gradients. You put the gradient specifier either in the endpoint member, or if you are specifying different Endpoints for each end of the Connector, in one or both of the values in the endpoints array. Also, this information applies to the case that you are creating standalone Endpoints that you will be configuring for drag and drop creation of new Connections.

This is an example of an Endpoint gradient that is different for each Endpoint in the Connector. This comes from the main demo; it is the Connector joining Window 2 to Window 3:

var w23Stroke = 'rgb(189,11,11)';
jsPlumb.connect({
	source : 'window2',
	target : 'window3',
	paintStyle:{
		lineWidth:8,
		strokeStyle:w23Stroke
	},
 	anchors:[ [0.3,1,0,1], "TopCenter" ],
 	endpoint:"Rectangle",
 	endpointStyles:[
 		{ gradient : {stops:[[0, w23Stroke], [1, '#558822']] } },
    	{ gradient : {stops:[[0, w23Stroke], [1, '#882255']] } }
    ]
});
The first entry in the gradient will be the one that is on the Connector end of the Endpoint. You can of course have as many color stops as you want in this gradient, just like with Connector gradients.

Applying the gradient in Endpoints

Only the Dot and Rectangle endpoints honour the presence of a gradient (and, remember, not in IE). The Image endpoint of course ignores a gradient as it does no painting of its own.

The type of gradient you will see depends on the Endpoint type:

Animation

jsPlumb offers an 'animate' function, which wraps the underlying animation engine for whichever library you happen to be using and inserts a callback for jsPlumb to repaint whatever it needs to at each step. You could of course do this yourself; it's a convenience method really.

The method signature is:

jsPlumb.animate : function(el, properties, options) 
The arguments are as follows:

Events

jsPlumb fires an event to registered listeners whenever a connection is made (we plan to support more events in the future).

Registering Event Listeners

To register an event listener you need to supply the event name and a listener object:
jsPlumb.bind("jsPlumbConnection", someListener); 
(you can also use 'addListener', but it has been deprecated in 1.2.4. It does the same thing as bind.

The listener object - in this case 'someListener' - must have a method with the same name as the event. For example, to define a listener inline, you could do a call like this:
jsPlumb.bind("jsPlumbConnection", function(data) {
	console.log("a connection was made from " + data.sourceId + " to " + data.targetId);
}); 
jsPlumb.bind("jsPlumbConnectionDetached", function(data) {
	console.log("a connection was detached from " + data.sourceId + " and " + data.targetId);
}); 

Event Types

event namefunction argumentsexplanation
jsPlumbConnectionparams - JS object containing sourceId, targetId, source, target, sourceEndpoint, targetEndpointfired whenever a new connection is made, either programmatically via jsPlumb.connect, or drag and drop
jsPlumbConnectionDetachedparams - JS object containing sourceId, targetId, source, target, sourceEndpoint, targetEndpointfired whenever a connection is detached, either programmatically via one of the jsPlumb.detach methods, or drag and drop

CSS Class Reference

jsPlumb attaches classes to each of the UI components it creates:
componentcss class
connector_jsPlumb_connector
endpoint_jsPlumb_endpoint
You would typically use these to establish appropriate z-indices for your UI.

jsPlumb.connect Examples

This section provides examples of how to use the programmatic API to establish Connections.

The basic syntax of a call is that you execute 'connect', providing a source and a target, and optionally a paintStyle and preferences for where you want the plumbing to be anchored on each element, as well as the type of connector to use.

Utility Functions

  • Detach window5 from all connections
    jsPlumb.detachAll("window5");
  • Hide all window5's connections
    jsPlumb.hide("window5");
  • Show all window5's connections
    jsPlumb.show("window5");
  • Toggle the visibility of window5's connections
    jsPlumb.toggle("window5");
  • Force repaint of all of window5's connections
    jsPlumb.repaint("window5");
  • Force repaint of all of window5, window6 and window11's connections
    jsPlumb.repaint( [ "window5", "window6", "window11" ] );
  • Force repaint of every connection
    jsPlumb.repaintEverything();
  • Detach every connection
    jsPlumb.detachEverything();
  • Remove the given Endpoint from element "window1", deleting its Connections.
    jsPlumb.removeEndpoint("window1", someEndpoint);
  • Remove all Endpoints for the element 'window1', deleting their Connections.
    jsPlumb.removeAllEndpoints("window1");
  • Removes every Endpoint managed by this instance of jsPlumb, deleting all Connections. This is the same as jsPlumb.reset(), effectively, but it does not clear out the event listeners list.
    jsPlumb.removeEveryEndpoint();
  • Deletes the given Endpoint and all its Connections.
    jsPlumb.deleteEndpoint(endpoint);
  • Removes every endpoint, detaches every connection, and clears the event listeners list. Returns jsPlumb instance to its initial state.
    jsPlumb.reset();
  • Set window1 to be not draggable, no matter what some jsPlumb command may request.
    jsPlumb.setDraggable("window1", false);
  • Set window1 and window2 to be not draggable, no matter what some jsPlumb command may request.
    jsPlumb.setDraggable(["window1","window2"], false);
  • Sets whether or not elements that are connected are draggable by default. The default for this is true.
    jsPlumb.setDraggableByDefault(false);
  • Initialises window1 as a draggable element (all libraries)
    jsPlumb.draggable("window1");
  • Initialises window1 and window2 as draggable elements (all libraries)
    jsPlumb.draggable(["window1","window2"]);
  • Initialises window1 as a draggable element (all libraries)
    jsPlumb.draggable("window1");
  • Initialises all elements with class 'window' as draggable elements (jQuery)
    jsPlumb.draggable($(".window"));
  • Initialises all elements with class 'window' as draggable elements (MooTools)
    jsPlumb.draggable($$(".window"));
  • Initialises all elements with class 'window' as draggable elements (YIU3)
    jsPlumb.draggable(Y.all(".window"));
  • Initialises window1 as a draggable element (jQuery)
    jsPlumb.draggable($("#window1"));
  • Initialises window1 as a draggable element (MooTools)
    jsPlumb.draggable($("window1"));
  • Initialises window1 as a draggable element (YUI3)
    jsPlumb.draggable(Y.one("window1"));
  • Draggable Connections Examples

    This is a list of examples of how to use jsPlumb to create Connections using drag and drop.

    The basic procedure is:

    1. Create Endpoints and register them on elements in your UI
    2. Drag and Drop
    That's all there is to it. Of course there are plenty of options you can set when doing this...it will be easier to show you some examples:

    Retrieving Connection Information

    jsPlumb offers one fairly versatile method - getConnections - to retrieve information about the currently managed connections.

    Before you use this method you should understand jsPlumb's notion of 'scope' - documentation is here

    getConnections optionally takes an object specifying filter parameters, of which there are three:

    Each of these three parameters may be supplied as a string, or a list of strings - see the examples below.

    The return value of a call to getConnection is a dictionary whose keys are scope names, and whose values are lists of sourceId/targetId pairs, for example:

    {
    	"_jsPlumb_DefaultScope" : [
    		{sourceId:"window1", targetId:"window2", source:<sourceElement>, target:<targetElement>, sourceEndpoint:<sourceEndpoint>, targetEndpoint:<targetEndpoint>, connection:<connection> },
    		{sourceId:"window5", targetId:"window3", source:<sourceElement>, target:<targetElement>, sourceEndpoint:<sourceEndpoint>, targetEndpoint:<targetEndpoint>, connection:<connection> }
    	],
    	"someCustomScope": [
    		{sourceId:"window6", targetId:"window2", source:<sourceElement>, target:<targetElement>, sourceEndpoint:<sourceEndpoint>, targetEndpoint:<targetEndpoint>, connection:<connection> },
    		{sourceId:"window4", targetId:"window13", source:<sourceElement>, target:<targetElement>, sourceEndpoint:<sourceEndpoint>, targetEndpoint:<targetEndpoint>, connection:<connection> },
    		{sourceId:"window2", targetId:"window10", source:<sourceElement>, target:<targetElement>, sourceEndpoint:<sourceEndpoint>, targetEndpoint:<targetEndpoint>, connection:<connection> }
    	]
    }
    

    The following examples show the various ways you can call this method: Note that the return value is always a dictionary and not an array, even if you specified a single scope in the getConnections call. So you always have to get the array you need by looking it up in the dictionary:
    var c = jsPlumb.getConnections({scope:"myScope", source:"mySourceElement"});
    var conns = c["myScope"];  
    
    The array may be null. If you have not registered any connections with that scope, it will be. Code defensively!

    Advanced Topics

    Which files are which?

    In development, jsPlumb is broken up into four main scripts: These four files are packaged together to form the scripts that people use, for example:

    Pluggable Library Support

    Out of the box, jsPlumb can be run on top of jQuery, MooTools or YUI3. This is achieved by delegating several core methods - tasks such as finding an element by id, finding an element's position or dimensions, initialising a draggable, etc - to the library in question.

    To develop one of these, your test page should include the first two scripts discussed above, and then your own script containing your library specific functionality. The two existing implementations should be documented well enough for you to create your own. If you do this, it would be great to share it with everyone...

    Custom Connectors

    You can provide your own connectors if you need to. A Connector consists of two functions, which work as a pair. First a call is made to the compute function:
    this.compute = function(sourcePos, targetPos, sourceAnchor, targetAnchor, lineWidth) {
    	...
    	return dimensions;
    }
    
    which is expected to return a list that the paint function can make sense of. The first four entries in the list must be the [x,y,width,height] values for the canvas that the connector will be drawn on; jsPlumb will use this information to size the canvas prior to calling the Connector's paint function. Therefore it is the Connector's responsibility to ensure that the returned dimensions describe a large enough space for the line that will be drawn on it.

    The next four elements must be the coordinates of the two endpoints of the line you are going to draw.

    The remainder of the items in the returned list are arbitrary, and will vary between Connector implementations; this list is passed in to a Connector's paint function, so each implementation will put into the list whatever it needs to paint itself. For instance, the straight line connector only needs the [x,y] location of each end of the line it will paint, and that is one of the required entries, so it does not have to do anything extra, whereas the Bezier connector adds the location of the two control points. Other types of Connectors will do whatever is appropriate for their particular situation.

    This is the method signature for the paint function:
    this.paint = function(dimensions, ctx) { .. }
    here, the 'dimensions' argument to the 'paint' function is the return value of the 'compute' function. The 'ctx' argument is the Canvas context; you will do all your drawing on this.

    To change the connector from the default, specify it in your connect call:
    jsPlumb.connect({source:'someWindow', target:'otherWindow', connector:new jsPlumb.Connectors.Straight()});
    note that you can use shorthand for connectors if you don't need to specify parameters to it:
    jsPlumb.connect({source:'someWindow', target:'otherWindow', connector:"Straight"});
    This works in the same way as specifying Anchors as string does.

    The section below this discusses Overlays, which allow you to decorate Connectors with things such as labels or arrows or whatever else you like. Overlays can only work with Connectors that implement a few helper functions.

    The concept of location

    Before discussing the helper functions you first must be across the concept of 'location' as used by this mechanism. The location on a connector can be a decimal value between 0 and 1 inclusive, which marks a proportionate amount of travel along the path inscribed by the Connector. For a straight line connector this is a simple piece of maths, but for Bezier connectors it's a little bit more involved.

    Required Helper Methods

    Custom Endpoints

    To create your own Endpoint implementation, you need to implement a single method:

    paint : function(anchorPoint, orientation, canvas, endpointStyle, connectorPaintStyle) { ... }
    The arguments to this method are as follows:

    It is your responsibility to size and locate the canvas to suit your needs. jsPlumb provides the following helper method to assist you:

    jsPlumb.sizeCanvas(canvas, x, y, width, height);
    Allows you to locate the canvas on screen and to size it.

    Custom Overlays

    Overlays can only work with Connectors that implement the methods pointOnPath, pointAlongPathFrom, gradientAtPoint, and perpendicularToPathAt. These are discussed in more detail in the Custom Connectors section above. Both of the Connectors that come with jsPlumb - Straight and Bezier -implement these methods; if you write a custom connector, or have written a custom connector, you will need to supply them.

    Overlay Interface

    An Overlay is required to implement two methods in order to be usable by jsPlumb:

    computeMaxSize methods

    This is the Arrow overlay's computeMaxSize method:
    this.computeMaxSize = function() { return width; }
    
    Here, width is a private member of Arrow that indicates the width of the arrow's tail. So the Arrow overlay reports that figure as the width it needs. Contrast this with the Label Overlay's computeMaxSize method:
    this.computeMaxSize = function(connector, ctx) {
      	if (labelText) {
      		ctx.save();
            if (self.labelStyle.font) ctx.font = self.labelStyle.font;
             var t = ctx.measureText(labelText).width;			            
    		// a fake text height measurement: use the width of upper case M
    		var h = ctx.measureText("M").width;					
    		labelPadding = self.labelStyle.padding || 0.25;
    		labelWidth = t + (2 * t * labelPadding);
    		labelHeight = h + (2 * h * labelPadding);
    		ctx.restore();
    		return Math.max(labelWidth, labelHeight);
      	}
     	return 0;
     };
    
    The Label overlay has to use the context to determine how big it will be on screen.

    draw methods

    To give you a taste for how you can interact with a connector, consider the first few lines of the Arrow overlay's draw method:
    this.draw = function(connector, ctx) {
    	// this is the arrow head position
    	var hxy = connector.pointAlongPathFrom(self.loc, length / 2);		
    	// this is the center of the tail
    	var txy = connector.pointAlongPathFrom(self.loc, -length / 2), tx = txy[0], ty = txy[1];
    	// this is the tail vector
    	var tail = connector.perpendicularToPathAt(self.loc, -length / 2, width);
    	
    	...
    

    The first two calls to the connector use the pointAlongPathFrom method, which passes self.loc as the location of the point on the path, and length / 2 as the number of pixels along the path to traverse.

    self.loc is Arrow's internal member describing the location of the overlay, and it is a decimal (between 0 and 1 inclusive) that points to a location at some distance along the path inscribed by the connector. So these first two calls get us [x,y] locations of points on the connector that mark the head and tail points for the arrow.

    The connector.perpendicularToPathAt(self.loc, -length / 2, width) call returns a line description of a line that is perpendicular to, and centered on, the connector at "-length / 2" pixels from the given point, with the given width (width is an internal member of Arrow). At this point, the Arrow object has the three main points it needs in order to draw itself.