Halo
Halo
creates a control panel above an element with various tools.
Learn more about the Halo plugin.
constructorβ
constructor(opt?: Halo.Options);
The Halo
constructor accepts several parameters:
bboxβ
bbox: dia.BBox | ((cellView: dia.CellView) => dia.BBox);
[optional] A bounding box within which the halo view will be rendered. It expects an area in paper coordinates.
new ui.Halo({
/* ... */
bbox: ({ model, paper }) => paper.localToPaperRect(model.getBBox().inflate(20))
});
boxContentβ
[optional] A string (text or HTML), or a function (of the form boxContent(cellView, boxDOMElement)
) that returns a
HTML string with the content that will be used in the information box below an element. By default, the box displays the
x, y coordinates, and width and height dimensions of the element. If boxContent
is set to false
(or an empty string),
the information box will be hidden
cellViewβ
[required] An element or link view. Previously, Halo
accepted also paper
and graph
options, but this is now
deprecated as those can always be inferred from cellView.paper
and cellView.paper.model
properties.
clearAllβ
[optional] If set to true
(the default value), clear all the existing halos from the page when a new halo is created.
This is the most common behavior as it is assumed that there is only one halo visible on the page at a time. However,
some applications might need to have more than one halo visible. In this case, set clearAll
to false
(and make sure
to call remove()
once you don't need a halo anymore)
clearOnBlankPointerdownβ
[optional] If set to true
(the default value), clear the halo when a user clicks the blank area of the paper.
cloneβ
(deprecated) in favor of the makeElement() callback. If makeElement()
is set, the clone
callback
is not called.
[optional] A function with signature function(cell, opt)
. This function will be called when cloning or forking actions
take place, and it should return a clone of the original cell. This is useful e.g. if you want the clone to be moved by
an offset after the user clicks the clone handle. The default function is:
function(cell, opt) { return cell.clone().unset('z') }
.
The callback may return an array of cells. This is useful if the element has nested cells that also need to be cloned. In this case, the user drags the first cell in the array.
new ui.Halo({
/* ... */
clone: (cell) => {
return cell.clone({ deep: true });
// const [cellClone, ...embedsClones] = cell.clone({ deep: true });
// return [cellClone, ...embedsClones];
}
});
groupsβ
groups: { [groupName: string]: Halo.HandleGroup }
[optional] An object for defining groups of handles. Handles are assigned to groups by their position
property.
The groups
option is only valid for the 'overlay'
type of Halo
.
Each group is an object with any of the following properties:
Property | Description |
---|---|
top | The CSS top property of the group. |
left | The CSS left property of the group. |
horizontalAlign | The horizontal alignment of the group. Possible values are 'left' , 'middle' , and 'right' . |
verticalAlign | The vertical alignment of the group. Possible values are 'top' , 'middle' , and 'bottom' . |
trackDirection | The direction of the group. Possible values are 'row' and 'column' . |
trackCount | The number of handles in the group. |
gap | The gap between handles in the group. |
className | The CSS class name of the group. |
It's also possible to change any of the default groups (e.g. n
, ne
, e
, etc.) by defining a group with the same name.
handlesβ
handles: Array<Halo.Handle>
[optional] An array of handles to be displayed in the halo.
The default handles are:
remove
,resize
,rotate
,fork
,clone
,link
,unlink
,rotate
for elementsremove
,direction
for links
Each handle is an object with the following properties:
Property | Description |
---|---|
name | [required] A unique name of the handle. The name is also set as a CSS class to the handle DOM element making it easy to select it in your CSS stylesheet. |
position | The position of the handle. Possible values are 'n' , 'nw' , 'w' , 'sw' , 's' , 'se' , 'e' , and 'ne' .Only the overlay type allows you to use custom positions defined in groups. |
events | An object with event handlers. |
attrs | An object with attributes to be set on the handle. e.g.{ '.handle': { 'style': 'border: 1px solid red;' }} |
icon | The URL of the icon used to render the handle. The icon is set as a background image on the tool handle DOM element. |
content | The content of the handle. e.g. '<b>Click here</b>' |
className | The CSS class name of the handle. |
hideOnDrag | If set to true , the halo will be hidden while the user is dragging the handle. |
data | Custom data that can be used in event handlers, and makeElement and makeLink callbacks. |
loopLinkPreferredSideβ
[optional] The preferred side for a self-loop link created from Halo
("top"|"bottom"|"left"|"right"
), the default
is "top"
.
loopLinkWidthβ
[optional] The self-loop link width in pixels, the default is 40
.
magnetβ
[optional] A function accepting an elementView returning an SVGElement used as a magnet for links created via linking or forking handles.
new joint.dia.Halo({
cellView: elementView,
magnet: (elementView, end, evt) => {
// where `end` is either "source" (linking and forking) or "target" (forking only)
// and `evt` is a `mousedown` event
// connect the link directly to a rectangle element as opposed to the element group
return elementView.el.querySelector('rect') || elementView.el;
}
})
makeElementβ
makeElement: (context: MakeElementContext, evt: dia.Event, halo: Halo) => dia.Element;
A function that creates a new element when the user clicks on the handle that extends the default clone
or fork
action.
The context
object has the following properties:
Property | Description |
---|---|
action | The action (the name of the handle) that triggered the creation of the new element. |
defaultAction | The default action name. Either clone or fork . |
elementView | The view of the element that the halo is attached to. |
data | The data object passed in the handle definition. |
validation | Since the makeElement() callback also runs in order to resolve the handle visibility, the validation property is set to true when the callback is called for validation purposes. |
makeLinkβ
makeLink: (context: MakeLinkContext, evt: dia.Event, halo: Halo) => dia.Link;
A function that creates a new link when the user clicks on the handle that extends the default link
or fork
action.
If no makeLink
callback is provided, the defaultLink() method is used to create the link.
The context
object has the following properties:
Property | Description |
---|---|
action | The action (the name of the handle) that triggered the creation of the new link. |
defaultAction | The default action name. Either link or fork . |
source | The source end of the link. e.g. { id: 'source-element-id' } .It will be set as link's source attribute and can be modified in the callback. |
sourceMagnet | The source magnet. e.g. <rect/> |
sourceView | The view of the source element (dia.ElementView ). |
target | The target end of the link. e.g. { x: 120, y: 240 } .It will be set as link's target attribute and can be modified in the callback. |
The following properties are only available when the action
is fork
:
Property | Description |
---|---|
targetMagnet | The target magnet. e.g <rect/> |
targetView | The view of the target element (dia.CellView ). |
pieIconSizeβ
[optional] (only valid for the 'pie'
type of Halo
) The size in pixels of the icon in the pie menu. It defaults
to 14
.
pieSliceAngleβ
[optional] (only valid for the 'pie'
type of Halo
) The angle of one slice in the pie menu. It defaults to 45
.
pieStartAngleOffsetβ
[optional] (only valid for the 'pie'
type of Halo
) The angular offset of the first handle in the pie menu.
It defaults to 0
.
pieTogglesβ
[optional] (only valid for the 'pie'
type of Halo
) An array of pie toggle buttons. Usually, there's only one
(the default), but you can have as many as you want. The default value is [{ name: 'default', position: 'e' }]
. Each
item in the array is an object of the form { name: [name of you toggle], position: [one of e/w/s/n] }
. The name is
passed in the options object in the state:close
and state:open
events triggered by the Halo
when the pie toggle
is clicked.
rotateAngleGridβ
[optional] The angle increments the rotate action snaps to, the default is 15
.
rotateEmbedsβ
[optional] Should the elements embedded inside the cellView element be rotated as well? The default is false
.
smallThresholdβ
[optional] If the set number value is higher than the halo bbox
width and height, a 'small' CSS class is applied to
the halo. This reduces the size of the halo. A 'small' class will not be applied, if a 'tiny' class is already present.
For elements, the default value is 80
. For links, the default halo bbox
width and height both equal 1
. This means
a value of 2
or higher is needed to apply the class.
tinyThresholdβ
[optional] If the set number value is higher than the halo bbox
width and height, a 'tiny' CSS class is applied to
the halo. This reduces the size of the halo. For elements, the default value is 40
. For links, the default halo bbox
width and height both equal 1
. This means a value of 2
or higher is needed to apply the class.
typeβ
[optional] The type of the halo control panel. There are four types of halo control panels:
- The
'overlay'
type allows the user to define the position of the halo handles. The default positions are spread around the cell. - The
'pie'
type displays the halo as a pie menu. - (deprecated) The
'toolbar'
type displays the halo tools the element in a small toolbar. - (deprecated) The
'surrounding'
type displays the halo tools around the element.
The default value is 'surrounding'
.
The 'surrounding'
and 'toolbar'
types are effectively deprecated as the 'overlay'
type can express both of them.
useModelGeometryβ
[optional] If set to true
, the model position and dimensions will be used as a basis for the halo tools position.
By default, this is set to false
which causes the halo tools position be based on the bounding box of the element view.
Sometimes though, your shapes can have certain SVG sub elements that "stick out" of the view, and you don't want these
sub elements to affect the halo tools position. In this case, set the useModelGeometry
to true
.
Methodsβ
addHandle()β
halo.addHandle(handle: Halo.Handle): this;
Add a custom tool to the halo. See handles option for more info.
addHandles()β
halo.addHandles(handles: Halo.Handle[]): this;
Add multiple handles in one go. This calls addHandle()
internally for each item of the handles
array.
removeHandle()β
halo.removeHandle(name: string): this;
Remove a tool handle named name
from the halo.
removeHandles()β
halo.removeHandles(): this;
Remove all handles from the halo.
changeHandle()β
halo.changeHandle(name: string, handle: Halo.Handle): this;
Change a tool handle named name
in the halo. The handle
object can contain the same parameters as the addHandle()
method except for the name
property. handle
parameters will be merged with those defined previously.
render()β
halo.render(): this;
Render the halo. This must be called after the halo object is instantiated.
on()β
halo.on(eventName: string, callback: EventHandler, context?: any): this;
Register a handler (callback) for an event. See the Halo
Events section for the list of events the halo
object triggers.
toggleState()β
halo.toggleState(toggleName: string): void;
Toggle (open/close) the sate of the halo (applicable for the pie type of halo). toggleName
is the name
of the pie
toggle as defined in the pieToggles
option. If toggleName
is not passed, all pie menus change state
(the most common usage as there is usually only one pie toggle).
isOpen()β
halo.isOpen(toggleName: string): boolean;
Return true
if the halo is open (applicable for the pie type of halo). toggleName
is the name
of the pie toggle
as defined in the pieToggles
option. If toggleName
is not passed, return true
if any of the pie menus are open.
remove()β
halo.remove(): this;
Remove/destroy the halo. Note that by default, the halo removes itself when the user clicks on a blank area in the paper. In some cases, however, it is useful to remove the halo programmatically.
Static Methodsβ
clear()β
ui.Halo.clear(paper: dia.Paper): void;
Remove all the halo panels (without having to have a reference to a particular halo object) from the paper
. Note that
this is a static function in the ui.Halo
namespace rather than a method of a halo object.
getDefaultHandle()β
ui.Halo.getDefaultHandle(name: Halo.DefaultHandles): Halo.Handle;
Get the default handle configuration by its name. The default handles include: remove
, resize
, rotate
, fork
, clone
, link
, unlink
, rotate
and direction
.
The method throws an exception if the handle with the given name does not exist:
ui.Halo: default handle not found: ${name}
Eventsβ
For the pointerdown
, pointermove
, pointerup
, and contextmenu
events, the data
object defined on the handle is available in the event handler as the
evt.data
property.
halo.on('action:resize:pointerdown', (evt) => {
console.log(evt.data);
});
action:[name]:pointerdownβ
Triggered when the user clicks (touches) on a tool handle named [name]
. The handler is called with the mousedown
event object, and x
and y
of the pointer in local coordinates.
action:[name]:pointermoveβ
Triggered when the user moves with mouse cursor after a tool handle named [name]
was mousedowned (touched). The handler
is called with the mousemove event object, and x
and y
of the pointer in local coordinates.
action:[name]:pointerupβ
Triggered when the user releases their mouse cursor after a tool handle named [name]
was mousedowned (touched). The
handler is called with the mouseup event object, and x
and y
of the pointer in local coordinates.
action:[name]:contextmenuβ
Triggered when the user invokes contextmenu on a tool handle named [name]
. The handler is called with the mousedown
event object, and x
and y
of the pointer in local coordinates.
action:[name]:addβ
Triggered after the user finishes creating a link with the default link tool (or a custom handle that uses the default action). This is useful if you want to do something with the link after it has been created. For example, to prevent the user from creating loose links (links that do not have both source and target set), you can do:
halo.on('action:link:add', (link) => {
if (!link.get('target').id) {
link.remove();
}
});
state:openβ
Triggered when the user opens the halo (applicable for the pie type of Halo). The handler is passed the pie toggle name
as defined in the pieToggles
option.
state:closeβ
Triggered when the user closes the halo (applicable for the pie type of halo). The handler is passed the pie toggle name
as defined in pieToggles
option.
closeβ
Triggered when the halo gets closed.
Typesβ
DefaultHandlesβ
type DefaultHandles =
'remove' | 'resize' | 'rotate' |
'fork' | 'clone' | 'link' |
'unlink' | 'rotate' | 'direction';
EventHandlerβ
type EventHandler = (evt: dia.Event, x: number, y: number) => void;
Handleβ
interface Handle {
name: string;
position?: HandlePosition | string;
events?: HandleEvents;
attrs?: { [CSSSelector: string]: { [attribute: string]: any },
icon?: string;
content?: string | HTMLElement;
className?: string;
hideOnDrag?: boolean;
data?: any;
}
HandleEventsβ
interface HandleEvents {
pointerdown?: string | EventHandler;
pointermove?: string | EventHandler;
pointerup?: string | EventHandler;
contextmenu?: string | EventHandler;
}
HandleGroupβ
interface HandleGroup {
top?: string;
left?: string;
horizontalAlign?: 'left' | 'middle' | 'right';
verticalAlign?: 'top' | 'middle' | 'bottom';
trackDirection?: 'row' | 'column';
trackCount?: number;
gap?: string;
className?: string;
}
HandlePositionβ
enum HandlePosition {
N = 'n', NW = 'nw',
W = 'w', SW = 'sw',
S = 's', SE = 'se',
E = 'e', NE = 'ne'
}
MakeElementContextβ
interface MakeElementContext {
action: string;
defaultAction: string;
validation: boolean;
elementView: dia.ElementView;
data: any;
}
MakeLinkContextβ
interface MakeLinkContext {
action: string;
defaultAction: string;
source: dia.Link.EndJSON;
sourceView: dia.ElementView;
sourceMagnet: SVGElement;
target: dia.Link.EndJSON;
targetView: dia.ElementView | null;
targetMagnet: SVGElement | null;
data: any;
}
Optionsβ
interface Options extends mvc.ViewOptions<undefined> {
cellView: dia.CellView;
loopLinkPreferredSide?: 'top' | 'bottom' | 'left' | 'right';
loopLinkWidth?: number;
rotateAngleGrid?: number;
rotateEmbeds?: boolean;
boxContent?: boolean | mvc.$HTMLElement | ((cellView: dia.CellView, boxElement: HTMLElement) => mvc.$HTMLElement);
handles?: Array<Handle>;
groups?: { [groupName: string]: HandleGroup };
clearAll?: boolean;
clearOnBlankPointerdown?: boolean;
useModelGeometry?: boolean;
type?: 'overlay' | 'pie' | 'toolbar' | 'surrounding';
pieSliceAngle?: number;
pieStartAngleOffset?: number;
pieIconSize?: number;
pieToggles?: Array<{ name: string, position: HandlePosition }>;
bbox?: dia.Point | dia.BBox | ((cellView: dia.CellView) => dia.Point | dia.BBox);
tinyThreshold?: number;
smallThreshold?: number;
magnet?: (elementView: dia.ElementView, end: 'source' | 'target', evt: dia.Event) => SVGElement;
// Deprecated
clone?: (cell: dia.Cell, opt: { [key: string]: any }) => dia.Cell | Array<dia.Cell>;
}