X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=portal%2Fstatic%2Funbound_reservation_static%2Fjs%2Fnode-network.js;fp=portal%2Fstatic%2Funbound_reservation_static%2Fjs%2Fnode-network.js;h=f4724626d6292ecdf6e1f2d002e137dee301a2ae;hb=729a9dbb380b51a217194ba2a4e5978186fe50b0;hp=0000000000000000000000000000000000000000;hpb=c4bd5da6e2630eddf1262aa8d808dbb48b097d53;p=unfold.git
diff --git a/portal/static/unbound_reservation_static/js/node-network.js b/portal/static/unbound_reservation_static/js/node-network.js
new file mode 100644
index 00000000..f4724626
--- /dev/null
+++ b/portal/static/unbound_reservation_static/js/node-network.js
@@ -0,0 +1,492 @@
+/* ---------------------------------------------------------------------------
+ (c) Telef�nica I+D, 2013
+ Author: Paulo Villegas
+
+ This script is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+ -------------------------------------------------------------------------- */
+
+
+// For MSIE < 9, forget it
+function D3notok() {
+ document.getElementById('sidepanel').style.visibility = 'hidden';
+ var nocontent = document.getElementById('nocontent');
+ nocontent.style.visibility = 'visible';
+ nocontent.style.pointerEvents = 'all';
+ var t = document.getElementsByTagName('body');
+ var body = document.getElementsByTagName('body')[0];
+ body.style.backgroundImage = "url('movie-network-screenshot-d.png')";
+ body.style.backgroundRepeat = "no-repeat";
+}
+
+// -------------------------------------------------------------------
+// A number of forward declarations. These variables need to be defined since
+// they are attached to static code in HTML. But we cannot define them yet
+// since they need D3.js stuff. So we put placeholders.
+
+
+// Highlight a movie in the graph. It is a closure within the d3.json() call.
+var selectNode = undefined;
+
+// Change status of a panel from visible to hidden or viceversa
+var toggleDiv = undefined;
+
+// Clear all help boxes and select a movie in network and in movie details panel
+var clearAndSelect = undefined;
+
+
+// The call to set a zoom value -- currently unused
+// (zoom is set via standard mouse-based zooming)
+var zoomCall = undefined;
+
+
+// -------------------------------------------------------------------
+
+// Do the stuff -- to be called after D3.js has loaded
+function D3ok(Network) {
+
+
+$("#graph").empty();
+d3.select("#graph").remove("svg:svg");
+
+ // Some constants
+ var WIDTH = 790,
+ HEIGHT = 957
+ SHOW_THRESHOLD = 2.5;
+
+ // Variables keeping graph state
+ var activeMovie = undefined;
+ var currentOffset = { x : 0, y : 0 };
+ var currentZoom = 1.0;
+
+ // The D3.js scales
+ var xScale = d3.scale.linear()
+ .domain([0, WIDTH])
+ .range([0, WIDTH]);
+ var yScale = d3.scale.linear()
+ .domain([0, HEIGHT])
+ .range([0, HEIGHT]);
+ var zoomScale = d3.scale.linear()
+ .domain([1,6])
+ .range([1,6])
+ .clamp(true);
+
+/* .......................................................................... */
+
+ // The D3.js force-directed layout
+ var force = d3.layout.force()
+ .charge(-320)
+ .size( [WIDTH, HEIGHT] )
+ .linkStrength( function(d,idx) { return d.weight; } );
+
+ // Add to the page the SVG element that will contain the movie network
+ var svg = d3.select("#netcanvas").append("svg:svg")
+ .attr('xmlns','http://www.w3.org/2000/svg')
+ .attr("width", WIDTH)
+ .attr("height", HEIGHT)
+ .attr("id","graph")
+ .attr("viewBox", "0 0 " + WIDTH + " " + HEIGHT )
+ .attr("preserveAspectRatio", "xMidYMid meet");
+
+ // Movie panel: the div into which the movie details info will be written
+ nodeInfoDiv = d3.select("#nodeInfo");
+
+ /* ....................................................................... */
+
+ // Get the current size & offset of the browser's viewport window
+ function getViewportSize( w ) {
+ var w = w || window;
+ if( w.innerWidth != null )
+ return { w: w.innerWidth,
+ h: w.innerHeight,
+ x : w.pageXOffset,
+ y : w.pageYOffset };
+ var d = w.document;
+ if( document.compatMode == "CSS1Compat" )
+ return { w: d.documentElement.clientWidth,
+ h: d.documentElement.clientHeight,
+ x: d.documentElement.scrollLeft,
+ y: d.documentElement.scrollTop };
+ else
+ return { w: d.body.clientWidth,
+ h: d.body.clientHeight,
+ x: d.body.scrollLeft,
+ y: d.body.scrollTop};
+ }
+
+
+
+ function getQStringParameterByName(name) {
+ var match = RegExp('[?&]' + name + '=([^&]*)').exec(window.location.search);
+ return match && decodeURIComponent(match[1].replace(/\+/g, ' '));
+ }
+
+
+ /* Change status of a panel from visible to hidden or viceversa
+ id: identifier of the div to change
+ status: 'on' or 'off'. If not specified, the panel will toggle status
+ */
+ toggleDiv = function( id, status ) {
+ d = d3.select('div#'+id);
+ if( status === undefined )
+ status = d.attr('class') == 'panel_on' ? 'off' : 'on';
+ d.attr( 'class', 'panel_' + status );
+ return false;
+ }
+
+
+ /* Clear all help boxes and select a movie in the network and in the
+ movie details panel
+ */
+ clearAndSelect = function (id) {
+ toggleDiv('faq','off');
+ toggleDiv('help','off');
+ selectNode(id,true); // we use here the selectNode() closure
+ }
+
+
+ /* Compose the content for the panel with movie details.
+ Parameters: the node data, and the array containing all nodes
+ */
+ function getnodeInfo( n, nodeArray ) {
+
+// $.each(n, function(key, element) {
+// alert('key: ' + key + '\n' + 'value: ' + element);
+//});
+ info = '
';
+ if( n.cover )
+ info += '
';
+ else
+ info += '
' + n.title + '
';
+ info +=
+ '
' +
+ '
';
+
+ info += '
'
+ if( n.ip_version )
+ info += '
IP version: '
+ + n.ip_version + '
';
+ if( n.select_type )
+ info += '
Node Type: '
+ + n.select_type + '
';
+ if( n.request_type )
+ info += '
Request Type: '
+ + n.request_type + '
';
+ if( n.select_comm_proto )
+ info += '
Image: ' + n.select_image
+ + 'Communication Protocol: '
+ + n.select_comm_proto + '
';
+ if( n.links ) {
+ info += '
';
+ }
+ return info;
+ }
+
+
+ // *************************************************************************
+
+////////// d3.json(
+////////// 'movie-network-25-7-3.json',
+////////// function(data) {
+ var data=Network;
+ // Declare the variables pointing to the node & link arrays
+ var nodeArray = data.nodes;
+ var linkArray = data.links;
+ //alert(linkArray);
+ //alert(nodeArray);
+ minLinkWeight =
+ Math.min.apply( null, linkArray.map( function(n) {return n.weight;} ) );
+ maxLinkWeight =
+ Math.max.apply( null, linkArray.map( function(n) {return n.weight;} ) );
+
+ // Add the node & link arrays to the layout, and start it
+ force
+ .nodes(nodeArray)
+ .links(linkArray)
+ .start();
+
+ // A couple of scales for node radius & edge width
+ var node_size = d3.scale.linear()
+ .domain([5,10]) // we know score is in this domain
+ .range([1,16])
+ .clamp(true);
+ var edge_width = d3.scale.pow().exponent(8)
+ .domain( [minLinkWeight,maxLinkWeight] )
+ .range([1,3])
+ .clamp(true);
+
+ /* Add drag & zoom behaviours */
+ svg.call( d3.behavior.drag()
+ .on("drag",dragmove) );
+ svg.call( d3.behavior.zoom()
+ .x(xScale)
+ .y(yScale)
+ .scaleExtent([1, 6])
+ .on("zoom", doZoom) );
+
+ // ------- Create the elements of the layout (links and nodes) ------
+
+ var networkGraph = svg.append('svg:g').attr('class','grpParent');
+
+ // links: simple lines
+ var graphLinks = networkGraph.append('svg:g').attr('class','grp gLinks')
+ .selectAll("line")
+ .data(linkArray, function(d) {return d.source.id+'-'+d.target.id;} )
+ .enter().append("line")
+ .style('stroke-width', function(d) { return edge_width(d.weight);} )
+ .attr("class", "link");
+
+ // nodes: an SVG circle
+ var graphNodes = networkGraph.append('svg:g').attr('class','grp gNodes')
+ .selectAll("circle")
+ .data( nodeArray, function(d){return d.label} )
+ .enter().append("svg:circle")
+ .attr('id', function(d) { return "c" + d.index; } )
+ .attr('class', function(d) { return 'node level'+d.level;} )
+ .attr('r', function(d) { return node_size(d.score); } )
+ .attr('pointer-events', 'all')
+ //.on("click", function(d) { highlightGraphNode(d,true,this); } )
+ .on("click", function(d) { showMoviePanel(d); } )
+ .on("mouseover", function(d) { highlightGraphNode(d,true,this); } )
+ .on("mouseout", function(d) { highlightGraphNode(d,false,this); } );
+
+ // labels: a group with two SVG text: a title and a shadow (as background)
+ var graphLabels = networkGraph.append('svg:g').attr('class','grp gLabel')
+ .selectAll("g.label")
+ .data( nodeArray, function(d){return d.label} )
+ .enter().append("svg:g")
+ .attr('id', function(d) { return "l" + d.index; } )
+ .attr('class','label');
+
+ shadows = graphLabels.append('svg:text')
+ .attr('x','-2em')
+ .attr('y','-.3em')
+ .attr('pointer-events', 'none') // they go to the circle beneath
+ .attr('id', function(d) { return "lb" + d.index; } )
+ .attr('class','nshadow')
+ .text( function(d) { return d.label; } );
+
+ labels = graphLabels.append('svg:text')
+ .attr('x','-2em')
+ .attr('y','-.3em')
+ .attr('pointer-events', 'none') // they go to the circle beneath
+ .attr('id', function(d) { return "lf" + d.index; } )
+ .attr('class','nlabel')
+ .text( function(d) { return d.label; } );
+
+
+ /* --------------------------------------------------------------------- */
+ /* Select/unselect a node in the network graph.
+ Parameters are:
+ - node: data for the node to be changed,
+ - on: true/false to show/hide the node
+ */
+ function highlightGraphNode( node, on )
+ {
+ //if( d3.event.shiftKey ) on = false; // for debugging
+
+ // If we are to activate a movie, and there's already one active,
+ // first switch that one off
+ if( on && activeMovie !== undefined ) {
+ highlightGraphNode( nodeArray[activeMovie], false );
+ }
+
+ // locate the SVG nodes: circle & label group
+ circle = d3.select( '#c' + node.index );
+ label = d3.select( '#l' + node.index );
+
+ // activate/deactivate the node itself
+ circle
+ .classed( 'main', on );
+ label
+ .classed( 'on', on || currentZoom >= SHOW_THRESHOLD );
+ label.selectAll('text')
+ .classed( 'main', on );
+
+ // activate all siblings
+ Object(node.links).forEach( function(id) {
+ d3.select("#c"+id).classed( 'sibling', on );
+ label = d3.select('#l'+id);
+ label.classed( 'on', on || currentZoom >= SHOW_THRESHOLD );
+ label.selectAll('text.nlabel')
+ .classed( 'sibling', on );
+ } );
+
+ // set the value for the current active movie
+ activeMovie = on ? node.index : undefined;
+ }
+
+
+ /* --------------------------------------------------------------------- */
+ /* Show the details panel for a movie AND highlight its node in
+ the graph. Also called from outside the d3.json context.
+ Parameters:
+ - new_idx: index of the movie to show
+ - doMoveTo: boolean to indicate if the graph should be centered
+ on the movie
+ */
+ selectNode = function( new_idx, doMoveTo ) {
+
+ // do we want to center the graph on the node?
+ doMoveTo = doMoveTo || false;
+ if( doMoveTo ) {
+ s = getViewportSize();
+ width = s.w
=SHOW_THRESHOLD )
+ svg.selectAll("g.label").classed('on',true);
+ else if( currentZoom>=SHOW_THRESHOLD && newZoom