http://git-wip-us.apache.org/repos/asf/flink-web/blob/9ec0a879/content/visualizer/js/graphCreator.js
----------------------------------------------------------------------
diff --git a/content/visualizer/js/graphCreator.js 
b/content/visualizer/js/graphCreator.js
new file mode 100755
index 0000000..86c8c81
--- /dev/null
+++ b/content/visualizer/js/graphCreator.js
@@ -0,0 +1,445 @@
+/*!
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Document initialization.
+ */
+$(document).ready(function () 
+{
+       zoom = d3.behavior.zoom("#svg-main").on("zoom", function() {
+               var ev = d3.event;
+               d3.select("#svg-main g")
+                       .attr("transform", "translate(" + ev.translate + ") 
scale(" + ev.scale + ")");
+               });
+       zoom.scaleExtent([0.3, 3])
+});
+
+//The current JSON file
+var JSONData; 
+//The informations for the iterations
+var iterationIds = new Array();
+var iterationGraphs = new Array();
+var iterationWidths = new Array();
+var iterationHeights = new Array();
+
+//The zoom element
+var zoom;
+//informations about the enviroment
+var svgWidth;
+var svgHeight;
+
+//Renders and draws the graph
+function drawGraph(data, svgID){
+       JSONData = data;
+       
+       //First step: precompute all iteration graphs
+       
+       //find all iterations
+       iterationNodes = searchForIterationNodes();
+       
+       //add the graphs of iterations and their sizes + Ids to arrays
+       if (iterationNodes != null) {
+               for (var i in iterationNodes) {
+                       var itNode = iterationNodes[i];
+                       iterationIds.push(itNode.id);
+                       var g0 = loadJsonToDagre(itNode);
+                       iterationGraphs.push(g0);
+                   var r = new dagreD3.Renderer();
+                       var l = dagreD3.layout()
+                                .nodeSep(20)
+                                .rankDir("LR");
+                   l = r.layout(l).run(g0, d3.select("#svg-main"));
+               
+                       iterationWidths.push(l._value.width);
+                       iterationHeights.push(l._value.height);
+                       
+                       //Clean svg
+                       $("#svg-main g").empty();
+               }
+       }
+               
+       //Continue normal
+       var g = loadJsonToDagre(data);
+       var selector = svgID + " g";
+       var renderer = new dagreD3.Renderer();
+       var layout = dagreD3.layout()
+                           .nodeSep(20)
+                           .rankDir("LR");
+       var svgElement = d3.select(selector);
+       layout = renderer.layout(layout).run(g, svgElement);
+       
+       svgHeight = layout._value.height;
+       svgWidth = layout._value.width;
+       
+        var svg = d3.select("#svg-main")
+               .attr("width", $(document).width() - 15)
+               .attr("height", $(document).height() - 15 - 110)
+//             .attr("viewBox", "0 0 "+ ($(document).width() - 150) +" 
"+($(document).height() - 15 - 110))
+               .call(zoom);
+               
+       // This should now draw the precomputed graphs in the svgs... . 
+       
+       for (var i in iterationIds) {
+               var workset = searchForNode(iterationIds[i]);
+               renderer = new dagreD3.Renderer();
+               layout = dagreD3.layout()
+                    .nodeSep(20)
+                    .rankDir("LR");
+           selector = "#svg-"+iterationIds[i]+" g";
+           svgElement = d3.select(selector);
+           layout = renderer.layout(layout).run(iterationGraphs[i], 
svgElement);
+       }
+               
+       //enable Overlays and register function for overlay-infos
+       $("a[rel]").overlay({ 
+               onBeforeLoad: function(){ 
+                       var id = this.getTrigger().attr("nodeID")
+                       showProperties(id);
+               }
+       });
+       
+       }
+
+//Creates the dagreD3 graph object
+//Responsible for adding nodes and edges
+function loadJsonToDagre(data){
+       
+       //stores all nodes that are in current graph -> no edges to nodes which 
are outside of current iterations!
+       var existingNodes = new Array;
+       
+       var g = new dagreD3.Digraph();
+       
+       //Find out whether we are in an iteration or in the normal json 
+       //Bulk variables
+       var partialSolution;
+       var nextPartialSolution;
+       //Workset variables
+       var workset;
+       var nextWorkset;
+       var solutionSet;
+       var solutionDelta;
+
+       if (data.nodes != null) {
+               //This is the normal json data
+               var toIterate = data.nodes;
+       } else {
+               //This is an iteration, we now store special iteration nodes if 
possible
+               var toIterate = data.step_function;
+               partialSolution = data.partial_solution;
+               nextPartialSolution = data.next_partial_solution;
+               workset = data.workset;
+               nextWorkset = data.next_workset;
+               solutionSet = data.solution_set;
+               solutionDelta = data.solution_delta;
+       }
+       
+       for (var i in toIterate) {
+               var el = toIterate[i];
+               //create node, send additional informations about the node if 
it is a special one
+               if (el.id == partialSolution) {
+                       g.addNode(el.id, { label: createLabelNode(el, 
"partialSolution"), nodesWithoutEdges: ""} );
+               } else if (el.id == nextPartialSolution) {
+                       g.addNode(el.id, { label: createLabelNode(el, 
"nextPartialSolution"), nodesWithoutEdges: ""} );
+               } else if (el.id == workset) {
+                       g.addNode(el.id, { label: createLabelNode(el, 
"workset"), nodesWithoutEdges: ""} );
+               } else if (el.id == nextWorkset) {
+                       g.addNode(el.id, { label: createLabelNode(el, 
"nextWorkset"), nodesWithoutEdges: ""} );
+               } else if (el.id == solutionSet) {
+                       g.addNode(el.id, { label: createLabelNode(el, 
"solutionSet"), nodesWithoutEdges: ""} );
+               } else if (el.id == solutionDelta) {
+                       g.addNode(el.id, { label: createLabelNode(el, 
"solutionDelta"), nodesWithoutEdges: ""} );
+               } else {
+                       g.addNode(el.id, { label: createLabelNode(el, ""), 
nodesWithoutEdges: ""} );
+               }
+               existingNodes.push(el.id);
+               
+               //create edgdes from predecessors to current node
+               if (el.predecessors != null) {
+                       for (var j in el.predecessors) {
+                               if 
(existingNodes.indexOf(el.predecessors[j].id) != -1) {
+                                       g.addEdge(null, el.predecessors[j].id, 
el.id, { label: createLabelEdge(el.predecessors[j]) });  
+                               } else {
+                                       var missingNode = 
searchForNode(el.predecessors[j].id);
+                                       if (missingNode.alreadyAdded != true) {
+                                               missingNode.alreadyAdded = true;
+                                               g.addNode(missingNode.id, 
{label: createLabelNode(missingNode, "mirror")});
+                                               g.addEdge(null, missingNode.id, 
el.id, { label: createLabelEdge(missingNode) });
+                                       }
+                               }
+                       }
+               }
+       }       
+       return g;
+}
+
+//create a label of an edge
+function createLabelEdge(el) {
+       var labelValue = "";
+       
+       if (el.ship_strategy != null || el.local_strategy != null) {
+               labelValue += "<div style=\"font-size: 100%; border:2px solid; 
padding:5px\">";
+               if (el.ship_strategy != null) {
+                       labelValue += el.ship_strategy;
+               }
+               if (el.temp_mode != undefined) {
+                       labelValue += " (" + el.temp_mode + ")";
+               }
+               if (el.local_strategy != undefined) {
+                       labelValue += ",<br>" + el.local_strategy;
+               }
+               labelValue += "</div>";
+       }
+       
+       return labelValue;
+}
+
+//creates the label of a node, in info is stored, whether it is a special node 
(like a mirror in an iteration)
+function createLabelNode(el, info) {
+//     if (info != "") {
+//             console.log("The node " + el.id + " is a " + info);     
+//     }
+       
+       //true, if the node is a special node from an iteration
+       var specialIterationNode = (info == "partialSolution" || info == 
"nextPartialSolution" || info == "workset" || info == "nextWorkset" || info == 
"solutionSet" || info == "solutionDelta" );
+       
+       var labelValue = "<div style=\"margin-top: 0\">";
+       //set color of panel
+       if (info == "mirror") {
+               labelValue += "<div style=\"border-color:#a8a8a8; 
border-width:4px; border-style:solid\">";
+       } else if (specialIterationNode) {
+               labelValue += "<div style=\"border-color:#CD3333; 
border-width:4px; border-style:solid\">";
+       } else {
+               //there is no info value, set normal color
+               if (el.pact == "Data Source") {
+                       labelValue += "<div style=\"border-color:#4ce199; 
border-width:4px; border-style:solid\">";
+               } else if (el.pact == "Data Sink") {
+                       labelValue += "<div style=\"border-color:#e6ec8b; 
border-width:4px; border-style:solid\">";
+               } else {
+                       labelValue += "<div style=\"border-color:#3fb6d8; 
border-width:4px; border-style:solid\">";
+               }
+       }
+       //Nodename
+       if (info == "mirror") {
+               labelValue += "<div><a nodeID=\""+el.id+"\" href=\"#\" 
rel=\"#propertyO\"><h3 style=\"text-align: center; "
+               + "font-size: 150%\">Mirror of " + el.pact + " (ID = 
"+el.id+")</h3></a>";
+       } else {
+               labelValue += "<div><a nodeID=\""+el.id+"\" href=\"#\" 
rel=\"#propertyO\"><h3 style=\"text-align: center; "
+               + "font-size: 150%\">" + el.pact + " (ID = "+el.id+")</h3></a>";
+       }
+       if (el.contents == "") {
+               labelValue += "</div>";
+       } else {
+               var stepName = el.contents;
+               //clean stepName
+               stepName = shortenString(stepName);
+               labelValue += "<h4 style=\"text-align: center; font-size: 
130%\">" + stepName + "</h4></div>";
+       }
+       
+       //If this node is an "iteration" we need a different panel-body
+       if (el.step_function != null) {
+               labelValue += extendLabelNodeForIteration(el.id);
+       } else {
+               //Otherwise add infos           
+               if (specialIterationNode) {
+                       labelValue += "<h5 style=\"font-size:115%; text-align: 
center; color:#CD3333\">" + info + " Node</h5>";
+               }
+               
+               if (el.parallelism != "") {
+                       labelValue += "<h5 
style=\"font-size:115%\">Parallelism: " + el.parallelism + "</h5>";
+               }
+       
+               if (el.driver_strategy != undefined) {
+                       labelValue += "<h5 style=\"font-size:115%\">Driver 
Strategy: " + el.driver_strategy + "</h5";
+               }
+               
+       }
+       //close divs
+       labelValue += "</div></div>";
+       return labelValue;
+}
+
+//Extends the label of a node with an additional svg Element to present the 
iteration.
+function extendLabelNodeForIteration(id) {
+       var svgID = "svg-" + id;
+
+       //Find out the position of the iterationElement in the 
iterationGraphArray
+       var index = iterationIds.indexOf(id);
+       //Set the size and the width of the svg Element as precomputetd
+       var width = iterationWidths[index] + 70;
+       var height = iterationHeights[index] + 40;
+       
+       var labelValue = "<div id=\"attach\"><svg id=\""+svgID+"\" 
width="+width+" height="+height+"><g transform=\"translate(20, 
20)\"/></svg></div>";
+       return labelValue;
+}
+
+//presents properties for a given nodeID in the propertyCanvas overlay
+function showProperties(nodeID) {
+       $("#propertyCanvas").empty();
+       node = searchForNode(nodeID);
+       var phtml = "<div style='overflow-y: scroll; max-height:490px; 
overflow-x:hidden'><h3>Properties of "+ shortenString(node.contents) + " - ID = 
" + nodeID + "</h3>";
+       phtml += "<div class=\"row\">";
+       
+       phtml += "<div class=\"col-sm-12\"><h4>Pact Properties</h4>";
+       phtml += "<table class=\"table\">";
+       phtml += tableRow("Operator", (node.driver_strategy == undefined ? 
"None" : node.driver_strategy));
+       phtml += tableRow("Parallelism", (node.parallelism == undefined ? 
"None" : node.parallelism));
+       phtml += tableRow("Subtasks-per-instance", (node.subtasks_per_instance 
== undefined ? "None" : node.subtasks_per_instance));
+       phtml += "</table></div>";
+       
+       phtml += "<div class=\"col-sm-12\"><h4>Global Data Properties</h4>";
+       phtml += "<table class=\"table\">";
+       if (node.global_properties != null) {
+               for (var i = 0; i < node.global_properties.length; i++) {
+               var prop = node.global_properties[i];
+               phtml += tableRow((prop.name == undefined ? '(unknown)' : 
prop.name),(prop.value == undefined ? "(none)" : prop.value));
+           }
+       } else {
+               phtml += tableRow("Global Properties", "None");
+       }
+       phtml += "</table></div>";
+
+       phtml += "<div class=\"col-sm-12\"><h4>Local Data Properties</h4>";
+       phtml += "<table class=\"table\">";
+       if (node.local_properties != null) {
+               for (var i = 0; i < node.local_properties.length; i++) {
+                       var prop = node.local_properties[i];
+               phtml += tableRow((prop.name == undefined ? '(unknown)' : 
prop.name),(prop.value == undefined ? "(none)" : prop.value));
+           }
+       } else {
+               phtml += tableRow("Local Properties", "None");
+       }
+       phtml += "</table></div></div>";
+       
+       phtml += "<div class=\"row\">";
+       phtml += "<div class=\"col-sm-12\"><h4>Size Estimates</h4>";
+       phtml += "<table class=\"table\">";
+       if (node.estimates != null) {
+               for (var i = 0; i < node.estimates.length; i++) {
+                       var prop = node.estimates[i];
+                       phtml += tableRow((prop.name == undefined ? '(unknown)' 
: prop.name),(prop.value == undefined ? "(none)" : prop.value));
+               }
+       } else {
+               phtml += tableRow("Size Estimates", "None");
+       }
+       phtml += "</table></div>";
+       
+       phtml += "<div class=\"col-sm-12\"><h4>Cost Estimates</h4>";    
+       phtml += "<table class=\"table\">";
+       if (node.costs != null) {
+               for (var i = 0; i < node.costs.length; i++) {
+               var prop = node.costs[i];
+               phtml += tableRow((prop.name == undefined ? '(unknown)' : 
prop.name),(prop.value == undefined ? "(none)" : prop.value));
+               }
+       } else {
+               phtml += tableRow("Cost Estimates", "None");
+       }
+       phtml += "</table></div>";
+       
+       phtml += "</div></div>";
+       $("#propertyCanvas").append(phtml);
+       
+}
+
+//searches in the global JSONData for the node with the given id
+function searchForNode(nodeID) {
+       for (var i in JSONData.nodes) {
+               var el = JSONData.nodes[i];
+               if (el.id == nodeID) {
+                       return el;
+               }
+               //look for nodes that are in iterations
+               if (el.step_function != null) {
+                       for (var j in el.step_function) {
+                               if (el.step_function[j].id == nodeID) {
+                                       return el.step_function[j];     
+                               }
+                       }       
+               }
+       }
+}
+
+//searches for all nodes in the global JSONData, that are iterations
+function searchForIterationNodes() {
+       var itN = new Array();
+       for (var i in JSONData.nodes) {
+               var el = JSONData.nodes[i];
+               if (el.step_function != null) {
+                       itN.push(el);
+               }
+       }
+       return itN;
+}
+
+//creates a row for a table with two collums
+function tableRow(nameX, valueX) {
+       var htmlCode = "";
+       htmlCode += "<tr><td align=\"left\">" + nameX + "</td><td 
align=\"right\">" + valueX + "</td></tr>";
+       return htmlCode;
+}
+
+//Split a string into multiple lines so that each line has less than 30 
letters.
+function shortenString(s) {
+       //make sure that name does not contain a < (because of html)
+       if (s.charAt(0) == "<") {
+                       s = s.replace("<", "&lt;");
+                       s = s.replace(">", "&gt;");
+       }
+       
+       sbr = ""
+       while (s.length > 30) {
+               sbr = sbr + s.substring(0, 30) + "<br>"
+               s = s.substring(30, s.length)
+       }
+       sbr = sbr + s
+
+       return sbr;
+}
+
+//activates the zoom buttons
+function activateZoomButtons() {
+       $("#zoomIn").click(function() {
+       console.log("Clicked zoom in");
+         if (zoom.scale() < 2.99) {    
+                               var svg = d3.select("#svg-main");
+                               //Calculate and store new values in zoom object
+                               var translate = zoom.translate();
+                               var v1 = translate[0] * (zoom.scale() + 0.1 / 
(zoom.scale()));
+                               var v2 = translate[1] * (zoom.scale() + 0.1 / 
(zoom.scale()));
+                               zoom.scale(zoom.scale() + 0.1);
+                               zoom.translate([v1, v2]);
+                               //Transform svg
+                               svg.select("#svg-main g")
+                               .attr("transform", "translate(" + v1 + ","+ v2 
+ ") scale(" + zoom.scale() + ")");
+               }       
+      });
+      
+      $("#zoomOut").click(function() {
+               if (zoom.scale() > 0.31) {      
+                               var svg = d3.select("#svg-main");
+                               //Calculate and store new values in zoom object
+                               zoom.scale(zoom.scale() - 0.1);
+                               var translate = zoom.translate();
+                               var v1 = translate[0] * (zoom.scale() - 0.1 / 
(zoom.scale()));
+                               var v2 = translate[1] * (zoom.scale() - 0.1 / 
(zoom.scale()));
+                               zoom.translate([v1, v2]);
+                               //Transform svg
+                               svg.select("#svg-main g")
+                               .attr("transform", "translate(" + v1 + ","+ v2 
+ ") scale(" + zoom.scale() + ")");
+               }
+      });
+}

Reply via email to