mirror of
https://github.com/gsi-upm/soil
synced 2024-11-22 19:22:29 +00:00
Tidying up the repository
This commit is contained in:
parent
3387cf6462
commit
94756a5002
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,2 +1,3 @@
|
|||||||
__pycache__/
|
__pycache__/
|
||||||
output/
|
output/
|
||||||
|
tests/
|
||||||
|
@ -1,25 +0,0 @@
|
|||||||
name: ControlModelM2_sim
|
|
||||||
max_time: 60
|
|
||||||
num_trials: 4
|
|
||||||
network_params:
|
|
||||||
generator: barabasi_albert_graph
|
|
||||||
n: 100
|
|
||||||
m: 2
|
|
||||||
network_agents:
|
|
||||||
- agent_type: ControlModelM2
|
|
||||||
weight: 0.1
|
|
||||||
state:
|
|
||||||
id: 1
|
|
||||||
- agent_type: SpreadModelM2
|
|
||||||
weight: 0.9
|
|
||||||
state:
|
|
||||||
id: 0
|
|
||||||
environment_params:
|
|
||||||
prob_neutral_making_denier: 0.035
|
|
||||||
prob_infect: 0.075
|
|
||||||
prob_cured_healing_infected: 0.035
|
|
||||||
prob_cured_vaccinate_neutral: 0.035
|
|
||||||
prob_vaccinated_healing_infected: 0.035
|
|
||||||
prob_vaccinated_vaccinate_neutral: 0.035
|
|
||||||
prob_generate_anti_rumor: 0.035
|
|
||||||
standard_variance: 0.055
|
|
@ -21,7 +21,7 @@ ws.onmessage = function(message) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'get_trial':
|
case 'get_trial':
|
||||||
//console.log(msg['data']);
|
console.log(msg['data']);
|
||||||
GraphVisualization.import(convertJSON(msg['data']), function() {
|
GraphVisualization.import(convertJSON(msg['data']), function() {
|
||||||
$('#load').hide();
|
$('#load').hide();
|
||||||
reset_configuration();
|
reset_configuration();
|
||||||
|
@ -1,20 +0,0 @@
|
|||||||
|
|
||||||
|
|
||||||
var _helpers = {
|
|
||||||
attributesInterval: function (attributes, callback) {
|
|
||||||
for ( var property in attributes ) {
|
|
||||||
for ( var i = 0; i < attributes[property].length; i++ ) {
|
|
||||||
attributes[property][i].interval.forEach(function(d) {
|
|
||||||
callback(d);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
dynamicAttsToArray: function(atts) {
|
|
||||||
var array = []
|
|
||||||
for ( var property in atts ) {
|
|
||||||
array.push(property)
|
|
||||||
}
|
|
||||||
return array;
|
|
||||||
}
|
|
||||||
};
|
|
@ -1,561 +0,0 @@
|
|||||||
//<![CDATA[
|
|
||||||
window.onload = function() {
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
|
|
||||||
// Public variables (User Configuration)
|
|
||||||
var colorProperty,
|
|
||||||
speed = 1000;
|
|
||||||
|
|
||||||
// Private variables
|
|
||||||
var width = window.innerWidth * 0.75,
|
|
||||||
height = window.innerHeight * 4 / 5,
|
|
||||||
focus_opacity = 0.1,
|
|
||||||
radius = 8;
|
|
||||||
|
|
||||||
// Private Graph variables
|
|
||||||
var color, // Color for nodes
|
|
||||||
zoom, // Zoom
|
|
||||||
force, // Set up the force layout
|
|
||||||
svg, // Svg item
|
|
||||||
|
|
||||||
groot, // Append sections to svg to have nodes and edges separately
|
|
||||||
glinks,
|
|
||||||
gnodes,
|
|
||||||
data_node, // Actual node data for the graph
|
|
||||||
data_link, // Actual link data for the graph
|
|
||||||
|
|
||||||
graph, // Graph
|
|
||||||
atts, // Dynamic attributes if it is necessary
|
|
||||||
linkedByIndex, // Nodes linked by index
|
|
||||||
link, // Line svgs
|
|
||||||
node; // Circles for the nodes
|
|
||||||
|
|
||||||
// Private Timeline variables
|
|
||||||
var minInterval, // Min value of the graph
|
|
||||||
maxInterval, // Max value of the graph
|
|
||||||
minUnix, // Min value for the timeline
|
|
||||||
maxUnix, // Max value for the timeline
|
|
||||||
stepUnix, // Step value for the timeline
|
|
||||||
slider, // Slider
|
|
||||||
time, // Variable to calculate date intervals
|
|
||||||
play; // Constant for the interval to play the simulation
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
d3.select('#graph')
|
|
||||||
.attr("width", width)
|
|
||||||
.attr("height", height);
|
|
||||||
|
|
||||||
d3.select('#slider3').attr("width", width).call(d3.slider().axis(true)
|
|
||||||
.min(0).max(100)
|
|
||||||
);
|
|
||||||
|
|
||||||
$('.load').css("left", width / 2 - 25)
|
|
||||||
.css("top", height / 2);
|
|
||||||
$('#configuration').css("height", height)
|
|
||||||
|
|
||||||
loader(false);
|
|
||||||
|
|
||||||
$('#file').change(function() {
|
|
||||||
var index = $('.custom-file-input').val().lastIndexOf("\\") + 1;
|
|
||||||
$('.custom-file-control').attr("data-content",
|
|
||||||
$('.custom-file-input').val().substr(index) || "Choose file...");
|
|
||||||
|
|
||||||
$.ajax({
|
|
||||||
url: 'upload.php', // point to server-side PHP script
|
|
||||||
type: 'POST',
|
|
||||||
data: new FormData($('form')[0]),
|
|
||||||
timeout: 3000,
|
|
||||||
cache: false,
|
|
||||||
contentType: false,
|
|
||||||
processData: false,
|
|
||||||
beforeSend: function() {
|
|
||||||
clearPreviousGraph();
|
|
||||||
}
|
|
||||||
|
|
||||||
}).done(function(response) {
|
|
||||||
// Show loader
|
|
||||||
loader(true);
|
|
||||||
$('.alert-danger').hide();
|
|
||||||
|
|
||||||
// Load File
|
|
||||||
setTimeout(function() {
|
|
||||||
loadFile(response);
|
|
||||||
}, 100);
|
|
||||||
|
|
||||||
}).fail(function(response) {
|
|
||||||
loader(false);
|
|
||||||
$('#error-message').text(response.responseText || "Connection timed out");
|
|
||||||
$('.alert-danger').show();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
function clearPreviousGraph() {
|
|
||||||
$('#graph').html('');
|
|
||||||
$('#slider3').html('');
|
|
||||||
$('#properties-dynamic').html('').show();
|
|
||||||
$('#properties-static').html('').show();
|
|
||||||
$('#percentTable > tbody').empty();
|
|
||||||
$('#info-graph > tbody').empty();
|
|
||||||
$('#info-graph > tbody').empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
function loader(show) {
|
|
||||||
$('.load').show();
|
|
||||||
// Show loader
|
|
||||||
if (show) {
|
|
||||||
$('svg#graph').css("background-color", "white");
|
|
||||||
$('.load').text("").addClass("loader");
|
|
||||||
|
|
||||||
// Show "No File"
|
|
||||||
} else {
|
|
||||||
$('svg#graph').css("background-color", "rgba(128,128,128,0.1)");
|
|
||||||
$('.load').text("No file").removeClass("loader");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
=====================================================================================================================================================================
|
|
||||||
|
|
||||||
function loadFile(file) {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* GRAPH
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Color
|
|
||||||
color = d3.scale.category20();
|
|
||||||
|
|
||||||
// Zoom
|
|
||||||
zoom = d3.behavior
|
|
||||||
.zoom()
|
|
||||||
.scaleExtent([1/10, 10])
|
|
||||||
.on('zoom', function () {
|
|
||||||
//console.trace("zoom", d3.event.translate, d3.event.scale);
|
|
||||||
groot.attr('transform',
|
|
||||||
'translate(' + d3.event.translate + ')scale(' + d3.event.scale + ')');
|
|
||||||
});
|
|
||||||
|
|
||||||
// Set up the force layout
|
|
||||||
force = d3.layout.force()
|
|
||||||
.charge(-500)
|
|
||||||
.linkDistance(30)
|
|
||||||
.size([width, height]);
|
|
||||||
|
|
||||||
// Activate zoom for the svg item
|
|
||||||
svg = d3.select('#graph')
|
|
||||||
.attr("width", width)
|
|
||||||
.attr("height", height)
|
|
||||||
.call(zoom);
|
|
||||||
|
|
||||||
// Append sections to svg to have nodes and edges separately
|
|
||||||
groot = svg.append("g") .attr("id", "root");
|
|
||||||
glinks = groot.append("g") .attr("id", "links");
|
|
||||||
gnodes = groot.append("g") .attr("id", "nodes");
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Read the data from the graph
|
|
||||||
graph = GexfParser.fetch(file);
|
|
||||||
console.log("Graph", graph);
|
|
||||||
|
|
||||||
if (graph.mode === "dynamic") {
|
|
||||||
atts = GexfParser.dynamic(file, graph.timeformat)
|
|
||||||
colorProperty = graph.model[0].title;
|
|
||||||
console.log("Dynamic Attributes", atts);
|
|
||||||
} else {
|
|
||||||
atts = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Number of nodes and links info table
|
|
||||||
$('<tr>').appendTo('#info-graph > tbody');
|
|
||||||
$('<th>').text('Nodes:').appendTo('#info-graph > tbody tr:nth-child(1)');
|
|
||||||
$('<th>').text(graph.nodes.length).addClass('text-right').appendTo('#info-graph > tbody tr:nth-child(1)');
|
|
||||||
|
|
||||||
$('<tr>').appendTo('#info-graph > tbody');
|
|
||||||
$('<th>').text('Links:').appendTo('#info-graph > tbody tr:nth-child(2)');
|
|
||||||
$('<th>').text(graph.links.length).addClass('text-right').appendTo('#info-graph > tbody tr:nth-child(2)');
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Update linkedByIndex
|
|
||||||
linkedByIndex = {};
|
|
||||||
graph.links.forEach(function(d) {
|
|
||||||
linkedByIndex[d.source + "," + d.target] = true;
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
// Creates the graph data structure out of the json data
|
|
||||||
force.nodes(graph.nodes)
|
|
||||||
.links(graph.links)
|
|
||||||
.start();
|
|
||||||
|
|
||||||
// Create all the line svgs but without locations yet
|
|
||||||
link = glinks.selectAll(".link").data(graph.links);
|
|
||||||
set_link(link);
|
|
||||||
|
|
||||||
// Do the same with the circles for the nodes - no
|
|
||||||
var lastFocusNode;
|
|
||||||
node = gnodes.selectAll(".node").data(graph.nodes);
|
|
||||||
set_node(node);
|
|
||||||
|
|
||||||
// Now we are giving the SVGs coordinates - the force layout is generating the coordinates which this code is using to update the attributes
|
|
||||||
// of the SVG elements
|
|
||||||
force.on("tick", function () {
|
|
||||||
|
|
||||||
link.attr("x1", function (d) {
|
|
||||||
return d.source.x;
|
|
||||||
})
|
|
||||||
.attr("y1", function (d) {
|
|
||||||
return d.source.y;
|
|
||||||
})
|
|
||||||
.attr("x2", function (d) {
|
|
||||||
return d.target.x;
|
|
||||||
})
|
|
||||||
.attr("y2", function (d) {
|
|
||||||
return d.target.y;
|
|
||||||
});
|
|
||||||
|
|
||||||
node.attr('transform', function translate(d) {
|
|
||||||
return 'translate(' + d.x + ',' + d.y + ')';
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
function set_node(node) {
|
|
||||||
// Add nodes if the data has more nodes than before
|
|
||||||
node.enter().append("circle")
|
|
||||||
.attr("class", "node")
|
|
||||||
.attr("r", radius)
|
|
||||||
.style("fill", function (d) {
|
|
||||||
return color(d.attributes[colorProperty]);
|
|
||||||
})
|
|
||||||
// Cancel zoom movement so you can move the node
|
|
||||||
.on("mousedown", function(d) {
|
|
||||||
d3.event.stopPropagation();
|
|
||||||
})
|
|
||||||
// Double-click to focus neighbours
|
|
||||||
.on("dblclick", function(d) {
|
|
||||||
d3.event.stopPropagation();
|
|
||||||
if (d === lastFocusNode) {
|
|
||||||
lastFocusNode = undefined;
|
|
||||||
node.style("opacity", 1);
|
|
||||||
link.style("opacity", 1);
|
|
||||||
} else {
|
|
||||||
lastFocusNode = d;
|
|
||||||
set_focus(d);
|
|
||||||
}
|
|
||||||
}).call(force.drag);
|
|
||||||
|
|
||||||
// Remove nodes if the data has less nodes than before
|
|
||||||
node.exit().remove();
|
|
||||||
}
|
|
||||||
|
|
||||||
function set_link(link) {
|
|
||||||
// Remove links if the data has more links than before
|
|
||||||
link.enter().append("line")
|
|
||||||
.attr("class", "link")
|
|
||||||
.style("stroke-width", function (d) {
|
|
||||||
return Math.sqrt(d.value);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Remove links if the data has less links than before
|
|
||||||
link.exit().remove();
|
|
||||||
}
|
|
||||||
|
|
||||||
function set_focus(d) {
|
|
||||||
|
|
||||||
node.style("opacity", function(o) {
|
|
||||||
return isConnected(d,o) || d.index == o.index ? 1 : focus_opacity;
|
|
||||||
});
|
|
||||||
|
|
||||||
link.style("opacity", function(o) {
|
|
||||||
return o.source.index == d.index || o.target.index == d.index ? 1 : focus_opacity;
|
|
||||||
});
|
|
||||||
|
|
||||||
function isConnected(source, neighbour) {
|
|
||||||
return linkedByIndex[source.index + "," + neighbour.index] ||
|
|
||||||
linkedByIndex[neighbour.index + "," + source.index];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
=====================================================================================================================================================================
|
|
||||||
|
|
||||||
/**
|
|
||||||
* TIMELINE
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Maximum and minimum of all the intervals
|
|
||||||
minInterval = Math.min();
|
|
||||||
maxInterval = Math.max();
|
|
||||||
_helpers.attributesInterval(atts, function(d) {
|
|
||||||
if ( d[0] < minInterval && d[0] != -Infinity ) minInterval = d[0];
|
|
||||||
if ( d[1] < minInterval && d[0] != +Infinity ) minInterval = d[1];
|
|
||||||
if ( d[0] > maxInterval && d[0] != -Infinity ) maxInterval = d[0];
|
|
||||||
if ( d[1] > maxInterval && d[1] != +Infinity ) maxInterval = d[1];
|
|
||||||
});
|
|
||||||
|
|
||||||
// Transform dates to ints
|
|
||||||
if ( graph.timeformat === "date" ) {
|
|
||||||
time = d3.scale.linear().domain([minInterval, maxInterval]).range([1, 20]);
|
|
||||||
// Attributes
|
|
||||||
_helpers.attributesInterval(atts, function(d) {
|
|
||||||
if (d[0] !== -Infinity) d[0] = time(d[0]);
|
|
||||||
if (d[1] !== +Infinity) d[1] = time(d[1]);
|
|
||||||
});
|
|
||||||
// Nodes
|
|
||||||
graph.nodes.forEach( function(node) {
|
|
||||||
if (Array.isArray(node.spell)) {
|
|
||||||
node.spell.forEach( function(d) {
|
|
||||||
if (d[0] !== -Infinity) d[0] = time(d[0]);
|
|
||||||
if (d[1] !== +Infinity) d[1] = time(d[1]);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// Links
|
|
||||||
graph.links.forEach( function(link) {
|
|
||||||
if (link.spell[0] !== -Infinity) link.spell[0] = time(link.spell[0]);
|
|
||||||
if (link.spell[1] !== +Infinity) link.spell[1] = time(link.spell[1]);
|
|
||||||
});
|
|
||||||
minInterval = 1;
|
|
||||||
maxInterval = 20;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
stepUnix = (maxInterval - minInterval) / 200;
|
|
||||||
minUnix = (minInterval !== Math.min()) ? minInterval - 2 * stepUnix : 0;
|
|
||||||
maxUnix = (maxInterval !== Math.max()) ? maxInterval + 2 * stepUnix : minUnix + 20;
|
|
||||||
|
|
||||||
// Create the slider
|
|
||||||
slider = d3.slider();
|
|
||||||
d3.select("#slider3").attr("width", width).call(slider.axis(true)
|
|
||||||
.min(minUnix).max(maxUnix).step(stepUnix).value(maxUnix)
|
|
||||||
.on("slide", function(evt, value) {
|
|
||||||
updateData(value);
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
function updateData(value) {
|
|
||||||
|
|
||||||
var statics = {};
|
|
||||||
$('#percentTable > tbody').empty();
|
|
||||||
|
|
||||||
// Reset data
|
|
||||||
var delete_links = true;
|
|
||||||
data_node = [];
|
|
||||||
data_link = graph.links.slice();
|
|
||||||
|
|
||||||
// Nodes
|
|
||||||
graph.nodes.forEach(function(n) {
|
|
||||||
if (Array.isArray(n.spell)) {
|
|
||||||
n.spell.forEach( function(d) {
|
|
||||||
if (d[0] < value && value <= d[1]) {
|
|
||||||
data_node.push(n);
|
|
||||||
delete_links = false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (delete_links) {
|
|
||||||
graph.links.forEach(function(e) {
|
|
||||||
if (e.source === n || e.target === n) {
|
|
||||||
data_link.splice(data_link.indexOf(e), 1);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
data_node.push(n);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Links
|
|
||||||
graph.links.forEach(function(e) {
|
|
||||||
if ( !(e.spell[0] < value && value <= e.spell[1]) && data_link.includes(e) )
|
|
||||||
data_link.splice(data_link.indexOf(e), 1);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Reset force
|
|
||||||
force.stop()
|
|
||||||
.nodes(data_node)
|
|
||||||
.links(data_link)
|
|
||||||
.start();
|
|
||||||
|
|
||||||
// Redraw Graph
|
|
||||||
link = glinks.selectAll(".link").data(data_link);
|
|
||||||
set_link(link);
|
|
||||||
|
|
||||||
node = gnodes.selectAll(".node").data(data_node);
|
|
||||||
set_node(node);
|
|
||||||
|
|
||||||
|
|
||||||
// Node Attributes
|
|
||||||
data_node.forEach(function(n) {
|
|
||||||
|
|
||||||
for (var property in atts) {
|
|
||||||
|
|
||||||
var interval = atts[property][n.index].interval
|
|
||||||
|
|
||||||
for ( var i = 0; i < interval.length; i++ ) {
|
|
||||||
//console.log(interval[i][0], value, interval[i][1], "->", interval[i][2])
|
|
||||||
if (interval[i][0] < value && value <= interval[i][1])
|
|
||||||
n.attributes[property] = interval[i][2];
|
|
||||||
else if (value === minUnix)
|
|
||||||
n.attributes[property] = interval[0][2];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Count node properties
|
|
||||||
statics[n.attributes[colorProperty]] = (!statics[n.attributes[colorProperty]]) ? 1 :
|
|
||||||
statics[n.attributes[colorProperty]] + 1;
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
node.style("fill", function (d) {
|
|
||||||
return color(d.attributes[colorProperty]);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Show the five properties with more percentage
|
|
||||||
var staticsSorted = Object.keys(statics).sort(function(a,b) {
|
|
||||||
return statics[b] - statics[a];
|
|
||||||
});
|
|
||||||
|
|
||||||
for ( var i = 0; ( i < staticsSorted.length ) && ( i < 5 ); i++ ) {
|
|
||||||
var percent = statics[staticsSorted[i]] / data_node.length * 100;
|
|
||||||
|
|
||||||
var propertyName = (staticsSorted[i].includes("class")) ?
|
|
||||||
staticsSorted[i].split('.').pop().split('\'')[0] : staticsSorted[i];
|
|
||||||
|
|
||||||
// Draw table every time
|
|
||||||
var appendTo = '#percentTable > tbody tr:nth-child(' + Number(i + 1) + ')';
|
|
||||||
|
|
||||||
$('<tr>').addClass('col-sm-12').appendTo('#percentTable > tbody');
|
|
||||||
$('<td>').css("background-color", color(staticsSorted[i])).addClass('col-sm-1').attr('data-value', staticsSorted[i]).appendTo(appendTo);
|
|
||||||
$('<td>').addClass('text-left col-sm-4').text(percent.toFixed(2) + " %").appendTo(appendTo);
|
|
||||||
$('<td>').addClass('text-right col-sm-6 property-name').text(propertyName).appendTo(appendTo);
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
=====================================================================================================================================================================
|
|
||||||
|
|
||||||
/**
|
|
||||||
* PAGE ELEMENTS
|
|
||||||
*/
|
|
||||||
|
|
||||||
$('.load').hide();
|
|
||||||
|
|
||||||
$('button#button_play').on('click', function() {
|
|
||||||
|
|
||||||
$('button#button_play').addClass('pressed').prop("disabled", true);
|
|
||||||
$('#speed-slider').slider('disable');
|
|
||||||
slider.step( 1 / speed );
|
|
||||||
|
|
||||||
if (slider.value() >= maxUnix) {
|
|
||||||
slider.value(minUnix);
|
|
||||||
updateData(slider.value());
|
|
||||||
|
|
||||||
setTimeout(player, 2000);
|
|
||||||
} else {
|
|
||||||
player();
|
|
||||||
}
|
|
||||||
|
|
||||||
var i = slider.value();
|
|
||||||
function player() {
|
|
||||||
clearInterval(play);
|
|
||||||
play = setInterval(function() {
|
|
||||||
|
|
||||||
if (slider.value() + slider.step() >= maxUnix) {
|
|
||||||
slider.value(maxUnix);
|
|
||||||
slider.step(stepUnix);
|
|
||||||
clearInterval(play);
|
|
||||||
$('button#button_play').removeClass('pressed').prop("disabled", false);
|
|
||||||
$('#speed-slider').slider('enable');
|
|
||||||
} else {
|
|
||||||
updateData(slider.value());
|
|
||||||
slider.value(i);
|
|
||||||
i += slider.step();
|
|
||||||
}
|
|
||||||
|
|
||||||
}, 5);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$('button#button_pause').on('click', function() {
|
|
||||||
clearInterval(play);
|
|
||||||
slider.step(stepUnix);
|
|
||||||
$('button#button_play').removeClass('pressed').prop("disabled", false);
|
|
||||||
$('#speed-slider').slider('enable');
|
|
||||||
});
|
|
||||||
|
|
||||||
var dynamicArray = _helpers.dynamicAttsToArray(atts);
|
|
||||||
for (var i = 0; i < graph.model.length; i++) {
|
|
||||||
if ( dynamicArray.includes(graph.model[i].title) )
|
|
||||||
$('<option>').val(graph.model[i].title).text(graph.model[i].title).appendTo('#properties-dynamic');
|
|
||||||
else
|
|
||||||
$('<option>').val(graph.model[i].title).text(graph.model[i].title).appendTo('#properties-static');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Hide optgroups if they are empty
|
|
||||||
if ( $('#properties-static').children().length === 0 ) $('#properties-static').hide();
|
|
||||||
if ( $('#properties-dynamic').children().length === 0 ) $('#properties-dynamic').hide();
|
|
||||||
|
|
||||||
$('select#properties').change(function() {
|
|
||||||
colorProperty = $('select#properties').val();
|
|
||||||
updateData(slider.value());
|
|
||||||
});
|
|
||||||
|
|
||||||
$('button#button_zoomFit').click(function() {
|
|
||||||
|
|
||||||
var paddingPercent = 0.7;
|
|
||||||
var transitionDuration = 750;
|
|
||||||
|
|
||||||
var bounds = groot.node().getBBox();
|
|
||||||
var parent = groot.node().parentElement;
|
|
||||||
var fullWidth = parent.clientWidth,
|
|
||||||
fullHeight = parent.clientHeight;
|
|
||||||
var widthBounds = bounds.width,
|
|
||||||
heightBounds = bounds.height;
|
|
||||||
var midX = bounds.x + widthBounds / 2,
|
|
||||||
midY = bounds.y + heightBounds / 2;
|
|
||||||
if (widthBounds == 0 || heightBounds == 0) return; // nothing to fit
|
|
||||||
var scale = (paddingPercent || 0.75) / Math.max(widthBounds / fullWidth, heightBounds / fullHeight);
|
|
||||||
var translate = [fullWidth / 2 - scale * midX, fullHeight / 2 - scale * midY];
|
|
||||||
|
|
||||||
//console.trace("zoomFit", translate, scale);
|
|
||||||
groot
|
|
||||||
.transition()
|
|
||||||
.duration(transitionDuration || 0) // milliseconds
|
|
||||||
.call(zoom.translate(translate).scale(scale).event);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Speed for the timeline
|
|
||||||
$('#speed-slider').slider('enable').on('change', function(value) {
|
|
||||||
speed = value.value.newValue;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Link distance between the nodes
|
|
||||||
$('#link-distance-slider').slider('enable').on('change', function(value) {
|
|
||||||
force.stop().linkDistance(value.value.newValue).start();
|
|
||||||
|
|
||||||
// Update radius of the nodes to see them better
|
|
||||||
var r = d3.scale.linear().domain([30, 1000]).range([8, 24]);
|
|
||||||
radius = r(value.value.newValue);
|
|
||||||
node.attr('r', radius);
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
updateData(slider.value());
|
|
||||||
|
|
||||||
// Clear all events
|
|
||||||
$('#file').change(function() {
|
|
||||||
$('button#button_play').off();
|
|
||||||
$('button#button_pause').off();
|
|
||||||
$('select#properties').off();
|
|
||||||
$('button#button_zoomFit').off();
|
|
||||||
$('#speed-slider').slider('disable');
|
|
||||||
$('#link-distance-slider').slider('disable').slider('setValue', 30);
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
///]]
|
|
@ -1,622 +0,0 @@
|
|||||||
|
|
||||||
;(function(undefined) {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* GEXF Parser
|
|
||||||
* ============
|
|
||||||
*
|
|
||||||
* Author: PLIQUE Guillaume (Yomguithereal)
|
|
||||||
* URL: https://github.com/Yomguithereal/gexf-parser
|
|
||||||
* Version: 1.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper Namespace
|
|
||||||
* -----------------
|
|
||||||
*
|
|
||||||
* A useful batch of function dealing with DOM operations and types.
|
|
||||||
*/
|
|
||||||
var _helpers = {
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
return {
|
|
||||||
id: properties.id,
|
|
||||||
index: properties.index,
|
|
||||||
label: properties.label,
|
|
||||||
attributes: properties.attributes || {},
|
|
||||||
viz: properties.viz || {},
|
|
||||||
spell: properties.spell || {}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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, nodeList) {
|
|
||||||
|
|
||||||
var list = _helpers.nodeListToArray(nodeList);
|
|
||||||
|
|
||||||
function findNodeSource (node) {
|
|
||||||
return node.id === properties.source;
|
|
||||||
}
|
|
||||||
|
|
||||||
function findNodeTarget (node) {
|
|
||||||
return node.id === properties.target;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Possible Properties
|
|
||||||
return {
|
|
||||||
id: properties.id,
|
|
||||||
type: properties.type || 'undirected',
|
|
||||||
label: properties.label || '',
|
|
||||||
source: list.indexOf(list.find(findNodeSource)),
|
|
||||||
target: list.indexOf(list.find(findNodeTarget)),
|
|
||||||
value: +properties.value || 1.0,
|
|
||||||
viz: properties.viz || {},
|
|
||||||
spell: properties.spell || {}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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],
|
|
||||||
model: xml.getElementsByTagName('attribute'),
|
|
||||||
nodes: xml.getElementsByTagName('node'),
|
|
||||||
links: xml.getElementsByTagName('edge')
|
|
||||||
};
|
|
||||||
|
|
||||||
_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';
|
|
||||||
_xml.timeformat = _xml.els.graph.getAttribute('timeformat') || null;
|
|
||||||
|
|
||||||
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() {
|
|
||||||
var attributes = [];
|
|
||||||
|
|
||||||
// Iterating through attributes
|
|
||||||
_helpers.nodeListEach(_xml.els.model, 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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.length > 0)
|
|
||||||
properties.attributes = _nodeData(model, n);
|
|
||||||
|
|
||||||
// Retrieving viz information
|
|
||||||
if (_xml.hasViz)
|
|
||||||
properties.viz = _nodeViz(n);
|
|
||||||
|
|
||||||
properties.spell = _nodeSpell(n);
|
|
||||||
|
|
||||||
// Pushing node
|
|
||||||
nodes.push(Node(properties));
|
|
||||||
});
|
|
||||||
|
|
||||||
return nodes;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Spells from nodes
|
|
||||||
function _nodeSpell(node) {
|
|
||||||
var spells = node.getElementsByTagName('spells')[0];
|
|
||||||
|
|
||||||
if (spells) {
|
|
||||||
var spell = spells.getElementsByTagName('spell');
|
|
||||||
var interval = [];
|
|
||||||
|
|
||||||
for ( var i = 0; i < spell.length; i++ ) {
|
|
||||||
var start = ( (_xml.timeformat !== "date") ? parseFloat(spell[i].getAttribute("start")) || -Infinity :
|
|
||||||
(spell[i].getAttribute('start') ? new Date(spell[i].getAttribute('start')) : -Infinity) );
|
|
||||||
|
|
||||||
var end = ( (_xml.timeformat !== "date") ? parseFloat(spell[i].getAttribute("end")) || Infinity :
|
|
||||||
(spell[i].getAttribute('end') ? new Date(spell[i].getAttribute('end')) : Infinity) );
|
|
||||||
|
|
||||||
interval.push([start, end]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return interval;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Data from nodes
|
|
||||||
function _nodeData(model, node) {
|
|
||||||
|
|
||||||
var data = {};
|
|
||||||
var attvalues_els = node.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?
|
|
||||||
var att_title = a.title.toLowerCase();
|
|
||||||
data[att_title] = !(a.id in ah) && 'defaultValue' in a ?
|
|
||||||
_helpers.enforceType(a.type, a.defaultValue) :
|
|
||||||
_helpers.enforceType(a.type, ah[a.id]);
|
|
||||||
});
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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(default_type) {
|
|
||||||
var edges = [];
|
|
||||||
|
|
||||||
// Iteration through edges
|
|
||||||
_helpers.nodeListEach(_xml.els.links, function(e) {
|
|
||||||
|
|
||||||
// Creating the edge
|
|
||||||
var properties = _helpers.namedNodeMapToObject(e.attributes);
|
|
||||||
if (!('type' in properties)) {
|
|
||||||
properties.type = default_type;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Retrieving viz information
|
|
||||||
if (_xml.hasViz)
|
|
||||||
properties.viz = _edgeViz(e);
|
|
||||||
|
|
||||||
properties.spell = _edgeSpell(e);
|
|
||||||
|
|
||||||
edges.push(Edge(properties, _xml.els.nodes));
|
|
||||||
});
|
|
||||||
|
|
||||||
return edges;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Spells from edges
|
|
||||||
function _edgeSpell(edge) {
|
|
||||||
var start = ( (_xml.timeformat !== "date") ? parseFloat(edge.getAttribute("start")) || -Infinity :
|
|
||||||
(edge.getAttribute('start') ? new Date(edge.getAttribute('start')) : -Infinity) );
|
|
||||||
|
|
||||||
var end = ( (_xml.timeformat !== "date") ? parseFloat(edge.getAttribute("end")) || Infinity :
|
|
||||||
(edge.getAttribute('end') ? new Date(edge.getAttribute('end')) : Infinity) );
|
|
||||||
|
|
||||||
return [start, end];
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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
|
|
||||||
//---------------------
|
|
||||||
_xml.model = _model();
|
|
||||||
|
|
||||||
return {
|
|
||||||
version: _xml.version,
|
|
||||||
mode: _xml.mode,
|
|
||||||
timeformat: _xml.timeformat,
|
|
||||||
defaultEdgeType: _xml.defaultEdgetype,
|
|
||||||
meta: _metaData(),
|
|
||||||
model: _xml.model,
|
|
||||||
nodes: _nodes(_xml.model),
|
|
||||||
links: _edges(_xml.defaultEdgetype)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Dynamics attributes parser.
|
|
||||||
* This structure parse a gexf string and return an object containing the
|
|
||||||
* dynamics attributes.
|
|
||||||
*
|
|
||||||
* @param {string} xml The xml string of the gexf file to parse.
|
|
||||||
* @return {object} The dynamics attributes and its values.
|
|
||||||
*/
|
|
||||||
function dynamicAttributes(xml, timeformat) {
|
|
||||||
|
|
||||||
var _xml = {};
|
|
||||||
|
|
||||||
_xml.els = {
|
|
||||||
nodes: xml.getElementsByTagName('node'),
|
|
||||||
attributes: xml.getElementsByTagName('attributes')
|
|
||||||
}
|
|
||||||
|
|
||||||
for ( var i = 0; i < _xml.els.attributes.length; i++ ) {
|
|
||||||
if (_xml.els.attributes[i].getAttribute("mode") === "dynamic")
|
|
||||||
_xml.els.attributes = _xml.els.attributes[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
var x = {};
|
|
||||||
for ( var i = 0; i < _xml.els.attributes.children.length; i++ ) {
|
|
||||||
var att = x[_xml.els.attributes.children[i].getAttribute("title")] = [];
|
|
||||||
|
|
||||||
var node = 0;
|
|
||||||
_helpers.nodeListEach(_xml.els.nodes, function(n) {
|
|
||||||
att[node] = { interval: [], index: node }
|
|
||||||
|
|
||||||
for ( var j = 0; j < n.getElementsByTagName('attvalue').length; j++ ) {
|
|
||||||
if (n.getElementsByTagName('attvalue')[j].getAttribute("for") === _xml.els.attributes.children[i].getAttribute("id")) {
|
|
||||||
|
|
||||||
var element = n.getElementsByTagName('attvalue')[j];
|
|
||||||
|
|
||||||
var start = ( (timeformat !== "date") ? parseFloat(element.getAttribute("start")) || -Infinity :
|
|
||||||
(element.getAttribute('start') ? new Date(element.getAttribute('start')) : -Infinity) );
|
|
||||||
|
|
||||||
var end = ( (timeformat !== "date") ? parseFloat(element.getAttribute("end")) || Infinity :
|
|
||||||
(element.getAttribute('end') ? new Date(element.getAttribute('end')) : Infinity) );
|
|
||||||
|
|
||||||
var value = element.getAttribute("value");
|
|
||||||
|
|
||||||
att[node].interval.push([start, end, value]);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
node++;
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return x;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function parseDynamicAttributes(gexf, timeformat) {
|
|
||||||
return dynamicAttributes(fetch(gexf), timeformat);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Exporting
|
|
||||||
* ----------
|
|
||||||
*/
|
|
||||||
this.GexfParser = {
|
|
||||||
|
|
||||||
// Functions
|
|
||||||
parse: parse,
|
|
||||||
fetch: fetchAndParse,
|
|
||||||
dynamic: parseDynamicAttributes,
|
|
||||||
|
|
||||||
// Version
|
|
||||||
version: '0.1'
|
|
||||||
};
|
|
||||||
|
|
||||||
}).call(this);
|
|
Loading…
Reference in New Issue
Block a user