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.
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, 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 the parameters of groups which are some kind of containers in the stencil, useful to organize cells with a similar type or usage. Then we have to add the stencil to DOM. We append 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 inputs object for 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 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 svg of 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 type range and we 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 of the function, we create an inspector instance using the configuration that we defined before as a second argument. The first argument of Inspector constructor is the ID to a DOM element where the Inspector should be rendered.
As a result, we’ve got UI for manipulating cell styles and description 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 and one more is provided with JointJS.
- 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), but in the end, it saves plenty of development time. I hope that this small tutorial gave you some insight into working with Rappid.