Skip to main content

Frequently asked questions

Advanced installation scenarios

Can I install JointJS as a UMD package?

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

Learn more...

Place the UMD distribution of JointJS into the root of your package.

One way to do that is via NPM
  1. Install the JointJS open-source package (@joint/core) using NPM:

    npm add @joint/core
  2. Navigate to the newly created node_modules folder.

  3. Copy the @joint/core/dist/joint.js file and paste it into the root of your package.

Include joint.js in your HTML:

index.html
<!--<div id="paper"></div>-->
<script src="joint.js"></script>
<!--<script src="joint.js"></script>-->

Access JointJS features through the joint namespace. Let's use a modified version of the final JointJS Quickstart demo as an example:

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 install JointJS+ 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 root of your package:

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

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>

Access JointJS+ features through the joint namespace. Let's use a modified version of the final JointJS+ Quickstart demo as an example:

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);
Can I install JointJS+ using an NPM registry?

Currently, there is no plan to publish JointJS+ to NPM, but you can host your own private NPM registry and serve JointJS+ from there.

Troubleshooting

Why can't I see any JointJS content when I open a JointJS application?

An error may have been encountered while loading JointJS - see below.

Why do I only see a blank page when I open a JointJS application?

An error may have been encountered while loading your application. This problem can have several causes.

Resolution steps...
  • Look into your browser's console for any error messages.

    How can I open my browser's console?
    • Google Chrome: View > Developer > JavaScript Console
    • Safari: Develop > Show JavaScript Console
    • Edge: Tools > Developer > JavaScript Console
    • Firefox: Tools > Browser Tools > Web Developer Tools > Console
  • See below on this page if you can find a matching error message and follow its resolution steps.

  • If you cannot resolve the issue on your own, reach out to us on one of our support channels.

Uncaught ReferenceError: joint is not defined

If you are using JointJS locally (e.g. you have downloaded it from GitHub), then this error may happen when you try to open a JointJS demo without first having followed the steps to set up JointJS.

Resolution steps...
  • Follow the directions in JointJS's README.md file (i.e. run yarn install and yarn run dist in the root folder of your local JointJS project).

  • Come back to the demo and try running it again.

info

Some demos have their own README.md files which specify additional setup steps. If you try opening such a demo without first having followed these additional steps, you will encounter another kind of error - see below.

Failed to load resource: net::ERR_FILE_NOT_FOUND for bundle.js

This is the Chrome / Edge version of the missing file error for bundle.js - see below.

Loading failed for the script with source for bundle.js

This is the Safari version of the missing file error for bundle.js - see below.

Not allowed to load local resource for bundle.js

This is the Firefox version of the missing file error for bundle.js - see below.

Why is a JointJS demo complaining about missing bundle.js file?

This error may happen when you try to open a JointJS / JointJS+ demo's index.html file without first having followed the demo's additional setup steps.

Resolution steps...
info

These steps assume that you have followed the steps to set up JointJS - see above.

  • Follow the directions in the demo's README.md file (usually, run npm install and npm start in the demo's folder).

  • Try opening the demo in your browser again.

Uncaught TypeError: Cannot read properties of undefined (reading 'Parser')

This error may happen when you try to open the JointJS+ apps/Visio/DefaultImport demo's index.html file without first having followed the demo's additional setup steps - see below.

Uncaught TypeError: Cannot read properties of undefined (reading 'fromURL')

This error may happen when you try to open the JointJS+ apps/Visio/DefaultImport demo's index.html file directly without first having followed the demo's additional setup steps.

Resolution steps...
  • Follow the directions in the demo's README.md file (i.e. run npm install and npm start in the demo's folder).

  • Try opening the demo in your browser again.

Stay in the know

Be where thousands of diagramming enthusiasts meet

Star us on GitHub