If you are using JointJS and you need a user interface for building diagrams, Rappid is the answer to your needs. It provides almost every feature that you would need, like a tooltip, toolbar, select box, halo (UI for creating links and cell manipulation), some algorithms for layout and pathfinding, etc. They make all JointJS-based applications more usable and easy to implement. Check out the complete list of features that Rappid provides.
In this article, we will go through the implementation of Stencil, Inspector, and layout algorithms usage.
Rappid features
Let’s assume that we are building an app using JointJS. The functionality that we need is the ability to add cells to canvas where every cell has its own properties, some auto-positioning of the graph would be also nice.
Here is an example screen from a Rappid demo of implemented stencil and inspector. There are also some other Rappid components in the picture, but they are not our main focus in this article.
ui.Stencil – one container to keep it simple
If we wanted to build a JointJS app without Rappid, we would need to implement a sidebar with all the cells, handle onclick events, and implement drag’n’drops. These are just a few examples of the quite time-consuming things that would have to be done if it weren’t for Rappid. But when we do use Rappid, all we need is ui.Stencil and a few lines of code to bring it alive.
In the code above, we create a new instance of Stencil. We pass the object with parameters to the constructor. We set the width, height, and parameters of groups, which are some kind of containers in the stencil that are useful to organize cells with a similar type or usage. Then, we have to add the stencil to the DOM. We append the stencil element to the element with id=’stencil-holder’, which we have previously specified in HTML. Then we load cells to stencil, stencil.load() takes the object which contains arrays that specify groups as an argument, we add two cells (we create clones from instances of cells that we should initialize before – see our earlier blog post about JointJS) to the group ‘cells’. After that, we should have a stencil instance which contains one group with two cells in #stencil-holder element, and it should give us a possibility to drag’n’drop cells to paper.
ui.Inspector – give sense to your cells
Inspector is a tool to manage properties of cells. Usually, we build diagrams to present some idea in a simple visual form, therefore every cell that we use entails some kind of information, whether it is the appearance of the cell or maybe some details like description. Users can specify this kind of information using Inspector.
Let’s try to create one.
First things first. Let’s specify what we want to place in our inspector.
First, we specify the input object for the Inspector. There is a description input which we define as a text area, it belongs to information group, has a label ‘Description’ and should be placed first in its group (index parameter). Then, we define the attrs object, which is a style object that is present in every cell, so if we change anything using inspector (from the user side) that is inside attrs, it will affect the visual aspects of the cell. Inside of attrs, we define text input, which refers to the text element inside the svg of the cell. Then, we define a text parameter of a text element (which will affect text value) as a text area, like in the description field. We would like the user to be able to change the font size of the text element, so we define the font size field with the type range and configure it inside. Ok, so we have our inputs defined; now it is time to define groups just like we did in the stencil. Then, we need to bind inspector to an event, it would be nice if inspector opens when the user clicks on a particular element, so we define a new action on event ‘element:pointerdown’. This action is a function that will take the cellView element as an argument. CellView is an object that defines the cell. Inside the function, we create an inspector instance using the configuration that we defined before as a second argument. The first argument of the Inspector constructor is the ID to a DOM element where the Inspector should be rendered.
As a result, we’ve got a UI for manipulating cell styles and descriptions rendered inside the #inspector element. The user can now change the text inside the cell, change the font size, and edit the cell description.
joint.layout – algorithms for layout ready to use
There are three layout algorithms that Rappid provides:
- ForceDirected – good approach to big, undirected graphs. The algorithm is basing layout on three forces, you can read about it in the Wikipedia article.
- GridLayout – usable when we want our graph to be shaped in the form of columns and rows.
- TreeLayout – for tree-like graphs, this kind of layout is useful when we are modeling an org chart, a mind map, or any kind of other graphs with a tree structure
Let’s try to implement the TreeLayout. We need to have an instance of a graph object first. Then, we basically define gaps between cells, the direction (‘T’ stands for top to bottom direction, there is also ‘B’ – bottom to top, ‘L’ – left to right and ‘R’ – right to left, you can also check diagonal possibilities in the documentation) of layout, and cell margins. Then, we just call the layout() method on the TreeLayout instance.
Sometimes, making optimal layout requires some experiments. Take some time to try different setups. I personally enjoy playing with Layout parameters to check if it can work better.
Working with Rappid is pretty fun, it gives you a lot of space for customization. Sometimes it requires some kind of backdoor solutions (I strongly recommend walking through the demo code on JointJS+ page), but in the end, it saves plenty of development time. I hope that this small tutorial gave you some insight into working with Rappid.