;(function(undefined) { 'use strict'; /** * Sigma SVG Exporter * =================== * * This plugin is designed to export a graph to a svg file that can be * downloaded or just used elsewhere. * * Author: Guillaume Plique (Yomguithereal) * Version: 0.0.1 */ // Terminating if sigma were not to be found if (typeof sigma === 'undefined') throw 'sigma.renderers.snapshot: sigma not in scope.'; /** * Polyfills */ var URL = this.URL || this.webkitURL || this; /** * Utilities */ function createBlob(data) { return new Blob( [data], {type: 'image/svg+xml;charset=utf-8'} ); } function download(string, filename) { // Creating blob href var blob = createBlob(string); // Anchor var o = {}; o.anchor = document.createElement('a'); o.anchor.setAttribute('href', URL.createObjectURL(blob)); o.anchor.setAttribute('download', filename); // Click event var event = document.createEvent('MouseEvent'); event.initMouseEvent('click', true, false, window, 0, 0, 0 ,0, 0, false, false, false, false, 0, null); URL.revokeObjectURL(blob); o.anchor.dispatchEvent(event); delete o.anchor; } /** * Defaults */ var DEFAULTS = { size: '1000', width: '1000', height: '1000', classes: true, labels: true, data: false, download: false, filename: 'graph.svg' }; var XMLNS = 'http://www.w3.org/2000/svg'; /** * Subprocesses */ function optimize(svg, prefix, params) { var nodeColorIndex = {}, edgeColorIndex = {}, count = 0, color, style, styleText = '', f, i, l; // Creating style tag if needed if (params.classes) { style = document.createElementNS(XMLNS, 'style'); style.setAttribute('type', 'text/css') svg.insertBefore(style, svg.firstChild); } // Iterating over nodes var nodes = svg.querySelectorAll('[id="' + prefix + '-group-nodes"] > [class="' + prefix + '-node"]'); for (i = 0, l = nodes.length, f = true; i < l; i++) { color = nodes[i].getAttribute('fill'); if (!params.data) nodes[i].removeAttribute('data-node-id'); if (params.classes) { if (!(color in nodeColorIndex)) { nodeColorIndex[color] = (f ? prefix + '-node' : 'c-' + (count++)); styleText += '.' + nodeColorIndex[color] + '{fill: ' + color + '}'; } if (nodeColorIndex[color] !== prefix + '-node') nodes[i].setAttribute('class', nodes[i].getAttribute('class') + ' ' + nodeColorIndex[color]); nodes[i].removeAttribute('fill'); } f = false; } // Iterating over edges var edges = svg.querySelectorAll('[id="' + prefix + '-group-edges"] > [class="' + prefix + '-edge"]'); for (i = 0, l = edges.length, f = true; i < l; i++) { color = edges[i].getAttribute('stroke'); if (!params.data) edges[i].removeAttribute('data-edge-id'); if (params.classes) { if (!(color in edgeColorIndex)) { edgeColorIndex[color] = (f ? prefix + '-edge' : 'c-' + (count++)); styleText += '.' + edgeColorIndex[color] + '{stroke: ' + color + '}'; } if (edgeColorIndex[color] !== prefix + '-edge') edges[i].setAttribute('class', edges[i].getAttribute('class') + ' ' + edgeColorIndex[color]); edges[i].removeAttribute('stroke'); } f = false; } if (params.classes) style.appendChild(document.createTextNode(styleText)); } /** * Extending prototype */ sigma.prototype.toSVG = function(params) { params = params || {}; var prefix = this.settings('classPrefix'), w = params.size || params.width || DEFAULTS.size, h = params.size || params.height || DEFAULTS.size; // Creating a dummy container var container = document.createElement('div'); container.setAttribute('width', w); container.setAttribute('height', h); container.setAttribute('style', 'position:absolute; top: 0px; left:0px; width: ' + w + 'px; height: ' + h + 'px;'); // Creating a camera var camera = this.addCamera(); // Creating a svg renderer var renderer = this.addRenderer({ camera: camera, container: container, type: 'svg', forceLabels: !!params.labels }); // Refreshing renderer.resize(w, h); this.refresh(); // Dropping camera and renderers before something nasty happens this.killRenderer(renderer); this.killCamera(camera); // Retrieving svg var svg = container.querySelector('svg'); svg.removeAttribute('style'); svg.setAttribute('width', w + 'px'); svg.setAttribute('height', h + 'px'); svg.setAttribute('x', '0px'); svg.setAttribute('y', '0px'); // svg.setAttribute('viewBox', '0 0 1000 1000'); // Dropping labels if (!params.labels) { var labelGroup = svg.querySelector('[id="' + prefix + '-group-labels"]'); svg.removeChild(labelGroup); } // Dropping hovers var hoverGroup = svg.querySelector('[id="' + prefix + '-group-hovers"]'); svg.removeChild(hoverGroup); // Optims? params.classes = (params.classes !== false); if (!params.data || params.classes) optimize(svg, prefix, params); // Retrieving svg string var svgString = svg.outerHTML; // Paranoid cleanup container = null; // Output string var output = '\n'; output += '\n'; output += svgString; if (params.download) download(output, params.filename || DEFAULTS.filename); return output; }; }).call(this);