UNPKG

elvis-network

Version:

Ember addon for vis.js integration (originally a fork of Suven/ember-cli-visjs)

313 lines (252 loc) 7.67 kB
/* globals vis */ import Ember from 'ember'; import ContainerMixin from 'elvis-network/mixins/container'; import layout from '../templates/components/visjs-network'; const { A, assert, debug } = Ember; export default Ember.Component.extend(ContainerMixin, { layout, classNames: ['ember-cli-visjs ember-cli-visjs-network elvis-network'], // The following is a list of methods that simply correspond to events // (e.g. the `resize` event will have a `resizeAction` method handling it) eventActions: [ 'startStabilizing', 'stabilizationIterationsDone', 'stabilized', 'stabilizationProgress', 'resize', 'initRedraw', 'beforeDrawing', 'afterDrawing', 'configChange' ], network: false, init() { this._super(...arguments); this.set('nodes', new vis.DataSet([])); this.set('edges', new vis.DataSet(this.get('edgesSet'))); }, didInsertElement() { this._super(...arguments); let options = this.get('options') || {}; options.manipulation = options.manipulation || {}; options.manipulation.addEdge = this.cEdgeAdded.bind(this); let network = new vis.Network( $(`#${this.get('elementId')} .network-canvas`)[0], { nodes: this.get('nodes'), edges: this.get('edges') }, options ); if(this.get('nodesSet') && this.get('edgesSet')) { network.setData({ nodes: this.get('nodesSet'), edges: this.get('edgesSet') }); } let _this = this; network.on('selectNode', (e) => { let [ selectedNode ] = e.nodes; let matchingChildNode = _this.get('_childLayers').find((c) => { return `${c.get('nId')}` === `${selectedNode}`; }); if (_this.get('selectedNodes')) { _this.set('selectedNodes', [selectedNode]); } if (matchingChildNode) { matchingChildNode.get('select')(selectedNode, e); } }); network.on('deselectNode', (e) => { if (_this.get('selectedNodes')) { _this.set('selectedNodes', []); } }); network.on('selectEdge', (e) => { let selectedEdges = e.edges; if (_this.get('selectedEdges')) { _this.set('selectedEdges', selectedEdges); } }); network.on('deselectEdge', (e) => { if (_this.get('selectedEdges')) { _this.set('selectedEdges', []); } }); network.on('dragEnd', (e) => { let newPositions = network.getPositions(e.nodes); Object.keys(newPositions).forEach((id) => { let matchingChild = _this.get('_childLayers').find((c) => { return `${c.get('nId')}` === `${id}`; }); if (matchingChild) { matchingChild.set('posX', newPositions[id].x); matchingChild.set('posY', newPositions[id].y); } }); }); // Here we map through all the event-action pairs we have and define each // action as a listener for that event (e.g. `resize` -> `resizeAction`) this.eventActions.map((event) => { network.on(`${event}`, (e) => { let action = this.attrs[`${event}Action`]; if (typeof action === 'function') { action(e); } }); }); this.set('network', network); this.set('storeAs', this); this.setupBackgroundImage(); }, didUpdateAttrs(changes) { this._super(...arguments); if (changes.newAttrs.backgroundImage) { this.setupBackgroundImage(); } if (changes.newAttrs.addEdges) { this.setupAddEdges(); } if (changes.newAttrs.options) { this.setupAddEdges(); } }, setupBackgroundImage() { if (!this.get('backgroundImage')) { return; } let backgroundImage = new Image(); let network = this.get('network'); let _this = this; backgroundImage.onload = function() { network.on('beforeDrawing', (ctx) => { let offset = { x: _this.get('backgroundOffsetX') || backgroundImage.width / -2, y: _this.get('backgroundOffsetY') || backgroundImage.height / -2 }; ctx.drawImage(backgroundImage, offset.x, offset.y); }); network.redraw(); }; backgroundImage.src = this.get('backgroundImage'); }, setupAddEdges() { if (this.get('addEdges')) { this.get('network').addEdgeMode(); } else { this.get('network').disableEditMode(); } }, cEdgeAdded(edge, callback) { let cbResult; // Trigger the optional callback if (this.get('edgeAdded')) { cbResult = this.get('edgeAdded')(edge); } // Actually places the adge on visjs if (cbResult !== false) { callback(edge); } // vis disables adding edges after every edge by default // this way we will reenable it after every edge if addEdges // is still set this.setupAddEdges(); }, registerChild(child) { this._super(...arguments); let type = child.get('type'); if (type === 'node') { this.addNode(child); } else if (type === 'edge') { this.addEdge(child); } else { debug(`Child of type ${type} not supported by elvis-network`); } }, unregisterChild(child) { this._super(...arguments); let type = child.get('type'); if (type === 'node') { this.get('nodes').remove(child.get('nId')); } else if (type !== 'edge') { debug(`Child of type ${type} not supported by elvis-network`); } }, addNode(node) { let nodes = this.get('nodes'); let simplifiedNode = { id: node.get('nId'), label: node.get('label') }; if (node.get('color')) { simplifiedNode.color = node.get('color'); } if (node.get('posX') || node.get('posX') === 0) { simplifiedNode.x = node.get('posX'); } if (node.get('posY') || node.get('posY') === 0) { simplifiedNode.y = node.get('posY'); } if (node.get('value') || node.get('value') === 0) { simplifiedNode.value = node.get('value'); } if (node.get('image')) { simplifiedNode.shape = 'image'; simplifiedNode.image = node.get('image'); } nodes.add(simplifiedNode); }, addEdge(edge) { let edges = this.get('edges'); let simplifiedEdge = { id: edge.get('eId'), from: edge.get('from'), to: edge.get('to') }; if (edge.get('arrows')) { simplifiedEdge.arrows = edge.get('arrows'); } if (edge.get('value')) { simplifiedEdge.value = edge.get('value'); } if (edge.get('color')) { simplifiedEdge.color = edge.get('color'); } edges.add(simplifiedEdge); }, moveTo(id) { this.get('network').focus(id, { scale: 1, animation: true }); }, focus(id) { this.get('network').focus(id, { scale: 1, animation: false }); }, unselectAll() { this.get('network').unselectAll(); }, updateNodeColor(nId, color) { this.get('nodes').update({ id: nId, color }); }, updateNodeLabel(nId, label) { label = label ? label : undefined; this.get('nodes').update({ id: nId, label }); }, updateNodeImage(nId, image) { let val = { id: nId }; val.shape = image ? 'image' : 'ellipse'; val.image = image ? image : undefined; this.get('nodes').update(val); }, updateEdgeArrow(eId, arrows) { console.log(arrows); this.get('edges').update({ id: eId, arrows }); console.log(this.get('edges')); }, setOptions(options) { this.get('network').setOptions(options); }, execute(fn, ...args) { let network = this.get('network'); if (typeof network[fn] === 'function') { return network[fn](...args); } else { console.error(`Could not find function ${fn}`); return false; } } });