8bc2a9937809491816023d38169af95822d8cba7
[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) {
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("Flow Description");
663             $fieldset.append($legend);
664             // name
665             var $label = one.lib.form.label("Name");
666             var $input = one.lib.form.input("Flow Name");
667             $input.attr('id', one.f.flows.id.modal.form.name);
668             $fieldset.append($label).append($input);
669             // node
670             var $label = one.lib.form.label("Node");
671             var $select = one.lib.form.select.create(nodes);
672             one.lib.form.select.prepend($select, { '' : 'Please Select a Node' });
673             $select.val($select.find("option:first").val());
674             $select.attr('id', one.f.flows.id.modal.form.nodes);
675
676             // bind onchange
677             $select.change(function() {
678                 // retrieve port value
679                 var node = $(this).find('option:selected').attr('value');
680                 var $ports = $('#'+one.f.flows.id.modal.form.port);
681                 if (node == '') {
682                     one.lib.form.select.inject($ports, {});
683                     return;
684                 }
685                 one.f.flows.registry['currentNode'] = node;
686                 var ports = nodeports[node]['ports'];
687                 one.lib.form.select.inject($ports, ports);
688                 one.lib.form.select.prepend($ports, { '' : 'Please Select a Port' });
689                 $ports.val($ports.find("option:first").val());
690             });
691
692             $fieldset.append($label).append($select);
693             // input port
694             var $label = one.lib.form.label("Input Port");
695             var $select = one.lib.form.select.create();
696             $select.attr('id', one.f.flows.id.modal.form.port);
697             $fieldset.append($label).append($select);
698             // priority
699             var $label = one.lib.form.label("Priority");
700             var $input = one.lib.form.input("Priority");
701             $input.attr('id', one.f.flows.id.modal.form.priority);
702             $input.val('500');
703             $fieldset.append($label).append($input);
704             // hardTimeout
705             var $label = one.lib.form.label("Hard Timeout");
706             var $input = one.lib.form.input("Hard Timeout");
707             $input.attr('id', one.f.flows.id.modal.form.hardTimeout);
708             $fieldset.append($label).append($input);
709             // idleTimeout
710             var $label = one.lib.form.label("Idle Timeout");
711             var $input = one.lib.form.input("Idle Timeout");
712             $input.attr('id', one.f.flows.id.modal.form.idleTimeout);
713             $fieldset.append($label).append($input);
714             // cookie
715             var $label = one.lib.form.label("Cookie");
716             var $input = one.lib.form.input("Cookie");
717             $input.attr('id', one.f.flows.id.modal.form.cookie);
718             $fieldset.append($label).append($input);
719             // layer 2
720             var $legend = one.lib.form.legend("Layer 2");
721             $fieldset.append($legend);
722             // etherType
723             var $label = one.lib.form.label("Ethernet Type");
724             var $input = one.lib.form.input("Ethernet Type");
725             $input.attr('id', one.f.flows.id.modal.form.etherType);
726             $input.val('0x800');
727             $fieldset.append($label).append($input);
728             // vlanId
729             var $label = one.lib.form.label("VLAN Identification Number");
730             var $input = one.lib.form.input("VLAN Identification Number");
731             $input.attr('id', one.f.flows.id.modal.form.vlanId);
732             var $help = one.lib.form.help("Range: 0 - 4095");
733             $fieldset.append($label).append($input).append($help);
734             // vlanPriority
735             var $label = one.lib.form.label("VLAN Priority");
736             var $input = one.lib.form.input("VLAN Priority");
737             $input.attr('id', one.f.flows.id.modal.form.vlanPriority);
738             var $help = one.lib.form.help("Range: 0 - 7");
739             $fieldset.append($label).append($input).append($help);
740             // srcMac
741             var $label = one.lib.form.label("Source MAC Address");
742             var $input = one.lib.form.input("Source MAC Address");
743             $input.attr('id', one.f.flows.id.modal.form.srcMac);
744             var $help = one.lib.form.help("Example: 00:11:22:aa:bb:cc");
745             $fieldset.append($label).append($input).append($help);
746             // dstMac
747             var $label = one.lib.form.label("Destination MAC Address");
748             var $input = one.lib.form.input("Destination MAC Address");
749             $input.attr('id', one.f.flows.id.modal.form.dstMac);
750             var $help = one.lib.form.help("Example: 00:11:22:aa:bb:cc");
751             $fieldset.append($label).append($input).append($help);
752             // layer 3
753             var $legend = one.lib.form.legend("Layer 3");
754             $fieldset.append($legend);
755             // srcIp
756             var $label = one.lib.form.label("Source IP Address");
757             var $input = one.lib.form.input("Source IP Address");
758             $input.attr('id', one.f.flows.id.modal.form.srcIp);
759             var $help = one.lib.form.help("Example: 127.0.0.1");
760             $fieldset.append($label).append($input).append($help);
761             // dstIp
762             var $label = one.lib.form.label("Destination IP Address");
763             var $input = one.lib.form.input("Destination IP Address");
764             $input.attr('id', one.f.flows.id.modal.form.dstIp);
765             var $help = one.lib.form.help("Example: 127.0.0.1");
766             $fieldset.append($label).append($input).append($help);
767             // tosBits
768             var $label = one.lib.form.label("TOS Bits");
769             var $input = one.lib.form.input("TOS Bits");
770             $input.attr('id', one.f.flows.id.modal.form.tosBits);
771             var $help = one.lib.form.help("Range: 0 - 63");
772             $fieldset.append($label).append($input).append($help);
773             // layer 4
774             var $legend = one.lib.form.legend("Layer 4");
775             $fieldset.append($legend);
776             // srcPort
777             var $label = one.lib.form.label("Source Port");
778             var $input = one.lib.form.input("Source Port");
779             $input.attr('id', one.f.flows.id.modal.form.srcPort);
780             var $help = one.lib.form.help("Range: 0 - 65535");
781             $fieldset.append($label).append($input).append($help);
782             // dstPort
783             var $label = one.lib.form.label("Destination Port");
784             var $input = one.lib.form.input("Destination Port");
785             $input.attr('id', one.f.flows.id.modal.form.dstPort);
786             var $help = one.lib.form.help("Range: 0 - 65535");
787             $fieldset.append($label).append($input).append($help);
788             // protocol
789             var $label = one.lib.form.label("Protocol");
790             var $input = one.lib.form.input("Protocol");
791             $input.attr('id', one.f.flows.id.modal.form.protocol);
792             $fieldset.append($label).append($input);
793             // actions
794             var $legend = one.lib.form.label("Actions");
795             $fieldset.append($legend);
796             // actions table
797             var tableAttributes = ["table-striped", "table-bordered", "table-condensed", "table-hover", "table-cursor"];
798             var $table = one.lib.dashlet.table.table(tableAttributes);
799             $table.attr('id', one.f.flows.id.modal.action.table);
800             var tableHeaders = ["Action", "Data", "Type"];
801             var $thead = one.lib.dashlet.table.header(tableHeaders);
802             var $tbody = one.lib.dashlet.table.body("", tableHeaders);
803             $table.append($thead).append($tbody);
804             // actions
805             var actions = {
806                 "" : "Please Select an Action",
807                 "drop" : "Drop",
808                 "loopback" : "Loopback",
809                 "flood" : "Flood",
810                 "softwarePath" : "Software Path",
811                 "hardwarePath" : "Hardware Path",
812                 "controller" : "Controller",
813                 "addOutputPorts" : "Add Output Ports",
814                 "setVlanId" : "Set VLAN ID",
815                 "setVlanPriority" : "Set VLAN Priority",
816                 "stripVlanHeader" : "Strip VLAN Header",
817                 "modifyDatalayerSourceAddress" : "Modify Datalayer Source Address",
818                 "modifyDatalayerDestinationAddress" : "Modify Datalayer Destination Address",
819                 "modifyNetworkSourceAddress" : "Modify Network Source Address",
820                 "modifyNetworkDestinationAddress" :"Modify Network Destination Address",
821                 "modifyTosBits" : "Modify TOS Bits",
822                 "modifyTransportSourcePort" : "Modify Transport Source Port",
823                 "modifyTransportDestinationPort" : "Modify Transport Destination Port"
824             };
825             var $select = one.lib.form.select.create(actions);
826             // when selecting an action
827             $select.change(function() {
828                 var action = $(this).find('option:selected');
829                 one.f.flows.modal.action.parse(action.attr('value'));
830                 $select[0].selectedIndex = 0;
831             });
832
833             $fieldset.append($select).append($table);
834
835             // return
836             $form.append($fieldset);
837             return $form;
838         },
839         action : {
840             parse : function(option) {
841                 switch (option) {
842                     case "addOutputPorts" :
843                         var h3 = "Add Output Port";
844                         var $modal = one.f.flows.modal.action.initialize(h3, one.f.flows.modal.action.body.addOutputPorts, one.f.flows.modal.action.add.addOutputPorts);
845                         $modal.modal();
846                         break;
847                     case "setVlanId" :
848                         var h3 = "Set VLAN ID";
849                         var placeholder = "VLAN Identification Number";
850                         var id = one.f.flows.id.modal.action.setVlanId;
851                         var help = "Range: 0 - 4095";
852                         var action = 'SET_VLAN_ID';
853                         var name = "VLAN ID";
854                         var body = function() {
855                             return one.f.flows.modal.action.body.set(h3, placeholder, id, help);
856                         };
857                         var add = function($modal) {
858                             one.f.flows.modal.action.add.set(name, id, action, $modal);
859                         };
860                         var $modal = one.f.flows.modal.action.initialize(h3, body, add);
861                         $modal.modal();
862                         break;
863                     case "setVlanPriority" :
864                         var h3 = "Set VLAN Priority";
865                         var placeholder = "VLAN Priority";
866                         var id = one.f.flows.id.modal.action.setVlanPriority;
867                         var help = "Range: 0 - 7";
868                         var action = 'SET_VLAN_PCP';
869                         var name = "VLAN Priority";
870                         var body = function() {
871                             return one.f.flows.modal.action.body.set(h3, placeholder, id, help);
872                         };
873                         var add = function($modal) {
874                             one.f.flows.modal.action.add.set(name, id, action, $modal);
875                         };
876                         var $modal = one.f.flows.modal.action.initialize(h3, body, add);
877                         $modal.modal();
878                         break;
879                     case "stripVlanHeader" :
880                         var name = "Strip VLAN Header";
881                         var action = 'POP_VLAN';
882                         one.f.flows.modal.action.add.add(name, action);
883                         break;
884                     case "modifyDatalayerSourceAddress" :
885                         var h3 = "Set Source MAC Address";
886                         var placeholder = "Source MAC Address";
887                         var id = one.f.flows.id.modal.action.modifyDatalayerSourceAddress;
888                         var help = "Example: 00:11:22:aa:bb:cc";
889                         var action = 'SET_DL_SRC';
890                         var name = "Source MAC";
891                         var body = function() {
892                             return one.f.flows.modal.action.body.set(h3, placeholder, id, help);
893                         };
894                         var add = function($modal) {
895                             one.f.flows.modal.action.add.set(name, id, action, $modal);
896                         };
897                         var $modal = one.f.flows.modal.action.initialize(h3, body, add);
898                         $modal.modal();
899                         break;
900                     case "modifyDatalayerDestinationAddress" :
901                         var h3 = "Set Destination MAC Address";
902                         var placeholder = "Destination MAC Address";
903                         var id = one.f.flows.id.modal.action.modifyDatalayerDestinationAddress;
904                         var help = "Example: 00:11:22:aa:bb:cc";
905                         var action = 'SET_DL_DST';
906                         var name = "Destination MAC";
907                         var body = function() {
908                             return one.f.flows.modal.action.body.set(h3, placeholder, id, help);
909                         };
910                         var add = function($modal) {
911                             one.f.flows.modal.action.add.set(name, id, action, $modal);
912                         };
913                         var $modal = one.f.flows.modal.action.initialize(h3, body, add);
914                         $modal.modal();
915                         break;
916                     case "modifyNetworkSourceAddress" :
917                         var h3 = "Set IP Source Address";
918                         var placeholder = "Source IP Address";
919                         var id = one.f.flows.id.modal.action.modifyNetworkSourceAddress;
920                         var help = "Example: 127.0.0.1";
921                         var action = 'SET_NW_SRC';
922                         var name = "Source IP";
923                         var body = function() {
924                             return one.f.flows.modal.action.body.set(h3, placeholder, id, help);
925                         };
926                         var add = function($modal) {
927                             one.f.flows.modal.action.add.set(name, id, action, $modal);
928                         };
929                         var $modal = one.f.flows.modal.action.initialize(h3, body, add);
930                         $modal.modal();
931                         break;
932                     case "modifyNetworkDestinationAddress" :
933                         var h3 = "Set IP Destination Address";
934                         var placeholder = "Destination IP Address";
935                         var id = one.f.flows.id.modal.action.modifyNetworkDestinationAddress;
936                         var help = "Example: 127.0.0.1";
937                         var action = 'SET_NW_DST';
938                         var name = "Destination IP";
939                         var body = function() {
940                             return one.f.flows.modal.action.body.set(h3, placeholder, id, help);
941                         };
942                         var add = function($modal) {
943                             one.f.flows.modal.action.add.set(name, id, action, $modal);
944                         };
945                         var $modal = one.f.flows.modal.action.initialize(h3, body, add);
946                         $modal.modal();
947                         break;
948                     case "modifyTosBits" :
949                         var h3 = "Set IPv4 ToS";
950                         var placeholder = "IPv4 ToS";
951                         var id = one.f.flows.id.modal.action.modifyTosBits;
952                         var help = "Range: 0 - 63";
953                         var action = 'SET_NW_TOS';
954                         var name = "TOS Bits";
955                         var body = function() {
956                             return one.f.flows.modal.action.body.set(h3, placeholder, id, help);
957                         };
958                         var add = function($modal) {
959                             one.f.flows.modal.action.add.set(name, id, action, $modal);
960                         };
961                         var $modal = one.f.flows.modal.action.initialize(h3, body, add);
962                         $modal.modal();
963                         break;
964                     case "modifyTransportSourcePort" :
965                         var h3 = "Set Transport Source Port";
966                         var placeholder = "Transport Source Port";
967                         var id = one.f.flows.id.modal.action.modifyTransportSourcePort;
968                         var help = "Range: 1 - 65535";
969                         var action = 'SET_TP_SRC';
970                         var name = "Source Port";
971                         var body = function() {
972                             return one.f.flows.modal.action.body.set(h3, placeholder, id, help);
973                         };
974                         var add = function($modal) {
975                             one.f.flows.modal.action.add.set(name, id, action, $modal);
976                         };
977                         var $modal = one.f.flows.modal.action.initialize(h3, body, add);
978                         $modal.modal();
979                         break;
980                     case "modifyTransportDestinationPort" :
981                         var h3 = "Set Transport Destination Port";
982                         var placeholder = "Transport Destination Port";
983                         var id = one.f.flows.id.modal.action.modifyTransportDestinationPort;
984                         var help = "Range: 1 - 65535";
985                         var action = 'SET_TP_DST';
986                         var name = "Destination Port";
987                         var body = function() {
988                             return one.f.flows.modal.action.body.set(h3, placeholder, id, help);
989                         };
990                         var add = function($modal) {
991                             one.f.flows.modal.action.add.set(name, id, action, $modal);
992                         };
993                         var $modal = one.f.flows.modal.action.initialize(h3, body, add);
994                         $modal.modal();
995                         break;
996                     case "drop" :
997                         var name = "Drop";
998                         var action = 'DROP';
999                         one.f.flows.modal.action.add.add(name, action);
1000                         break;
1001                     case "loopback" :
1002                         var name = "Loopback";
1003                         var action = 'LOOPBACK';
1004                         one.f.flows.modal.action.add.add(name, action);
1005                         break;
1006                     case "flood" :
1007                         var name = "Flood";
1008                         var action = 'FLOOD';
1009                         one.f.flows.modal.action.add.add(name, action);
1010                         break;
1011                     case "softwarePath" :
1012                         var name = "Software Path";
1013                         var action = 'SW_PATH';
1014                         one.f.flows.modal.action.add.add(name, action);
1015                         break;
1016                     case "hardwarePath" :
1017                         var name = "Hardware Path";
1018                         var action = 'HW_PATH';
1019                         one.f.flows.modal.action.add.add(name, action);
1020                         break;
1021                     case "controller" :
1022                         var name = "Controller";
1023                         var action = 'CONTROLLER';
1024                         one.f.flows.modal.action.add.add(name, action);
1025                         break;
1026                 }
1027             },
1028             initialize : function(h3, bodyCallback, addCallback) {
1029                 var footer = one.f.flows.modal.action.footer();
1030                 var $body = bodyCallback();
1031                 var $modal = one.lib.modal.spawn(one.f.flows.id.modal.action.modal, h3, $body, footer);
1032                 // bind close button
1033                 $('#'+one.f.flows.id.modal.action.close, $modal).click(function() {
1034                     $modal.modal('hide');
1035                 });
1036                 // bind add flow button
1037                 $('#'+one.f.flows.id.modal.action.add, $modal).click(function() {
1038                     addCallback($modal);
1039                 });
1040                 return $modal;
1041             },
1042             add : {
1043                 addOutputPorts : function($modal) {
1044                     var $options = $('#'+one.f.flows.id.modal.action.addOutputPorts).find('option:selected');
1045                     var ports = '';
1046                     var pid = '';
1047                     $options.each(function(index, value) {
1048                         ports = ports+$(value).text()+", ";
1049                         pid = pid+$(value).attr('value')+",";
1050                     });
1051                     ports = ports.slice(0,-2);
1052                     pid = pid.slice(0,-1);
1053                     var $tr = one.f.flows.modal.action.table.add("Add Output Ports", ports);
1054                     $tr.attr('id', 'addOutputPorts');
1055                     $tr.data('action', 'OUTPUT='+pid);
1056                     $tr.click(function() {
1057                         one.f.flows.modal.action.add.modal.initialize(this);
1058                     });
1059                     one.f.flows.modal.action.table.append($tr);
1060                     $modal.modal('hide');
1061                 },
1062                 add : function(name, action) {
1063                     var $tr = one.f.flows.modal.action.table.add(name);
1064                     $tr.attr('id', action);
1065                     $tr.data('action', action);
1066                     $tr.click(function() {
1067                         one.f.flows.modal.action.add.modal.initialize(this);
1068                     });
1069                     one.f.flows.modal.action.table.append($tr);
1070                 },
1071                 set : function(name, id, action, $modal) {
1072                     var $input = $('#'+id);
1073                     var value = $input.val();
1074                     var $tr = one.f.flows.modal.action.table.add(name, value);
1075                     $tr.attr('id', action);
1076                     $tr.data('action', action+'='+value);
1077                     $tr.click(function() {
1078                         one.f.flows.modal.action.add.modal.initialize(this);
1079                     });
1080                     one.f.flows.modal.action.table.append($tr);
1081                     $modal.modal('hide');
1082                 },
1083                 remove : function(that) {
1084                     $(that).remove();
1085                     var $table = $('#'+one.f.flows.id.modal.action.table);
1086                     if ($table.find('tbody').find('tr').size() == 0) {
1087                         var $tr = $(document.createElement('tr'));
1088                         var $td = $(document.createElement('td'));
1089                         $td.attr('colspan', '3');
1090                         $tr.addClass('empty');
1091                         $td.text('No data available');
1092                         $tr.append($td);
1093                         $table.find('tbody').append($tr);
1094                     }
1095                 },
1096                 modal : {
1097                     initialize : function(that) {
1098                         var h3 = "Remove Action";
1099                         var footer = one.f.flows.modal.action.add.modal.footer();
1100                         var $body = one.f.flows.modal.action.add.modal.body();
1101                         var $modal = one.lib.modal.spawn(one.f.flows.id.modal.action.modal.modal, h3, $body, footer);
1102
1103                         // bind cancel button
1104                         $('#'+one.f.flows.id.modal.action.modal.cancel, $modal).click(function() {
1105                             $modal.modal('hide');
1106                         });
1107
1108                         // bind remove button
1109                         $('#'+one.f.flows.id.modal.action.modal.remove, $modal).click(function() {
1110                             one.f.flows.modal.action.add.remove(that);
1111                             $modal.modal('hide');
1112                         });
1113
1114                         $modal.modal();
1115                     },
1116                     body : function() {
1117                         var $p = $(document.createElement('p'));
1118                         $p.append("Remove this action?");
1119                         return $p;
1120                     },
1121                     footer : function() {
1122                         var footer = [];
1123
1124                         var removeButton = one.lib.dashlet.button.single("Remove Action", one.f.flows.id.modal.action.modal.remove, "btn-danger", "");
1125                         var $removeButton = one.lib.dashlet.button.button(removeButton);
1126                         footer.push($removeButton);
1127
1128                         var cancelButton = one.lib.dashlet.button.single("Cancel", one.f.flows.id.modal.action.modal.cancel, "", "");
1129                         var $cancelButton = one.lib.dashlet.button.button(cancelButton);
1130                         footer.push($cancelButton);
1131
1132                         return footer;
1133                     }
1134                 }
1135             },
1136             table : {
1137                 add : function(action, data, type) {
1138                     var $tr = $(document.createElement('tr'));
1139                     var $td = $(document.createElement('td'));
1140                     $td.append(action);
1141                     $tr.append($td);
1142                     var $td = $(document.createElement('td'));
1143                     if (data != undefined) $td.append(data);
1144                     $tr.append($td);
1145                     var $td = $(document.createElement('td'));
1146                     if (type != undefined) $td.append(type);
1147                     $tr.append($td);
1148                     return $tr;
1149                 },
1150                 append : function($tr) {
1151                     var $table = $('#'+one.f.flows.id.modal.action.table);
1152                     var $empty = $table.find('.empty').parent();
1153                     if ($empty.size() > 0) $empty.remove();
1154                     $table.append($tr);
1155                 }
1156             },
1157             body : {
1158                 common : function() {
1159                     var $form = $(document.createElement('form'));
1160                     var $fieldset = $(document.createElement('fieldset'));
1161                     return [$form, $fieldset];
1162                 },
1163                 addOutputPorts : function() {
1164                     var common = one.f.flows.modal.action.body.common();
1165                     var $form = common[0];
1166                     var $fieldset = common[1];
1167                     // output port
1168                     $label = one.lib.form.label("Select Output Ports");
1169                     var ports = one.f.flows.registry.nodeports[one.f.flows.registry.currentNode]['ports'];
1170                     $select = one.lib.form.select.create(ports, true);
1171                     $select.attr('id', one.f.flows.id.modal.action.addOutputPorts);
1172                     one.lib.form.select.prepend($select, {'':'Select a Port'});
1173                     $fieldset.append($label).append($select);
1174                     $form.append($fieldset);
1175                     return $form;
1176                 },
1177                 set : function(label, placeholder, id, help) {
1178                     var common = one.f.flows.modal.action.body.common();
1179                     var $form = common[0];
1180                     var $fieldset = common[1];
1181                     // input
1182                     $label = one.lib.form.label(label);
1183                     $input = one.lib.form.input(placeholder);
1184                     $input.attr('id', id);
1185                     $help = one.lib.form.help(help);
1186                     // append
1187                     $fieldset.append($label).append($input).append($help);
1188                     $form.append($fieldset);
1189                     return $form;
1190                 }
1191             },
1192             footer : function() {
1193                 var footer = [];
1194                 var addButton = one.lib.dashlet.button.single("Add Action", one.f.flows.id.modal.action.add, "btn-primary", "");
1195                 var $addButton = one.lib.dashlet.button.button(addButton);
1196                 footer.push($addButton);
1197
1198                 var closeButton = one.lib.dashlet.button.single("Close", one.f.flows.id.modal.action.close, "", "");
1199                 var $closeButton = one.lib.dashlet.button.button(closeButton);
1200                 footer.push($closeButton);
1201
1202                 return footer;
1203             }
1204         },
1205         footer : function() {
1206             var footer = [];
1207
1208             var installButton = one.lib.dashlet.button.single("Install Flow", one.f.flows.id.modal.install, "btn-success", "");
1209             var $installButton = one.lib.dashlet.button.button(installButton);
1210             footer.push($installButton);
1211
1212             var addButton = one.lib.dashlet.button.single("Save Flow", one.f.flows.id.modal.add, "btn-primary", "");
1213             var $addButton = one.lib.dashlet.button.button(addButton);
1214             footer.push($addButton);
1215
1216             var closeButton = one.lib.dashlet.button.single("Close", one.f.flows.id.modal.close, "", "");
1217             var $closeButton = one.lib.dashlet.button.button(closeButton);
1218             footer.push($closeButton);
1219
1220             return footer;
1221         },
1222         removeMultiple: {
1223             dialog: function(flows) {
1224                 var h3 = 'Remove Flow Entry';
1225                 var flowList = [];
1226                 for (var i = 0; i < flows.length; i++) {
1227                     flowList.push(flows[i]["name"]);
1228                 }
1229                 var footer = one.f.flows.modal.removeMultiple.footer();
1230                 var $body = one.f.flows.modal.removeMultiple.body(flowList);
1231                 var $modal = one.lib.modal.spawn(one.f.flows.id.modal.dialog.modal, h3, $body, footer);
1232
1233                 // bind close button
1234                 $('#'+one.f.flows.id.modal.dialog.close, $modal).click(function() {
1235                     $modal.modal('hide');
1236                 });
1237
1238                 // bind remove rule button
1239                 $('#'+one.f.flows.id.modal.dialog.remove, $modal).click(this, function(e) {
1240                     var resource = {};
1241                     resource['body'] = JSON.stringify(flows);
1242
1243                     $.post(one.f.address.root+one.f.address.flows.deleteFlows, resource, function(response) {
1244                         $modal.modal('hide');
1245                         if(response == "Success") {
1246                             one.lib.alert("Flow Entry(s) successfully removed");
1247                         } else {
1248                             one.lib.alert(response);
1249                         }
1250                         one.main.dashlet.right.bottom.empty();
1251                         one.f.detail.dashlet(one.main.dashlet.right.bottom);
1252                         one.main.dashlet.left.top.empty();
1253                         one.f.flows.dashlet(one.main.dashlet.left.top);
1254                     });
1255                 });
1256                 $modal.modal();
1257             },
1258             footer : function() {
1259                 var footer = [];
1260                 var remove = one.lib.dashlet.button.single('Remove Flow Entry',one.f.flows.id.modal.dialog.remove, 'btn-danger', '');
1261                 var $remove = one.lib.dashlet.button.button(remove);
1262                 footer.push($remove);
1263
1264                 var cancel = one.lib.dashlet.button.single('Cancel', one.f.flows.id.modal.dialog.close, '', '');
1265                 var $cancel = one.lib.dashlet.button.button(cancel);
1266                 footer.push($cancel);
1267
1268                 return footer;
1269             },
1270             body : function (flows) {
1271                 var $p = $(document.createElement('p'));
1272                 var p = 'Remove the following Flow Entry(s)?';
1273                 //creata a BS label for each rule and append to list
1274                 $(flows).each(function(){
1275                     var $span = $(document.createElement('span'));
1276                     $span.append(this);
1277                     p += '<br/>' + $span[0].outerHTML;
1278                 });
1279                 $p.append(p);
1280                 return $p;
1281             }
1282         }
1283     },
1284     ajax : {
1285         dashlet : function(callback) {
1286             $.getJSON(one.f.address.root+one.f.address.flows.main, function(data) {
1287                 one.f.flows.registry['flows'] = data.flows;
1288                 one.f.flows.registry['privilege'] = data.privilege;
1289                 callback(data);
1290             });
1291         }
1292     },
1293     data : {
1294         flowsDataGrid: function(data) {
1295             var source = new StaticDataSource({
1296                     columns: [
1297                         {
1298                             property: 'selector',
1299                             label: "<input type='checkbox' id='"+one.f.flows.id.dashlet.datagrid.selectAllFlows+"'/>",
1300                             sortable: false
1301                         },
1302                         {
1303                             property: 'name',
1304                             label: 'Flow Name',
1305                             sortable: true
1306                         },
1307                         {
1308                             property: 'node',
1309                             label: 'Node',
1310                             sortable: true
1311                         }
1312                     ],
1313                     data: data.flows,
1314                     formatter: function(items) {
1315                         $.each(items, function(index, item) {
1316                                     var $checkbox = document.createElement("input");
1317                             $checkbox.setAttribute("type", "checkbox");
1318                             $checkbox.setAttribute("name", item.name);
1319                             $checkbox.setAttribute("node", item.node);
1320                             $checkbox.setAttribute('class','flowEntry')
1321                             item.selector = $checkbox.outerHTML;
1322                                   item["name"] = '<span data-installInHw=' + item["flow"]["installInHw"] + 
1323                                 ' data-flowstatus=' + item["flow"]["status"] + 
1324                                 ' data-nodeId=' + item["nodeId"] + '>' + item["name"] + '</span>';
1325                         });
1326
1327                     },
1328                     delay: 0
1329                 });
1330             return source;
1331         },
1332         dashlet : function(data) {
1333             var body = [];
1334             $(data).each(function(index, value) {
1335                 var tr = {};
1336                 var entry = [];
1337
1338                 
1339                 entry.push(value['name']);
1340                 entry.push(value['node']);
1341                 if (value['flow']['installInHw'] == 'true' && value['flow']['status'] == 'Success')
1342                     tr['type'] = ['success'];
1343                 else if (value['flow']['installInHw'] == 'false' && value['flow']['status'] == 'Success')
1344                     tr['type'] = ['warning'];
1345                 else 
1346                     tr['type'] = ['warning'];
1347                 tr['entry'] = entry;
1348                 tr['id'] = value['nodeId'];
1349
1350                 body.push(tr);
1351             });
1352             return body;
1353         }
1354     },
1355     body : {
1356         dashlet : function(body, callback) {
1357             var attributes = ['table-striped', 'table-bordered', 'table-hover', 'table-condensed', 'table-cursor'];
1358             var $table = one.lib.dashlet.table.table(attributes);
1359
1360             var headers = ['Flow Name', 'Node'];
1361                 
1362             var $thead = one.lib.dashlet.table.header(headers);
1363             $table.append($thead);
1364
1365             var $tbody = one.lib.dashlet.table.body(body);
1366             $table.append($tbody);
1367             return $table;
1368         }
1369     }
1370 }
1371
1372 /** INIT **/
1373 // populate nav tabs
1374 $(one.f.menu.left.top).each(function(index, value) {
1375     var $nav = $(".nav", "#left-top");
1376     one.main.page.dashlet($nav, value);
1377 });
1378
1379 $(one.f.menu.left.bottom).each(function(index, value) {
1380     var $nav = $(".nav", "#left-bottom");
1381     one.main.page.dashlet($nav, value);
1382 });
1383
1384 $(one.f.menu.right.bottom).each(function(index, value) {
1385     var $nav = $(".nav", "#right-bottom");
1386     one.main.page.dashlet($nav, value);
1387 });
1388
1389 one.f.populate = function($dashlet, header) {
1390     var $h4 = one.lib.dashlet.header(header);
1391     $dashlet.append($h4);
1392 };
1393
1394 // bind dashlet nav
1395 $('.dash .nav a', '#main').click(function() {
1396     // de/activation
1397     var $li = $(this).parent();
1398     var $ul = $li.parent();
1399     one.lib.nav.unfocus($ul);
1400     $li.addClass('active');
1401     // clear respective dashlet
1402     var $dashlet = $ul.parent().find('.dashlet');
1403     one.lib.dashlet.empty($dashlet);
1404     // callback based on menu
1405     var id = $(this).attr('id');
1406     var menu = one.f.dashlet;
1407     switch (id) {
1408         case menu.flows.id:
1409             one.f.flows.dashlet($dashlet);
1410             break;
1411         case menu.nodes.id:
1412             one.f.nodes.dashlet($dashlet);
1413             break;
1414         case menu.detail.id:
1415             one.f.detail.dashlet($dashlet);
1416             break;
1417     };
1418 });
1419
1420 // activate first tab on each dashlet
1421 $('.dash .nav').each(function(index, value) {
1422     $($(value).find('li')[0]).find('a').click();
1423 });