## Connection and Endpoint Types

1. Introduction
2. Connection Types
3. Parameterized Connection Types
4. Endpoint Types
5. Parameterized Endpoint Types
6. Reapplying Types
7. Fluid Interface

### Introduction

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:

- `hasType`
- `addType`
- `removeType`
- `toggleType`
- `setType`

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.

### Connection Type

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 }
        },
        "selected":{
            paintStyle:{ strokeStyle:"red", lineWidth:5 },
            hoverPaintStyle:{ lineWidth: 7 }
        }
    });

    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 `connectorType` parameter, like so:

    var e1 = jsPlumb.addEndpoint("someDiv", {
        connectorType:"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 `connectorType` 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 `connectorType`. This is the same way jsPlumb treats other Connector parameters such as `paintStyle` etc - the source Endpoint wins.

##### Supported Parameters in Connection Type objects

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. 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:

- detachable - whether or not the Connection is detachable using the mouse
- paintStyle
- hoverPaintStyle
- scope - remember, Connections support a single scope. So if you have multiple Types applied, you will get the scope from the last Type that defines one.
- parameters - when you add/set a Type that has parameters, any existing parameters with the same keys will be overwritten. When you remove a Type that has parameters, its parameters are NOT removed from the Connection.
- overlays - when you have multiple types applied to a Connection, you get the union of all the Overlays defined across the various Types. Note when you create a Connection using jsPlumb.connect and you provide a 'type', that is equivalent to calling 'addType': you will get the Overlays defined by the Type(s) you set as well as any others you have provided to the constructor.

##### Parameterized Connection Types

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 } },
      "bar":{ paintStyle:{ strokeStyle:"blue", lineWidth:10 } },
      "baz":{ paintStyle:{ strokeStyle:"green", lineWidth:1 } },
      "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
    });

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.

### Endpoint Type

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`
- `hoverPaintStyle`
- `maxConnections`
- `connectorStyle` - paint style for any Connections that use this Endpoint.
- `connectorHoverStyle` - hover paint style for Connections from this Endpoint.
- `connector` - a Connector definition, like `StateMachine`, or `[ "Flowchart", { stub:50 } ]`
- `connectionType` - This allows you to specify the Connection Type for Connections made from this Endpoint.
- `scope` - remember, Endpoints support a single scope. So if you have multiple Types applied, you will get the scope from the last Type that defines one.
- `parameters` - when you add/set a Type that has parameters, any existing parameters with the same keys will be overwritten. When you remove a Type that has parameters, its parameters are NOT removed from the Connection.
- `overlays` - when you have multiple Types applied to an Endpoint, you get the union of all the Overlays defined across the various types.

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.

### Parameterized Endpoint Types

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" }
    });

##### Reapplying Types

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.registerConnectionStyle("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.

#### Fluid Interface

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.