A Type is a collection of attributes such as paint style, hover paint style, overlays etc - it is a subset, including most but not all, of the parameters you can set in an Endpoint or Connection definition. It also covers behavioural attributes such as isSource
or maxConnections
on Endpoints.
An Endpoint or Connection can have zero or more Types assigned; they are merged as granularly as possible, in the order in which they were assigned. There is a supporting API that works in the same way as the class stuff does in jQuery:
and each of these methods (except hasType
) takes a space-separated string so you can add several at once. Support for these methods has been added to the jsPlumb.select
and jsPlumb.selectEndpoint
methods, and you can also now specify a type
parameter to an Endpoint or Connection at create time.
Types are a useful tool when you are building a UI that has connections whose appearance change under certain circumstances, or a UI that has various types of connections etc.
Probably the easiest way to explain Types is with some code. In this snippet, we'll register a Connection Type on jsPlumb, create a Connection, and then assign the Type to it:
jsPlumb.registerConnectionType("example", {
paintStyle:{ strokeStyle:"blue", lineWidth:5 },
hoverPaintStyle:{ strokeStyle:"red", lineWidth:7 }
});
var c = jsPlumb.connect({ source:"someDiv", target:"someOtherDiv" });
c.bind("click", function() {
c.setType("example");
});
Another example - a better one, in fact. Say you have a UI in which you can click to select or deselect Connections, and you want a different appearance for each state. Connection Types to the rescue!
jsPlumb.registerConnectionTypes({
"basic": {
paintStyle:{ strokeStyle:"blue", lineWidth:5 },
hoverPaintStyle:{ strokeStyle:"red", lineWidth:7 },
cssClass:"connector-normal"
},
"selected":{
paintStyle:{ strokeStyle:"red", lineWidth:5 },
hoverPaintStyle:{ lineWidth: 7 },
cssClass:"connector-selected"
}
});
var c = jsPlumb.connect({ source:"someDiv", target:"someOtherDiv", type:"basic" });
c.bind("click", function() {
c.toggleType("selected");
});
Notice here how we used a different method -registerConnectionTypes
- to register a few Types at once.
Notice also the hoverPaintStyle
for the selected
Type: it declares only a lineWidth
. As mentioned above, Types are merged with as much granularity as possible, so that means that in this case the lineWidth
value from selected
will be merged into the hoverPaintStyle
from basic
, and voila, red, 7 pixels.
These examples, of course, use the jsPlumb.connect
method, but in many UIs Connections are created via drag and drop. How would you assign that basic
Type to a Connection created with drag and drop? You provide it as the Endpoint's connectionType
parameter, like so:
var e1 = jsPlumb.addEndpoint("someDiv", {
connectionType:"basic",
isSource:true
});
var e2 = jsPlumb.addEndpoint("someOtherDiv", {
isTarget:true
});
//... user then perhaps drags a connection...or we do it programmatically:
var c = jsPlumb.connect({ source:e1, target:e2 });
// now c has type 'basic'
console.log(c.hasType("basic)); // -> true
Note that the second Endpoint we created did not have a connectionType
parameter - we didn't need it, as the source Endpoint in the Connection had one. But we could have supplied one, and jsPlumb will use it, but only if the source Endpoint has not declared connectionType
. This is the same way jsPlumb treats other Connector parameters such as paintStyle
etc - the source Endpoint wins.
Not every parameter from a Connection's constructor is supported in a Connection Type - as mentioned above, Types act
pretty much like CSS classes, so the things that are supported are related to behaviour or appearance (including
the ability to set CSS classes on the UI artefacts). For instance, source
is not supported: it indicates the source
element for some particular Connection and therefore does not make sense inside a type specification: you cannot
make a Connection Type that is fixed to a specific source element. Here's the full list of supported properties in
Connection Type objects:
scope
, when multiple types assign a CSS class, the UI artefact gets all of them written to it.Connection Types support parameterized values - values that are derived at runtime by some object you supply. Here's the first example from above, with a parameterized value for strokeStyle
:
jsPlumb.registerConnectionType("example", {
paintStyle:{ strokeStyle:"${color}", lineWidth:5 },
hoverPaintStyle:{ strokeStyle:"red", lineWidth:7 }
});
var c = jsPlumb.connect({ source:"someDiv", target:"someOtherDiv" });
c.bind("click", function() {
c.setType("example", { color:"blue" });
});
setType
, addType
and toggleType
all now support this optional second argument.
You can also use a parameterized Type in a jsPlumb.connect
call, by supplying a data
value:
jsPlumb.registerConnectionType("example", {
paintStyle:{ strokeStyle:"${color}", lineWidth:5 },
hoverPaintStyle:{ strokeStyle:"red", lineWidth:7 }
});
var c = jsPlumb.connect({
source:"someDiv",
target:"someOtherDiv",
type:"example",
data:{ color: "blue" }
});
Here are a few examples showing you the full Type API:
jsPlumb.registerConnectionTypes({
"foo":{ paintStyle:{ strokeStyle:"yellow", lineWidth:5, cssClass:"foo" } },
"bar":{ paintStyle:{ strokeStyle:"blue", lineWidth:10 } },
"baz":{ paintStyle:{ strokeStyle:"green", lineWidth:1, cssClass:"${clazz}" } },
"boz":{ paintStyle: { strokeStyle:"${color}", lineWidth:"${width}" } }
});
var c = jsPlumb.connect({
source:"someDiv",
target:"someOtherDiv",
type:"foo"
});
// see what types the connection has.
console.log(c.hasType("foo")); // -> true
console.log(c.hasType("bar")); // -> false
// add type 'bar'
c.addType("bar");
// toggle both types (they will be removed in this case)
c.toggleType("foo bar");
// toggle them back
c.toggleType("foo bar");
// getType returns a list of current types.
console.log(c.getType()); // -> [ "foo", "bar" ]
// set type to be 'baz' only
c.setType("baz");
// add foo and bar back in
c.addType("foo bar");
// remove baz and bar
c.removeType("baz bar");
// what are we left with? good old foo.
console.log(c.getType()); // -> [ "foo" ]
// now let's add 'boz', a parameterized type
c.addType("boz", {
color:"#456",
width:35
});
console.log(c.getType()); // -> [ "foo", "boz" ]
// now clear all types
c.clearTypes();
console.log(c.getType()); // -> [ ]
Things to note here are that every method except hasType can take a space-delimited list of Types to work with. So types work like CSS classes, basically. I think I might have mentioned that already though.
Endpoints can also be assigned one or more Types, both at creation and programmatically using the API discussed above.
The only real differences between Endpoint and Connection Types are the allowed parameters. Here's the list for Endpoints:
paintStyle
are provided, this takes precedencehoverPaintStyle
are provided, this takes precedenceStateMachine
, or [ "Flowchart", { stub:50 } ]
Note There are two sets of parameters you can use to set paint styles for Endpoints - endpointStyle
/endpointHoverStyle
and paintStyle
/hoverPaintStyle
. The idea behind this is that when you use the endpoint..
versions, you can use a single object to define a Type that is shared between Endpoints and Connectors.
One thing to be aware of is that the parameters here that are passed to Connections are only passed from a source Endpoint, not targets. Here's an example of using Endpoint Types:
jsPlumb.registerEndpointTypes({
"basic":{
paintStyle:{fillStyle:"blue"}
},
"selected":{
paintStyle:{fillStyle:"red"}
}
});
var e = jsPlumb.addEndpoint("someElement", {
anchor:"TopMiddle",
type:"basic"
});
e.bind("click", function() {
e.toggleType("selected");
});
So it works the same way as Connection Types. There are several parameters allowed by an Endpoint Type that affect Connections coming from that Endpoint. Note that this does not affect existing Connections. It affects only Connections that are created after you set the new Type(s) on an Endpoint.
You can use parameterized Types for Endpoints just as you can Connections:
jsPlumb.registerEndpointType("example", {
paintStyle:{ fillStyle:"${color}"}
});
var e = jsPlumb.addEndpoint("someDiv", {
type:"example",
data:{ color: "blue" }
});
If you have one or more parameterized Types set on some object and you wish for them to change to reflect a change in their underlying data, you can use the reapplyTypes
function:
jsPlumb.registerConnectionType("boz",{
paintStyle: {
strokeStyle:"${color}",
lineWidth:"${width}"
}
});
var c = jsPlumb.connect({ source:"s", target:"t" });
c.addType("boz",{ color:"green", width:23 });
.. things happen ..
c.reapplyTypes({ color:"red", width:0 });
reapplyTypes
applies the new parameters to the merged result of all Types currently set on an object.
As mentioned previously, all of the Type operations are supported by the select
and selectEndpoints
methods.
So you can do things like this:
jsPlumb.selectEndpoints({
scope:"terminal"
}).toggleType("active");
jsPlumb.select({
source:"someElement"
}).addType("highlighted available");
Obviously, in these examples, available
and highlighted
would have previously been registered on jsPlumb using the appropriate register methods.