Disclaimer - The following tutorial was created with a past version of JointJS. The tutorial is still provided for those who may face a similar problem, but it may no longer show the best practices of JointJS. You may encounter the following issues:
JointJS provides a facility to create hierarchy in your diagrams. The API is simple and
contains three methods and two properties dealing with parent-child relationships between elements.
The methods are embed(),
The properties are
parent (Please refer to the Nesting
of the joint.dia.Element model reference).
This tutorial shows how to take advantage of these methods in order to implement three functionalities common to parent-child relationships: child movement restriction to the parent area, expanding parent area to cover its children and reparenting.
The goal is to restrict the movement of an element embedded in a parent in order disallow the user to drag the element outside the parent element area.
The trick here is to detect when the child element bounding box gets outside the bounding box of the parent and revert the child position if that happens.
Try to move the child element outside the parent element area.
This section shows how to make the parent element automatically resizable so that it coveres its children.
Again, we'll react on the
change:position event on the graph but this time we resize the parent
element based on the position and size of its children. We also store the original position and size of the
parent element so that we can shrink the parent element back if the child element we manipulate
fits into the original parent element area.
Try to move the child element outside the parent element area and see how the parent element automatically expands/shirnks.
Another useful technique when dealing with parent-child relationships is being able to drop an element above another element and let the element below become a new parent of the dropped element. This way we alow the user to change the parentage via the UI.
First, we register a handler for the
cell:pointerdown event on the paper that is triggered
whenever a mousedown (touchstart) above a cell is emitted. This is where the dragging begins. In this
we unembed the dragged element if it was a child of a parent. Note that we also show the dragged element
above all the other cells (
toFront()) so that we always see it in the front while dragging.
Second, we register a handler for the
cell:pointerup event which is triggered when we
drop the dragged element. In this handler, we find all the cells that are below the center of the
dragged element. In this example, we pick the first one that is not the dragged element itself
and make it a new parent of the dragged element. If you have more than one level of hierarchy in
your application, you might want to find an element the most in the front (by looking at the
property) instead. We left this out of this example for simplicity.
Try to move the El B over El A, then move the El A. You should see the El B moves as well as it became a child of El A.