/**
|
|
* This plugin provides a method to retrieve the neighborhood of a node.
|
|
* Basically, it loads a graph and stores it in a headless sigma.classes.graph
|
|
* instance, that you can query to retrieve neighborhoods.
|
|
*
|
|
* It is useful for people who want to provide a neighborhoods navigation
|
|
* inside a big graph instead of just displaying it, and without having to
|
|
* deploy an API or the list of every neighborhoods.
|
|
*
|
|
* This plugin also adds to the graph model a method called "neighborhood".
|
|
* Check the code for more information.
|
|
*
|
|
* Here is how to use it:
|
|
*
|
|
* > var db = new sigma.plugins.neighborhoods();
|
|
* > db.load('path/to/my/graph.json', function() {
|
|
* > var nodeId = 'anyNodeID';
|
|
* > mySigmaInstance
|
|
* > .read(db.neighborhood(nodeId))
|
|
* > .refresh();
|
|
* > });
|
|
*/
|
|
(function() {
|
|
'use strict';
|
|
|
|
if (typeof sigma === 'undefined')
|
|
throw 'sigma is not declared';
|
|
|
|
/**
|
|
* This method takes the ID of node as argument and returns the graph of the
|
|
* specified node, with every other nodes that are connected to it and every
|
|
* edges that connect two of the previously cited nodes. It uses the built-in
|
|
* indexes from sigma's graph model to search in the graph.
|
|
*
|
|
* @param {string} centerId The ID of the center node.
|
|
* @return {object} The graph, as a simple descriptive object, in
|
|
* the format required by the "read" graph method.
|
|
*/
|
|
sigma.classes.graph.addMethod(
|
|
'neighborhood',
|
|
function(centerId) {
|
|
var k1,
|
|
k2,
|
|
k3,
|
|
node,
|
|
center,
|
|
// Those two local indexes are here just to avoid duplicates:
|
|
localNodesIndex = {},
|
|
localEdgesIndex = {},
|
|
// And here is the resulted graph, empty at the moment:
|
|
graph = {
|
|
nodes: [],
|
|
edges: []
|
|
};
|
|
|
|
// Check that the exists:
|
|
if (!this.nodes(centerId))
|
|
return graph;
|
|
|
|
// Add center. It has to be cloned to add it the "center" attribute
|
|
// without altering the current graph:
|
|
node = this.nodes(centerId);
|
|
center = {};
|
|
center.center = true;
|
|
for (k1 in node)
|
|
center[k1] = node[k1];
|
|
|
|
localNodesIndex[centerId] = true;
|
|
graph.nodes.push(center);
|
|
|
|
// Add neighbors and edges between the center and the neighbors:
|
|
for (k1 in this.allNeighborsIndex[centerId]) {
|
|
if (!localNodesIndex[k1]) {
|
|
localNodesIndex[k1] = true;
|
|
graph.nodes.push(this.nodesIndex[k1]);
|
|
}
|
|
|
|
for (k2 in this.allNeighborsIndex[centerId][k1])
|
|
if (!localEdgesIndex[k2]) {
|
|
localEdgesIndex[k2] = true;
|
|
graph.edges.push(this.edgesIndex[k2]);
|
|
}
|
|
}
|
|
|
|
// Add edges connecting two neighbors:
|
|
for (k1 in localNodesIndex)
|
|
if (k1 !== centerId)
|
|
for (k2 in localNodesIndex)
|
|
if (
|
|
k2 !== centerId &&
|
|
k1 !== k2 &&
|
|
this.allNeighborsIndex[k1][k2]
|
|
)
|
|
for (k3 in this.allNeighborsIndex[k1][k2])
|
|
if (!localEdgesIndex[k3]) {
|
|
localEdgesIndex[k3] = true;
|
|
graph.edges.push(this.edgesIndex[k3]);
|
|
}
|
|
|
|
// Finally, let's return the final graph:
|
|
return graph;
|
|
}
|
|
);
|
|
|
|
sigma.utils.pkg('sigma.plugins');
|
|
|
|
/**
|
|
* sigma.plugins.neighborhoods constructor.
|
|
*/
|
|
sigma.plugins.neighborhoods = function() {
|
|
var ready = false,
|
|
readyCallbacks = [],
|
|
graph = new sigma.classes.graph();
|
|
|
|
/**
|
|
* This method just returns the neighborhood of a node.
|
|
*
|
|
* @param {string} centerNodeID The ID of the center node.
|
|
* @return {object} Returns the neighborhood.
|
|
*/
|
|
this.neighborhood = function(centerNodeID) {
|
|
return graph.neighborhood(centerNodeID);
|
|
};
|
|
|
|
/**
|
|
* This method loads the JSON graph at "path", stores it in the local graph
|
|
* instance, and executes the callback.
|
|
*
|
|
* @param {string} path The path of the JSON graph file.
|
|
* @param {?function} callback Eventually a callback to execute.
|
|
*/
|
|
this.load = function(path, callback) {
|
|
// Quick XHR polyfill:
|
|
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 data.';
|
|
|
|
xhr.open('GET', path, true);
|
|
xhr.onreadystatechange = function() {
|
|
if (xhr.readyState === 4) {
|
|
graph.clear().read(JSON.parse(xhr.responseText));
|
|
|
|
if (callback)
|
|
callback();
|
|
}
|
|
};
|
|
|
|
// Start loading the file:
|
|
xhr.send();
|
|
|
|
return this;
|
|
};
|
|
|
|
/**
|
|
* This method cleans the graph instance "reads" a graph into it.
|
|
*
|
|
* @param {object} g The graph object to read.
|
|
*/
|
|
this.read = function(g) {
|
|
graph.clear().read(g);
|
|
};
|
|
};
|
|
}).call(window);
|