/** * Update plugin. Use updateUrl and updateInterval (optional, default is 60000ms) * in the meta data of the diagram to configure the plugin. It will send the XML * of the current page to the given URL as a POST request (with a parameter called * xml) and allows for the following type of XML response (with CORS headers): * * * * * * Where update must contain an id attribute to reference the cell in the diagram. * * - An optional value attribute that contains XML markup is used as the value for * the cell, with label and tooltip for the label and tooltip, respectively. * Additionally, placeholders="1" can be used to enable placeholders in the label * or tooltip of the cell. * * - An optional replace-value attribute that contains 1 can be specified to * replace the value of the cell. Default is to add the attributes of the XML * value specified above to the existing value of the cell. (Attributes with * an empty string value are removed.) * * - An optional style attribute that contains the cell style is be used to replace * the existing cell style. * * - An optional icon attribute that contains JSON is used to add an icon to the * given cell. The object value that the icon attribute is parsed to may contain * a tooltip (string), align ("left"|"center"|"right", default is "right"), valign * (top|middle|bottom, default is bottom) and append (true|false, default is false) * for adding or replacing existing icons. The image attribute is an object value * with src, width and height for defining the icon to be displayed (default is * mxGraph.warningImage). An empty string for the attribute removes all icons. * * See below for an example XML. */ Draw.loadPlugin(function(editorUi) { if (editorUi.editor.chromeless) { var graph = editorUi.editor.graph; var interval = 60000; function createOverlay(desc) { var overlay = new mxCellOverlay(desc.image || graph.warningImage, desc.tooltip, desc.align, desc.valign, desc.offset); // Installs a handler for clicks on the overlay overlay.addListener(mxEvent.CLICK, function(sender, evt) { editorUi.alert(desc.tooltip); }); return overlay; }; function parseUpdates(xml) { if (xml != null && xml.length > 0) { var doc = mxUtils.parseXml(xml); if (doc != null && doc.documentElement != null) { var model = graph.getModel(); var nodes = doc.documentElement.getElementsByTagName('update'); if (nodes != null && nodes.length > 0) { model.beginUpdate(); try { for (var i = 0; i < nodes.length; i++) { // Resolves the cell ID var cell = model.getCell(nodes[i].getAttribute('id')); if (cell != null) { // Changes the value try { var value = nodes[i].getAttribute('value'); if (value != null) { var node = mxUtils.parseXml(value).documentElement; if (node != null) { if (nodes[i].getAttribute('replace-value') == '1') { graph.model.setValue(cell, node); } else { var attrs = node.attributes; for (var j = 0; j < attrs.length; j++) { graph.setAttributeForCell(cell, attrs[j].nodeName, (attrs[j].nodeValue.length > 0) ? attrs[j].nodeValue : null); } } } } } catch (e) { console.log('Error in value for ' + cell.id + ': ' + e); } // Changes the style try { var style = nodes[i].getAttribute('style'); if (style != null) { graph.model.setStyle(cell, style); } } catch (e) { console.log('Error in style for ' + cell.id + ': ' + e); } // Adds or removes an overlay icon try { var icon = nodes[i].getAttribute('icon'); if (icon != null) { var desc = (icon.length > 0) ? JSON.parse(icon) : null; if (desc == null || !desc.append) { graph.removeCellOverlays(cell); } if (desc != null) { graph.addCellOverlay(cell, createOverlay(desc)); } } } catch (e) { console.log('Error in icon for ' + cell.id + ': ' + e); } } } // for } finally { model.endUpdate(); } } } } }; var currentThread = null; function scheduleUpdates() { var root = editorUi.editor.graph.getModel().getRoot(); var result = false; if (root.value != null && typeof(root.value) == 'object') { interval = parseInt(root.value.getAttribute('updateInterval') || interval); var url = root.value.getAttribute('updateUrl'); if (url != null) { var currentXml = mxUtils.getXml(editorUi.editor.getGraphXml()); function doUpdate() { if (url === 'demo') { parseUpdates(mxUtils.getXml(createDemoResponse().documentElement)); schedule(); } else { mxUtils.post(url, 'xml=' + encodeURIComponent(currentXml), function(req) { if (root === editorUi.editor.graph.getModel().getRoot()) { if (req.getStatus() >= 200 && req.getStatus() <= 300) { parseUpdates(mxUtils.getXml(req.getDocumentElement())); schedule(); } else { editorUi.handleError({message: mxResources.get('error') + ' ' + req.getStatus()}); } } }, function(err) { editorUi.handleError(err); }); } }; function schedule() { currentThread = window.setTimeout(doUpdate, interval); }; doUpdate(); result = true; } } return result; }; function startUpdates() { var result = scheduleUpdates(); if (result) { editorUi.editor.addListener('pageSelected', function() { window.clearTimeout(currentThread); scheduleUpdates(); }); } return result; }; function createDemoResponse() { var doc = mxUtils.createXmlDocument(); var status = doc.createElement('updates'); for (var id in graph.model.cells) { var cell = graph.model.cells[id]; if (graph.model.isVertex(cell)) { // For the purpose of the demo we flag stuff to update with update="1". // This is not needed for the general case. if (cell.value != null && typeof(cell.value) == 'object' && cell.value.getAttribute('update') == '1') { if (Math.random() > 0.5) { var update = doc.createElement('update'); update.setAttribute('id', cell.id); update.setAttribute('value', ''); update.setAttribute('style', cell.style + ';fillColor=#d5e8d4;gradientColor=white;'); update.setAttribute('icon', JSON.stringify({tooltip: 'Running', align: "right", valign: "top", image: {src: IMAGE_PATH + '/spin.gif', width: 12, height: 12}})); status.appendChild(update); // Adds another icon if (Math.random() > 0.5) { var update = doc.createElement('update'); update.setAttribute('id', cell.id); update.setAttribute('icon', JSON.stringify({tooltip: 'Locked', append: true, image: {src: IMAGE_PATH + '/locked.png', width: 12, height:12}})); status.appendChild(update); } } else { var update = doc.createElement('update'); update.setAttribute('id', cell.id); update.setAttribute('style', cell.style + ';fillColor=#d4e1f5;gradientColor=white;'); update.setAttribute('value', ''); update.setAttribute('icon', ''); status.appendChild(update); } } } } doc.appendChild(status); return doc; }; // Wait for file to be loaded if no animation data is present if (!startUpdates()) { editorUi.editor.addListener('fileLoaded', startUpdates); } } });