Refactor frontend JS 13/213/5
authorAndrew Kim <andrekim@cisco.com>
Tue, 16 Apr 2013 22:35:12 +0000 (15:35 -0700)
committerAndrew Kim <andrekim@cisco.com>
Fri, 19 Apr 2013 02:05:43 +0000 (19:05 -0700)
Refactored one.js into lib.js and open.js. lib.js contains all the common library functions
one.js and other page.js can use. open.js is the core engine that runs the web UI.

Frontend is now extensible by automatically including  lib.js and overriding default JS engine.

Use spaces instead of tabs.

Change-Id: Ia6678a81a23266c6d0e1c1d56c6cec547f792487
Signed-off-by: Andrew Kim <andrekim@cisco.com>
opendaylight/web/root/src/main/resources/WEB-INF/jsp/main.jsp
opendaylight/web/root/src/main/resources/js/lib.js [new file with mode: 0644]
opendaylight/web/root/src/main/resources/js/one-topology.js [deleted file]
opendaylight/web/root/src/main/resources/js/one.js [deleted file]
opendaylight/web/root/src/main/resources/js/open-topology.js [new file with mode: 0644]
opendaylight/web/root/src/main/resources/js/open.js [new file with mode: 0644]

index ceb462daff9cd38b5aee6aa107df75c394ef604a..a3d9dcff638cfba6318b0c59e7cba22551af2b7a 100644 (file)
  - terms of the Eclipse Public License v1.0 which accompanies this distribution, 
  - and is available at http://www.eclipse.org/legal/epl-v10.html
 --%>
-<%@ page import="java.net.URL" %>
-<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
+<%@ page import="java.net.URL"%>
+<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
 
 <!DOCTYPE html>
 <html>
 
 <head>
-       <meta name="viewport" content="width=device-width, initial-scale=1.0">
+<meta name="viewport" content="width=device-width, initial-scale=1.0">
 
-       <!-- Bootstrap CSS - 1 -->
-       <link href="/css/bootstrap.min.css" rel="stylesheet" media="screen">
+<!-- Bootstrap CSS - 1 -->
+<link href="/css/bootstrap.min.css" rel="stylesheet" media="screen">
 
-       <!-- Core CSS - 2 -->
-       <link rel="stylesheet/less" type="text/css" href="/css/one.less">
+<!-- Core CSS - 2 -->
+<link rel="stylesheet/less" type="text/css" href="/css/one.less">
 
-<c:set var="version" value="Version 0.1" scope="application"/>
-<c:set var="name" value="OpenDaylight" scope="application"/>
+<c:set var="version" value="Version 0.1" scope="application" />
+<c:set var="name" value="OpenDaylight" scope="application" />
 
-<%     
-    String filePath = "/WEB-INF/jsp/custommain.jsp"; 
+<%
+    String filePath = "/WEB-INF/jsp/custommain.jsp";
     URL fileURL = pageContext.getServletContext().getResource(filePath);
-    if(fileURL!=null) {
+    if (fileURL != null) {
 %>
-         <jsp:include page="<%=filePath%>" flush="true"/>
-<% } %>
-
-    <title>${name}</title>
-       <!-- jQuery - 1 -->
-       <script src="/js/jquery-1.9.1.min.js"></script>
-       
-       <!-- Bootstrap JS - 2 -->
-       <script src="/js/bootstrap.min.js"></script>
-
-       <!-- LESS - 3 -->
-       <script type="text/javascript">
-               less = {
-                       env: "production"
-               };
-       </script>
-       <script src="/js/less-1.3.3.min.js"></script>
-       
-       <!-- Topology - 4 -->
-       <script src="/js/jit.js"></script>
+<jsp:include page="<%=filePath%>" flush="true" />
+<%
+    }
+%>
+
+<title>${name}</title>
+<!-- jQuery - 1 -->
+<script src="/js/jquery-1.9.1.min.js"></script>
+
+<!-- Bootstrap JS - 2 -->
+<script src="/js/bootstrap.min.js"></script>
+
+<!-- LESS - 3 -->
+<script type="text/javascript">
+    less = {
+        env : "production"
+    };
+</script>
+<script src="/js/less-1.3.3.min.js"></script>
+
+<!-- Topology - 4 -->
+<script src="/js/jit.js"></script>
 </head>
 <body>
 
-<!-- #menu -->
-<div id="menu" class="navbar navbar-fixed-top">
-       <div class="navbar-inner row-fluid">
-               <div class="span10">
-                       <a class="brand" href="/" title="${version}">${name}</a> 
-                       <ul class="nav nav-tabs">
-                       </ul>
-               </div>
-               <div class="span2">
-                       <div id="toolbar" class="btn-group">
-                               <a class="btn dropdown-toggle" data-toggle="dropdown" href="#">
-                                       <div class="icon-user"></div> ${username}
-                                       <span class="caret"></span>
-                               </a>
-                               <ul class="dropdown-menu">
-                                       <li><a href="#admin" id="admin" data-role="${role}"><div class="icon-users"></div> Users</a></li>
-                                       <li><a href="#save" id="save"><div class="icon-save"></div> Save</a></li>
-                                       <li><a href="#logout" id="logout"><div class="icon-logout"></div> Logout</a></li>
-                               </ul>
-                       </div>
-               </div>
-       </div>
-</div><!-- END #menu -->
-
-<!-- #footer -->
-<div id="footer" class="navbar navbar-fixed-bottom">
-       <div class="navbar-inner row-fluid">
-               <div class="alert hide" id="alert">
-                       <button type="button" class="close">&times;</button>
-                       <p></p>
-               </div>
-       </div>
-</div><!-- END #footer -->
-
-<!-- #main -->
-<div id="main">
-       
-<!-- #left -->
-<div id="left">
-
-       <!-- #left-top -->
-       <div id="left-top">
-
-               <div class="dash">
-                       <ul class="nav nav-tabs">
-                       </ul>
-                       <div class="dashlet row-fluid">
-                       </div>
-               </div>
-
-       </div><!-- END #left-top -->
-
-       <!-- #left-bottom -->
-       <div id="left-bottom">
-
-               <div class="dash">
-                       <ul class="nav nav-tabs">
-                       </ul>
-                       <div class="dashlet row-fluid">
-                       </div>
-               </div>
-
-       </div><!-- END #left-bottom -->
-
-</div><!-- END #left -->
-
-<!-- #right -->
-<div id="right">
-
-       <!-- #right-top -->
-       <div id="right-top">
-
-               <div class="dash">
-                       <div id="topology"></div>
-               </div>
-
-       </div><!-- END #right-top -->
-
-       <!-- #right-bottom -->
-       <div id="right-bottom">
-
-               <div class="dash">
-                       <ul class="nav nav-tabs">
-                       </ul>
-                       <div class="dashlet row-fluid">
-                       </div>
-               </div>
-
-       </div><!-- END #right-bottom -->
-
-</div><!-- END #right -->
-
-</div><!-- END #main -->
-
-<!-- modal -->
-<div id="modal" class="modal hide fade">
-       <div class="modal-header">
-               <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
-               <h3></h3>
-       </div>
-       <div class="modal-body"></div>
-       <div class="modal-footer"></div>
-</div>
-<!-- END modal -->
-
-<!-- Core JS - 6 -->
-<script src="/js/one.js"></script>
-
-<!-- Topology JS - 7 -->
-<script src="/js/one-topology.js"></script>
+ <!-- #menu -->
+ <div id="menu" class="navbar navbar-fixed-top">
+  <div class="navbar-inner row-fluid">
+   <div class="span10">
+    <a class="brand" href="/" title="${version}">${name}</a>
+    <ul class="nav nav-tabs">
+    </ul>
+   </div>
+   <div class="span2">
+    <div id="toolbar" class="btn-group">
+     <a class="btn dropdown-toggle" data-toggle="dropdown" href="#">
+      <div class="icon-user"></div> ${username} <span class="caret"></span>
+     </a>
+     <ul class="dropdown-menu">
+      <li><a href="#admin" id="admin" data-role="${role}"><div
+         class="icon-users"></div> Users</a></li>
+      <li><a href="#save" id="save"><div class="icon-save"></div>
+        Save</a></li>
+      <li><a href="#logout" id="logout"><div
+         class="icon-logout"></div> Logout</a></li>
+     </ul>
+    </div>
+   </div>
+  </div>
+ </div>
+ <!-- END #menu -->
+
+ <!-- #footer -->
+ <div id="footer" class="navbar navbar-fixed-bottom">
+  <div class="navbar-inner row-fluid">
+   <div class="alert hide" id="alert">
+    <button type="button" class="close">&times;</button>
+    <p></p>
+   </div>
+  </div>
+ </div>
+ <!-- END #footer -->
+
+ <!-- #main -->
+ <div id="main">
+
+  <!-- #left -->
+  <div id="left">
+
+   <!-- #left-top -->
+   <div id="left-top">
+
+    <div class="dash">
+     <ul class="nav nav-tabs">
+     </ul>
+     <div class="dashlet row-fluid"></div>
+    </div>
+
+   </div>
+   <!-- END #left-top -->
+
+   <!-- #left-bottom -->
+   <div id="left-bottom">
+
+    <div class="dash">
+     <ul class="nav nav-tabs">
+     </ul>
+     <div class="dashlet row-fluid"></div>
+    </div>
+
+   </div>
+   <!-- END #left-bottom -->
+
+  </div>
+  <!-- END #left -->
+
+  <!-- #right -->
+  <div id="right">
+
+   <!-- #right-top -->
+   <div id="right-top">
+
+    <div class="dash">
+     <div id="topology"></div>
+    </div>
+
+   </div>
+   <!-- END #right-top -->
+
+   <!-- #right-bottom -->
+   <div id="right-bottom">
+
+    <div class="dash">
+     <ul class="nav nav-tabs">
+     </ul>
+     <div class="dashlet row-fluid"></div>
+    </div>
+
+   </div>
+   <!-- END #right-bottom -->
+
+  </div>
+  <!-- END #right -->
+
+ </div>
+ <!-- END #main -->
+
+ <!-- modal -->
+ <div id="modal" class="modal hide fade">
+  <div class="modal-header">
+   <button type="button" class="close" data-dismiss="modal"
+    aria-hidden="true">&times;</button>
+   <h3></h3>
+  </div>
+  <div class="modal-body"></div>
+  <div class="modal-footer"></div>
+ </div>
+ <!-- END modal -->
+
+ <!-- Lib JS - 6 -->
+ <script src="/js/lib.js"></script>
+ <%
+     String jsPath = "/WEB-INF/jsp/customjs.jsp";
+     URL jsURL = pageContext.getServletContext().getResource(jsPath);
+     if (jsURL != null) {
+ %>
+ <jsp:include page="<%=jsPath%>" flush="true" />
+ <%
+     } else {
+ %>
+ <!-- Core JS - 7 -->
+ <script src="/js/open.js"></script>
+
+ <!-- Topology JS - 8 -->
+ <script src="/js/open-topology.js"></script>
+ <%
+     }
+ %>
 
 </body>
 
diff --git a/opendaylight/web/root/src/main/resources/js/lib.js b/opendaylight/web/root/src/main/resources/js/lib.js
new file mode 100644 (file)
index 0000000..8118857
--- /dev/null
@@ -0,0 +1,282 @@
+// global
+var one = {
+    // global variables
+    global : {
+        remoteAddress : "/"
+    },
+    role : null
+}
+
+// one ui library
+one.lib = {};
+
+// registry
+one.lib.registry = {};
+
+/** DASHLET */
+one.lib.dashlet = {
+    empty : function($dashlet) {
+        $dashlet.empty();
+    },
+    append : function($dashlet, $content) {
+        $dashlet.append($content);
+    },
+    header : function(header) {
+        var $h4 = $(document.createElement('h4'));
+        $h4.text(header);
+        return $h4;
+    },
+    list : function(list) {
+        var $ul = $(document.createElement('ul'));
+        $(list).each(function(index, value) {
+            var $li = $(document.createElement('li'));
+            $li.append(value);
+            $ul.append($li);
+        });
+        return $ul;
+    },
+    button : {
+        config : function(name, id, type, size) {
+            var button = {};
+            button['name'] = name;
+            button['id'] = id;
+            button['type'] = type;
+            button['size'] = size;
+            return button;
+        },
+        single : function(name, id, type, size) {
+            var buttonList = [];
+            var button = one.lib.dashlet.button.config(name, id, type, size);
+            buttonList.push(button);
+            return buttonList;
+        },
+        button : function(buttonList) {
+            var $buttonGroup = $(document.createElement('div'));
+            $buttonGroup.addClass("btn-group");
+            $(buttonList).each(function(index, value) {
+                var $button = $(document.createElement('button'));
+                $button.text(value.name);
+                $button.addClass('btn');
+                $button.addClass(value['type']);
+                $button.addClass(value['size']);
+                if (!(typeof value.id === 'undefined')) {
+                    $button.attr('id', value.id);
+                }
+                $buttonGroup.append($button);
+            });
+            return $buttonGroup;
+        }
+    },
+    table : {
+        table : function(classes, id) {
+            var $table = $(document.createElement('table'));
+            $table.addClass("table");
+            $(classes).each(function(index, value) {
+                $table.addClass(value);
+            });
+            if (!(typeof id === 'undefined'))
+                $table.attr("id", id);
+            return $table;
+        },
+        header : function(headers) {
+            var $thead = $(document.createElement('thead'));
+            var $tr = $(document.createElement('tr'));
+            $(headers).each(function(index, value) {
+                $th = $(document.createElement('th'));
+                $th.append(value);
+                $tr.append($th);
+            });
+            $thead.append($tr);
+            return $thead;
+        },
+        body : function(body, thead) {
+            var $tbody = $(document.createElement('tbody'));
+            // if empty
+            if (body.length == 0 && !(typeof thead === 'undefined')) {
+                var $tr = $(document.createElement('tr'));
+                var $td = $(document.createElement('td'));
+                $td.attr("colspan", thead.length);
+                $td.text("No data available");
+                $td.addClass("empty");
+                $tr.append($td);
+                $tbody.append($tr);
+                return $tbody;
+            }
+            // else, populate as usual
+            $(body).each(function(index, value) {
+                var $tr = $(document.createElement('tr'));
+                // data-id
+                if (value['id'] != undefined) {
+                    $tr.attr('data-id', value['id']);
+                }
+                // add classes
+                $(value["type"]).each(function(index, value) {
+                    $tr.addClass(value);
+                });
+                // add entries
+                $(value["entry"]).each(function(index, value) {
+                    var $td = $(document.createElement('td'));
+                    $td.append(value);
+                    $tr.append($td);
+                });
+                $tbody.append($tr);
+            });
+            return $tbody;
+        }
+    },
+    description : function(description, horizontal) {
+        var $dl = $(document.createElement('dl'));
+        if (horizontal == true) {
+            $dl.addClass("dl-horizontal");
+        }
+        $(description).each(function(index, value) {
+            var $dt = $(document.createElement('dt'));
+            $dt.text(value.dt);
+            var $dd = $(document.createElement('dd'));
+            $dd.text(value.dd);
+            $dl.append($dt).append($dd);
+        });
+        return $dl;
+    }
+}
+
+/** MODAL */
+one.lib.modal = {
+    // clone default modal
+    clone : function(id) {
+        var $clone = $("#modal").clone(true);
+        $clone.attr("id", id);
+        return $clone;
+    },
+    // populate modal
+    populate : function($modal, header, $body, footer) {
+        var $h3 = $modal.find("h3");
+        $h3.text(header);
+
+        var $modalBody = $modal.find(".modal-body");
+        $modalBody.append($body);
+
+        $(footer).each(function(index, value) {
+            $modal.find(".modal-footer").append(value);
+        });
+    },
+    // clone and populate modal
+    spawn : function(id, header, $body, footer) {
+        var $modal = one.lib.modal.clone(id);
+        one.lib.modal.populate($modal, header, $body, footer);
+        return $modal;
+    },
+    // empty modal
+    empty : function($modal) {
+        $modal.find("h3").empty();
+        $modal.find(".modal-body").empty();
+        $modal.find(".modal-footer").empty();
+    },
+    // injection
+    inject : {
+        body : function($modal, $body) {
+            $modal.find(".modal-body").empty();
+            $modal.find(".modal-body").append($body);
+        }
+    }
+}
+
+/** FORM */
+one.lib.form = {
+    // create select-option form element
+    select : {
+        create : function(options, multiple) {
+            // assert - auto assign
+            if (options == undefined)
+                options = {};
+
+            var $select = $(document.createElement('select'));
+            if (multiple == true) {
+                $select.attr("multiple", "multiple");
+            }
+            var optionArray = one.lib.form.select.options(options);
+            $(optionArray).each(function(index, value) {
+                $select.append(value);
+            });
+            return $select;
+        },
+        options : function(options) {
+            var result = [];
+            $.each(options, function(key, value) {
+                var $option = $(document.createElement('option'));
+                $option.attr("value", key);
+                $option.text(value);
+                result.push($option);
+            });
+            return result;
+        },
+        empty : function($select) {
+            $select.empty();
+        },
+        inject : function($select, options) {
+            $select.empty();
+            var options = one.lib.form.select.options(options);
+            $select.append(options);
+        },
+        prepend : function($select, options) {
+            var options = one.lib.form.select.options(options);
+            $select.prepend(options);
+        },
+        bubble : function($select, bubble) {
+            $($select.find("option")).each(function(index, value) {
+                if ($(value).attr("value") == bubble) {
+                    var option = $(value);
+                    $(value).remove();
+                    $select.prepend(option);
+                    return;
+                }
+            });
+        }
+    },
+    // create legend form element
+    legend : function(name) {
+        var $legend = $(document.createElement('legend'));
+        $legend.text(name);
+        return $legend;
+    },
+    // create label form element
+    label : function(name) {
+        var $label = $(document.createElement('label'));
+        $label.text(name);
+        return $label;
+    },
+    // create help block form element
+    help : function(help) {
+        var $help = $(document.createElement('span'));
+        $help.text(help);
+        $help.addClass("help-block");
+        return $help;
+    },
+    // create generic text input
+    input : function(placeholder) {
+        var $input = $(document.createElement('input'));
+        $input.attr('type', 'text');
+        $input.attr('placeholder', placeholder);
+        return $input;
+    }
+}
+
+/** NAV */
+one.lib.nav = {
+    unfocus : function($nav) {
+        $($nav.find("li")).each(function(index, value) {
+            $(value).removeClass("active");
+        });
+    }
+}
+
+/** ALERT */
+one.lib.alert = function(alert) {
+    $("#alert p").text(alert);
+    $("#alert").hide();
+    $("#alert").slideToggle();
+    clearTimeout(one.lib.registry.alert);
+    one.lib.registry.alert = setTimeout(function() {
+        $("#alert").slideUp();
+    }, 8000);
+}
\ No newline at end of file
diff --git a/opendaylight/web/root/src/main/resources/js/one-topology.js b/opendaylight/web/root/src/main/resources/js/one-topology.js
deleted file mode 100644 (file)
index 27aabca..0000000
+++ /dev/null
@@ -1,227 +0,0 @@
-/** COMMON **/
-var labelType, useGradients, nativeTextSupport, animate;
-
-(function() {
-       var ua = navigator.userAgent,
-       iStuff = ua.match(/iPhone/i) || ua.match(/iPad/i),
-       typeOfCanvas = typeof HTMLCanvasElement,
-       nativeCanvasSupport = (typeOfCanvas == 'object' || typeOfCanvas == 'function'),
-       textSupport = nativeCanvasSupport 
-       && (typeof document.createElement('canvas').getContext('2d').fillText == 'function');
-       //I'm setting this based on the fact that ExCanvas provides text support for IE
-       //and that as of today iPhone/iPad current text support is lame
-       labelType = (!nativeCanvasSupport || (textSupport && !iStuff))? 'Native' : 'HTML';
-       nativeTextSupport = labelType == 'Native';
-       useGradients = nativeCanvasSupport;
-       animate = !(iStuff || !nativeCanvasSupport);
-})();
-
-/** TOPOLOGY **/
-one.topology = {};
-
-one.topology.option = {
-       navigation : function(enable, panning, zooming) {
-               var option = {};
-               option["enable"] = enable;
-               option["panning"] = panning;
-               option["zooming"] = zooming;
-               return option;
-       },
-       node : function(overridable, color, height, dim) {
-               var option = {};
-               option["overridable"] = overridable;
-               option["color"] = color;
-               option["height"] = height;
-               option["dim"] = dim;
-               return option;
-       },
-       edge : function(overridable, color, lineWidth, epsilon) {
-               var option = {};
-               option["overridable"] = overridable;
-               option["color"] = color;
-               option["lineWidth"] = lineWidth;
-               if (epsilon != undefined)
-                       option["epsilon"] = epsilon;
-               return option;
-       },
-       label : function(style, node) {
-               var marginTop, minWidth;
-               if (node.data["$type"] == "swtch") {
-                       marginTop = "42px";
-                       minWidth = "65px";
-               } else if (node.data["$type"] == "host") {
-                       marginTop = "48px";
-                       minWidth = "";
-               } else if (node.data["$type"].indexOf("monitor") == 0) {
-                       marginTop = "52px";
-                       minWidth = "";
-               }
-               style.marginTop = marginTop;
-               style.minWidth = minWidth;
-               style.background = "rgba(68,68,68,0.7)";
-               style.borderRadius = "4px";
-               style.color = "#fff";
-               style.cursor = "default";
-       }
-};
-
-one.topology.init = function(json) {
-       if (json.length == 0) {
-               $div = $(document.createElement('div'));
-               $img = $(document.createElement('div'));
-               $img.css('height', '128px');
-               $img.css('width', '128px');
-               $img.css('background-image', 'url(/img/topology_view_1033_128.png)');
-               $img.css('clear', 'both');
-               $img.css('margin', '0 auto');
-               $p = $(document.createElement('p'));
-               $p.addClass('text-center');
-               $p.addClass('text-info');
-               $p.css('width', '100%');
-               $p.css('padding', '10px 0');
-               $p.css('cursor', 'default');
-               $p.append('No Network Elements Connected');
-               $div.css('position', 'absolute');
-               $div.css('top', '25%');
-               $div.css('margin', '0 auto');
-               $div.css('width', '100%');
-               $div.css('text-align', 'center');
-               $div.append($img).append($p);
-               $("#topology").append($div);
-               return false;
-       }
-       one.topology.graph = new $jit.MultiTopology({
-               injectInto: 'topology',
-               Navigation: one.topology.option.navigation(true, 'avoid nodes', 10),
-               Node: one.topology.option.node(true, '#444', 25, 27),
-               Edge: one.topology.option.edge(true, '23A4FF', 1.5),
-               Tips: {
-                       enable: true,
-                       type: 'Native',
-                       onShow: function(tip, node) {
-                               if (node.name != undefined)
-                                       tip.innerHTML = "";
-                               //tipsOnShow(tip, node);
-                       }
-               },
-               Events: {
-                       enable: true,
-                       type: 'Native',
-                       onMouseEnter: function(node, eventInfo, e) {
-                               // if node
-                               if (node.id != undefined) {
-                                       one.topology.graph.canvas.getElement().style.cursor = 'move';
-                               } else if (eventInfo.edge != undefined && 
-                                               eventInfo.edge.nodeTo.data["$type"] == "swtch" && 
-                                               eventInfo.edge.nodeFrom.data["$type"] == "swtch") {
-                                       one.topology.graph.canvas.getElement().style.cursor = 'pointer';
-                               }
-                       },
-                       onMouseLeave: function(node, eventInfo, e) {
-                               one.topology.graph.canvas.getElement().style.cursor = '';
-                       },
-                       //Update node positions when dragged
-                       onDragMove: function(node, eventInfo, e) {
-                               var pos = eventInfo.getPos();
-                               node.pos.setc(pos.x, pos.y);
-                               one.topology.graph.plot();
-                               one.topology.graph.canvas.getElement().style.cursor = 'crosshair';
-                       },
-                       //Implement the same handler for touchscreens
-                       onTouchMove: function(node, eventInfo, e) {
-                               $jit.util.event.stop(e); //stop default touchmove event
-                               this.onDragMove(node, eventInfo, e);
-                       },
-                       onDragEnd: function(node, eventInfo, e) {
-                               var ps = eventInfo.getPos();
-                               var did = node.id;
-                               var data = {};
-                               data['x'] = ps.x;
-                               data['y'] = ps.y;
-                               $.post('/controller/web/topology/node/' + did, data);
-                       },
-                       onClick: function(node, eventInfo, e) {
-                               if(one.f.topology === undefined) {
-                                       return false;
-                               } else {
-                                       one.f.topology.Events.onClick(node, eventInfo);
-                               }
-                       }
-               },
-               iterations: 200,
-               levelDistance: 130,
-               onCreateLabel: function(domElement, node){
-                       var nameContainer = document.createElement('span'),
-                       closeButton = document.createElement('span'),
-                       style = nameContainer.style;
-                       nameContainer.className = 'name';
-                       var nodeDesc = node.data["$desc"];
-                       if (nodeDesc == "None" || nodeDesc == "" || nodeDesc == "undefined" || nodeDesc == undefined) {
-                               nameContainer.innerHTML = "<small>"+node.name+"</small>";
-                       } else {
-                               nameContainer.innerHTML = nodeDesc;
-                       }
-                       domElement.appendChild(nameContainer);
-                       style.fontSize = "1.0em";
-                       style.color = "#000";
-                       style.fontWeight = "bold";
-                       style.width = "100%";
-                       style.padding = "1.5px 4px";
-                       style.display = "block";
-
-                       one.topology.option.label(style, node);
-               },
-               onPlaceLabel: function(domElement, node){
-                       var style = domElement.style;
-                       var left = parseInt(style.left);
-                       var top = parseInt(style.top);
-                       var w = domElement.offsetWidth;
-                       style.left = (left - w / 2) + 'px';
-                       style.top = (top - 15) + 'px';
-                       style.display = '';
-                       style.minWidth = "28px";
-                       style.width = "auto";
-                       style.height = "28px";
-                       style.textAlign = "center";
-               }
-       });
-
-       one.topology.graph.loadJSON(json);
-       // compute positions incrementally and animate.
-       one.topology.graph.computeIncremental({
-               iter: 40,
-               property: 'end',
-               onStep: function(perc){
-                       console.log(perc + '% loaded');
-               },
-               onComplete: function(){
-                       for (var idx in one.topology.graph.graph.nodes) {
-                               var node = one.topology.graph.graph.nodes[idx];
-                               if(node.getData("x") && node.getData("y")) {
-                                       var x = node.getData("x");
-                                       var y = node.getData("y");
-                                       node.setPos(new $jit.Complex(x, y), "end");
-                               }
-                       }
-                        console.log('done');
-                       one.topology.graph.animate({
-                               modes: ['linear'],
-                               transition: $jit.Trans.Elastic.easeOut,
-                               duration: 0
-                       });
-               }
-       });
-       one.topology.graph.canvas.setZoom(0.8,0.8);
-}
-
-one.topology.update = function() {
-       $('#topology').empty();
-       $.getJSON(one.global.remoteAddress+"controller/web/topology/visual.json", function(data) {
-               one.topology.init(data);
-       });
-}
-
-/** INIT */
-$.getJSON(one.global.remoteAddress+"controller/web/topology/visual.json", function(data) {
-       one.topology.init(data);
-});
diff --git a/opendaylight/web/root/src/main/resources/js/one.js b/opendaylight/web/root/src/main/resources/js/one.js
deleted file mode 100644 (file)
index d517c7f..0000000
+++ /dev/null
@@ -1,720 +0,0 @@
-// global
-var one = {
-       // global variables
-       global : {
-               remoteAddress : "/"
-       },
-       role : null
-}
-
-// one ui library
-one.lib = {};
-
-// registry
-one.lib.registry = {};
-
-/** DASHLET */
-one.lib.dashlet = {
-       empty : function($dashlet) {
-               $dashlet.empty();
-       },
-       append : function($dashlet, $content) {
-               $dashlet.append($content);
-       },
-       header : function(header) {
-               var $h4 = $(document.createElement('h4'));
-               $h4.text(header);
-               return $h4;
-       },
-       list : function(list) {
-               var $ul = $(document.createElement('ul'));
-               $(list).each(function(index, value) {
-                       var $li = $(document.createElement('li'));
-                       $li.append(value);
-                       $ul.append($li);
-               });
-               return $ul;
-       },
-       button : {
-               config : function(name, id, type, size) {
-                       var button = {};
-                       button['name'] = name;
-                       button['id'] = id;
-                       button['type'] = type;
-                       button['size'] = size;
-                       return button;
-               },
-               single : function(name, id, type, size) {
-                       var buttonList = [];
-                       var button = one.lib.dashlet.button.config(name, id, type, size);
-                       buttonList.push(button);
-                       return buttonList;
-               },
-               button : function(buttonList) {
-                       var $buttonGroup = $(document.createElement('div'));
-                       $buttonGroup.addClass("btn-group");
-                       $(buttonList).each(function(index, value) {
-                               var $button = $(document.createElement('button'));
-                               $button.text(value.name);
-                               $button.addClass('btn');
-                               $button.addClass(value['type']);
-                               $button.addClass(value['size']);
-                               if(!(typeof value.id === 'undefined')) {
-                                       $button.attr('id', value.id);
-                               }
-                               $buttonGroup.append($button);
-                       });
-                       return $buttonGroup;
-               }
-       },
-       table : {
-               table : function(classes, id) {
-                       var $table = $(document.createElement('table'));
-                       $table.addClass("table");
-                       $(classes).each(function(index, value) {
-                               $table.addClass(value);
-                       });
-                       if (!(typeof id === 'undefined'))
-                               $table.attr("id", id);
-                       return $table;
-               },
-               header : function(headers) {
-                       var $thead = $(document.createElement('thead'));
-                       var $tr = $(document.createElement('tr'));
-                       $(headers).each(function(index, value) {
-                               $th = $(document.createElement('th'));
-                               $th.append(value);
-                               $tr.append($th);
-                       });
-                       $thead.append($tr);
-                       return $thead;
-               },
-               body : function(body, thead) {
-                       var $tbody = $(document.createElement('tbody'));
-                       // if empty
-                       if (body.length == 0 && !(typeof thead === 'undefined')) {
-                               var $tr = $(document.createElement('tr'));
-                               var $td = $(document.createElement('td'));
-                               $td.attr("colspan", thead.length);
-                               $td.text("No data available");
-                               $td.addClass("empty");
-                               $tr.append($td);
-                               $tbody.append($tr);
-                               return $tbody;
-                       }
-                       // else, populate as usual
-                       $(body).each(function(index, value) {
-                               var $tr = $(document.createElement('tr'));
-                               // data-id
-                               if(value['id'] != undefined) {
-                                       $tr.attr('data-id', value['id']);
-                               }
-                               // add classes
-                               $(value["type"]).each(function(index, value) {
-                                       $tr.addClass(value);
-                               });
-                               // add entries
-                               $(value["entry"]).each(function(index, value) {
-                                       var $td = $(document.createElement('td'));
-                                       $td.append(value);
-                                       $tr.append($td);
-                               });
-                               $tbody.append($tr);
-                       });
-                       return $tbody;
-               }
-       },
-       description : function(description, horizontal) {
-               var $dl = $(document.createElement('dl'));
-               if(horizontal == true) {
-                       $dl.addClass("dl-horizontal");
-               }
-               $(description).each(function(index, value) {
-                       var $dt = $(document.createElement('dt'));
-                       $dt.text(value.dt);
-                       var $dd = $(document.createElement('dd'));
-                       $dd.text(value.dd);
-                       $dl.append($dt).append($dd);
-               });
-               return $dl;
-       }
-}
-
-/** MODAL */
-one.lib.modal = {
-       // clone default modal
-       clone : function(id) {
-               var $clone = $("#modal").clone(true);
-               $clone.attr("id", id);
-               return $clone;
-       },
-       // populate modal
-       populate : function($modal, header, $body, footer) {
-               var $h3 = $modal.find("h3");
-               $h3.text(header);
-
-               var $modalBody = $modal.find(".modal-body");
-               $modalBody.append($body);
-
-               $(footer).each(function(index, value) {
-                       $modal.find(".modal-footer").append(value);
-               });
-       },
-       // clone and populate modal
-       spawn : function(id, header, $body, footer) {
-               var $modal = one.lib.modal.clone(id);
-               one.lib.modal.populate($modal, header, $body, footer);
-               return $modal;
-       },
-       // empty modal
-       empty : function($modal) {
-               $modal.find("h3").empty();
-               $modal.find(".modal-body").empty();
-               $modal.find(".modal-footer").empty();
-       },
-       // injection
-       inject : {
-               body : function($modal, $body) {
-                       $modal.find(".modal-body").empty();
-                       $modal.find(".modal-body").append($body);
-               }
-       }
-}
-
-/** FORM */
-one.lib.form = {
-       // create select-option form element
-       select : {
-               create : function(options, multiple) {
-                       // assert - auto assign
-                       if(options == undefined) options = {};
-
-                       var $select = $(document.createElement('select'));
-                       if (multiple == true) {
-                               $select.attr("multiple", "multiple");
-                       }
-                       var optionArray = one.lib.form.select.options(options);
-                       $(optionArray).each(function(index, value) {
-                               $select.append(value);
-                       });
-                       return $select;
-               },
-               options : function(options) {
-                       var result = [];
-                       $.each(options, function(key, value) {
-                               var $option = $(document.createElement('option'));
-                               $option.attr("value", key);
-                               $option.text(value);
-                               result.push($option);
-                       });
-                       return result;
-               },
-               empty : function($select) {
-                       $select.empty();
-               },
-               inject : function($select, options) {
-                       $select.empty();
-                       var options = one.lib.form.select.options(options);
-                       $select.append(options);
-               },
-               prepend : function($select, options) {
-                       var options = one.lib.form.select.options(options);
-                       $select.prepend(options);
-               },
-               bubble : function($select, bubble) {
-                       $($select.find("option")).each(function(index, value) {
-                               if( $(value).attr("value") == bubble ) {
-                                       var option = $(value);
-                                       $(value).remove();
-                                       $select.prepend(option);
-                                       return;
-                               }
-                       });
-               }
-       },
-       // create legend form element
-       legend : function(name) {
-               var $legend = $(document.createElement('legend'));
-               $legend.text(name);
-               return $legend;
-       },
-       // create label form element
-       label : function(name) {
-               var $label = $(document.createElement('label'));
-               $label.text(name);
-               return $label;
-       },
-       // create help block form element
-       help : function(help) {
-               var $help = $(document.createElement('span'));
-               $help.text(help);
-               $help.addClass("help-block");
-               return $help;
-       },
-       // create generic text input
-       input : function(placeholder) {
-               var $input = $(document.createElement('input'));
-               $input.attr('type', 'text');
-               $input.attr('placeholder', placeholder);
-               return $input;
-       }
-}
-
-/** NAV */
-one.lib.nav = {
-       unfocus : function($nav) {
-               $($nav.find("li")).each(function(index, value) {
-                       $(value).removeClass("active");
-               });
-       }
-}
-
-/** ALERT */
-one.lib.alert = function(alert) {
-       $("#alert p").text(alert);
-       $("#alert").hide();
-       $("#alert").slideToggle();
-       clearTimeout(one.lib.registry.alert);
-       one.lib.registry.alert = setTimeout(function() {
-               $("#alert").slideUp();
-       }, 8000);
-}
-
-/* 
-       INITIALIZATION
-       executable JS code starts here
-*/
-//OpenDaylight root page
-one.main = {};
-
-one.main.constants = {
-    address : {
-        menu : "/web.json",
-        prefix : "/controller/web",
-        save : "/save"
-    }
-}
-
-one.main.menu = {
-    load : function() {
-        one.main.menu.ajax(function(data) {
-            // reparse the ajax data
-            var result = one.main.menu.data.menu(data);
-            // transform into list to append to menu
-            var $div = one.main.menu.menu(result);
-            // append to menu
-            $("#menu .nav").append($div.children());
-            // binding all menu items
-            var $menu = $("#menu .nav a");
-            $menu.click(function() {
-                var href = $(this).attr('href').substring(1);
-                one.main.page.load(href);
-                var $li = $(this).parent();
-                // reset all other active
-                $menu.each(function(index, value) {
-                       $(value).parent().removeClass('active');
-                });
-                $li.addClass('active');
-            });
-            // reset or go to first menu item by default
-            var currentLocation = location.hash;
-            if (data[currentLocation.substring(1)] == undefined) {
-               $($menu[0]).click();
-            } else {
-               $menu.each(function(index, value) {
-                       var menuLocation = $(value).attr('href');
-                       if (currentLocation == menuLocation) {
-                               $($menu[index]).click();
-                               return;
-                       }
-               });
-            }
-        });
-    },
-    menu : function(result) {
-        var $div = $(document.createElement('div'));
-        $(result).each(function(index, value) {
-            if( value != undefined) {
-                var $li = $(document.createElement('li'));
-                var $a = $(document.createElement('a'));
-                $a.text(value['name']);
-                $a.attr('href', '#'+value['id']);
-                $li.append($a);
-                $div.append($li);
-            }
-        });
-        return $div;
-    },
-    ajax : function(successCallback) {
-        $.getJSON(one.main.constants.address.menu, function(data) {
-            successCallback(data);
-        });
-    },
-    data : {
-        menu : function(data) {
-            var result = [];
-            $.each(data, function(key, value) {
-                var order = value['order'];
-                if (order >= 0) {
-                       var name = value['name'];
-                       var entry = {
-                           'name' : name,
-                           'id' : key
-                       };
-                       result[order] = entry;
-                }
-            });
-            return result;
-        }
-    }
-}
-
-one.main.page = {
-    load : function(page) {
-               if (one.f !== undefined && one.f.cleanUp !== undefined) {
-                   one.f.cleanUp();
-               }       
-        // clear page related
-        delete one.f;
-        $('.dashlet', '#main').empty();
-        $('.nav', '#main').empty();
-        // fetch page's js
-        $.getScript(one.main.constants.address.prefix+"/"+page+"/js/page.js");
-        
-        $.ajaxSetup({
-               data : {
-                       'x-page-url' : page
-               }
-        });
-    },
-    dashlet : function($nav, dashlet) {
-        var $li = $(document.createElement('li'));
-        var $a = $(document.createElement('a'));
-        $a.text(dashlet.name);
-        $a.attr('id', dashlet.id);
-        $a.attr('href', '#');
-        $li.append($a);
-        $nav.append($li);
-    }
-}
-
-one.main.admin = {
-    id : {
-        modal : {
-            main : "one_main_admin_id_modal_main",
-            close : "one_main_admin_id_modal_close",
-            user : "one_main_admin_id_modal_user",
-            add : {
-                user : "one_main_admin_id_modal_add_user",
-                close : "one_main_admin_id_modal_add_close",
-                form : {
-                    name : "one_main_admin_id_modal_add_form_name",
-                    role : "one_main_admin_id_modal_add_form_role",
-                    password : "one_main_admin_id_modal_add_form_password"
-                }
-            },
-            remove : {
-                user : "one_main_admin_id_modal_remove_user",
-                close : "one_main_admin_id_modal_remove_close"
-            }
-        },
-        add : {
-            user : "one_main_admin_id_add_user"
-        }
-    },
-    address : {
-        root : "/admin",
-        users : "/users"
-    },
-    modal : {
-        initialize : function(callback) {
-            var h3 = "Welcome "+$('#admin').text();
-            var footer = one.main.admin.modal.footer();
-            var $modal = one.lib.modal.spawn(one.main.admin.id.modal.main, h3, '', footer);
-            
-            // close binding
-            $('#'+one.main.admin.id.modal.close, $modal).click(function() {
-                $modal.modal('hide');
-            });
-            
-            // body inject
-            one.main.admin.ajax.users(function($body) {
-                one.lib.modal.inject.body($modal, $body);
-            });
-            
-            // modal show callback
-            callback($modal);
-        },
-        footer : function() {
-            var footer = [];
-            
-            var closeButton = one.lib.dashlet.button.single("Close", one.main.admin.id.modal.close, "", "");
-            var $closeButton = one.lib.dashlet.button.button(closeButton);
-            footer.push($closeButton);
-            
-            return footer;
-        }
-    },
-    ajax : {
-        users : function(callback) {
-            $.getJSON(one.main.admin.address.root+one.main.admin.address.users, function(data) {
-                var body = one.main.admin.data.users(data);
-                var $body = one.main.admin.body.users(body);
-                callback($body);
-            });
-        }
-    },
-    data : {
-        users : function(data) {
-            var body = [];
-            $(data).each(function(index, value) {
-                var tr = {};
-                var entry = [];
-                entry.push(value['user']);
-                entry.push(value['role']);
-                tr['entry'] = entry;
-                tr['id'] = value['user'];
-                body.push(tr);
-            });
-            return body;
-        }
-    },
-    body : {
-        users : function(body) {
-            var $div = $(document.createElement('div'));
-            var $h5 = $(document.createElement('h5'));
-            $h5.append("Manage Users");
-            var attributes = ["table-striped", "table-bordered", "table-hover", "table-cursor"];
-            var $table = one.lib.dashlet.table.table(attributes);
-            var headers = ["User", "Role"];
-            var $thead = one.lib.dashlet.table.header(headers);
-            var $tbody = one.lib.dashlet.table.body(body);
-            $table.append($thead).append($tbody);
-            
-            // bind table
-            if (one.role < 2) {
-                   $table.find('tr').click(function() {
-                       var id = $(this).data('id');
-                       one.main.admin.remove.modal.initialize(id);
-                   });
-            }
-            
-            // append to div
-            $div.append($h5).append($table);
-            
-            if (one.role < 2) {
-                   var addUserButton = one.lib.dashlet.button.single("Add User", one.main.admin.id.add.user, "btn-primary", "btn-mini");
-                   var $addUserButton = one.lib.dashlet.button.button(addUserButton);
-                   $div.append($addUserButton);
-                   
-                   // add user binding
-                   $addUserButton.click(function() {
-                       one.main.admin.add.modal.initialize();
-                   });
-            }
-            
-            return $div;
-        }
-    },
-    remove : {
-        modal : {
-            initialize : function(id) {
-                var h3 = "Remove User";
-                var footer = one.main.admin.remove.footer();
-                var $body = one.main.admin.remove.body();
-                var $modal = one.lib.modal.spawn(one.main.admin.id.modal.user, h3, $body, footer);
-                
-                // close binding
-                $('#'+one.main.admin.id.modal.remove.close, $modal).click(function() {
-                    $modal.modal('hide');
-                });
-                
-                // remove binding
-                $('#'+one.main.admin.id.modal.remove.user, $modal).click(function() {
-                    one.main.admin.remove.modal.ajax(id, function(result) {
-                        if (result == 'Success') {
-                            $modal.modal('hide');
-                            // body inject
-                            var $admin = $('#'+one.main.admin.id.modal.main);
-                            one.main.admin.ajax.users(function($body) {
-                                one.lib.modal.inject.body($admin, $body);
-                            });
-                        } else alert("Failed to remove user: "+result);
-                    });
-                });
-                
-                $modal.modal();
-            },
-            ajax : function(id, callback) {
-                $.post(one.main.admin.address.root+one.main.admin.address.users+'/'+id, function(data) {
-                    callback(data);
-                });
-            },
-        },
-        
-        footer : function() {
-            var footer = [];
-            
-            var removeButton = one.lib.dashlet.button.single("Remove User", one.main.admin.id.modal.remove.user, "btn-danger", "");
-            var $removeButton = one.lib.dashlet.button.button(removeButton);
-            footer.push($removeButton);
-            
-            var closeButton = one.lib.dashlet.button.single("Close", one.main.admin.id.modal.remove.close, "", "");
-            var $closeButton = one.lib.dashlet.button.button(closeButton);
-            footer.push($closeButton);
-            
-            return footer;
-        },
-        body : function() {
-            var $p = $(document.createElement('p'));
-            $p.append("Remove user?");
-            return $p;
-        },
-    },
-    add : {
-        modal : {
-            initialize : function() {
-                var h3 = "Add User";
-                var footer = one.main.admin.add.footer();
-                var $body = one.main.admin.add.body();
-                var $modal = one.lib.modal.spawn(one.main.admin.id.modal.user, h3, $body, footer);
-                
-                // close binding
-                $('#'+one.main.admin.id.modal.add.close, $modal).click(function() {
-                    $modal.modal('hide');
-                });
-                
-                // add binding
-                $('#'+one.main.admin.id.modal.add.user, $modal).click(function() {
-                    one.main.admin.add.modal.add($modal, function(result) {
-                        if(result == 'Success') {
-                            $modal.modal('hide');
-                            // body inject
-                            var $admin = $('#'+one.main.admin.id.modal.main);
-                            one.main.admin.ajax.users(function($body) {
-                                one.lib.modal.inject.body($admin, $body);
-                            });
-                        } else alert("Failed to add user: "+result);
-                    });
-                });
-                
-                $modal.modal();
-            },
-            add : function($modal, callback) {
-                var user = {};
-                user['user'] = $modal.find('#'+one.main.admin.id.modal.add.form.name).val();
-                user['password'] = $modal.find('#'+one.main.admin.id.modal.add.form.password).val();
-                user['role'] = $modal.find('#'+one.main.admin.id.modal.add.form.role).find('option:selected').attr('value');
-                
-                var resource = {};
-                resource['json'] = JSON.stringify(user);
-                resource['action'] = 'add'
-                
-                one.main.admin.add.modal.ajax(resource, callback);
-            },
-            ajax : function(data, callback) {
-                $.post(one.main.admin.address.root+one.main.admin.address.users, data, function(data) {
-                    callback(data);
-                });
-            }
-        },
-        body : function() {
-            var $form = $(document.createElement('form'));
-            var $fieldset = $(document.createElement('fieldset'));
-            // user
-            var $label = one.lib.form.label('Username');
-            var $input = one.lib.form.input('Username');
-            $input.attr('id', one.main.admin.id.modal.add.form.name);
-            $fieldset.append($label).append($input);
-            // password
-            var $label = one.lib.form.label('Password');
-            var $input = one.lib.form.input('Password');
-            $input.attr('id', one.main.admin.id.modal.add.form.password);
-            $input.attr('type', 'password');
-            $fieldset.append($label).append($input);
-            // roles
-            var $label = one.lib.form.label('Roles');
-            var options = {
-                "Network-Admin" : "Network Administrator",
-                "Network-Operator" : "Network Operator"
-            };
-            var $select = one.lib.form.select.create(options);
-            $select.attr('id', one.main.admin.id.modal.add.form.role);
-            $fieldset.append($label).append($select);
-            $form.append($fieldset);
-            return $form;
-        },
-        footer : function() {
-            var footer = [];
-            
-            var addButton = one.lib.dashlet.button.single("Add User", one.main.admin.id.modal.add.user, "btn-primary", "");
-            var $addButton = one.lib.dashlet.button.button(addButton);
-            footer.push($addButton);
-            
-            var closeButton = one.lib.dashlet.button.single("Close", one.main.admin.id.modal.add.close, "", "");
-            var $closeButton = one.lib.dashlet.button.button(closeButton);
-            footer.push($closeButton);
-            
-            return footer;
-        }
-    }
-}
-
-one.main.dashlet = {
-       left : {
-               top : $("#left-top .dashlet"),
-               bottom : $("#left-bottom .dashlet")
-       },
-       right : {
-               bottom : $("#right-bottom .dashlet")
-       }
-}
-
-/** BOOTSTRAP */
-$(".modal").on('hidden', function() {
-    $(this).remove();
-});
-
-$("#alert .close").click(function() {
-       $("#alert").hide();
-});
-
-/** INIT */
-
-// parse role
-one.role = $('#admin').data('role');
-
-// user admin
-$("#admin").click(function() {
-    one.main.admin.modal.initialize(function($modal) {
-        $modal.modal();
-    });
-});
-
-// save
-$("#save").click(function() {
-       $.post(one.main.constants.address.save, function(data) {
-               if (data == "Success") {
-                       one.lib.alert("Configuration Saved");
-               } else {
-                       one.lib.alert("Unable to save configuration: "+data);
-               }
-       });
-});
-
-// logout
-$("#logout").click(function() {
-       location.href = "/logout";
-});
-
-$.ajaxSetup({
-    complete : function(xhr,textStatus) {
-       var mime = xhr.getResponseHeader('Content-Type');
-        if (mime.substring(0, 9) == 'text/html') {
-            location.href = '/';
-        }
-    }
-});
-
-/** MAIN PAGE LOAD */
-one.main.menu.load();
\ No newline at end of file
diff --git a/opendaylight/web/root/src/main/resources/js/open-topology.js b/opendaylight/web/root/src/main/resources/js/open-topology.js
new file mode 100644 (file)
index 0000000..21a37e4
--- /dev/null
@@ -0,0 +1,232 @@
+/** COMMON * */
+var labelType, useGradients, nativeTextSupport, animate;
+
+(function() {
+    var ua = navigator.userAgent, iStuff = ua.match(/iPhone/i)
+            || ua.match(/iPad/i), typeOfCanvas = typeof HTMLCanvasElement, nativeCanvasSupport = (typeOfCanvas == 'object' || typeOfCanvas == 'function'), textSupport = nativeCanvasSupport
+            && (typeof document.createElement('canvas').getContext('2d').fillText == 'function');
+    // I'm setting this based on the fact that ExCanvas provides text support
+    // for IE
+    // and that as of today iPhone/iPad current text support is lame
+    labelType = (!nativeCanvasSupport || (textSupport && !iStuff)) ? 'Native'
+            : 'HTML';
+    nativeTextSupport = labelType == 'Native';
+    useGradients = nativeCanvasSupport;
+    animate = !(iStuff || !nativeCanvasSupport);
+})();
+
+/** TOPOLOGY * */
+one.topology = {};
+
+one.topology.option = {
+    navigation : function(enable, panning, zooming) {
+        var option = {};
+        option["enable"] = enable;
+        option["panning"] = panning;
+        option["zooming"] = zooming;
+        return option;
+    },
+    node : function(overridable, color, height, dim) {
+        var option = {};
+        option["overridable"] = overridable;
+        option["color"] = color;
+        option["height"] = height;
+        option["dim"] = dim;
+        return option;
+    },
+    edge : function(overridable, color, lineWidth, epsilon) {
+        var option = {};
+        option["overridable"] = overridable;
+        option["color"] = color;
+        option["lineWidth"] = lineWidth;
+        if (epsilon != undefined)
+            option["epsilon"] = epsilon;
+        return option;
+    },
+    label : function(style, node) {
+        var marginTop, minWidth;
+        if (node.data["$type"] == "swtch") {
+            marginTop = "42px";
+            minWidth = "65px";
+        } else if (node.data["$type"] == "host") {
+            marginTop = "48px";
+            minWidth = "";
+        } else if (node.data["$type"].indexOf("monitor") == 0) {
+            marginTop = "52px";
+            minWidth = "";
+        }
+        style.marginTop = marginTop;
+        style.minWidth = minWidth;
+        style.background = "rgba(68,68,68,0.7)";
+        style.borderRadius = "4px";
+        style.color = "#fff";
+        style.cursor = "default";
+    }
+};
+
+one.topology.init = function(json) {
+    if (json.length == 0) {
+        $div = $(document.createElement('div'));
+        $img = $(document.createElement('div'));
+        $img.css('height', '128px');
+        $img.css('width', '128px');
+        $img.css('background-image', 'url(/img/topology_view_1033_128.png)');
+        $img.css('clear', 'both');
+        $img.css('margin', '0 auto');
+        $p = $(document.createElement('p'));
+        $p.addClass('text-center');
+        $p.addClass('text-info');
+        $p.css('width', '100%');
+        $p.css('padding', '10px 0');
+        $p.css('cursor', 'default');
+        $p.append('No Network Elements Connected');
+        $div.css('position', 'absolute');
+        $div.css('top', '25%');
+        $div.css('margin', '0 auto');
+        $div.css('width', '100%');
+        $div.css('text-align', 'center');
+        $div.append($img).append($p);
+        $("#topology").append($div);
+        return false;
+    }
+    one.topology.graph = new $jit.MultiTopology(
+            {
+                injectInto : 'topology',
+                Navigation : one.topology.option.navigation(true,
+                        'avoid nodes', 10),
+                Node : one.topology.option.node(true, '#444', 25, 27),
+                Edge : one.topology.option.edge(true, '23A4FF', 1.5),
+                Tips : {
+                    enable : true,
+                    type : 'Native',
+                    onShow : function(tip, node) {
+                        if (node.name != undefined)
+                            tip.innerHTML = "";
+                        // tipsOnShow(tip, node);
+                    }
+                },
+                Events : {
+                    enable : true,
+                    type : 'Native',
+                    onMouseEnter : function(node, eventInfo, e) {
+                        // if node
+                        if (node.id != undefined) {
+                            one.topology.graph.canvas.getElement().style.cursor = 'move';
+                        } else if (eventInfo.edge != undefined
+                                && eventInfo.edge.nodeTo.data["$type"] == "swtch"
+                                && eventInfo.edge.nodeFrom.data["$type"] == "swtch") {
+                            one.topology.graph.canvas.getElement().style.cursor = 'pointer';
+                        }
+                    },
+                    onMouseLeave : function(node, eventInfo, e) {
+                        one.topology.graph.canvas.getElement().style.cursor = '';
+                    },
+                    // Update node positions when dragged
+                    onDragMove : function(node, eventInfo, e) {
+                        var pos = eventInfo.getPos();
+                        node.pos.setc(pos.x, pos.y);
+                        one.topology.graph.plot();
+                        one.topology.graph.canvas.getElement().style.cursor = 'crosshair';
+                    },
+                    // Implement the same handler for touchscreens
+                    onTouchMove : function(node, eventInfo, e) {
+                        $jit.util.event.stop(e); // stop default touchmove
+                        // event
+                        this.onDragMove(node, eventInfo, e);
+                    },
+                    onDragEnd : function(node, eventInfo, e) {
+                        var ps = eventInfo.getPos();
+                        var did = node.id;
+                        var data = {};
+                        data['x'] = ps.x;
+                        data['y'] = ps.y;
+                        $.post('/controller/web/topology/node/' + did, data);
+                    },
+                    onClick : function(node, eventInfo, e) {
+                        if (one.f.topology === undefined) {
+                            return false;
+                        } else {
+                            one.f.topology.Events.onClick(node, eventInfo);
+                        }
+                    }
+                },
+                iterations : 200,
+                levelDistance : 130,
+                onCreateLabel : function(domElement, node) {
+                    var nameContainer = document.createElement('span'), closeButton = document
+                            .createElement('span'), style = nameContainer.style;
+                    nameContainer.className = 'name';
+                    var nodeDesc = node.data["$desc"];
+                    if (nodeDesc == "None" || nodeDesc == ""
+                            || nodeDesc == "undefined" || nodeDesc == undefined) {
+                        nameContainer.innerHTML = "<small>" + node.name
+                                + "</small>";
+                    } else {
+                        nameContainer.innerHTML = nodeDesc;
+                    }
+                    domElement.appendChild(nameContainer);
+                    style.fontSize = "1.0em";
+                    style.color = "#000";
+                    style.fontWeight = "bold";
+                    style.width = "100%";
+                    style.padding = "1.5px 4px";
+                    style.display = "block";
+
+                    one.topology.option.label(style, node);
+                },
+                onPlaceLabel : function(domElement, node) {
+                    var style = domElement.style;
+                    var left = parseInt(style.left);
+                    var top = parseInt(style.top);
+                    var w = domElement.offsetWidth;
+                    style.left = (left - w / 2) + 'px';
+                    style.top = (top - 15) + 'px';
+                    style.display = '';
+                    style.minWidth = "28px";
+                    style.width = "auto";
+                    style.height = "28px";
+                    style.textAlign = "center";
+                }
+            });
+
+    one.topology.graph.loadJSON(json);
+    // compute positions incrementally and animate.
+    one.topology.graph.computeIncremental({
+        iter : 40,
+        property : 'end',
+        onStep : function(perc) {
+            console.log(perc + '% loaded');
+        },
+        onComplete : function() {
+            for ( var idx in one.topology.graph.graph.nodes) {
+                var node = one.topology.graph.graph.nodes[idx];
+                if (node.getData("x") && node.getData("y")) {
+                    var x = node.getData("x");
+                    var y = node.getData("y");
+                    node.setPos(new $jit.Complex(x, y), "end");
+                }
+            }
+            console.log('done');
+            one.topology.graph.animate({
+                modes : [ 'linear' ],
+                transition : $jit.Trans.Elastic.easeOut,
+                duration : 0
+            });
+        }
+    });
+    one.topology.graph.canvas.setZoom(0.8, 0.8);
+}
+
+one.topology.update = function() {
+    $('#topology').empty();
+    $.getJSON(one.global.remoteAddress + "controller/web/topology/visual.json",
+            function(data) {
+                one.topology.init(data);
+            });
+}
+
+/** INIT */
+$.getJSON(one.global.remoteAddress + "controller/web/topology/visual.json",
+        function(data) {
+            one.topology.init(data);
+        });
diff --git a/opendaylight/web/root/src/main/resources/js/open.js b/opendaylight/web/root/src/main/resources/js/open.js
new file mode 100644 (file)
index 0000000..629d5bb
--- /dev/null
@@ -0,0 +1,481 @@
+one.main = {};
+
+one.main.constants = {
+    address : {
+        menu : "/web.json",
+        prefix : "/controller/web",
+        save : "/save"
+    }
+}
+
+one.main.menu = {
+    load : function() {
+        one.main.menu.ajax(function(data) {
+            // reparse the ajax data
+            var result = one.main.menu.data.menu(data);
+            // transform into list to append to menu
+            var $div = one.main.menu.menu(result);
+            // append to menu
+            $("#menu .nav").append($div.children());
+            // binding all menu items
+            var $menu = $("#menu .nav a");
+            $menu.click(function() {
+                var href = $(this).attr('href').substring(1);
+                one.main.page.load(href);
+                var $li = $(this).parent();
+                // reset all other active
+                $menu.each(function(index, value) {
+                    $(value).parent().removeClass('active');
+                });
+                $li.addClass('active');
+            });
+            // reset or go to first menu item by default
+            var currentLocation = location.hash;
+            if (data[currentLocation.substring(1)] == undefined) {
+                $($menu[0]).click();
+            } else {
+                $menu.each(function(index, value) {
+                    var menuLocation = $(value).attr('href');
+                    if (currentLocation == menuLocation) {
+                        $($menu[index]).click();
+                        return;
+                    }
+                });
+            }
+        });
+    },
+    menu : function(result) {
+        var $div = $(document.createElement('div'));
+        $(result).each(function(index, value) {
+            if (value != undefined) {
+                var $li = $(document.createElement('li'));
+                var $a = $(document.createElement('a'));
+                $a.text(value['name']);
+                $a.attr('href', '#' + value['id']);
+                $li.append($a);
+                $div.append($li);
+            }
+        });
+        return $div;
+    },
+    ajax : function(successCallback) {
+        $.getJSON(one.main.constants.address.menu, function(data) {
+            successCallback(data);
+        });
+    },
+    data : {
+        menu : function(data) {
+            var result = [];
+            $.each(data, function(key, value) {
+                var order = value['order'];
+                if (order >= 0) {
+                    var name = value['name'];
+                    var entry = {
+                        'name' : name,
+                        'id' : key
+                    };
+                    result[order] = entry;
+                }
+            });
+            return result;
+        }
+    }
+}
+
+one.main.page = {
+    load : function(page) {
+        if (one.f !== undefined && one.f.cleanUp !== undefined) {
+            one.f.cleanUp();
+        }
+        // clear page related
+        delete one.f;
+        $('.dashlet', '#main').empty();
+        $('.nav', '#main').empty();
+        // fetch page's js
+        $.getScript(one.main.constants.address.prefix + "/" + page
+                + "/js/page.js");
+
+        $.ajaxSetup({
+            data : {
+                'x-page-url' : page
+            }
+        });
+    },
+    dashlet : function($nav, dashlet) {
+        var $li = $(document.createElement('li'));
+        var $a = $(document.createElement('a'));
+        $a.text(dashlet.name);
+        $a.attr('id', dashlet.id);
+        $a.attr('href', '#');
+        $li.append($a);
+        $nav.append($li);
+    }
+}
+
+one.main.admin = {
+    id : {
+        modal : {
+            main : "one_main_admin_id_modal_main",
+            close : "one_main_admin_id_modal_close",
+            user : "one_main_admin_id_modal_user",
+            add : {
+                user : "one_main_admin_id_modal_add_user",
+                close : "one_main_admin_id_modal_add_close",
+                form : {
+                    name : "one_main_admin_id_modal_add_form_name",
+                    role : "one_main_admin_id_modal_add_form_role",
+                    password : "one_main_admin_id_modal_add_form_password"
+                }
+            },
+            remove : {
+                user : "one_main_admin_id_modal_remove_user",
+                close : "one_main_admin_id_modal_remove_close"
+            }
+        },
+        add : {
+            user : "one_main_admin_id_add_user"
+        }
+    },
+    address : {
+        root : "/admin",
+        users : "/users"
+    },
+    modal : {
+        initialize : function(callback) {
+            var h3 = "Welcome " + $('#admin').text();
+            var footer = one.main.admin.modal.footer();
+            var $modal = one.lib.modal.spawn(one.main.admin.id.modal.main, h3,
+                    '', footer);
+
+            // close binding
+            $('#' + one.main.admin.id.modal.close, $modal).click(function() {
+                $modal.modal('hide');
+            });
+
+            // body inject
+            one.main.admin.ajax.users(function($body) {
+                one.lib.modal.inject.body($modal, $body);
+            });
+
+            // modal show callback
+            callback($modal);
+        },
+        footer : function() {
+            var footer = [];
+
+            var closeButton = one.lib.dashlet.button.single("Close",
+                    one.main.admin.id.modal.close, "", "");
+            var $closeButton = one.lib.dashlet.button.button(closeButton);
+            footer.push($closeButton);
+
+            return footer;
+        }
+    },
+    ajax : {
+        users : function(callback) {
+            $.getJSON(one.main.admin.address.root
+                    + one.main.admin.address.users, function(data) {
+                var body = one.main.admin.data.users(data);
+                var $body = one.main.admin.body.users(body);
+                callback($body);
+            });
+        }
+    },
+    data : {
+        users : function(data) {
+            var body = [];
+            $(data).each(function(index, value) {
+                var tr = {};
+                var entry = [];
+                entry.push(value['user']);
+                entry.push(value['role']);
+                tr['entry'] = entry;
+                tr['id'] = value['user'];
+                body.push(tr);
+            });
+            return body;
+        }
+    },
+    body : {
+        users : function(body) {
+            var $div = $(document.createElement('div'));
+            var $h5 = $(document.createElement('h5'));
+            $h5.append("Manage Users");
+            var attributes = [ "table-striped", "table-bordered",
+                    "table-hover", "table-cursor" ];
+            var $table = one.lib.dashlet.table.table(attributes);
+            var headers = [ "User", "Role" ];
+            var $thead = one.lib.dashlet.table.header(headers);
+            var $tbody = one.lib.dashlet.table.body(body);
+            $table.append($thead).append($tbody);
+
+            // bind table
+            if (one.role < 2) {
+                $table.find('tr').click(function() {
+                    var id = $(this).data('id');
+                    one.main.admin.remove.modal.initialize(id);
+                });
+            }
+
+            // append to div
+            $div.append($h5).append($table);
+
+            if (one.role < 2) {
+                var addUserButton = one.lib.dashlet.button.single("Add User",
+                        one.main.admin.id.add.user, "btn-primary", "btn-mini");
+                var $addUserButton = one.lib.dashlet.button
+                        .button(addUserButton);
+                $div.append($addUserButton);
+
+                // add user binding
+                $addUserButton.click(function() {
+                    one.main.admin.add.modal.initialize();
+                });
+            }
+
+            return $div;
+        }
+    },
+    remove : {
+        modal : {
+            initialize : function(id) {
+                var h3 = "Remove User";
+                var footer = one.main.admin.remove.footer();
+                var $body = one.main.admin.remove.body();
+                var $modal = one.lib.modal.spawn(one.main.admin.id.modal.user,
+                        h3, $body, footer);
+
+                // close binding
+                $('#' + one.main.admin.id.modal.remove.close, $modal).click(
+                        function() {
+                            $modal.modal('hide');
+                        });
+
+                // remove binding
+                $('#' + one.main.admin.id.modal.remove.user, $modal)
+                        .click(
+                                function() {
+                                    one.main.admin.remove.modal
+                                            .ajax(
+                                                    id,
+                                                    function(result) {
+                                                        if (result == 'Success') {
+                                                            $modal
+                                                                    .modal('hide');
+                                                            // body inject
+                                                            var $admin = $('#'
+                                                                    + one.main.admin.id.modal.main);
+                                                            one.main.admin.ajax
+                                                                    .users(function($body) {
+                                                                        one.lib.modal.inject
+                                                                                .body(
+                                                                                        $admin,
+                                                                                        $body);
+                                                                    });
+                                                        } else
+                                                            alert("Failed to remove user: "
+                                                                    + result);
+                                                    });
+                                });
+
+                $modal.modal();
+            },
+            ajax : function(id, callback) {
+                $.post(one.main.admin.address.root
+                        + one.main.admin.address.users + '/' + id,
+                        function(data) {
+                            callback(data);
+                        });
+            },
+        },
+
+        footer : function() {
+            var footer = [];
+
+            var removeButton = one.lib.dashlet.button.single("Remove User",
+                    one.main.admin.id.modal.remove.user, "btn-danger", "");
+            var $removeButton = one.lib.dashlet.button.button(removeButton);
+            footer.push($removeButton);
+
+            var closeButton = one.lib.dashlet.button.single("Close",
+                    one.main.admin.id.modal.remove.close, "", "");
+            var $closeButton = one.lib.dashlet.button.button(closeButton);
+            footer.push($closeButton);
+
+            return footer;
+        },
+        body : function() {
+            var $p = $(document.createElement('p'));
+            $p.append("Remove user?");
+            return $p;
+        },
+    },
+    add : {
+        modal : {
+            initialize : function() {
+                var h3 = "Add User";
+                var footer = one.main.admin.add.footer();
+                var $body = one.main.admin.add.body();
+                var $modal = one.lib.modal.spawn(one.main.admin.id.modal.user,
+                        h3, $body, footer);
+
+                // close binding
+                $('#' + one.main.admin.id.modal.add.close, $modal).click(
+                        function() {
+                            $modal.modal('hide');
+                        });
+
+                // add binding
+                $('#' + one.main.admin.id.modal.add.user, $modal)
+                        .click(
+                                function() {
+                                    one.main.admin.add.modal
+                                            .add(
+                                                    $modal,
+                                                    function(result) {
+                                                        if (result == 'Success') {
+                                                            $modal
+                                                                    .modal('hide');
+                                                            // body inject
+                                                            var $admin = $('#'
+                                                                    + one.main.admin.id.modal.main);
+                                                            one.main.admin.ajax
+                                                                    .users(function($body) {
+                                                                        one.lib.modal.inject
+                                                                                .body(
+                                                                                        $admin,
+                                                                                        $body);
+                                                                    });
+                                                        } else
+                                                            alert("Failed to add user: "
+                                                                    + result);
+                                                    });
+                                });
+
+                $modal.modal();
+            },
+            add : function($modal, callback) {
+                var user = {};
+                user['user'] = $modal.find(
+                        '#' + one.main.admin.id.modal.add.form.name).val();
+                user['password'] = $modal.find(
+                        '#' + one.main.admin.id.modal.add.form.password).val();
+                user['role'] = $modal.find(
+                        '#' + one.main.admin.id.modal.add.form.role).find(
+                        'option:selected').attr('value');
+
+                var resource = {};
+                resource['json'] = JSON.stringify(user);
+                resource['action'] = 'add'
+
+                one.main.admin.add.modal.ajax(resource, callback);
+            },
+            ajax : function(data, callback) {
+                $.post(one.main.admin.address.root
+                        + one.main.admin.address.users, data, function(data) {
+                    callback(data);
+                });
+            }
+        },
+        body : function() {
+            var $form = $(document.createElement('form'));
+            var $fieldset = $(document.createElement('fieldset'));
+            // user
+            var $label = one.lib.form.label('Username');
+            var $input = one.lib.form.input('Username');
+            $input.attr('id', one.main.admin.id.modal.add.form.name);
+            $fieldset.append($label).append($input);
+            // password
+            var $label = one.lib.form.label('Password');
+            var $input = one.lib.form.input('Password');
+            $input.attr('id', one.main.admin.id.modal.add.form.password);
+            $input.attr('type', 'password');
+            $fieldset.append($label).append($input);
+            // roles
+            var $label = one.lib.form.label('Roles');
+            var options = {
+                "Network-Admin" : "Network Administrator",
+                "Network-Operator" : "Network Operator"
+            };
+            var $select = one.lib.form.select.create(options);
+            $select.attr('id', one.main.admin.id.modal.add.form.role);
+            $fieldset.append($label).append($select);
+            $form.append($fieldset);
+            return $form;
+        },
+        footer : function() {
+            var footer = [];
+
+            var addButton = one.lib.dashlet.button.single("Add User",
+                    one.main.admin.id.modal.add.user, "btn-primary", "");
+            var $addButton = one.lib.dashlet.button.button(addButton);
+            footer.push($addButton);
+
+            var closeButton = one.lib.dashlet.button.single("Close",
+                    one.main.admin.id.modal.add.close, "", "");
+            var $closeButton = one.lib.dashlet.button.button(closeButton);
+            footer.push($closeButton);
+
+            return footer;
+        }
+    }
+}
+
+one.main.dashlet = {
+    left : {
+        top : $("#left-top .dashlet"),
+        bottom : $("#left-bottom .dashlet")
+    },
+    right : {
+        bottom : $("#right-bottom .dashlet")
+    }
+}
+
+/** BOOTSTRAP */
+$(".modal").on('hidden', function() {
+    $(this).remove();
+});
+
+$("#alert .close").click(function() {
+    $("#alert").hide();
+});
+
+/** INIT */
+
+// parse role
+one.role = $('#admin').data('role');
+
+// user admin
+$("#admin").click(function() {
+    one.main.admin.modal.initialize(function($modal) {
+        $modal.modal();
+    });
+});
+
+// save
+$("#save").click(function() {
+    $.post(one.main.constants.address.save, function(data) {
+        if (data == "Success") {
+            one.lib.alert("Configuration Saved");
+        } else {
+            one.lib.alert("Unable to save configuration: " + data);
+        }
+    });
+});
+
+// logout
+$("#logout").click(function() {
+    location.href = "/logout";
+});
+
+$.ajaxSetup({
+    complete : function(xhr, textStatus) {
+        var mime = xhr.getResponseHeader('Content-Type');
+        if (mime.substring(0, 9) == 'text/html') {
+            location.href = '/';
+        }
+    }
+});
+
+/** MAIN PAGE LOAD */
+one.main.menu.load();
\ No newline at end of file