jointjs
Version:
JavaScript diagramming library
167 lines (126 loc) • 4.72 kB
JavaScript
(function(joint, $) {
var graph = new joint.dia.Graph;
var paper = new joint.dia.Paper({
el: document.getElementById('paper'),
width: 650,
height: 400,
model: graph
});
// Create a custom element.
// ------------------------
joint.dia.Element.define('html.Element', {
attrs: {
placeholder: {
refWidth: '100%',
refHeight: '100%',
stroke: 'gray'
}
}
}, {
markup: [{
tagName: 'rect',
selector: 'placeholder'
}]
});
// Create a custom view for that element that displays an HTML div above it.
// -------------------------------------------------------------------------
joint.shapes.html.ElementView = joint.dia.ElementView.extend({
template: [
'<div class="my-html-element">',
'<label data-attribute="mylabel"></label>',
'<input data-attribute="myinput" type="text"/>',
'</div>'
].join(''),
init: function() {
// Update the box position whenever the underlying model changes.
this.listenTo(this.model, 'change', this.updateBox);
},
onBoxChange: function(evt) {
var input = evt.target;
var attribute = input.dataset.attribute;
if (attribute) {
this.model.set(attribute, input.value);
}
},
onRender: function() {
if (this.$box) this.$box.remove();
var boxMarkup = joint.util.template(this.template)();
var $box = this.$box = $(boxMarkup);
this.$attributes = $box.find('[data-attribute]');
// React on all box changes. e.g. input change
$box.on('change', this.onBoxChange.bind(this));
// Update the box size and position whenever the paper transformation changes.
// Note: there is no paper yet on `init` method.
this.listenTo(this.paper, 'scale translate', this.updateBox);
$box.appendTo(this.paper.el);
this.updateBox();
return this;
},
updateBox: function() {
// Set the position and the size of the box so that it covers the JointJS element
// (taking the paper transformations into account).
var bbox = this.getBBox({ useModelGeometry: true });
var scale = paper.scale();
this.$box.css({
transform: 'scale(' + scale.sx + ',' + scale.sy + ')',
transformOrigin: '0 0',
width: bbox.width / scale.sx,
height: bbox.height / scale.sy,
left: bbox.x,
top: bbox.y
});
this.updateAttributes();
},
updateAttributes: function() {
var model = this.model;
this.$attributes.each(function() {
var value = model.get(this.dataset.attribute);
switch (this.tagName.toUpperCase()) {
case 'LABEL':
this.textContent = value;
break;
case 'INPUT':
this.value = value;
break;
}
});
},
onRemove: function() {
this.$box.remove();
}
});
// Create JointJS elements and add them to the graph as usual.
// -----------------------------------------------------------
var el1 = new joint.shapes.html.Element({
position: { x: 80, y: 80 },
size: { width: 150, height: 80 },
myinput: 'I am an input',
mylabel: 'I am a label'
});
var el2 = new joint.shapes.html.Element({
position: { x: 350, y: 150 },
size: { width: 150, height: 80 },
myinput: 'I am HTML input',
mylabel: 'I am HTML label'
});
var l = new joint.shapes.standard.Link({
source: { id: el1.id },
target: { id: el2.id }
});
graph.addCells([el1, el2, l]);
// Zooming
// ------------
var zoomLevel = 1;
$('#zoom-in').on('click', function() {
zoomLevel = Math.min(3, zoomLevel + 0.2);
var size = paper.getComputedSize();
paper.translate(0,0);
paper.scale(zoomLevel, zoomLevel, size.width / 2, size.height / 2);
});
$('#zoom-out').on('click', function() {
zoomLevel = Math.max(0.2, zoomLevel - 0.2);
var size = paper.getComputedSize();
paper.translate(0,0);
paper.scale(zoomLevel, zoomLevel, size.width / 2, size.height / 2);
});
})(joint, $);