MD-SAL RuntimeDataProvider for Forwarding Rules
[controller.git] / opendaylight / web / flows / src / main / resources / js / page.js
1 /*
2  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9 //PAGE flows
10 one.f = {};
11
12 // specify dashlets and layouts
13 one.f.dashlet = {
14     flows : {
15         id : 'flows',
16         name : 'Flow Entries'
17     },
18     nodes : {
19         id : 'nodes',
20         name : 'Nodes'
21     },
22     detail : {
23         id : 'detail',
24         name : 'Flow Detail'
25     }
26 };
27
28 one.f.menu = {
29     left : {
30         top : [
31             one.f.dashlet.flows
32         ],
33         bottom : [
34             one.f.dashlet.nodes
35         ]
36     },
37     right : {
38         top : [],
39         bottom : [
40             one.f.dashlet.detail
41         ]
42     }
43 };
44
45 one.f.address = {
46     root : "/controller/web/flows",
47     flows : {
48         main : "/main",
49         flows : "/node-flows",
50         nodes : "/node-ports",
51         flow : "/flow",
52         deleteFlows:"/flow/deleteFlows"
53     }
54 }
55
56 /** NODES **/
57 one.f.nodes = {
58     id : {
59         dashlet: {
60             datagrid: "one_f_nodes_id_dashlet_datagrid"
61         }
62     },
63     registry : {},
64     dashlet : function($dashlet) {
65         var $h4 = one.lib.dashlet.header("Nodes");
66         $dashlet.append($h4);
67
68         one.f.nodes.ajax.dashlet(function(data) {
69             var $gridHTML = one.lib.dashlet.datagrid.init(one.f.nodes.id.dashlet.datagrid, {
70                 searchable: true,
71                 filterable: false,
72                 pagination: true,
73                 flexibleRowsPerPage: true
74                 }, "table-striped table-condensed");
75             $dashlet.append($gridHTML);
76             var dataSource = one.f.nodes.data.nodesDataGrid(data);
77             $("#" + one.f.nodes.id.dashlet.datagrid).datagrid({dataSource: dataSource});
78         });
79     },
80     ajax : {
81         dashlet : function(callback) {
82             $.getJSON(one.f.address.root+one.f.address.flows.flows, function(data) {
83                 callback(data);
84             });
85         }
86     },
87     data : {
88         nodesDataGrid: function(data) {
89             var gridData = [];
90             $.each(data, function(nodeName, flow) {
91                 var nodeFlowObject = {};
92                 nodeFlowObject["nodeName"] = nodeName;
93                 nodeFlowObject["flows"] = flow;
94                 nodeFlowObject["rowData"] = nodeName + flow + "-foobar";
95                 gridData.push(nodeFlowObject);
96             });
97
98             var source = new StaticDataSource({
99                     columns: [
100                         {
101                             property: 'nodeName',
102                             label: 'Node',
103                             sortable: true
104                         },
105                         {
106                             property: 'flows',
107                             label: 'Flows',
108                             sortable: true
109                         }
110                     ],
111                     data: gridData,
112                     delay: 0
113                 });
114             return source;
115         }
116     },
117     body : {
118         dashlet : function(body, callback) {
119             var attributes = ['table-striped', 'table-bordered', 'table-hover', 'table-condensed'];
120             var $table = one.lib.dashlet.table.table(attributes);
121
122             var headers = ['Node', 'Flows'];
123             var $thead = one.lib.dashlet.table.header(headers);
124             $table.append($thead);
125
126             var $tbody = one.lib.dashlet.table.body(body);
127             $table.append($tbody);
128
129             return $table;
130         }
131     }
132 }
133
134 /** FLOW DETAIL **/
135 one.f.detail = {
136     id : {},
137     registry : {},
138     dashlet : function($dashlet, details) {
139         var $h4 = one.lib.dashlet.header("Flow Details");
140         $dashlet.append($h4);
141
142         // details
143         if (details == undefined) {
144             var $none = $(document.createElement('div'));
145             $none.addClass('none');
146             var $p = $(document.createElement('p'));
147             $p.text('Please select a flow');
148             $p.addClass('text-center').addClass('text-info');
149
150             $dashlet.append($none)
151                 .append($p);
152         }
153     },
154     data : {
155         dashlet : function(data) {
156             var body = [];
157             var tr = {};
158             var entry = [];
159
160             entry.push(data['name']);
161             entry.push(data['node']);
162             entry.push(data['flow']['priority']);
163             entry.push(data['flow']['hardTimeout']);
164             entry.push(data['flow']['idleTimeout']);
165
166             tr.entry = entry;
167             body.push(tr);
168             return body;
169         },
170         description : function(data) {
171             var body = [];
172             var tr = {};
173             var entry = [];
174                         entry.push(data['flow']['ingressPort']);
175             entry.push(data['flow']['etherType']);
176             entry.push(data['flow']['vlanId']);
177             entry.push(data['flow']['vlanPriority']);
178             entry.push(data['flow']['srcMac']);
179             entry.push(data['flow']['dstMac']);
180             entry.push(data['flow']['srcIp']);
181             entry.push(data['flow']['dstIp']);
182             entry.push(data['flow']['tosBits']);
183             entry.push(data['flow']['srcPort']);
184             entry.push(data['flow']['dstPort']);
185             entry.push(data['flow']['protocol']);
186             entry.push(data['flow']['cookie']);
187
188             tr.entry = entry;
189             body.push(tr);
190             return body;
191         },
192         actions : function(data) {
193             var body = [];
194             var tr = {};
195             var entry = [];
196
197             var actions = '';
198             $(data['flow']['actions']).each(function(index, value) {
199                 actions += value + ', ';
200             });
201             actions = actions.slice(0,-2);
202             entry.push(actions);
203
204             tr.entry = entry;
205             body.push(tr);
206             return body;
207         }
208     },
209     body : {
210         dashlet : function(body) {
211             // create table
212             var header = ['Flow Name', 'Node', 'Priority', 'Hard Timeout', 'Idle Timeout'];
213             var $thead = one.lib.dashlet.table.header(header);
214             var attributes = ['table-striped', 'table-bordered', 'table-condensed'];
215             var $table = one.lib.dashlet.table.table(attributes);
216             $table.append($thead);
217
218             var $tbody = one.lib.dashlet.table.body(body);
219             $table.append($tbody);
220
221             return $table;
222         },
223         description : function(body) {
224             var header = ['Input Port', 'Ethernet Type', 'VLAN ID', 'VLAN Priority', 'Source MAC', 'Dest MAC', 'Source IP', 'Dest IP', 'ToS', 'Source Port', 'Dest Port', 'Protocol', 'Cookie'];
225             var $thead = one.lib.dashlet.table.header(header);
226             var attributes = ['table-striped', 'table-bordered', 'table-condensed'];
227             var $table = one.lib.dashlet.table.table(attributes);
228             $table.append($thead);
229
230             var $tbody = one.lib.dashlet.table.body(body);
231             $table.append($tbody);
232
233             return $table;
234         },
235         actions : function(body) {
236             var header = ['Actions'];
237             var $thead = one.lib.dashlet.table.header(header);
238             var attributes = ['table-striped', 'table-bordered', 'table-condensed'];
239             var $table = one.lib.dashlet.table.table(attributes);
240             $table.append($thead);
241
242             var $tbody = one.lib.dashlet.table.body(body);
243             $table.append($tbody);
244
245             return $table;
246         }
247     }
248 }
249
250 /** FLOW ENTRIES **/
251 one.f.flows = {
252     id : {
253         dashlet : {
254             add : "one_f_flows_id_dashlet_add",
255             removeMultiple : "one_f_flows_id_dashlet_removeMultiple",
256             remove : "one_f_flows_id_dashlet_remove",
257             toggle : "one_f_flows_id_dashlet_toggle",
258             datagrid : "one_f_flows_id_dashlet_datagrid",
259             selectAllFlows : "one_f_flows_id_dashlet_selectAllFlows"
260         },
261         modal : {
262             install : "one_f_flows_id_modal_install",
263             add : "one_f_flows_id_modal_add",
264             close : "one_f_flows_id_modal_close",
265             modal : "one_f_flows_id_modal_modal",
266             dialog : {
267                 modal : "one_f_flows_id_modal_dialog_modal",
268                 remove : "one_f_flows_id_modal_dialog_remove",
269                 close : "one_f_flows_id_modal_dialog_close"
270             },
271             action : {
272                 button : "one_f_flows_id_modal_action_button",
273                 modal : "one_f_flows_id_modal_action_modal",
274                 add : "one_f_flows_id_modal_action_add",
275                 close : "one_f_flows_id_modal_action_close",
276                 table : "one_f_flows_id_modal_action_table",
277                 addOutputPorts : "one_f_flows_id_modal_action_addOutputPorts",
278                 setVlanId : "one_f_flows_id_modal_action_setVlanId",
279                 setVlanPriority : "one_f_flows_id_modal_action_setVlanPriority",
280                 modifyDatalayerSourceAddress : "one_f_flows_id_modal_action_modifyDatalayerSourceAddress",
281                 modifyDatalayerDestinationAddress : "one_f_flows_id_modal_action_modifyDatalayerDestinationAddress",
282                 modifyNetworkSourceAddress : "one_f_flows_modal_action_modifyNetworkSourceAddress",
283                 modifyNetworkDestinationAddress : "one_f_flows_modal_action_modifyNetworkDestinationAddress",
284                 modifyTosBits : "one_f_flows_modal_action_modifyTosBits",
285                 modifyTransportSourcePort : "one_f_flows_modal_action_modifyTransportSourcePort",
286                 modifyTransportDestinationPort : "one_f_flows_modal_action_modifyTransportDestinationPort",
287                 modal : {
288                     modal : "one_f_flows_modal_action_modal_modal",
289                     remove : "one_f_flows_modal_action_modal_remove",
290                     cancel : "one_f_flows_modal_action_modal_cancel"
291                 }
292             },
293             form : {
294                 name : "one_f_flows_id_modal_form_name",
295                 nodes : "one_f_flows_id_modal_form_nodes",
296                 port : "one_f_flows_id_modal_form_port",
297                 priority : "one_f_flows_id_modal_form_priority",
298                 hardTimeout : "one_f_flows_id_modal_form_hardTimeout",
299                 idleTimeout : "one_f_flows_id_modal_form_idleTimeout",
300                 cookie : "one_f_flows_id_modal_form_cookie",
301                 etherType : "one_f_flows_id_modal_form_etherType",
302                 vlanId : "one_f_flows_id_modal_form_vlanId",
303                 vlanPriority : "one_f_flows_id_modal_form_vlanPriority",
304                 srcMac : "one_f_flows_id_modal_form_srcMac",
305                 dstMac : "one_f_flows_id_modal_form_dstMac",
306                 srcIp : "one_f_flows_id_modal_form_srcIp",
307                 dstIp : "one_f_flows_id_modal_form_dstIp",
308                 tosBits : "one_f_flows_id_modal_form_tosBits",
309                 srcPort : "one_f_flows_id_modal_form_srcPort",
310                 dstPort : "one_f_flows_id_modal_form_dstPort",
311                 protocol : "one_f_flows_id_modal_form_protocol"
312             }
313         }
314     },
315     registry : {},
316     dashlet : function($dashlet, callback) {
317
318         // load body
319         one.f.flows.ajax.dashlet(function(data) {
320
321             var $h4 = one.lib.dashlet.header("Flow Entries");
322
323             $dashlet.append($h4);
324             if (one.f.flows.registry.privilege === 'WRITE') {
325                 var button = one.lib.dashlet.button.single("Add Flow Entry", one.f.flows.id.dashlet.add, "btn-primary", "btn-mini");
326                 var $button = one.lib.dashlet.button.button(button);
327
328                 $button.click(function() {
329                     var $modal = one.f.flows.modal.initialize();
330                     $modal.modal();
331                 });
332                 $dashlet.append($button);
333                 var button = one.lib.dashlet.button.single("Remove Flow Entry", one.f.flows.id.dashlet.removeMultiple, "btn-danger", "btn-mini");
334                 var $button = one.lib.dashlet.button.button(button);
335
336                 $button.click(function() {
337                     var checkedCheckBoxes = $('.flowEntry[type=checkbox]:checked');
338                     if (checkedCheckBoxes.size() === 0) {
339                         return false;
340                     }
341                     
342                     var requestData = [];
343                     
344                     checkedCheckBoxes.each(function(index, value) {
345                         var flowEntry = {};
346                         flowEntry['name'] = checkedCheckBoxes[index].name;
347                         flowEntry['node'] = checkedCheckBoxes[index].getAttribute("node");
348                         requestData.push(flowEntry);  
349                     });
350                     one.f.flows.modal.removeMultiple.dialog(requestData);
351                 });
352                 $dashlet.append($button);
353
354             }
355
356             var $gridHTML = one.lib.dashlet.datagrid.init(one.f.flows.id.dashlet.datagrid, {
357                 searchable: true,
358                 filterable: false,
359                 pagination: true,
360                 flexibleRowsPerPage: true
361                 }, "table-striped table-condensed");
362             $dashlet.append($gridHTML);
363             var dataSource = one.f.flows.data.flowsDataGrid(data);
364             $("#" + one.f.flows.id.dashlet.datagrid).datagrid({dataSource: dataSource}).on("loaded", function() {
365                     $("#"+one.f.flows.id.dashlet.datagrid.selectAllFlows).click(function() {
366                                 $("#" + one.f.flows.id.dashlet.datagrid).find(':checkbox').prop('checked',
367                                         $("#"+one.f.flows.id.dashlet.datagrid.selectAllFlows).is(':checked'));
368                     });
369                     
370                     $("#" + one.f.flows.id.dashlet.datagrid).find("tbody tr").each(function(index, tr) {
371                     $tr = $(tr);
372                     $span = $("td span", $tr);
373                     var flowstatus = $span.data("flowstatus");
374                     if($span.data("installinhw") != null) {
375                         var installInHw = $span.data("installinhw").toString();
376                         if(installInHw == "true" && flowstatus == "Success") {
377                             $tr.addClass("success");
378                         } else {
379                             $tr.addClass("warning");
380                         }
381                     }
382                     // attach mouseover to show pointer cursor
383                     $tr.mouseover(function() {
384                         $(this).css("cursor", "pointer");
385                     });
386                     // attach click event
387                     $tr.click(function() {
388                         var $td = $($(this).find("td")[1]);
389                         var id = $td.text();
390                         var node = $td.find("span").data("nodeid");
391                         one.f.flows.detail(id, node);
392                     });
393                     $(".flowEntry").click(function(e){
394                                 if (!$('.flowEntry[type=checkbox]:not(:checked)').length) {
395                             $("#"+one.f.flows.id.dashlet.datagrid.selectAllFlows)
396                                 .prop("checked",
397                               true);
398                         } else {
399                             $("#"+one.f.flows.id.dashlet.datagrid.selectAllFlows)
400                                 .prop("checked",
401                              false);
402                         }
403                         e.stopPropagation();
404                     });
405                 });
406             });
407             
408             // details callback
409             if(callback != undefined) callback();
410         });
411     },
412     detail : function(id, node) {
413         // clear flow details
414         var $detailDashlet = one.main.dashlet.right.bottom;
415         $detailDashlet.empty();
416         var $h4 = one.lib.dashlet.header("Flow Overview");
417         $detailDashlet.append($h4);
418
419         // details
420         var flows = one.f.flows.registry.flows;
421         var flow;
422         $(flows).each(function(index, value) {
423           if (value.name == id && value.nodeId == node) {
424             flow = value;
425           }
426         });
427         if (one.f.flows.registry.privilege === 'WRITE') {
428             // remove button
429             var button = one.lib.dashlet.button.single("Remove Flow", one.f.flows.id.dashlet.remove, "btn-danger", "btn-mini");
430             var $button = one.lib.dashlet.button.button(button);
431             $button.click(function() {
432                 var $modal = one.f.flows.modal.dialog.initialize(id, node);
433                 $modal.modal();
434             });
435             // toggle button
436             var toggle;
437             if (flow['flow']['installInHw'] == 'true' && flow['flow']['status'] == 'Success') {
438                 toggle = one.lib.dashlet.button.single("Uninstall Flow", one.f.flows.id.dashlet.toggle, "btn-warning", "btn-mini");
439             } else {
440                 toggle = one.lib.dashlet.button.single("Install Flow", one.f.flows.id.dashlet.toggle, "btn-success", "btn-mini");
441             }
442             var $toggle = one.lib.dashlet.button.button(toggle);
443             $toggle.click(function() {
444                 one.f.flows.modal.ajax.toggleflow(id, node, function(data) {
445                     if(data == "Success") {
446                         one.main.dashlet.right.bottom.empty();
447                         one.f.detail.dashlet(one.main.dashlet.right.bottom);
448                         one.main.dashlet.left.top.empty();
449                         one.f.flows.dashlet(one.main.dashlet.left.top, function() {
450                            // checks are backwards due to stale registry
451                            if(flow['flow']['installInHw'] == 'true') {
452                                one.lib.alert('Uninstalled Flow');
453                            } else {
454                                one.lib.alert('Installed Flow');
455                            }
456                            one.f.flows.detail(id, node)
457                         });
458                     } else {
459                         one.lib.alert('Cannot toggle flow: '+data);
460                     }
461                 });
462             });
463
464             $detailDashlet.append($button).append($toggle);
465         }
466         // append details
467         var body = one.f.detail.data.dashlet(flow);
468         var $body = one.f.detail.body.dashlet(body);
469         $detailDashlet.append($body);
470         var body = one.f.detail.data.description(flow);
471         var $body = one.f.detail.body.description(body);
472         $detailDashlet.append($body);
473         var body = one.f.detail.data.actions(flow);
474         var $body = one.f.detail.body.actions(body);
475         $detailDashlet.append($body);
476     },
477     modal : {
478         dialog : {
479             initialize : function(id, node) {
480                 var h3 = "Remove Flow";
481                 var $p = one.f.flows.modal.dialog.body(id);
482                 var footer = one.f.flows.modal.dialog.footer();
483                 var $modal = one.lib.modal.spawn(one.f.flows.id.modal.dialog.modal, h3, $p, footer);
484                 $('#'+one.f.flows.id.modal.dialog.close, $modal).click(function() {
485                     $modal.modal('hide');
486                 });
487                 $('#'+one.f.flows.id.modal.dialog.remove, $modal).click(function() {
488                     one.f.flows.modal.ajax.removeflow(id, node, function(data) {
489                         if (data == "Success") {
490                             $modal.modal('hide');
491                             one.main.dashlet.right.bottom.empty();
492                             one.f.detail.dashlet(one.main.dashlet.right.bottom);
493                             one.main.dashlet.left.top.empty();
494                             one.f.flows.dashlet(one.main.dashlet.left.top);
495                             one.lib.alert('Flow removed');
496                         } else {
497                             one.lib.alert('Cannot remove flow: '+data);
498                         }
499                     });
500                 });
501                 return $modal;
502             },
503             footer : function() {
504                 var footer = [];
505
506                 var removeButton = one.lib.dashlet.button.single("Remove Flow", one.f.flows.id.modal.dialog.remove, "btn-danger", "");
507                 var $removeButton = one.lib.dashlet.button.button(removeButton);
508                 footer.push($removeButton);
509
510                 var closeButton = one.lib.dashlet.button.single("Cancel", one.f.flows.id.modal.dialog.close, "", "");
511                 var $closeButton = one.lib.dashlet.button.button(closeButton);
512                 footer.push($closeButton);
513
514                 return footer;
515             },
516             body : function(id) {
517                 var $p = $(document.createElement('p'));
518                 $p.append('Remove flow '+id+'?');
519                 return $p;
520             }
521         },
522         initialize : function() {
523             var h3 = "Add Flow Entry";
524             var footer = one.f.flows.modal.footer();
525             var $modal = one.lib.modal.spawn(one.f.flows.id.modal.modal, h3, "", footer);
526
527             // bind close button
528             $('#'+one.f.flows.id.modal.close, $modal).click(function() {
529                 $modal.modal('hide');
530             });
531
532             // bind add flow button
533             $('#'+one.f.flows.id.modal.add, $modal).click(function() {
534                 one.f.flows.modal.add($modal, 'false');
535             });
536
537             // bind install flow button
538             $('#'+one.f.flows.id.modal.install, $modal).click(function() {
539                 one.f.flows.modal.add($modal, 'true');
540             });
541
542             // inject body (nodePorts)
543             one.f.flows.modal.ajax.nodes(function(nodes, nodeports) {
544                 var $body = one.f.flows.modal.body(nodes, nodeports);
545                 one.lib.modal.inject.body($modal, $body);
546             });
547
548             return $modal;
549         },
550         add : function($modal, install) {
551             var result = {};
552
553             result['name'] = $('#'+one.f.flows.id.modal.form.name, $modal).val();
554             result['ingressPort'] = $('#'+one.f.flows.id.modal.form.port, $modal).val();
555             result['priority'] = $('#'+one.f.flows.id.modal.form.priority, $modal).val();
556             result['hardTimeout'] = $('#'+one.f.flows.id.modal.form.hardTimeout, $modal).val();
557             result['idleTimeout'] = $('#'+one.f.flows.id.modal.form.idleTimeout, $modal).val();
558             result['cookie'] = $('#'+one.f.flows.id.modal.form.cookie, $modal).val();
559             result['etherType'] = $('#'+one.f.flows.id.modal.form.etherType, $modal).val();
560             result['vlanId'] = $('#'+one.f.flows.id.modal.form.vlanId, $modal).val();
561             result['vlanPriority'] = $('#'+one.f.flows.id.modal.form.vlanPriority, $modal).val();
562             result['dlSrc'] = $('#'+one.f.flows.id.modal.form.srcMac, $modal).val();
563             result['dlDst'] = $('#'+one.f.flows.id.modal.form.dstMac, $modal).val();
564             result['nwSrc'] = $('#'+one.f.flows.id.modal.form.srcIp, $modal).val();
565             result['nwDst'] = $('#'+one.f.flows.id.modal.form.dstIp, $modal).val();
566             result['tosBits'] = $('#'+one.f.flows.id.modal.form.tosBits, $modal).val();
567             result['tpSrc'] = $('#'+one.f.flows.id.modal.form.srcPort, $modal).val();
568             result['tpDst'] = $('#'+one.f.flows.id.modal.form.dstPort, $modal).val();
569             result['protocol'] = $('#'+one.f.flows.id.modal.form.protocol, $modal).val();
570
571             result['installInHw'] = install;
572
573             var nodeId = $('#'+one.f.flows.id.modal.form.nodes, $modal).val();
574
575             $.each(result, function(key, value) {
576                 if (value == "") delete result[key];
577             });
578
579             var action = [];
580             var $table = $('#'+one.f.flows.id.modal.action.table, $modal);
581             $($table.find('tbody').find('tr')).each(function(index, value) {
582                 if (!$(this).find('td').hasClass('empty')) {
583                     action.push($(value).data('action'));
584                 }
585             });
586             result['actions'] = action;
587
588             // frontend validation
589             if (result['name'] == undefined) {
590                 alert('Need flow name');
591                 return;
592             }
593             if (nodeId == '') {
594                 alert('Select node');
595                 return;
596             }
597             if (action.length == 0) {
598                 alert('Please specify an action');
599                 return;
600             }
601
602             // package for ajax call
603             var resource = {};
604             resource['body'] = JSON.stringify(result);
605             resource['action'] = 'add';
606             resource['nodeId'] = nodeId;
607
608             one.f.flows.modal.ajax.saveflow(resource, function(data) {
609                 if (data == "Success") {
610                     $modal.modal('hide');
611                     one.lib.alert('Flow Entry added');
612                     one.main.dashlet.left.top.empty();
613                     one.f.flows.dashlet(one.main.dashlet.left.top);
614                 } else {
615                     alert('Could not add flow: '+data);
616                 }
617             });
618         },
619         ajax : {
620             nodes : function(successCallback) {
621                 $.getJSON(one.f.address.root+one.f.address.flows.nodes, function(data) {
622                     var nodes = one.f.flows.modal.data.nodes(data);
623                     var nodeports = data;
624                     one.f.flows.registry['nodeports'] = nodeports;
625
626                     successCallback(nodes, nodeports);
627                 });
628             },
629             saveflow : function(resource, callback) {
630                 $.post(one.f.address.root+one.f.address.flows.flow, resource, function(data) {
631                     callback(data);
632                 });
633             },
634             removeflow : function(id, node, callback) {
635                 resource = {};
636                 resource['action'] = 'remove';
637                 $.post(one.f.address.root+one.f.address.flows.flow+'/'+node+'/'+id, resource, function(data) {
638                     callback(data);
639                 });
640             },
641             toggleflow : function(id, node, callback) {
642                 resource = {};
643                 resource['action'] = 'toggle';
644                 $.post(one.f.address.root+one.f.address.flows.flow+'/'+node+'/'+id, resource, function(data) {
645                     callback(data);
646                 });
647             }
648         },
649         data : {
650             nodes : function(data) {
651                 result = {};
652                 $.each(data, function(key, value) {
653                     result[key] = value['name'];
654                 });
655                 return result;
656             }
657         },
658         body : function(nodes, nodeports) {
659             var $form = $(document.createElement('form'));
660             var $fieldset = $(document.createElement('fieldset'));
661             // flow description
662             var $legend = one.lib.form.legend("");
663             $legend.css('visibility', 'hidden');
664             $fieldset.append($legend);
665             // name
666             var $label = one.lib.form.label("Name");
667             var $input = one.lib.form.input("Flow Name");
668             $input.attr('id', one.f.flows.id.modal.form.name);
669             $fieldset.append($label).append($input);
670             // node
671             var $label = one.lib.form.label("Node");
672             var $select = one.lib.form.select.create(nodes);
673             one.lib.form.select.prepend($select, { '' : 'Please Select a Node' });
674             $select.val($select.find("option:first").val());
675             $select.attr('id', one.f.flows.id.modal.form.nodes);
676
677             // bind onchange
678             $select.change(function() {
679                 // retrieve port value
680                 var node = $(this).find('option:selected').attr('value');
681                 var $ports = $('#'+one.f.flows.id.modal.form.port);
682                 if (node == '') {
683                     one.lib.form.select.inject($ports, {});
684                     return;
685                 }
686                 one.f.flows.registry['currentNode'] = node;
687                 var ports = nodeports[node]['ports'];
688                 one.lib.form.select.inject($ports, ports);
689                 one.lib.form.select.prepend($ports, { '' : 'Please Select a Port' });
690                 $ports.val($ports.find("option:first").val());
691             });
692
693             $fieldset.append($label).append($select);
694             // input port
695             var $label = one.lib.form.label("Input Port");
696             var $select = one.lib.form.select.create();
697             $select.attr('id', one.f.flows.id.modal.form.port);
698             $fieldset.append($label).append($select);
699             // priority
700             var $label = one.lib.form.label("Priority");
701             var $input = one.lib.form.input("Priority");
702             $input.attr('id', one.f.flows.id.modal.form.priority);
703             $input.val('500');
704             $fieldset.append($label).append($input);
705             // hardTimeout
706             var $label = one.lib.form.label("Hard Timeout");
707             var $input = one.lib.form.input("Hard Timeout");
708             $input.attr('id', one.f.flows.id.modal.form.hardTimeout);
709             $fieldset.append($label).append($input);
710             // idleTimeout
711             var $label = one.lib.form.label("Idle Timeout");
712             var $input = one.lib.form.input("Idle Timeout");
713             $input.attr('id', one.f.flows.id.modal.form.idleTimeout);
714             $fieldset.append($label).append($input);
715             // cookie
716             var $label = one.lib.form.label("Cookie");
717             var $input = one.lib.form.input("Cookie");
718             $input.attr('id', one.f.flows.id.modal.form.cookie);
719             $fieldset.append($label).append($input);
720             // layer 2
721             var $legend = one.lib.form.legend("Layer 2");
722             $fieldset.append($legend);
723             // etherType
724             var $label = one.lib.form.label("Ethernet Type");
725             var $input = one.lib.form.input("Ethernet Type");
726             $input.attr('id', one.f.flows.id.modal.form.etherType);
727             $input.val('0x800');
728             $fieldset.append($label).append($input);
729             // vlanId
730             var $label = one.lib.form.label("VLAN Identification Number");
731             var $input = one.lib.form.input("VLAN Identification Number");
732             $input.attr('id', one.f.flows.id.modal.form.vlanId);
733             var $help = one.lib.form.help("Range: 0 - 4095");
734             $fieldset.append($label).append($input).append($help);
735             // vlanPriority
736             var $label = one.lib.form.label("VLAN Priority");
737             var $input = one.lib.form.input("VLAN Priority");
738             $input.attr('id', one.f.flows.id.modal.form.vlanPriority);
739             var $help = one.lib.form.help("Range: 0 - 7");
740             $fieldset.append($label).append($input).append($help);
741             // srcMac
742             var $label = one.lib.form.label("Source MAC Address");
743             var $input = one.lib.form.input("3c:97:0e:75:c3:f7");
744             $input.attr('id', one.f.flows.id.modal.form.srcMac);
745             $fieldset.append($label).append($input);
746             // dstMac
747             var $label = one.lib.form.label("Destination MAC Address");
748             var $input = one.lib.form.input("7c:d1:c3:e8:e6:99");
749             $input.attr('id', one.f.flows.id.modal.form.dstMac);
750             $fieldset.append($label).append($input);
751             // layer 3
752             var $legend = one.lib.form.legend("Layer 3");
753             $fieldset.append($legend);
754             // srcIp
755             var $label = one.lib.form.label("Source IP Address");
756             var $input = one.lib.form.input("192.168.3.128");
757             $input.attr('id', one.f.flows.id.modal.form.srcIp);
758             $fieldset.append($label).append($input);
759             // dstIp
760             var $label = one.lib.form.label("Destination IP Address");
761             var $input = one.lib.form.input("2001:2334::0/32");
762             $input.attr('id', one.f.flows.id.modal.form.dstIp);
763             $fieldset.append($label).append($input);
764             // tosBits
765             var $label = one.lib.form.label("ToS Bits");
766             var $input = one.lib.form.input("ToS Bits");
767             $input.attr('id', one.f.flows.id.modal.form.tosBits);
768             var $help = one.lib.form.help("Range: 0 - 63");
769             $fieldset.append($label).append($input).append($help);
770             // layer 4
771             var $legend = one.lib.form.legend("Layer 4");
772             $fieldset.append($legend);
773             // srcPort
774             var $label = one.lib.form.label("Source Port");
775             var $input = one.lib.form.input("Source Port");
776             $input.attr('id', one.f.flows.id.modal.form.srcPort);
777             var $help = one.lib.form.help("Range: 0 - 65535");
778             $fieldset.append($label).append($input).append($help);
779             // dstPort
780             var $label = one.lib.form.label("Destination Port");
781             var $input = one.lib.form.input("Destination Port");
782             $input.attr('id', one.f.flows.id.modal.form.dstPort);
783             var $help = one.lib.form.help("Range: 0 - 65535");
784             $fieldset.append($label).append($input).append($help);
785             // protocol
786             var $label = one.lib.form.label("Protocol");
787             var $input = one.lib.form.input("Protocol");
788             $input.attr('id', one.f.flows.id.modal.form.protocol);
789             $fieldset.append($label).append($input);
790             // actions
791             var $legend = one.lib.form.label("Actions");
792             $fieldset.append($legend);
793             // actions table
794             var tableAttributes = ["table-striped", "table-bordered", "table-condensed", "table-hover", "table-cursor"];
795             var $table = one.lib.dashlet.table.table(tableAttributes);
796             $table.attr('id', one.f.flows.id.modal.action.table);
797             var tableHeaders = ["Action", "Data", "Type"];
798             var $thead = one.lib.dashlet.table.header(tableHeaders);
799             var $tbody = one.lib.dashlet.table.body("", tableHeaders);
800             $table.append($thead).append($tbody);
801             // actions
802             var actions = {
803                 "" : "Please Select an Action",
804                 "drop" : "Drop",
805                 "loopback" : "Loopback",
806                 "flood" : "Flood",
807                 "softwarePath" : "Software Path",
808                 "hardwarePath" : "Hardware Path",
809                 "controller" : "Controller",
810                 "addOutputPorts" : "Add Output Ports",
811                 "setVlanId" : "Set VLAN ID",
812                 "setVlanPriority" : "Set VLAN Priority",
813                 "stripVlanHeader" : "Strip VLAN Header",
814                 "modifyDatalayerSourceAddress" : "Modify Datalayer Source Address",
815                 "modifyDatalayerDestinationAddress" : "Modify Datalayer Destination Address",
816                 "modifyNetworkSourceAddress" : "Modify Network Source Address",
817                 "modifyNetworkDestinationAddress" :"Modify Network Destination Address",
818                 "modifyTosBits" : "Modify ToS Bits",
819                 "modifyTransportSourcePort" : "Modify Transport Source Port",
820                 "modifyTransportDestinationPort" : "Modify Transport Destination Port"
821             };
822             var $select = one.lib.form.select.create(actions);
823             // when selecting an action
824             $select.change(function() {
825                 var action = $(this).find('option:selected');
826                 one.f.flows.modal.action.parse(action.attr('value'));
827                 $select[0].selectedIndex = 0;
828             });
829
830             $fieldset.append($select).append($table);
831
832             // return
833             $form.append($fieldset);
834             return $form;
835         },
836         action : {
837             parse : function(option) {
838                 switch (option) {
839                     case "addOutputPorts" :
840                         var h3 = "Add Output Port";
841                         var $modal = one.f.flows.modal.action.initialize(h3, one.f.flows.modal.action.body.addOutputPorts, one.f.flows.modal.action.add.addOutputPorts);
842                         $modal.modal();
843                         break;
844                     case "setVlanId" :
845                         var h3 = "Set VLAN ID";
846                         var placeholder = "VLAN Identification Number";
847                         var id = one.f.flows.id.modal.action.setVlanId;
848                         var help = "Range: 0 - 4095";
849                         var action = 'SET_VLAN_ID';
850                         var name = "VLAN ID";
851                         var body = function() {
852                             return one.f.flows.modal.action.body.set(h3, placeholder, id, help);
853                         };
854                         var add = function($modal) {
855                             one.f.flows.modal.action.add.set(name, id, action, $modal);
856                         };
857                         var $modal = one.f.flows.modal.action.initialize(h3, body, add);
858                         $modal.modal();
859                         break;
860                     case "setVlanPriority" :
861                         var h3 = "Set VLAN Priority";
862                         var placeholder = "VLAN Priority";
863                         var id = one.f.flows.id.modal.action.setVlanPriority;
864                         var help = "Range: 0 - 7";
865                         var action = 'SET_VLAN_PCP';
866                         var name = "VLAN Priority";
867                         var body = function() {
868                             return one.f.flows.modal.action.body.set(h3, placeholder, id, help);
869                         };
870                         var add = function($modal) {
871                             one.f.flows.modal.action.add.set(name, id, action, $modal);
872                         };
873                         var $modal = one.f.flows.modal.action.initialize(h3, body, add);
874                         $modal.modal();
875                         break;
876                     case "stripVlanHeader" :
877                         var name = "Strip VLAN Header";
878                         var action = 'POP_VLAN';
879                         one.f.flows.modal.action.add.add(name, action);
880                         break;
881                     case "modifyDatalayerSourceAddress" :
882                         var h3 = "Set Source MAC Address";
883                         var placeholder = "Source MAC Address";
884                         var id = one.f.flows.id.modal.action.modifyDatalayerSourceAddress;
885                         var help = "Example: 00:11:22:aa:bb:cc";
886                         var action = 'SET_DL_SRC';
887                         var name = "Source MAC";
888                         var body = function() {
889                             return one.f.flows.modal.action.body.set(h3, placeholder, id, help);
890                         };
891                         var add = function($modal) {
892                             one.f.flows.modal.action.add.set(name, id, action, $modal);
893                         };
894                         var $modal = one.f.flows.modal.action.initialize(h3, body, add);
895                         $modal.modal();
896                         break;
897                     case "modifyDatalayerDestinationAddress" :
898                         var h3 = "Set Destination MAC Address";
899                         var placeholder = "Destination MAC Address";
900                         var id = one.f.flows.id.modal.action.modifyDatalayerDestinationAddress;
901                         var help = "Example: 00:11:22:aa:bb:cc";
902                         var action = 'SET_DL_DST';
903                         var name = "Destination MAC";
904                         var body = function() {
905                             return one.f.flows.modal.action.body.set(h3, placeholder, id, help);
906                         };
907                         var add = function($modal) {
908                             one.f.flows.modal.action.add.set(name, id, action, $modal);
909                         };
910                         var $modal = one.f.flows.modal.action.initialize(h3, body, add);
911                         $modal.modal();
912                         break;
913                     case "modifyNetworkSourceAddress" :
914                         var h3 = "Set IP Source Address";
915                         var placeholder = "Source IP Address";
916                         var id = one.f.flows.id.modal.action.modifyNetworkSourceAddress;
917                         var help = "Example: 127.0.0.1";
918                         var action = 'SET_NW_SRC';
919                         var name = "Source IP";
920                         var body = function() {
921                             return one.f.flows.modal.action.body.set(h3, placeholder, id, help);
922                         };
923                         var add = function($modal) {
924                             one.f.flows.modal.action.add.set(name, id, action, $modal);
925                         };
926                         var $modal = one.f.flows.modal.action.initialize(h3, body, add);
927                         $modal.modal();
928                         break;
929                     case "modifyNetworkDestinationAddress" :
930                         var h3 = "Set IP Destination Address";
931                         var placeholder = "Destination IP Address";
932                         var id = one.f.flows.id.modal.action.modifyNetworkDestinationAddress;
933                         var help = "Example: 127.0.0.1";
934                         var action = 'SET_NW_DST';
935                         var name = "Destination IP";
936                         var body = function() {
937                             return one.f.flows.modal.action.body.set(h3, placeholder, id, help);
938                         };
939                         var add = function($modal) {
940                             one.f.flows.modal.action.add.set(name, id, action, $modal);
941                         };
942                         var $modal = one.f.flows.modal.action.initialize(h3, body, add);
943                         $modal.modal();
944                         break;
945                     case "modifyTosBits" :
946                         var h3 = "Set IPv4 ToS";
947                         var placeholder = "IPv4 ToS";
948                         var id = one.f.flows.id.modal.action.modifyTosBits;
949                         var help = "Range: 0 - 63";
950                         var action = 'SET_NW_TOS';
951                         var name = "ToS Bits";
952                         var body = function() {
953                             return one.f.flows.modal.action.body.set(h3, placeholder, id, help);
954                         };
955                         var add = function($modal) {
956                             one.f.flows.modal.action.add.set(name, id, action, $modal);
957                         };
958                         var $modal = one.f.flows.modal.action.initialize(h3, body, add);
959                         $modal.modal();
960                         break;
961                     case "modifyTransportSourcePort" :
962                         var h3 = "Set Transport Source Port";
963                         var placeholder = "Transport Source Port";
964                         var id = one.f.flows.id.modal.action.modifyTransportSourcePort;
965                         var help = "Range: 1 - 65535";
966                         var action = 'SET_TP_SRC';
967                         var name = "Source Port";
968                         var body = function() {
969                             return one.f.flows.modal.action.body.set(h3, placeholder, id, help);
970                         };
971                         var add = function($modal) {
972                             one.f.flows.modal.action.add.set(name, id, action, $modal);
973                         };
974                         var $modal = one.f.flows.modal.action.initialize(h3, body, add);
975                         $modal.modal();
976                         break;
977                     case "modifyTransportDestinationPort" :
978                         var h3 = "Set Transport Destination Port";
979                         var placeholder = "Transport Destination Port";
980                         var id = one.f.flows.id.modal.action.modifyTransportDestinationPort;
981                         var help = "Range: 1 - 65535";
982                         var action = 'SET_TP_DST';
983                         var name = "Destination Port";
984                         var body = function() {
985                             return one.f.flows.modal.action.body.set(h3, placeholder, id, help);
986                         };
987                         var add = function($modal) {
988                             one.f.flows.modal.action.add.set(name, id, action, $modal);
989                         };
990                         var $modal = one.f.flows.modal.action.initialize(h3, body, add);
991                         $modal.modal();
992                         break;
993                     case "drop" :
994                         var name = "Drop";
995                         var action = 'DROP';
996                         one.f.flows.modal.action.add.add(name, action);
997                         break;
998                     case "loopback" :
999                         var name = "Loopback";
1000                         var action = 'LOOPBACK';
1001                         one.f.flows.modal.action.add.add(name, action);
1002                         break;
1003                     case "flood" :
1004                         var name = "Flood";
1005                         var action = 'FLOOD';
1006                         one.f.flows.modal.action.add.add(name, action);
1007                         break;
1008                     case "softwarePath" :
1009                         var name = "Software Path";
1010                         var action = 'SW_PATH';
1011                         one.f.flows.modal.action.add.add(name, action);
1012                         break;
1013                     case "hardwarePath" :
1014                         var name = "Hardware Path";
1015                         var action = 'HW_PATH';
1016                         one.f.flows.modal.action.add.add(name, action);
1017                         break;
1018                     case "controller" :
1019                         var name = "Controller";
1020                         var action = 'CONTROLLER';
1021                         one.f.flows.modal.action.add.add(name, action);
1022                         break;
1023                 }
1024             },
1025             initialize : function(h3, bodyCallback, addCallback) {
1026                 var footer = one.f.flows.modal.action.footer();
1027                 var $body = bodyCallback();
1028                 var $modal = one.lib.modal.spawn(one.f.flows.id.modal.action.modal, h3, $body, footer);
1029                 // bind close button
1030                 $('#'+one.f.flows.id.modal.action.close, $modal).click(function() {
1031                     $modal.modal('hide');
1032                 });
1033                 // bind add flow button
1034                 $('#'+one.f.flows.id.modal.action.add, $modal).click(function() {
1035                     addCallback($modal);
1036                 });
1037                 return $modal;
1038             },
1039             add : {
1040                 addOutputPorts : function($modal) {
1041                     var $options = $('#'+one.f.flows.id.modal.action.addOutputPorts).find('option:selected');
1042                     var ports = '';
1043                     var pid = '';
1044                     $options.each(function(index, value) {
1045                         ports = ports+$(value).text()+", ";
1046                         pid = pid+$(value).attr('value')+",";
1047                     });
1048                     ports = ports.slice(0,-2);
1049                     pid = pid.slice(0,-1);
1050                     var $tr = one.f.flows.modal.action.table.add("Add Output Ports", ports);
1051                     $tr.attr('id', 'addOutputPorts');
1052                     $tr.data('action', 'OUTPUT='+pid);
1053                     $tr.click(function() {
1054                         one.f.flows.modal.action.add.modal.initialize(this);
1055                     });
1056                     one.f.flows.modal.action.table.append($tr);
1057                     $modal.modal('hide');
1058                 },
1059                 add : function(name, action) {
1060                     var $tr = one.f.flows.modal.action.table.add(name);
1061                     $tr.attr('id', action);
1062                     $tr.data('action', action);
1063                     $tr.click(function() {
1064                         one.f.flows.modal.action.add.modal.initialize(this);
1065                     });
1066                     one.f.flows.modal.action.table.append($tr);
1067                 },
1068                 set : function(name, id, action, $modal) {
1069                     var $input = $('#'+id);
1070                     var value = $input.val();
1071                     var $tr = one.f.flows.modal.action.table.add(name, value);
1072                     $tr.attr('id', action);
1073                     $tr.data('action', action+'='+value);
1074                     $tr.click(function() {
1075                         one.f.flows.modal.action.add.modal.initialize(this);
1076                     });
1077                     one.f.flows.modal.action.table.append($tr);
1078                     $modal.modal('hide');
1079                 },
1080                 remove : function(that) {
1081                     $(that).remove();
1082                     var $table = $('#'+one.f.flows.id.modal.action.table);
1083                     if ($table.find('tbody').find('tr').size() == 0) {
1084                         var $tr = $(document.createElement('tr'));
1085                         var $td = $(document.createElement('td'));
1086                         $td.attr('colspan', '3');
1087                         $tr.addClass('empty');
1088                         $td.text('No data available');
1089                         $tr.append($td);
1090                         $table.find('tbody').append($tr);
1091                     }
1092                 },
1093                 modal : {
1094                     initialize : function(that) {
1095                         var h3 = "Remove Action";
1096                         var footer = one.f.flows.modal.action.add.modal.footer();
1097                         var $body = one.f.flows.modal.action.add.modal.body();
1098                         var $modal = one.lib.modal.spawn(one.f.flows.id.modal.action.modal.modal, h3, $body, footer);
1099
1100                         // bind cancel button
1101                         $('#'+one.f.flows.id.modal.action.modal.cancel, $modal).click(function() {
1102                             $modal.modal('hide');
1103                         });
1104
1105                         // bind remove button
1106                         $('#'+one.f.flows.id.modal.action.modal.remove, $modal).click(function() {
1107                             one.f.flows.modal.action.add.remove(that);
1108                             $modal.modal('hide');
1109                         });
1110
1111                         $modal.modal();
1112                     },
1113                     body : function() {
1114                         var $p = $(document.createElement('p'));
1115                         $p.append("Remove this action?");
1116                         return $p;
1117                     },
1118                     footer : function() {
1119                         var footer = [];
1120
1121                         var removeButton = one.lib.dashlet.button.single("Remove Action", one.f.flows.id.modal.action.modal.remove, "btn-danger", "");
1122                         var $removeButton = one.lib.dashlet.button.button(removeButton);
1123                         footer.push($removeButton);
1124
1125                         var cancelButton = one.lib.dashlet.button.single("Cancel", one.f.flows.id.modal.action.modal.cancel, "", "");
1126                         var $cancelButton = one.lib.dashlet.button.button(cancelButton);
1127                         footer.push($cancelButton);
1128
1129                         return footer;
1130                     }
1131                 }
1132             },
1133             table : {
1134                 add : function(action, data, type) {
1135                     var $tr = $(document.createElement('tr'));
1136                     var $td = $(document.createElement('td'));
1137                     $td.append(action);
1138                     $tr.append($td);
1139                     var $td = $(document.createElement('td'));
1140                     if (data != undefined) $td.append(data);
1141                     $tr.append($td);
1142                     var $td = $(document.createElement('td'));
1143                     if (type != undefined) $td.append(type);
1144                     $tr.append($td);
1145                     return $tr;
1146                 },
1147                 append : function($tr) {
1148                     var $table = $('#'+one.f.flows.id.modal.action.table);
1149                     var $empty = $table.find('.empty').parent();
1150                     if ($empty.size() > 0) $empty.remove();
1151                     $table.append($tr);
1152                 }
1153             },
1154             body : {
1155                 common : function() {
1156                     var $form = $(document.createElement('form'));
1157                     var $fieldset = $(document.createElement('fieldset'));
1158                     return [$form, $fieldset];
1159                 },
1160                 addOutputPorts : function() {
1161                     var common = one.f.flows.modal.action.body.common();
1162                     var $form = common[0];
1163                     var $fieldset = common[1];
1164                     // output port
1165                     $label = one.lib.form.label("Select Output Ports");
1166                     var ports = one.f.flows.registry.nodeports[one.f.flows.registry.currentNode]['ports'];
1167                     $select = one.lib.form.select.create(ports, true);
1168                     $select.attr('id', one.f.flows.id.modal.action.addOutputPorts);
1169                     one.lib.form.select.prepend($select, {'':'Select a Port'});
1170                     $fieldset.append($label).append($select);
1171                     $form.append($fieldset);
1172                     return $form;
1173                 },
1174                 set : function(label, placeholder, id, help) {
1175                     var common = one.f.flows.modal.action.body.common();
1176                     var $form = common[0];
1177                     var $fieldset = common[1];
1178                     // input
1179                     $label = one.lib.form.label(label);
1180                     $input = one.lib.form.input(placeholder);
1181                     $input.attr('id', id);
1182                     $help = one.lib.form.help(help);
1183                     // append
1184                     $fieldset.append($label).append($input).append($help);
1185                     $form.append($fieldset);
1186                     return $form;
1187                 }
1188             },
1189             footer : function() {
1190                 var footer = [];
1191                 var addButton = one.lib.dashlet.button.single("Add Action", one.f.flows.id.modal.action.add, "btn-primary", "");
1192                 var $addButton = one.lib.dashlet.button.button(addButton);
1193                 footer.push($addButton);
1194
1195                 var closeButton = one.lib.dashlet.button.single("Close", one.f.flows.id.modal.action.close, "", "");
1196                 var $closeButton = one.lib.dashlet.button.button(closeButton);
1197                 footer.push($closeButton);
1198
1199                 return footer;
1200             }
1201         },
1202         footer : function() {
1203             var footer = [];
1204
1205             var installButton = one.lib.dashlet.button.single("Install Flow", one.f.flows.id.modal.install, "btn-success", "");
1206             var $installButton = one.lib.dashlet.button.button(installButton);
1207             footer.push($installButton);
1208
1209             var addButton = one.lib.dashlet.button.single("Save Flow", one.f.flows.id.modal.add, "btn-primary", "");
1210             var $addButton = one.lib.dashlet.button.button(addButton);
1211             footer.push($addButton);
1212
1213             var closeButton = one.lib.dashlet.button.single("Close", one.f.flows.id.modal.close, "", "");
1214             var $closeButton = one.lib.dashlet.button.button(closeButton);
1215             footer.push($closeButton);
1216
1217             return footer;
1218         },
1219         removeMultiple: {
1220             dialog: function(flows) {
1221                 var h3 = 'Remove Flow Entry';
1222                 var flowList = [];
1223                 for (var i = 0; i < flows.length; i++) {
1224                     flowList.push(flows[i]["name"]);
1225                 }
1226                 var footer = one.f.flows.modal.removeMultiple.footer();
1227                 var $body = one.f.flows.modal.removeMultiple.body(flowList);
1228                 var $modal = one.lib.modal.spawn(one.f.flows.id.modal.dialog.modal, h3, $body, footer);
1229
1230                 // bind close button
1231                 $('#'+one.f.flows.id.modal.dialog.close, $modal).click(function() {
1232                     $modal.modal('hide');
1233                 });
1234
1235                 // bind remove rule button
1236                 $('#'+one.f.flows.id.modal.dialog.remove, $modal).click(this, function(e) {
1237                     var resource = {};
1238                     resource['body'] = JSON.stringify(flows);
1239
1240                     $.post(one.f.address.root+one.f.address.flows.deleteFlows, resource, function(response) {
1241                         $modal.modal('hide');
1242                         if(response == "Success") {
1243                             one.lib.alert("Flow Entry(s) successfully removed");
1244                         } else {
1245                             one.lib.alert(response);
1246                         }
1247                         one.main.dashlet.right.bottom.empty();
1248                         one.f.detail.dashlet(one.main.dashlet.right.bottom);
1249                         one.main.dashlet.left.top.empty();
1250                         one.f.flows.dashlet(one.main.dashlet.left.top);
1251                     });
1252                 });
1253                 $modal.modal();
1254             },
1255             footer : function() {
1256                 var footer = [];
1257                 var remove = one.lib.dashlet.button.single('Remove Flow Entry',one.f.flows.id.modal.dialog.remove, 'btn-danger', '');
1258                 var $remove = one.lib.dashlet.button.button(remove);
1259                 footer.push($remove);
1260
1261                 var cancel = one.lib.dashlet.button.single('Cancel', one.f.flows.id.modal.dialog.close, '', '');
1262                 var $cancel = one.lib.dashlet.button.button(cancel);
1263                 footer.push($cancel);
1264
1265                 return footer;
1266             },
1267             body : function (flows) {
1268                 var $p = $(document.createElement('p'));
1269                 var p = 'Remove the following Flow Entry(s)?';
1270                 //creata a BS label for each rule and append to list
1271                 $(flows).each(function(){
1272                     var $span = $(document.createElement('span'));
1273                     $span.append(this);
1274                     p += '<br/>' + $span[0].outerHTML;
1275                 });
1276                 $p.append(p);
1277                 return $p;
1278             }
1279         }
1280     },
1281     ajax : {
1282         dashlet : function(callback) {
1283             $.getJSON(one.f.address.root+one.f.address.flows.main, function(data) {
1284                 one.f.flows.registry['flows'] = data.flows;
1285                 one.f.flows.registry['privilege'] = data.privilege;
1286                 callback(data);
1287             });
1288         }
1289     },
1290     data : {
1291         flowsDataGrid: function(data) {
1292             var source = new StaticDataSource({
1293                     columns: [
1294                         {
1295                             property: 'selector',
1296                             label: "<input type='checkbox' id='"+one.f.flows.id.dashlet.datagrid.selectAllFlows+"'/>",
1297                             sortable: false
1298                         },
1299                         {
1300                             property: 'name',
1301                             label: 'Flow Name',
1302                             sortable: true
1303                         },
1304                         {
1305                             property: 'node',
1306                             label: 'Node',
1307                             sortable: true
1308                         }
1309                     ],
1310                     data: data.flows,
1311                     formatter: function(items) {
1312                         $.each(items, function(index, item) {
1313                             var $checkbox = document.createElement("input");
1314                             $checkbox.setAttribute("type", "checkbox");
1315                             $checkbox.setAttribute("name", item.name);
1316                             $checkbox.setAttribute("node", item.nodeId);
1317                             $checkbox.setAttribute('class','flowEntry')
1318                             item.selector = $checkbox.outerHTML;
1319                                   item["name"] = '<span data-installInHw=' + item["flow"]["installInHw"] + 
1320                                 ' data-flowstatus=' + item["flow"]["status"] + 
1321                                 ' data-nodeId=' + item["nodeId"] + '>' + item["name"] + '</span>';
1322                         });
1323
1324                     },
1325                     delay: 0
1326                 });
1327             return source;
1328         },
1329         dashlet : function(data) {
1330             var body = [];
1331             $(data).each(function(index, value) {
1332                 var tr = {};
1333                 var entry = [];
1334
1335                 
1336                 entry.push(value['name']);
1337                 entry.push(value['node']);
1338                 if (value['flow']['installInHw'] == 'true' && value['flow']['status'] == 'Success')
1339                     tr['type'] = ['success'];
1340                 else if (value['flow']['installInHw'] == 'false' && value['flow']['status'] == 'Success')
1341                     tr['type'] = ['warning'];
1342                 else 
1343                     tr['type'] = ['warning'];
1344                 tr['entry'] = entry;
1345                 tr['id'] = value['nodeId'];
1346
1347                 body.push(tr);
1348             });
1349             return body;
1350         }
1351     },
1352     body : {
1353         dashlet : function(body, callback) {
1354             var attributes = ['table-striped', 'table-bordered', 'table-hover', 'table-condensed', 'table-cursor'];
1355             var $table = one.lib.dashlet.table.table(attributes);
1356
1357             var headers = ['Flow Name', 'Node'];
1358                 
1359             var $thead = one.lib.dashlet.table.header(headers);
1360             $table.append($thead);
1361
1362             var $tbody = one.lib.dashlet.table.body(body);
1363             $table.append($tbody);
1364             return $table;
1365         }
1366     }
1367 }
1368
1369 /** INIT **/
1370 // populate nav tabs
1371 $(one.f.menu.left.top).each(function(index, value) {
1372     var $nav = $(".nav", "#left-top");
1373     one.main.page.dashlet($nav, value);
1374 });
1375
1376 $(one.f.menu.left.bottom).each(function(index, value) {
1377     var $nav = $(".nav", "#left-bottom");
1378     one.main.page.dashlet($nav, value);
1379 });
1380
1381 $(one.f.menu.right.bottom).each(function(index, value) {
1382     var $nav = $(".nav", "#right-bottom");
1383     one.main.page.dashlet($nav, value);
1384 });
1385
1386 one.f.populate = function($dashlet, header) {
1387     var $h4 = one.lib.dashlet.header(header);
1388     $dashlet.append($h4);
1389 };
1390
1391 // bind dashlet nav
1392 $('.dash .nav a', '#main').click(function() {
1393     // de/activation
1394     var $li = $(this).parent();
1395     var $ul = $li.parent();
1396     one.lib.nav.unfocus($ul);
1397     $li.addClass('active');
1398     // clear respective dashlet
1399     var $dashlet = $ul.parent().find('.dashlet');
1400     one.lib.dashlet.empty($dashlet);
1401     // callback based on menu
1402     var id = $(this).attr('id');
1403     var menu = one.f.dashlet;
1404     switch (id) {
1405         case menu.flows.id:
1406             one.f.flows.dashlet($dashlet);
1407             break;
1408         case menu.nodes.id:
1409             one.f.nodes.dashlet($dashlet);
1410             break;
1411         case menu.detail.id:
1412             one.f.detail.dashlet($dashlet);
1413             break;
1414     };
1415 });
1416
1417 // activate first tab on each dashlet
1418 $('.dash .nav').each(function(index, value) {
1419     $($(value).find('li')[0]).find('a').click();
1420 });