Skip to main content
Version: 4.1

JavaScript

With build process​

The standard way to use JointJS is by importing the @joint/core or @joint/plus package as a dependency with a package manager of your choice. Follow the steps in our Quickstart installation guide to get started.

You can access JointJS features by importing them from the respective package, like this:

import { dia, shapes } from '@joint/core';

Without build process​

JointJS can be used without any build process. It is as simple as including the UMD version of JointJS in your HTML with a <script> tag, which enables you to use JointJS functionality on your website.

Include the UMD distribution of JointJS into your HTML. Most commonly, this means loading it from a CDN such as jsDelivr or UNPKG:

index.html
<html>
<head>
<meta charset="utf8"/>
<title>JointJS UMD Installation example</title>
<!--<link rel="stylesheet" type="text/css" href="styles.css" />-->
</head>
<body>
<div id="paper"></div>
<script src="https://cdn.jsdelivr.net/npm/@joint/core/dist/joint.js"></script>
<script src="index.js"></script>
</body>
</html>
Alternatively, you may download the file manually and place it into the same folder as your HTML
index.html
<html>
<head>
<meta charset="utf8"/>
<title>JointJS UMD Installation example</title>
<!--<link rel="stylesheet" type="text/css" href="styles.css" />-->
</head>
<body>
<div id="paper"></div>
<script src="joint.js"></script>
<script src="index.js"></script>
</body>
</html>

Loading the joint.js file before your own code (index.js in the above example), exposes three global variables with JointJS functionality:

Instead of relying on import statements, you access JointJS objects via these global variables. For example:

  • const namespace = joint.shapes; instead of import { shapes } from '@joint/core'; const namespace = shapes;
  • const graph = new joint.dia.Graph(/*...*/); instead of import { dia } from '@joint/core'; const graph = new dia.Graph(/*...*/);

Let's illustrate this by modifying the final JointJS Quickstart demo accordingly. Note the use of joint. everywhere:

index.js
// create paper
const namespace = joint.shapes;

const graph = new joint.dia.Graph({}, { cellNamespace: namespace });

const paper = new joint.dia.Paper({
el: document.getElementById('paper'),
model: graph,
width: 300,
height: 300,
background: { color: '#F5F5F5' },
cellViewNamespace: namespace
});

// create elements
const rect1 = new joint.shapes.standard.Rectangle();
rect1.position(25, 25);
rect1.resize(180, 50);
rect1.addTo(graph);

const rect2 = new joint.shapes.standard.Rectangle();
rect2.position(95, 225);
rect2.resize(180, 50);
rect2.addTo(graph);

rect1.attr('body', { stroke: '#C94A46', rx: 2, ry: 2 });
rect2.attr('body', { stroke: '#C94A46', rx: 2, ry: 2 });

rect1.attr('label', { text: 'Hello', fill: '#353535' });
rect2.attr('label', { text: 'World!', fill: '#353535' });

// create link
const link = new joint.shapes.standard.Link();
link.source(rect1);
link.target(rect2);
link.addTo(graph);

link.appendLabel({
attrs: {
text: {
text: 'to the'
}
}
});
link.router('orthogonal');
link.connector('straight', { cornerType: 'line' });

Frequently asked questions​

Can I use JointJS without a build process (as a UMD package)?​

Yes, but there are a few differences from the usual installation process.

Learn more...

Include the UMD distribution of JointJS into your HTML. Most commonly, this means loading it from a CDN such as jsDelivr or UNPKG:

index.html
<html>
<head>
<meta charset="utf8"/>
<title>JointJS UMD Installation example</title>
<!--<link rel="stylesheet" type="text/css" href="styles.css" />-->
</head>
<body>
<div id="paper"></div>
<script src="https://cdn.jsdelivr.net/npm/@joint/core/dist/joint.js"></script>
<script src="index.js"></script>
</body>
</html>
Alternatively, you may download the file manually and place it into the same folder as your HTML
index.html
<html>
<head>
<meta charset="utf8"/>
<title>JointJS UMD Installation example</title>
<!--<link rel="stylesheet" type="text/css" href="styles.css" />-->
</head>
<body>
<div id="paper"></div>
<script src="joint.js"></script>
<script src="index.js"></script>
</body>
</html>

Loading the joint.js file before your own code (index.js in the above example), exposes three global variables with JointJS functionality:

Instead of relying on import statements, you access JointJS objects via these global variables. For example:

  • const namespace = joint.shapes; instead of import { shapes } from '@joint/core'; const namespace = shapes;
  • const graph = new joint.dia.Graph(/*...*/); instead of import { dia } from '@joint/core'; const graph = new dia.Graph(/*...*/);

Let's illustrate this by modifying the final JointJS Quickstart demo accordingly. Note the use of joint. everywhere:

index.js
// create paper
const namespace = joint.shapes;

const graph = new joint.dia.Graph({}, { cellNamespace: namespace });

const paper = new joint.dia.Paper({
el: document.getElementById('paper'),
model: graph,
width: 300,
height: 300,
background: { color: '#F5F5F5' },
cellViewNamespace: namespace
});

// create elements
const rect1 = new joint.shapes.standard.Rectangle();
rect1.position(25, 25);
rect1.resize(180, 50);
rect1.addTo(graph);

const rect2 = new joint.shapes.standard.Rectangle();
rect2.position(95, 225);
rect2.resize(180, 50);
rect2.addTo(graph);

rect1.attr('body', { stroke: '#C94A46', rx: 2, ry: 2 });
rect2.attr('body', { stroke: '#C94A46', rx: 2, ry: 2 });

rect1.attr('label', { text: 'Hello', fill: '#353535' });
rect2.attr('label', { text: 'World!', fill: '#353535' });

// create link
const link = new joint.shapes.standard.Link();
link.source(rect1);
link.target(rect2);
link.addTo(graph);

link.appendLabel({
attrs: {
text: {
text: 'to the'
}
}
});
link.router('orthogonal');
link.connector('straight', { cornerType: 'line' });
Can I use JointJS+ without a build process (as a UMD package)?​

Yes, but there are a few differences from the usual installation process.

Learn more...

Place the UMD distribution of JointJS+, plus its CSS definition, into the same folder as your HTML:

  1. Navigate to the build/package folder inside the unzipped JointJS+ archive.
  2. Copy the joint-plus.js file and paste it into the same folder as your HTML.
  3. Copy the joint-plus.css file and paste it into the same folder as your HTML.

Include joint-plus.js and joint-plus.css in your HTML:

index.html
<html>
<head>
<meta charset="utf8"/>
<title>JointJS+ UMD Installation example</title>
<link rel="stylesheet" type="text/css" href="joint-plus.css" />
<!--<link rel="stylesheet" type="text/css" href="styles.css" />-->
</head>
<body>
<div id="paper"></div>
<script src="joint-plus.js"></script>
<script src="index.js"></script>
</body>
</html>

Loading the joint-plus.js file before your own code (index.js in the above example), exposes three global variables with JointJS functionality:

  • joint (all JointJS+ functionality and most JointJS functionality)
  • g (Geometry)
  • V (Vectorizer)

Instead of relying on import statements, you access JointJS objects via these global variables. For example:

  • const namespace = joint.shapes;
    • instead of import { shapes } from '@joint/plus'; const namespace = shapes;
  • const graph = new joint.dia.Graph(/*...*/);
    • instead of import { dia } from '@joint/plus'; const graph = new dia.Graph(/*...*/);
  • const paperScroller = new joint.ui.PaperScroller(/*...*/);
    • instead of import { ui } from '@joint/plus'; const paperScroller = new ui.PaperScroller(/*...*/);

Let's illustrate this by modifying the final JointJS+ Quickstart demo accordingly. Note the use of joint. everywhere:

index.js
// create paper scroller
const namespace = joint.shapes;

const graph = new joint.dia.Graph({}, { cellNamespace: namespace })

const paper = new joint.dia.Paper({
model: graph,
width: 2000,
height: 2000,
background: { color: '#F5F5F5' },
cellViewNamespace: namespace,
defaultRouter: { name: 'orthogonal' },
defaultConnector: { name: 'straight', args: { cornerType: 'line' }}
});

const paperScroller = new joint.ui.PaperScroller({
paper: paper,
scrollWhileDragging: true
});
document.getElementById('paper').appendChild(paperScroller.render().el);

// implement pinch interaction
paper.on('paper:pinch', (_evt, ox, oy, scale) => {
const zoom = paperScroller.zoom();
paperScroller.zoom(zoom * scale, { min: 0.2, max: 5, ox, oy, absolute: true });
});

// create elements
const rect1 = new joint.shapes.standard.Rectangle();
rect1.position(875, 885);
rect1.resize(180, 50);
rect1.addTo(graph);

const rect2 = new joint.shapes.standard.Rectangle();
rect2.position(945, 1065);
rect2.resize(180, 50);
rect2.addTo(graph);

rect1.attr('body', { stroke: '#C94A46', rx: 2, ry: 2 });
rect2.attr('body', { stroke: '#C94A46', rx: 2, ry: 2 });

rect1.attr('label', { text: 'Hello', fill: '#353535' });
rect2.attr('label', { text: 'World!', fill: '#353535' });

// create link
const link = new joint.shapes.standard.Link();
link.source(rect1);
link.target(rect2);
link.addTo(graph);

link.appendLabel({
attrs: {
text: {
text: 'to the'
}
}
});
link.router('orthogonal');
link.connector('straight', { cornerType: 'line' });

// center content
paperScroller.centerContent();

// create stencil
const stencil = new joint.ui.Stencil({
paper: paper,
width: 170,
height: '100%',
layout: true,
dropAnimation: true
});
stencil.render();
document.getElementById('stencil').appendChild(stencil.el);

const elements = [
{
type: 'standard.Rectangle',
size: { width: 70, height: 50 },
attrs: {
body: {
stroke: '#C94A46',
rx: 2,
ry: 2
}
}
},
{
type: 'standard.Ellipse',
size: { width: 70, height: 50 },
attrs: {
body: {
stroke: '#C94A46',
}
}
},
{
type: 'standard.Polygon',
size: { width: 70, height: 50 },
attrs: {
body: {
stroke: '#C94A46',
points: 'calc(w/2),0 calc(w),calc(h/2) calc(w/2),calc(h) 0,calc(h/2)'
}
}
},
{
type: 'standard.Cylinder',
size: { width: 70, height: 50 },
attrs: {
body: {
stroke: '#C94A46',
},
top: {
fill: '#C94A46',
stroke: '#C94A46'
}
}
}
];
stencil.load(elements);

// create halo
function openHalo(cellView) {
new joint.ui.Halo({ cellView: cellView }).render();
}

paper.on('cell:pointerup', (cellView) => {
openHalo(cellView);
});

// open halo for first element by default
openHalo(paper.findViewByModel(rect1));

// create toolbar
const toolbar = new joint.ui.Toolbar({
tools: [
{
type: 'button',
name: 'json',
text: 'Export JSON'
},
{
type: 'button',
name: 'svg',
text: 'Export SVG'
},
'separator',
'zoomToFit',
'zoomSlider'
],
references: {
paperScroller: paperScroller
}
});
toolbar.render();
document.getElementById('toolbar').appendChild(toolbar.el);

toolbar.on('json:pointerclick', () => {
const str = JSON.stringify(graph.toJSON());
const bytes = new TextEncoder().encode(str);
const blob = new Blob([bytes], { type: 'application/json;charset=utf-8' });
joint.util.downloadBlob(blob, 'joint-plus.json');
});

toolbar.on('svg:pointerclick', () => {
joint.format.toSVG(
paper,
(svg) => {
joint.util.downloadDataUri(
`data:image/svg+xml,${encodeURIComponent(svg)}`,
'joint-plus.svg'
);
},
{ useComputedStyles: false }
);
});

// create inspector
function openInspector(cell) {
closeInspector(); // close inspector if currently open

joint.ui.Inspector.create('#inspector', {
cell: cell,
inputs: getInspectorConfig(cell)
});
}

function closeInspector() {
joint.ui.Inspector.close();
}

function getInspectorConfig(cell) {
if (cell.isElement()) {
return {
attrs: {
label: {
text: {
type: 'content-editable',
label: 'Label'
}
}
}
};

} else { // cell.isLink()
return {
labels: {
type: 'list',
label: 'Labels',
item: {
type: 'object',
properties: {
attrs: {
text: {
text: {
type: 'content-editable',
label: 'Text',
defaultValue: 'label'
}
},
},
position: {
type: 'select-box',
options: [
{ value: 30, content: 'Source' },
{ value: 0.5, content: 'Middle' },
{ value: -30, content: 'Target' }
],
defaultValue: 0.5,
label: 'Position'
}
}
}
}
};
}
}

paper.on('cell:pointerdown', function (cellView) {
openInspector(cellView.model);
});

stencil.on('element:drop', function (elementView) {
openInspector(elementView.model);
});

paper.on('blank:pointerdown', () => {
closeInspector(); // close inspector if currently open
});

// open inspector for first element by default
openInspector(rect1);

Stay in the know

Be where thousands of diagramming enthusiasts meet

Star us on GitHub