UNPKG

jointjs

Version:

JavaScript diagramming library

222 lines (205 loc) 7.37 kB
(function(joint, util, V) { var Element = joint.dia.Element; var ElementView = joint.dia.ElementView; Element.define('html.Element', { size: { width: 250, height: 228 }, fields: { header: 'Task', name: '', resource: '', state: '' }, attrs: { placeholder: { refWidth: '100%', refHeight: '100%', fill: 'transparent', stroke: '#D4D4D4' } } }, { markup: [{ tagName: 'rect', selector: 'placeholder' }], htmlMarkup: [{ tagName: 'div', className: 'html-element', selector: 'htmlRoot', groupSelector: 'field', style: { 'position': 'absolute', 'pointer-events': 'auto', 'user-select': 'none', 'box-sizing': 'border-box' }, attributes: { 'data-attribute': 'state' }, children: [{ tagName: 'label', className: 'html-element-header', groupSelector: 'field', attributes: { 'data-attribute': 'header' } }, { tagName: 'label', className: 'html-element-label', textContent: 'Name', children: [{ tagName: 'input', className: 'html-element-field', groupSelector: 'field', attributes: { 'data-attribute': 'name', 'placeholder': 'Name' }, style: { 'pointer-events': 'auto' } }] }, { tagName: 'label', className: 'html-element-label', textContent: 'Resource', children: [{ tagName: 'select', className: 'html-element-field', groupSelector: 'field', attributes: { 'data-attribute': 'resource' }, style: { 'pointer-events': 'auto' }, children: [{ tagName: 'option', textContent: 'Resource', attributes: { 'value': '', 'disabled': 'true' } }, { tagName: 'option', textContent: 'John', attributes: { 'value': 'john' } }, { tagName: 'option', textContent: 'Mary', attributes: { 'value': 'mary' } }, { tagName: 'option', textContent: 'Bob', attributes: { 'value': 'bob' } }] }] }] }] }); // Custom view for JointJS HTML element that displays an HTML <div></div> above the SVG Element. joint.shapes.html.ElementView = ElementView.extend({ html: null, presentationAttributes: ElementView.addPresentationAttributes({ position: ['HTML_UPDATE'], size: ['HTML_UPDATE'], fields: ['HTML_FIELD_UPDATE'], z: ['HTML_Z_INDEX'] }), // Run these upon first render initFlag: ElementView.prototype.initFlag.concat([ 'HTML_UPDATE', 'HTML_FIELD_UPDATE', 'HTML_Z_INDEX' ]), confirmUpdate: function() { var flags = ElementView.prototype.confirmUpdate.apply(this, arguments); if (this.hasFlag(flags, 'HTML_UPDATE')) { this.updateHTML(); flags = this.removeFlag(flags, 'HTML_UPDATE'); } if (this.hasFlag(flags, 'HTML_FIELD_UPDATE')) { this.updateFields(); flags = this.removeFlag(flags, 'HTML_FIELD_UPDATE'); } if (this.hasFlag(flags, 'HTML_Z_INDEX')) { this.updateZIndex(); flags = this.removeFlag(flags, 'HTML_Z_INDEX'); } return flags; }, onRender: function() { this.removeHTMLMarkup(); this.renderHTMLMarkup(); return this; }, renderHTMLMarkup: function() { var doc = util.parseDOMJSON(this.model.htmlMarkup, V.namespace.xhtml); var html = doc.selectors.htmlRoot; var fields = doc.groupSelectors.field; // React on all box changes. e.g. input change html.addEventListener('change', this.onFieldChange.bind(this), false); this.paper.htmlContainer.appendChild(doc.fragment); this.html = html; this.fields = fields; html.setAttribute('model-id', this.model.id); }, removeHTMLMarkup: function() { var html = this.html; if (!html) return; this.paper.htmlContainer.removeChild(html); this.html = null; this.fields = null; }, updateHTML: function() { var bbox = this.model.getBBox(); var html = this.html; html.style.width = bbox.width + 'px'; html.style.height = bbox.height + 'px'; html.style.left = bbox.x + 'px'; html.style.top = bbox.y + 'px'; }, onFieldChange: function(evt) { var input = evt.target; var attribute = input.dataset.attribute; if (attribute) { this.model.prop(['fields', attribute], input.value); } }, updateFields: function() { this.fields.forEach(function(field) { var attribute = field.dataset.attribute; var value = this.model.prop(['fields', attribute]); switch (field.tagName.toUpperCase()) { case 'LABEL': field.textContent = value; break; case 'INPUT': case 'SELECT': field.value = value; if (value) { field.classList.remove('field-empty'); } else { field.classList.add('field-empty'); } break; case 'DIV': field.dataset[attribute] = value; break; } }.bind(this)); }, updateZIndex: function() { this.html.style.zIndex = this.model.get('z') || 0; }, onRemove: function() { this.removeHTMLMarkup(); } }); })(joint, joint.util, V);