## Element Tools

This is the seventh article of the intermediate section of the JointJS tutorial. Go back to link labels. Alternatively, you can return to index of all articles.

JointJS allows creating fully customizable user interaction tools for your elements. These tools show up on user interaction (e.g. mouseover) with an element view and allow the user to interact with the underlying element model. For example:

JointJS source code: element-tools-example.js

The process of getting element tools up and running on your element view is relatively straightforward:

- Create individual element tools.
- Add the element tools to a toolsView.
- Add the toolsView to an element view.
- Make the tools interactive.

We will explain every step in turn. We will also touch on creating custom buttons.

### Element Tools

An element tool (type `joint.dia.ToolView`) is a view that renders a certain type of control elements on top of the element view it is attached to; for example the `Boundary` tool renders an outline around the bounding box of the element. The JointJS library comes with a collection of pre-made element tool definitions in the `joint.elementTools` namespace.

The pre-made element tools include:

- `Boundary` - shows the bounding box of the element
- `Remove` - adds an interactive remove button

To create a new element tool, we call its constructor:

    var boundaryTool = new joint.elementTools.Boundary();

The element tool constructors also accept optional arguments that modify the appearance and function of the created tools:

    var boundaryTool = new joint.elementTools.Boundary({
        padding: 20,
        rotate: true,
        useModelGeometry: true,
    });

### Add to Tools View

Element tools always need to come bundled in a tools view object (type `joint.dia.ToolsView`). This allows them to be shown/hidden as a group above an element. We create a new tools view and add our tools to it:

    var boundaryTool = new joint.elementTools.Boundary();
    var removeButton = new joint.elementTools.Remove();

    var toolsView = new joint.dia.ToolsView({
        tools: [
            boundaryTool,
            removeButton
        ]
    });

Remember, it is necessary to create a new set of tools for every new tools view object we create; tools are automatically reassigned to the last tools view that uses them.

### Add to Element View

Finally, we need to add our tools view to an element view. The `joint.dia.ElementView` class comes with a suite of tools-related methods:

- `elementView.addTools(toolsView)` - adds given `toolsView` onto the element view. The tools are visible by default.
- `elementView.showTools()` - shows tools on the element view.
- `elementView.hideTools()` - hides tools on the element view.
- `elementView.removeTools()` - removes tools from the element view.

We can thus show all of our tools in one place:

    var elementView = element.findView(paper);
    elementView.addTools(toolsView);

JointJS source code: element-tools-all.js

Remember, it is necessary to create a new tools view object for every element view; tools view objects are automatically reassigned to the last element view that uses them.

### Interaction

You can easily toggle visibility of element tools using the `'element:mouseenter'`/`'element:mouseleave'` Paper events:

    paper.on('element:mouseenter', function(elementView) {
        elementView.showTools();
    });

    paper.on('element:mouseleave', function(elementView) {
        elementView.hideTools();
    });

JointJS source code: element-tools-interaction.js

More complex interaction scenarios might require showing, hiding or removing all tools at once. You can find relevant functions in the Paper class:

- `paper.showTools()` - shows tools on all element and link views.
- `paper.hideTools()` - hides tools on all element and link views.
- `paper.removeTools()` - removes tools from all element and link views.

Note that our example toggles visibility of element tools by using the `showTools()`/`hideTools()` functions. Element tools may also be toggled by `addTools()`/`removeTools()` functions, which are demonstrated in the link tools tutorial. For element tools, there is no practical difference between the two approaches.

### Custom Buttons

It is possible to create custom buttons to complement the pre-made `Remove` button tool; JointJS exposes the `joint.elementTools.Button` class for you to extend. The markup of the new button can be sent as `options.markup`, while the behavior of the button on pointerdown interaction is determined by the callback function provided in `options.action`.

You can add the extended button to the `joint.elementTools` namespace and then just use that class in the code:

    joint.elementTools.InfoButton = joint.elementTools.Button.extend({
        name: 'info-button',
        options: {
            markup: [{
                tagName: 'circle',
                selector: 'button',
                attributes: {
                    'r': 7,
                    'fill': '#001DFF',
                    'cursor': 'pointer'
                }
            }, {
                tagName: 'path',
                selector: 'icon',
                attributes: {
                    'd': 'M -2 4 2 4 M 0 3 0 0 M -2 -1 1 -1 M -1 -4 1 -4',
                    'fill': 'none',
                    'stroke': '#FFFFFF',
                    'stroke-width': 2,
                    'pointer-events': 'none'
                }
            }],
            x: '100%',
            y: '100%'
            offset: {
                x: 0,
                y: 0
            },
            rotate: true,
            action: function(evt) {
                alert('View id: ' + this.id + '\n' + 'Model id: ' + this.model.id);
            }
        }
    });

    var infoButton = new joint.elementTools.InfoButton();
    var toolsView = new joint.dia.ToolsView({
        tools: [infoButton]
    });

    var elementView = element.findView(paper);
    elementView.addTools(toolsView);

JointJS source code: element-tools-custom-button.js

A single-use custom button can also be created by direct reference to the `Button` class, without making an entry in the `joint.elementTools` namespace:

    var infoButton = new joint.elementTools.Button({
        markup: [{
            tagName: 'circle',
            selector: 'button',
            attributes: {
                'r': 7,
                'fill': '#001DFF',
                'cursor': 'pointer'
            }
        }, {
            tagName: 'path',
            selector: 'icon',
            attributes: {
                'd': 'M -2 4 2 4 M 0 3 0 0 M -2 -1 1 -1 M -1 -4 1 -4',
                'fill': 'none',
                'stroke': '#FFFFFF',
                'stroke-width': 2,
                'pointer-events': 'none'
            }
        }],
        x: '100%',
        y: '100%',
        offset: {
            x: 0,
            y: 0
        },
        rotate: true,
        action: function(evt) {
            alert('View id: ' + this.id + '\n' + 'Model id: ' + this.model.id);
        }
    });

    var toolsView = new joint.dia.ToolsView({
        tools: [infoButton]
    });

    var elementView = element.findView(paper);
    elementView.addTools(toolsView);

In the next section of the intermediate tutorial, we will learn about link tools.