react-sigma-conglei
Version:
Lightweight but powerful library for drawing network graphs built on top of dunnock/react-sigma
766 lines (611 loc) • 19.5 kB
JavaScript
var Sigma =
/******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId]) {
/******/ return installedModules[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // identity function for calling harmony imports with the correct context
/******/ __webpack_require__.i = function(value) { return value; };
/******/
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, {
/******/ configurable: false,
/******/ enumerable: true,
/******/ get: getter
/******/ });
/******/ }
/******/ };
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
/******/ };
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = 136);
/******/ })
/************************************************************************/
/******/ ({
/***/ 136:
/***/ (function(module, exports, __webpack_require__) {
__webpack_require__(19);
module.exports = __webpack_require__(20);
/***/ }),
/***/ 19:
/***/ (function(module, exports) {
/*** IMPORTS FROM imports-loader ***/
(function() {
;(function(undefined) {
'use strict';
/**
* GEXF Library
* =============
*
* Author: PLIQUE Guillaume (Yomguithereal)
* URL: https://github.com/Yomguithereal/gexf-parser
* Version: 0.1.1
*/
/**
* Helper Namespace
* -----------------
*
* A useful batch of function dealing with DOM operations and types.
*/
var _helpers = {
getModelTags: function(xml) {
var attributesTags = xml.getElementsByTagName('attributes'),
modelTags = {},
l = attributesTags.length,
i;
for (i = 0; i < l; i++)
modelTags[attributesTags[i].getAttribute('class')] =
attributesTags[i].childNodes;
return modelTags;
},
nodeListToArray: function(nodeList) {
// Return array
var children = [];
// Iterating
for (var i = 0, len = nodeList.length; i < len; ++i) {
if (nodeList[i].nodeName !== '#text')
children.push(nodeList[i]);
}
return children;
},
nodeListEach: function(nodeList, func) {
// Iterating
for (var i = 0, len = nodeList.length; i < len; ++i) {
if (nodeList[i].nodeName !== '#text')
func(nodeList[i]);
}
},
nodeListToHash: function(nodeList, filter) {
// Return object
var children = {};
// Iterating
for (var i = 0; i < nodeList.length; i++) {
if (nodeList[i].nodeName !== '#text') {
var prop = filter(nodeList[i]);
children[prop.key] = prop.value;
}
}
return children;
},
namedNodeMapToObject: function(nodeMap) {
// Return object
var attributes = {};
// Iterating
for (var i = 0; i < nodeMap.length; i++) {
attributes[nodeMap[i].name] = nodeMap[i].value;
}
return attributes;
},
getFirstElementByTagNS: function(node, ns, tag) {
var el = node.getElementsByTagName(ns + ':' + tag)[0];
if (!el)
el = node.getElementsByTagNameNS(ns, tag)[0];
if (!el)
el = node.getElementsByTagName(tag)[0];
return el;
},
getAttributeNS: function(node, ns, attribute) {
var attr_value = node.getAttribute(ns + ':' + attribute);
if (attr_value === undefined)
attr_value = node.getAttributeNS(ns, attribute);
if (attr_value === undefined)
attr_value = node.getAttribute(attribute);
return attr_value;
},
enforceType: function(type, value) {
switch (type) {
case 'boolean':
value = (value === 'true');
break;
case 'integer':
case 'long':
case 'float':
case 'double':
value = +value;
break;
case 'liststring':
value = value ? value.split('|') : [];
break;
}
return value;
},
getRGB: function(values) {
return (values[3]) ?
'rgba(' + values.join(',') + ')' :
'rgb(' + values.slice(0, -1).join(',') + ')';
}
};
/**
* Parser Core Functions
* ----------------------
*
* The XML parser's functions themselves.
*/
/**
* Node structure.
* A function returning an object guarded with default value.
*
* @param {object} properties The node properties.
* @return {object} The guarded node object.
*/
function Node(properties) {
// Possible Properties
var node = {
id: properties.id,
label: properties.label
};
if (properties.viz)
node.viz = properties.viz;
if (properties.attributes)
node.attributes = properties.attributes;
return node;
}
/**
* Edge structure.
* A function returning an object guarded with default value.
*
* @param {object} properties The edge properties.
* @return {object} The guarded edge object.
*/
function Edge(properties) {
// Possible Properties
var edge = {
id: properties.id,
type: properties.type || 'undirected',
label: properties.label || '',
source: properties.source,
target: properties.target,
weight: +properties.weight || 1.0
};
if (properties.viz)
edge.viz = properties.viz;
if (properties.attributes)
edge.attributes = properties.attributes;
return edge;
}
/**
* Graph parser.
* This structure parse a gexf string and return an object containing the
* parsed graph.
*
* @param {string} xml The xml string of the gexf file to parse.
* @return {object} The parsed graph.
*/
function Graph(xml) {
var _xml = {};
// Basic Properties
//------------------
_xml.els = {
root: xml.getElementsByTagName('gexf')[0],
graph: xml.getElementsByTagName('graph')[0],
meta: xml.getElementsByTagName('meta')[0],
nodes: xml.getElementsByTagName('node'),
edges: xml.getElementsByTagName('edge'),
model: _helpers.getModelTags(xml)
};
// Information
_xml.hasViz = !!_helpers.getAttributeNS(_xml.els.root, 'xmlns', 'viz');
_xml.version = _xml.els.root.getAttribute('version') || '1.0';
_xml.mode = _xml.els.graph.getAttribute('mode') || 'static';
var edgeType = _xml.els.graph.getAttribute('defaultedgetype');
_xml.defaultEdgetype = edgeType || 'undirected';
// Parser Functions
//------------------
// Meta Data
function _metaData() {
var metas = {};
if (!_xml.els.meta)
return metas;
// Last modified date
metas.lastmodifieddate = _xml.els.meta.getAttribute('lastmodifieddate');
// Other information
_helpers.nodeListEach(_xml.els.meta.childNodes, function(child) {
metas[child.tagName.toLowerCase()] = child.textContent;
});
return metas;
}
// Model
function _model(cls) {
var attributes = [];
// Iterating through attributes
if (_xml.els.model[cls])
_helpers.nodeListEach(_xml.els.model[cls], function(attr) {
// Properties
var properties = {
id: attr.getAttribute('id') || attr.getAttribute('for'),
type: attr.getAttribute('type') || 'string',
title: attr.getAttribute('title') || ''
};
// Defaults
var default_el = _helpers.nodeListToArray(attr.childNodes);
if (default_el.length > 0)
properties.defaultValue = default_el[0].textContent;
// Creating attribute
attributes.push(properties);
});
return attributes.length > 0 ? attributes : false;
}
// Data from nodes or edges
function _data(model, node_or_edge) {
var data = {};
var attvalues_els = node_or_edge.getElementsByTagName('attvalue');
// Getting Node Indicated Attributes
var ah = _helpers.nodeListToHash(attvalues_els, function(el) {
var attributes = _helpers.namedNodeMapToObject(el.attributes);
var key = attributes.id || attributes['for'];
// Returning object
return {key: key, value: attributes.value};
});
// Iterating through model
model.map(function(a) {
// Default value?
data[a.id] = !(a.id in ah) && 'defaultValue' in a ?
_helpers.enforceType(a.type, a.defaultValue) :
_helpers.enforceType(a.type, ah[a.id]);
});
return data;
}
// Nodes
function _nodes(model) {
var nodes = [];
// Iteration through nodes
_helpers.nodeListEach(_xml.els.nodes, function(n) {
// Basic properties
var properties = {
id: n.getAttribute('id'),
label: n.getAttribute('label') || ''
};
// Retrieving data from nodes if any
if (model)
properties.attributes = _data(model, n);
// Retrieving viz information
if (_xml.hasViz)
properties.viz = _nodeViz(n);
// Pushing node
nodes.push(Node(properties));
});
return nodes;
}
// Viz information from nodes
function _nodeViz(node) {
var viz = {};
// Color
var color_el = _helpers.getFirstElementByTagNS(node, 'viz', 'color');
if (color_el) {
var color = ['r', 'g', 'b', 'a'].map(function(c) {
return color_el.getAttribute(c);
});
viz.color = _helpers.getRGB(color);
}
// Position
var pos_el = _helpers.getFirstElementByTagNS(node, 'viz', 'position');
if (pos_el) {
viz.position = {};
['x', 'y', 'z'].map(function(p) {
viz.position[p] = +pos_el.getAttribute(p);
});
}
// Size
var size_el = _helpers.getFirstElementByTagNS(node, 'viz', 'size');
if (size_el)
viz.size = +size_el.getAttribute('value');
// Shape
var shape_el = _helpers.getFirstElementByTagNS(node, 'viz', 'shape');
if (shape_el)
viz.shape = shape_el.getAttribute('value');
return viz;
}
// Edges
function _edges(model, default_type) {
var edges = [];
// Iteration through edges
_helpers.nodeListEach(_xml.els.edges, function(e) {
// Creating the edge
var properties = _helpers.namedNodeMapToObject(e.attributes);
if (!('type' in properties)) {
properties.type = default_type;
}
// Retrieving edge data
if (model)
properties.attributes = _data(model, e);
// Retrieving viz information
if (_xml.hasViz)
properties.viz = _edgeViz(e);
edges.push(Edge(properties));
});
return edges;
}
// Viz information from edges
function _edgeViz(edge) {
var viz = {};
// Color
var color_el = _helpers.getFirstElementByTagNS(edge, 'viz', 'color');
if (color_el) {
var color = ['r', 'g', 'b', 'a'].map(function(c) {
return color_el.getAttribute(c);
});
viz.color = _helpers.getRGB(color);
}
// Shape
var shape_el = _helpers.getFirstElementByTagNS(edge, 'viz', 'shape');
if (shape_el)
viz.shape = shape_el.getAttribute('value');
// Thickness
var thick_el = _helpers.getFirstElementByTagNS(edge, 'viz', 'thickness');
if (thick_el)
viz.thickness = +thick_el.getAttribute('value');
return viz;
}
// Returning the Graph
//---------------------
var nodeModel = _model('node'),
edgeModel = _model('edge');
var graph = {
version: _xml.version,
mode: _xml.mode,
defaultEdgeType: _xml.defaultEdgetype,
meta: _metaData(),
model: {},
nodes: _nodes(nodeModel),
edges: _edges(edgeModel, _xml.defaultEdgetype)
};
if (nodeModel)
graph.model.node = nodeModel;
if (edgeModel)
graph.model.edge = edgeModel;
return graph;
}
/**
* Public API
* -----------
*
* User-accessible functions.
*/
// Fetching GEXF with XHR
function fetch(gexf_url, callback) {
var xhr = (function() {
if (window.XMLHttpRequest)
return new XMLHttpRequest();
var names,
i;
if (window.ActiveXObject) {
names = [
'Msxml2.XMLHTTP.6.0',
'Msxml2.XMLHTTP.3.0',
'Msxml2.XMLHTTP',
'Microsoft.XMLHTTP'
];
for (i in names)
try {
return new ActiveXObject(names[i]);
} catch (e) {}
}
return null;
})();
if (!xhr)
throw 'XMLHttpRequest not supported, cannot load the file.';
// Async?
var async = (typeof callback === 'function'),
getResult;
// If we can't override MIME type, we are on IE 9
// We'll be parsing the response string then.
if (xhr.overrideMimeType) {
xhr.overrideMimeType('text/xml');
getResult = function(r) {
return r.responseXML;
};
}
else {
getResult = function(r) {
var p = new DOMParser();
return p.parseFromString(r.responseText, 'application/xml');
};
}
xhr.open('GET', gexf_url, async);
if (async)
xhr.onreadystatechange = function() {
if (xhr.readyState === 4)
callback(getResult(xhr));
};
xhr.send();
return (async) ? xhr : getResult(xhr);
}
// Parsing the GEXF File
function parse(gexf) {
return Graph(gexf);
}
// Fetch and parse the GEXF File
function fetchAndParse(gexf_url, callback) {
if (typeof callback === 'function') {
return fetch(gexf_url, function(gexf) {
callback(Graph(gexf));
});
} else
return Graph(fetch(gexf_url));
}
/**
* Exporting
* ----------
*/
if (typeof this.gexf !== 'undefined')
throw 'gexf: error - a variable called "gexf" already ' +
'exists in the global scope';
this.gexf = {
// Functions
parse: parse,
fetch: fetchAndParse,
// Version
version: '0.1.1'
};
if (typeof exports !== 'undefined' && this.exports !== exports)
module.exports = this.gexf;
}).call(window);
}.call(window));
/***/ }),
/***/ 20:
/***/ (function(module, exports) {
/*** IMPORTS FROM imports-loader ***/
(function() {
;(function(undefined) {
'use strict';
if (typeof sigma === 'undefined')
throw 'sigma is not declared';
// Initialize package:
sigma.utils.pkg('sigma.parsers');
// Just a basic ID generator:
var _id = 0;
function edgeId() {
return 'e' + (_id++);
}
/**
* If the first arguments is a valid URL, this function loads a GEXF file and
* creates a new sigma instance or updates the graph of a given instance. It
* is possible to give a callback that will be executed at the end of the
* process. And if the first argument is a DOM element, it will skip the
* loading step and parse the given XML tree to fill the graph.
*
* @param {string|DOMElement} target The URL of the GEXF file or a valid
* GEXF tree.
* @param {object|sigma} sig A sigma configuration object or a
* sigma instance.
* @param {?function} callback Eventually a callback to execute
* after having parsed the file. It will
* be called with the related sigma
* instance as parameter.
*/
sigma.parsers.gexf = function(target, sig, callback) {
var i,
l,
arr,
obj;
function parse(graph) {
// Adapt the graph:
arr = graph.nodes;
for (i = 0, l = arr.length; i < l; i++) {
obj = arr[i];
obj.id = obj.id;
if (obj.viz && typeof obj.viz === 'object') {
if (obj.viz.position && typeof obj.viz.position === 'object') {
obj.x = obj.viz.position.x;
obj.y = -obj.viz.position.y; // Needed otherwise it's up side down
}
obj.size = obj.viz.size;
obj.color = obj.viz.color;
}
}
arr = graph.edges;
for (i = 0, l = arr.length; i < l; i++) {
obj = arr[i];
obj.id = typeof obj.id === 'string' ? obj.id : edgeId();
obj.source = '' + obj.source;
obj.target = '' + obj.target;
if (obj.viz && typeof obj.viz === 'object') {
obj.color = obj.viz.color;
obj.size = obj.viz.thickness;
}
// Weight over viz.thickness?
obj.size = obj.weight;
// Changing type to be direction so it won't mess with sigma's naming
obj.direction = obj.type;
delete obj.type;
}
// Update the instance's graph:
if (sig instanceof sigma) {
sig.graph.clear();
arr = graph.nodes;
for (i = 0, l = arr.length; i < l; i++)
sig.graph.addNode(arr[i]);
arr = graph.edges;
for (i = 0, l = arr.length; i < l; i++)
sig.graph.addEdge(arr[i]);
// ...or instantiate sigma if needed:
} else if (typeof sig === 'object') {
sig.graph = graph;
sig = new sigma(sig);
// ...or it's finally the callback:
} else if (typeof sig === 'function') {
callback = sig;
sig = null;
}
// Call the callback if specified:
if (callback) {
callback(sig || graph);
return;
} else
return graph;
}
if (typeof target === 'string')
gexf.fetch(target, parse);
else if (typeof target === 'object')
return parse(gexf.parse(target));
};
}).call(window);
}.call(window));
/***/ })
/******/ });