1<div id="netmap_pane_tooltip" class="net_gobrechts_d3_force_tooltip" style="top: 0px; left: 0px;"></div> 2<script> 3 4// *********************************************** 5// ************ retrieve network map ************* 6// *********************************************** 7 8$.getJSON('[% uri_for('/ajax/data/device/netmap') | none %]?[% my_query | none %]', function(mapdata) { 9 10 jQuery(document).ready(function() { 11 window.graph = netGobrechtsD3Force('netmap_pane') 12 // .debug(true) 13 .width( parseInt(jQuery('#netmap_pane').parent().css('width')) ) 14 .height( window.innerHeight - 100 ) 15 .showSelfLinks(true) 16 .wrapLabels(true) 17 .lassoMode(true) 18 .dragMode(true) 19 .zoomMode(true) 20 .pinMode(true) 21 [% '.showLegend(false)' UNLESS (params.colorby == 'hgroup' OR params.colorby == 'lgroup') %] 22 .showLinkDirection(false) 23 .colorScheme('color10') 24 //.preventLabelOverlappingOnForceEnd( 25 // (mapdata['newnodes'] && ('[% params.mapshow | html_entity %]' == 'neighbors')) 26 // ? true : false 27 //) 28 .nodeEventToStopPinMode('none') 29 .showTooltips(true) 30 .tooltipPosition('svgTopLeft') 31 .nodeEventToOpenLink('dblclick') 32 .nodeLinkTarget('none') 33 .minNodeRadius(4) 34 .maxNodeRadius(4 + (mapdata['numsizes'] || 0)) 35 .minZoomFactor(0.1) 36 .maxZoomFactor(10) 37 .labelDistance(2) 38 .linkDistance(120) 39 .charge(-550) 40 .gravity(0.3); 41 42 graph['nd2'] = {}; 43 graph['nd2']['centernode'] = mapdata['centernode']; 44 graph['nd2']['dragging'] = false; 45 46 // *************************************** 47 // *********** fullscreen icon *********** 48 // *************************************** 49 50 graph.inspect().dom.svg 51 .append("g") 52 .attr("id", "nd2_netmap-fullscreen-container") 53 .attr("transform", "translate(" + (graph.width() - 17) + ",17)") 54 .append("svg:text") 55 .attr("id", "nd2_netmap-fullscreen") 56 .attr("class", "link") 57 .attr("text-anchor", "start") 58 .attr("font-family", "FontAwesome") 59 .text('\uf065') 60 .on("click", function() { 61 requestFullScreen(document.getElementById('netmap_pane')); 62 }); 63 64 // ************************************************** 65 // *********** force running spinner icon *********** 66 // ************************************************** 67 68 graph.inspect().dom.svg 69 .append("g") 70 .attr("id", "nd2_netmap-spinner-container") 71 .attr("transform", "translate(" + (graph.width() - 15) + "," + (graph.height() - 15) + ")") 72 .append("path") 73 .attr("id", "nd2_netmap-spinner"); 74 75 graph.inspect().main.force.on('start.nd2spinner', function() { 76 d3.select("#nd2_netmap-spinner").call(spin); 77 }); 78 79 // **************************************************** 80 // *********** link labels that track links *********** 81 // **************************************************** 82 83 graph.inspect().main.force.on('tick.movelinklabel', function() { 84 graph.inspect().dom.svg.selectAll('text.nd_netmap-linklabel') 85 .attr('x', function(d) { 86 var sx = graph.nodeDataById($(this).attr('data-source')); 87 var tx = graph.nodeDataById($(this).attr('data-target')); 88 if (!(sx && tx)) { return 0 } 89 return ((sx.x + tx.x) / 2); 90 }) 91 .attr('y', function(d) { 92 var sy = graph.nodeDataById($(this).attr('data-source')); 93 var ty = graph.nodeDataById($(this).attr('data-target')); 94 if (!(sy && ty)) { return 0 } 95 return ((sy.y + ty.y) / 2); 96 }); 97 }); 98 99 graph.inspect().main.force.on('start.movelinklabel', function() { 100 mapdata['data']['links'].forEach(function(link) { 101 graph.inspect().dom.svg.select('g.graph') 102 .append('svg:text') 103 .attr('class', 'nd_netmap-linklabel') 104 .attr('data-source', link['FROMID']) 105 .attr('data-target', link['TOID']) 106 .attr('text-anchor', 'middle') 107 [% ".attr('fill', 'black')" IF params.showspeed %] 108 .text(link['SPEED']); 109 }); 110 111 graph.inspect().main.force.on('start.movelinklabel', null); 112 }); 113 114 // ********************************************************** 115 // ********* node lasso and group-dragging support ********** 116 // ********************************************************** 117 118 graph.inspect().main.force.on('start.draggednode', function() { 119 graph.inspect().main.nodes.on('mousedown.dragall', function(n) { 120 if (this.nodeName !== 'circle') { return } 121 graph['nd2']['dragging'] = true; 122 graph['nd2']['dragStartX'] = n.x; 123 graph['nd2']['dragStartY'] = n.y; 124 graph['nd2']['draggedNode'] = n.index; 125 console.log(graph['nd2']); 126 }); 127 128 graph.inspect().main.nodes.on('mousemove.dragall', function(draggedNode) { 129 var evt = window.event; 130 if (!("buttons" in evt) || (evt.buttons !== 1)) { return } 131 if (!(graph['nd2']['dragging']) || !(graph['nd2']['draggedNode'])) { return } 132 if (draggedNode.index !== graph['nd2']['draggedNode']) { return } 133 134 var dx = (draggedNode.x - graph['nd2']['dragStartX']), 135 dy = (draggedNode.y - graph['nd2']['dragStartY']); 136 graph['nd2']['dragStartX'] += dx; 137 graph['nd2']['dragStartY'] += dy; 138 139 graph.inspect().main.nodes 140 .filter(function(n) { return (n.selected && (n.index !== draggedNode.index)) }) 141 .each(function(n) { 142 n.x += dx; n.y += dy; 143 n.px += dx; n.py += dy; 144 }); 145 }); 146 147 graph.inspect().main.nodes.on('mouseup.dragall', function(n) { 148 graph['nd2']['dragging'] = false; 149 }); 150 151 graph.inspect().main.force.on('start.draggednode', null); 152 }); 153 154 // ***************************** 155 // ********* DO IT!! *********** 156 // ***************************** 157 158 graph.start(mapdata); 159 160 // about a second after render starts, zoom in a bit 161 if ('[% params.mapshow | html_entity %]' == 'neighbors') { 162 setTimeout(function() { 163 //if ('[% params.dynamicsize | html_entity %]' == 'on') { 164 // graph.zoomToFit(); 165 //} else { 166 var node = graph.nodeDataById( graph['nd2']['centernode'] ); 167 graph.zoomSmooth(node.x, node.y, node.radius * 125); 168 //} 169 }, 1500); 170 } 171 }); // document.onReady 172 173}); // getJSON 174 175// *********************************************** 176// ******** force engine status spinner ********* 177// *********************************************** 178 179var radius = 12; 180var tau = 2 * Math.PI; 181 182var arc = d3.svg.arc() 183 .innerRadius(radius * 0.5) 184 .outerRadius(radius * 0.8) 185 .startAngle(0) 186 .endAngle(0.33 * tau); 187 188var circle = d3.svg.arc() 189 .innerRadius(radius * 0.5) 190 .outerRadius(radius * 0.8) 191 .startAngle(0) 192 .endAngle(tau); 193 194function spin(selection, duration) { 195 duration = duration || 1500; 196 if (! graph.inspect().status.forceRunning) { 197 d3.select('#nd2_netmap-spinner').style('fill', '#CCFFCC').attr('d', circle); 198 saveMapPositions(); 199 return; 200 } 201 d3.select('#nd2_netmap-spinner').style('fill', '#FFE4B5').attr('d', arc); 202 selection.transition() 203 .ease("linear") 204 .duration(duration) 205 .attrTween("transform", function() { 206 return d3.interpolateString("rotate(0)", "rotate(360)"); 207 }); 208 setTimeout(function() { spin(selection, duration); }, duration); 209} 210 211// ******************************************************** 212// ********* save new node positions back to DB *********** 213// ******************************************************** 214 215function saveMapPositions() { 216 graph.inspect().main.nodes.each(function(n) { n.fixed = true }); 217 $.post( 218 '[% uri_for('/ajax/data/device/netmappositions') | none %]' 219 ,$("#nd_vlan-entry, #nd_hgroup-select, #nd_lgroup-select, #nq, input[name='mapshow']").serialize() 220 + '&positions=' + JSON.stringify(graph.positions()) 221 ); 222 // toastr.success('Saved map positions.'); 223} 224 225// *********************************************** 226// ************ full screen handling ************* 227// *********************************************** 228 229function isFullScreen() { 230 return (document.webkitFullscreenElement || document.mozFullScreenElement || document.fullscreenElement); 231} 232 233function requestFullScreen(elt) { 234 if (isFullScreen()) { 235 if (document.exitFullscreen) { 236 document.exitFullscreen(); 237 } else if (document.msExitFullscreen) { 238 document.msExitFullscreen(); 239 } else if (document.mozCancelFullScreen) { 240 document.mozCancelFullScreen(); 241 } else if (document.webkitExitFullscreen) { 242 document.webkitExitFullscreen(); 243 } 244 } 245 else { 246 if (elt.requestFullscreen) { 247 elt.requestFullscreen(); 248 } else if (elt.msRequestFullscreen) { 249 elt.msRequestFullscreen(); 250 } else if (elt.mozRequestFullScreen) { 251 elt.mozRequestFullScreen(); 252 } else if (elt.webkitRequestFullscreen) { 253 elt.webkitRequestFullscreen(); 254 } 255 } 256} 257 258$(document).on('webkitfullscreenchange mozfullscreenchange fullscreenchange', function() { 259 resizeGraphContainer(); 260 $('#nd2_netmap-fullscreen').text(function() { 261 return (isFullScreen() ? '\uf066' : '\uf065'); 262 }); 263}); 264 265// ************************************************** 266// ************ react to sidebar in/out ************* 267// ************************************************** 268 269// custom resize function as there is no event to fire and we need 270// to react to the sidebar. 271function resizeGraphContainer() { 272 setTimeout(function(){ 273 var netmap_pane = jQuery('#netmap_pane'); 274 graph.width( parseInt(netmap_pane.parent().css('width')) ).resume(); 275 graph.height( window.innerHeight - 100 ).resume(); 276 d3.select("#nd2_netmap-spinner-container").attr("transform", 277 "translate(" + (graph.width() - 15) + "," + (graph.height() - 15) + ")"); 278 d3.select("#nd2_netmap-fullscreen-container").attr("transform", 279 "translate(" + (graph.width() - 17) + ",17)"); 280 }, 500) 281} 282 283$('#nd_sidebar-toggle-img-in').on("click", resizeGraphContainer); 284$('#nd_sidebar-toggle-img-out').on("click", resizeGraphContainer); 285$(window).on("resize", resizeGraphContainer); 286 287// vim: ft=javascript 288</script> 289