JointJS - Resize element based on the text inside
Resize JointJS HTML Element based on the text inside an input
HTML
<script src="http://jointjs.com/js/joint.js"></script>
<link rel="stylesheet" href="http://jointjs.com/css/joint.css">
<!-- JointJS Fiddle -->
<div id="paper"></div>
CSS
#paper {
position: relative;
border: 1px solid gray;
display: inline-block;
background: transparent;
overflow: hidden;
}
#paper svg {
background: transparent;
}
#paper svg .link {
z-index: 2;
}
.html-element {
position: absolute;
background: #3498DB;
/* Make sure events are propagated to the JointJS element so, e.g. dragging works.*/
pointer-events: none;
-webkit-user-select: none;
border-radius: 4px;
border: 2px solid #2980B9;
box-shadow: inset 0 0 5px black, 2px 2px 1px gray;
padding: 5px;
box-sizing: border-box;
z-index: 2;
}
.html-element select,
.html-element input,
.html-element button {
/* Enable interacting with inputs only. */
pointer-events: auto;
}
.html-element button.delete {
color: white;
border: none;
background-color: #C0392B;
border-radius: 20px;
width: 15px;
height: 15px;
line-height: 15px;
text-align: middle;
position: absolute;
top: -15px;
left: -15px;
padding: 0;
margin: 0;
font-weight: bold;
cursor: pointer;
}
.html-element button.delete:hover {
width: 20px;
height: 20px;
line-height: 20px;
}
.html-element select {
position: absolute;
right: 2px;
bottom: 28px;
}
.html-element input {
position: absolute;
bottom: 0;
left: 0;
right: 0;
border: none;
color: #333;
padding: 5px;
height: 16px;
}
.html-element label {
color: #333;
text-shadow: 1px 0 0 lightgray;
font-weight: bold;
}
.html-element span {
position: absolute;
top: 2px;
right: 9px;
color: white;
font-size: 10px;
}
JavaScript
var graph = new joint.dia.Graph;
var paper = new joint.dia.Paper({ el: $('#paper'), width: 650, height: 400, gridSize: 1, model: graph });
// Create a custom element.
// ------------------------
joint.shapes.html = {};
joint.shapes.html.Element = joint.shapes.basic.Rect.extend({
defaults: joint.util.deepSupplement({
type: 'html.Element',
attrs: {
rect: { stroke: 'none', 'fill-opacity': 0 }
}
}, joint.shapes.basic.Rect.prototype.defaults)
});
// 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="html-element">',
'<label></label>',
'<input type="text" value="I\'m HTML input" />',
'</div>'
].join(''),
initialize: function() {
_.bindAll(this, 'updateBox', 'onTextInput');
joint.dia.ElementView.prototype.initialize.apply(this, arguments);
this.$box = $(_.template(this.template)());
this.$input = this.$box.find('input').on('input', this.onTextInput);
this.model.on('change', this.updateBox, this);
this.model.on('remove', this.removeBox, this);
this.updateBox();
},
onTextInput: function(evt) {
var $input = $(evt.target);
$input.attr('size', Math.max($input.val().length, 10));
this.model.resize($input.outerWidth() + 5, $input.outerHeight() + 40);
this.model.set('input', $input.val());
},
render: function() {
joint.dia.ElementView.prototype.render.apply(this, arguments);
this.paper.$el.prepend(this.$box);
this.$input.trigger('input');
return this;
},
updateBox: function() {
// Set the position and dimension of the box so that it covers the JointJS element.
var bbox = this.model.getBBox();
// Example of updating the HTML...