Delete Multiple flows in a single click
[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-primary", "btn-mini");
334                 var $button = one.lib.dashlet.button.button(button);
335
336                 $button.click(function() {
337                     var checkedCheckBoxes = $('.flowEntry[type=checkbox]:checked');
338                     
339                     var requestData = [];
340                     
341                     var resource = {};
342                     checkedCheckBoxes.each(function(index, value) {
343                         var flowEntry = {};
344                         flowEntry['name'] = checkedCheckBoxes[index].name;
345                         flowEntry['node'] = checkedCheckBoxes[index].getAttribute("node");
346                         requestData.push(flowEntry);  
347                     });
348                     resource['body'] = JSON.stringify(requestData);
349
350                     $.post(one.f.address.root+one.f.address.flows.deleteFlows, resource, function(response) {
351                         if(response == "Success") {
352                             one.lib.alert("Flow(s) successfully removed");                            
353                         } else {
354                             one.lib.alert(response);
355                         }
356                         one.main.dashlet.right.bottom.empty();
357                         one.f.detail.dashlet(one.main.dashlet.right.bottom);
358                         one.main.dashlet.left.top.empty();
359                         one.f.flows.dashlet(one.main.dashlet.left.top);
360                     });                    
361                 });
362                 $dashlet.append($button);
363
364             }
365
366             var $gridHTML = one.lib.dashlet.datagrid.init(one.f.flows.id.dashlet.datagrid, {
367                 searchable: true,
368                 filterable: false,
369                 pagination: true,
370                 flexibleRowsPerPage: true
371                 }, "table-striped table-condensed");
372             $dashlet.append($gridHTML);
373             var dataSource = one.f.flows.data.flowsDataGrid(data);
374             $("#" + one.f.flows.id.dashlet.datagrid).datagrid({dataSource: dataSource}).on("loaded", function() {
375                     $("#"+one.f.flows.id.dashlet.datagrid.selectAllFlows).click(function() {
376                                 $("#" + one.f.flows.id.dashlet.datagrid).find(':checkbox').prop('checked',
377                                         $("#"+one.f.flows.id.dashlet.datagrid.selectAllFlows).is(':checked'));
378                     });
379                     
380                     $("#" + one.f.flows.id.dashlet.datagrid).find("tbody tr").each(function(index, tr) {
381                     $tr = $(tr);
382                     $span = $("td span", $tr);
383                     var flowstatus = $span.data("flowstatus");
384                     if($span.data("installinhw") != null) {
385                         var installInHw = $span.data("installinhw").toString();
386                         if(installInHw == "true" && flowstatus == "Success") {
387                             $tr.addClass("success");
388                         } else {
389                             $tr.addClass("warning");
390                         }
391                     }
392                     // attach mouseover to show pointer cursor
393                     $tr.mouseover(function() {
394                         $(this).css("cursor", "pointer");
395                     });
396                     // attach click event
397                     $tr.click(function() {
398                         var $td = $($(this).find("td")[1]);
399                         var id = $td.text();
400                         var node = $td.find("span").data("nodeid");
401                         one.f.flows.detail(id, node);
402                     });
403                     $(".flowEntry").click(function(){
404                                 if (!$('.flowEntry[type=checkbox]:not(:checked)').length) {
405                             $("#"+one.f.flows.id.dashlet.datagrid.selectAllFlows)
406                                 .prop("checked",
407                               true);
408                         } else {
409                             $("#"+one.f.flows.id.dashlet.datagrid.selectAllFlows)
410                                 .prop("checked",
411                              false);
412                         }
413                         event.stopPropagation();
414                     });
415                 });
416             });
417             
418             // details callback
419             if(callback != undefined) callback();
420         });
421     },
422     detail : function(id, node) {
423         // clear flow details
424         var $detailDashlet = one.main.dashlet.right.bottom;
425         $detailDashlet.empty();
426         var $h4 = one.lib.dashlet.header("Flow Overview");
427         $detailDashlet.append($h4);
428
429         // details
430         var flows = one.f.flows.registry.flows;
431         var flow;
432         $(flows).each(function(index, value) {
433             if (value['name'] == id) {
434                 flow = value;
435             }
436         });
437         if (one.f.flows.registry.privilege === 'WRITE') {
438             // remove button
439             var button = one.lib.dashlet.button.single("Remove Flow", one.f.flows.id.dashlet.remove, "btn-danger", "btn-mini");
440             var $button = one.lib.dashlet.button.button(button);
441             $button.click(function() {
442                 var $modal = one.f.flows.modal.dialog.initialize(id, node);
443                 $modal.modal();
444             });
445             // toggle button
446             var toggle;
447             if (flow['flow']['installInHw'] == 'true' && flow['flow']['status'] == 'Success') {
448                 toggle = one.lib.dashlet.button.single("Uninstall Flow", one.f.flows.id.dashlet.toggle, "btn-warning", "btn-mini");
449             } else {
450                 toggle = one.lib.dashlet.button.single("Install Flow", one.f.flows.id.dashlet.toggle, "btn-success", "btn-mini");
451             }
452             var $toggle = one.lib.dashlet.button.button(toggle);
453             $toggle.click(function() {
454                 one.f.flows.modal.ajax.toggleflow(id, node, function(data) {
455                     if(data == "Success") {
456                         one.main.dashlet.right.bottom.empty();
457                         one.f.detail.dashlet(one.main.dashlet.right.bottom);
458                         one.main.dashlet.left.top.empty();
459                         one.f.flows.dashlet(one.main.dashlet.left.top, function() {
460                            // checks are backwards due to stale registry
461                            if(flow['flow']['installInHw'] == 'true') {
462                                one.lib.alert('Uninstalled Flow');
463                            } else {
464                                one.lib.alert('Installed Flow');
465                            }
466                            one.f.flows.detail(id, node)
467                         });
468                     } else {
469                         one.lib.alert('Cannot toggle flow: '+data);
470                     }
471                 });
472             });
473
474             $detailDashlet.append($button).append($toggle);
475         }
476         // append details
477         var body = one.f.detail.data.dashlet(flow);
478         var $body = one.f.detail.body.dashlet(body);
479         $detailDashlet.append($body);
480         var body = one.f.detail.data.description(flow);
481         var $body = one.f.detail.body.description(body);
482         $detailDashlet.append($body);
483         var body = one.f.detail.data.actions(flow);
484         var $body = one.f.detail.body.actions(body);
485         $detailDashlet.append($body);
486     },
487     modal : {
488         dialog : {
489             initialize : function(id, node) {
490                 var h3 = "Remove Flow?";
491                 var $p = one.f.flows.modal.dialog.body(id);
492                 var footer = one.f.flows.modal.dialog.footer();
493                 var $modal = one.lib.modal.spawn(one.f.flows.id.modal.dialog.modal, h3, $p, footer);
494                 $('#'+one.f.flows.id.modal.dialog.close, $modal).click(function() {
495                     $modal.modal('hide');
496                 });
497                 $('#'+one.f.flows.id.modal.dialog.remove, $modal).click(function() {
498                     one.f.flows.modal.ajax.removeflow(id, node, function(data) {
499                         if (data == "Success") {
500                             $modal.modal('hide');
501                             one.main.dashlet.right.bottom.empty();
502                             one.f.detail.dashlet(one.main.dashlet.right.bottom);
503                             one.main.dashlet.left.top.empty();
504                             one.f.flows.dashlet(one.main.dashlet.left.top);
505                             one.lib.alert('Flow removed');
506                         } else {
507                             one.lib.alert('Cannot remove flow: '+data);
508                         }
509                     });
510                 });
511                 return $modal;
512             },
513             footer : function() {
514                 var footer = [];
515
516                 var removeButton = one.lib.dashlet.button.single("Remove Flow", one.f.flows.id.modal.dialog.remove, "btn-danger", "");
517                 var $removeButton = one.lib.dashlet.button.button(removeButton);
518                 footer.push($removeButton);
519
520                 var closeButton = one.lib.dashlet.button.single("Cancel", one.f.flows.id.modal.dialog.close, "", "");
521                 var $closeButton = one.lib.dashlet.button.button(closeButton);
522                 footer.push($closeButton);
523
524                 return footer;
525             },
526             body : function(id) {
527                 var $p = $(document.createElement('p'));
528                 $p.append('Remove flow '+id+'?');
529                 return $p;
530             }
531         },
532         initialize : function() {
533             var h3 = "Add Flow Entry";
534             var footer = one.f.flows.modal.footer();
535             var $modal = one.lib.modal.spawn(one.f.flows.id.modal.modal, h3, "", footer);
536
537             // bind close button
538             $('#'+one.f.flows.id.modal.close, $modal).click(function() {
539                 $modal.modal('hide');
540             });
541
542             // bind add flow button
543             $('#'+one.f.flows.id.modal.add, $modal).click(function() {
544                 one.f.flows.modal.add($modal, 'false');
545             });
546
547             // bind install flow button
548             $('#'+one.f.flows.id.modal.install, $modal).click(function() {
549                 one.f.flows.modal.add($modal, 'true');
550             });
551
552             // inject body (nodePorts)
553             one.f.flows.modal.ajax.nodes(function(nodes, nodeports) {
554                 var $body = one.f.flows.modal.body(nodes, nodeports);
555                 one.lib.modal.inject.body($modal, $body);
556             });
557
558             return $modal;
559         },
560         add : function($modal, install) {
561             var result = {};
562
563             result['name'] = $('#'+one.f.flows.id.modal.form.name, $modal).val();
564             result['ingressPort'] = $('#'+one.f.flows.id.modal.form.port, $modal).val();
565             result['priority'] = $('#'+one.f.flows.id.modal.form.priority, $modal).val();
566             result['hardTimeout'] = $('#'+one.f.flows.id.modal.form.hardTimeout, $modal).val();
567             result['idleTimeout'] = $('#'+one.f.flows.id.modal.form.idleTimeout, $modal).val();
568             result['cookie'] = $('#'+one.f.flows.id.modal.form.cookie, $modal).val();
569             result['etherType'] = $('#'+one.f.flows.id.modal.form.etherType, $modal).val();
570             result['vlanId'] = $('#'+one.f.flows.id.modal.form.vlanId, $modal).val();
571             result['vlanPriority'] = $('#'+one.f.flows.id.modal.form.vlanPriority, $modal).val();
572             result['dlSrc'] = $('#'+one.f.flows.id.modal.form.srcMac, $modal).val();
573             result['dlDst'] = $('#'+one.f.flows.id.modal.form.dstMac, $modal).val();
574             result['nwSrc'] = $('#'+one.f.flows.id.modal.form.srcIp, $modal).val();
575             result['nwDst'] = $('#'+one.f.flows.id.modal.form.dstIp, $modal).val();
576             result['tosBits'] = $('#'+one.f.flows.id.modal.form.tosBits, $modal).val();
577             result['tpSrc'] = $('#'+one.f.flows.id.modal.form.srcPort, $modal).val();
578             result['tpDst'] = $('#'+one.f.flows.id.modal.form.dstPort, $modal).val();
579             result['protocol'] = $('#'+one.f.flows.id.modal.form.protocol, $modal).val();
580
581             result['installInHw'] = install;
582
583             var nodeId = $('#'+one.f.flows.id.modal.form.nodes, $modal).val();
584
585             $.each(result, function(key, value) {
586                 if (value == "") delete result[key];
587             });
588
589             var action = [];
590             var $table = $('#'+one.f.flows.id.modal.action.table, $modal);
591             $($table.find('tbody').find('tr')).each(function(index, value) {
592                 if (!$(this).find('td').hasClass('empty')) {
593                     action.push($(value).data('action'));
594                 }
595             });
596             result['actions'] = action;
597
598             // frontend validation
599             if (result['name'] == undefined) {
600                 alert('Need flow name');
601                 return;
602             }
603             if (nodeId == '') {
604                 alert('Select node');
605                 return;
606             }
607             if (action.length == 0) {
608                 alert('Please specify an action');
609                 return;
610             }
611
612             // package for ajax call
613             var resource = {};
614             resource['body'] = JSON.stringify(result);
615             resource['action'] = 'add';
616             resource['nodeId'] = nodeId;
617
618             one.f.flows.modal.ajax.saveflow(resource, function(data) {
619                 if (data == "Success") {
620                     $modal.modal('hide');
621                     one.lib.alert('Flow added');
622                     one.main.dashlet.left.top.empty();
623                     one.f.flows.dashlet(one.main.dashlet.left.top);
624                 } else {
625                     alert('Could not add flow: '+data);
626                 }
627             });
628         },
629         ajax : {
630             nodes : function(successCallback) {
631                 $.getJSON(one.f.address.root+one.f.address.flows.nodes, function(data) {
632                     var nodes = one.f.flows.modal.data.nodes(data);
633                     var nodeports = data;
634                     one.f.flows.registry['nodeports'] = nodeports;
635
636                     successCallback(nodes, nodeports);
637                 });
638             },
639             saveflow : function(resource, callback) {
640                 $.post(one.f.address.root+one.f.address.flows.flow, resource, function(data) {
641                     callback(data);
642                 });
643             },
644             removeflow : function(id, node, callback) {
645                 resource = {};
646                 resource['action'] = 'remove';
647                 $.post(one.f.address.root+one.f.address.flows.flow+'/'+node+'/'+id, resource, function(data) {
648                     callback(data);
649                 });
650             },
651             toggleflow : function(id, node, callback) {
652                 resource = {};
653                 resource['action'] = 'toggle';
654                 $.post(one.f.address.root+one.f.address.flows.flow+'/'+node+'/'+id, resource, function(data) {
655                     callback(data);
656                 });
657             }
658         },
659         data : {
660             nodes : function(data) {
661                 result = {};
662                 $.each(data, function(key, value) {
663                     result[key] = value['name'];
664                 });
665                 return result;
666             }
667         },
668         body : function(nodes, nodeports) {
669             var $form = $(document.createElement('form'));
670             var $fieldset = $(document.createElement('fieldset'));
671             // flow description
672             var $legend = one.lib.form.legend("Flow Description");
673             $fieldset.append($legend);
674             // name
675             var $label = one.lib.form.label("Name");
676             var $input = one.lib.form.input("Flow Name");
677             $input.attr('id', one.f.flows.id.modal.form.name);
678             $fieldset.append($label).append($input);
679             // node
680             var $label = one.lib.form.label("Node");
681             var $select = one.lib.form.select.create(nodes);
682             one.lib.form.select.prepend($select, { '' : 'Please Select a Node' });
683             $select.val($select.find("option:first").val());
684             $select.attr('id', one.f.flows.id.modal.form.nodes);
685
686             // bind onchange
687             $select.change(function() {
688                 // retrieve port value
689                 var node = $(this).find('option:selected').attr('value');
690                 var $ports = $('#'+one.f.flows.id.modal.form.port);
691                 if (node == '') {
692                     one.lib.form.select.inject($ports, {});
693                     return;
694                 }
695                 one.f.flows.registry['currentNode'] = node;
696                 var ports = nodeports[node]['ports'];
697                 one.lib.form.select.inject($ports, ports);
698                 one.lib.form.select.prepend($ports, { '' : 'Please Select a Port' });
699                 $ports.val($ports.find("option:first").val());
700             });
701
702             $fieldset.append($label).append($select);
703             // input port
704             var $label = one.lib.form.label("Input Port");
705             var $select = one.lib.form.select.create();
706             $select.attr('id', one.f.flows.id.modal.form.port);
707             $fieldset.append($label).append($select);
708             // priority
709             var $label = one.lib.form.label("Priority");
710             var $input = one.lib.form.input("Priority");
711             $input.attr('id', one.f.flows.id.modal.form.priority);
712             $input.val('500');
713             $fieldset.append($label).append($input);
714             // hardTimeout
715             var $label = one.lib.form.label("Hard Timeout");
716             var $input = one.lib.form.input("Hard Timeout");
717             $input.attr('id', one.f.flows.id.modal.form.hardTimeout);
718             $fieldset.append($label).append($input);
719             // idleTimeout
720             var $label = one.lib.form.label("Idle Timeout");
721             var $input = one.lib.form.input("Idle Timeout");
722             $input.attr('id', one.f.flows.id.modal.form.idleTimeout);
723             $fieldset.append($label).append($input);
724             // cookie
725             var $label = one.lib.form.label("Cookie");
726             var $input = one.lib.form.input("Cookie");
727             $input.attr('id', one.f.flows.id.modal.form.cookie);
728             $fieldset.append($label).append($input);
729             // layer 2
730             var $legend = one.lib.form.legend("Layer 2");
731             $fieldset.append($legend);
732             // etherType
733             var $label = one.lib.form.label("Ethernet Type");
734             var $input = one.lib.form.input("Ethernet Type");
735             $input.attr('id', one.f.flows.id.modal.form.etherType);
736             $input.val('0x800');
737             $fieldset.append($label).append($input);
738             // vlanId
739             var $label = one.lib.form.label("VLAN Identification Number");
740             var $input = one.lib.form.input("VLAN Identification Number");
741             $input.attr('id', one.f.flows.id.modal.form.vlanId);
742             var $help = one.lib.form.help("Range: 0 - 4095");
743             $fieldset.append($label).append($input).append($help);
744             // vlanPriority
745             var $label = one.lib.form.label("VLAN Priority");
746             var $input = one.lib.form.input("VLAN Priority");
747             $input.attr('id', one.f.flows.id.modal.form.vlanPriority);
748             var $help = one.lib.form.help("Range: 0 - 7");
749             $fieldset.append($label).append($input).append($help);
750             // srcMac
751             var $label = one.lib.form.label("Source MAC Address");
752             var $input = one.lib.form.input("Source MAC Address");
753             $input.attr('id', one.f.flows.id.modal.form.srcMac);
754             var $help = one.lib.form.help("Example: 00:11:22:aa:bb:cc");
755             $fieldset.append($label).append($input).append($help);
756             // dstMac
757             var $label = one.lib.form.label("Destination MAC Address");
758             var $input = one.lib.form.input("Destination MAC Address");
759             $input.attr('id', one.f.flows.id.modal.form.dstMac);
760             var $help = one.lib.form.help("Example: 00:11:22:aa:bb:cc");
761             $fieldset.append($label).append($input).append($help);
762             // layer 3
763             var $legend = one.lib.form.legend("Layer 3");
764             $fieldset.append($legend);
765             // srcIp
766             var $label = one.lib.form.label("Source IP Address");
767             var $input = one.lib.form.input("Source IP Address");
768             $input.attr('id', one.f.flows.id.modal.form.srcIp);
769             var $help = one.lib.form.help("Example: 127.0.0.1");
770             $fieldset.append($label).append($input).append($help);
771             // dstIp
772             var $label = one.lib.form.label("Destination IP Address");
773             var $input = one.lib.form.input("Destination IP Address");
774             $input.attr('id', one.f.flows.id.modal.form.dstIp);
775             var $help = one.lib.form.help("Example: 127.0.0.1");
776             $fieldset.append($label).append($input).append($help);
777             // tosBits
778             var $label = one.lib.form.label("TOS Bits");
779             var $input = one.lib.form.input("TOS Bits");
780             $input.attr('id', one.f.flows.id.modal.form.tosBits);
781             var $help = one.lib.form.help("Range: 0 - 63");
782             $fieldset.append($label).append($input).append($help);
783             // layer 4
784             var $legend = one.lib.form.legend("Layer 4");
785             $fieldset.append($legend);
786             // srcPort
787             var $label = one.lib.form.label("Source Port");
788             var $input = one.lib.form.input("Source Port");
789             $input.attr('id', one.f.flows.id.modal.form.srcPort);
790             var $help = one.lib.form.help("Range: 0 - 65535");
791             $fieldset.append($label).append($input).append($help);
792             // dstPort
793             var $label = one.lib.form.label("Destination Port");
794             var $input = one.lib.form.input("Destination Port");
795             $input.attr('id', one.f.flows.id.modal.form.dstPort);
796             var $help = one.lib.form.help("Range: 0 - 65535");
797             $fieldset.append($label).append($input).append($help);
798             // protocol
799             var $label = one.lib.form.label("Protocol");
800             var $input = one.lib.form.input("Protocol");
801             $input.attr('id', one.f.flows.id.modal.form.protocol);
802             $fieldset.append($label).append($input);
803             // actions
804             var $legend = one.lib.form.label("Actions");
805             $fieldset.append($legend);
806             // actions table
807             var tableAttributes = ["table-striped", "table-bordered", "table-condensed", "table-hover", "table-cursor"];
808             var $table = one.lib.dashlet.table.table(tableAttributes);
809             $table.attr('id', one.f.flows.id.modal.action.table);
810             var tableHeaders = ["Action", "Data", "Type"];
811             var $thead = one.lib.dashlet.table.header(tableHeaders);
812             var $tbody = one.lib.dashlet.table.body("", tableHeaders);
813             $table.append($thead).append($tbody);
814             // actions
815             var actions = {
816                 "" : "Please Select an Action",
817                 "drop" : "Drop",
818                 "loopback" : "Loopback",
819                 "flood" : "Flood",
820                 "softwarePath" : "Software Path",
821                 "hardwarePath" : "Hardware Path",
822                 "controller" : "Controller",
823                 "addOutputPorts" : "Add Output Ports",
824                 "setVlanId" : "Set VLAN ID",
825                 "setVlanPriority" : "Set VLAN Priority",
826                 "stripVlanHeader" : "Strip VLAN Header",
827                 "modifyDatalayerSourceAddress" : "Modify Datalayer Source Address",
828                 "modifyDatalayerDestinationAddress" : "Modify Datalayer Destination Address",
829                 "modifyNetworkSourceAddress" : "Modify Network Source Address",
830                 "modifyNetworkDestinationAddress" :"Modify Network Destination Address",
831                 "modifyTosBits" : "Modify TOS Bits",
832                 "modifyTransportSourcePort" : "Modify Transport Source Port",
833                 "modifyTransportDestinationPort" : "Modify Transport Destination Port"
834             };
835             var $select = one.lib.form.select.create(actions);
836             // when selecting an action
837             $select.change(function() {
838                 var action = $(this).find('option:selected');
839                 one.f.flows.modal.action.parse(action.attr('value'));
840                 $select[0].selectedIndex = 0;
841             });
842
843             $fieldset.append($select).append($table);
844
845             // return
846             $form.append($fieldset);
847             return $form;
848         },
849         action : {
850             parse : function(option) {
851                 switch (option) {
852                     case "addOutputPorts" :
853                         var h3 = "Add Output Port";
854                         var $modal = one.f.flows.modal.action.initialize(h3, one.f.flows.modal.action.body.addOutputPorts, one.f.flows.modal.action.add.addOutputPorts);
855                         $modal.modal();
856                         break;
857                     case "setVlanId" :
858                         var h3 = "Set VLAN ID";
859                         var placeholder = "VLAN Identification Number";
860                         var id = one.f.flows.id.modal.action.setVlanId;
861                         var help = "Range: 0 - 4095";
862                         var action = 'SET_VLAN_ID';
863                         var name = "VLAN ID";
864                         var body = function() {
865                             return one.f.flows.modal.action.body.set(h3, placeholder, id, help);
866                         };
867                         var add = function($modal) {
868                             one.f.flows.modal.action.add.set(name, id, action, $modal);
869                         };
870                         var $modal = one.f.flows.modal.action.initialize(h3, body, add);
871                         $modal.modal();
872                         break;
873                     case "setVlanPriority" :
874                         var h3 = "Set VLAN Priority";
875                         var placeholder = "VLAN Priority";
876                         var id = one.f.flows.id.modal.action.setVlanPriority;
877                         var help = "Range: 0 - 7";
878                         var action = 'SET_VLAN_PCP';
879                         var name = "VLAN Priority";
880                         var body = function() {
881                             return one.f.flows.modal.action.body.set(h3, placeholder, id, help);
882                         };
883                         var add = function($modal) {
884                             one.f.flows.modal.action.add.set(name, id, action, $modal);
885                         };
886                         var $modal = one.f.flows.modal.action.initialize(h3, body, add);
887                         $modal.modal();
888                         break;
889                     case "stripVlanHeader" :
890                         var name = "Strip VLAN Header";
891                         var action = 'POP_VLAN';
892                         one.f.flows.modal.action.add.add(name, action);
893                         break;
894                     case "modifyDatalayerSourceAddress" :
895                         var h3 = "Set Source MAC Address";
896                         var placeholder = "Source MAC Address";
897                         var id = one.f.flows.id.modal.action.modifyDatalayerSourceAddress;
898                         var help = "Example: 00:11:22:aa:bb:cc";
899                         var action = 'SET_DL_SRC';
900                         var name = "Source MAC";
901                         var body = function() {
902                             return one.f.flows.modal.action.body.set(h3, placeholder, id, help);
903                         };
904                         var add = function($modal) {
905                             one.f.flows.modal.action.add.set(name, id, action, $modal);
906                         };
907                         var $modal = one.f.flows.modal.action.initialize(h3, body, add);
908                         $modal.modal();
909                         break;
910                     case "modifyDatalayerDestinationAddress" :
911                         var h3 = "Set Destination MAC Address";
912                         var placeholder = "Destination MAC Address";
913                         var id = one.f.flows.id.modal.action.modifyDatalayerDestinationAddress;
914                         var help = "Example: 00:11:22:aa:bb:cc";
915                         var action = 'SET_DL_DST';
916                         var name = "Destination MAC";
917                         var body = function() {
918                             return one.f.flows.modal.action.body.set(h3, placeholder, id, help);
919                         };
920                         var add = function($modal) {
921                             one.f.flows.modal.action.add.set(name, id, action, $modal);
922                         };
923                         var $modal = one.f.flows.modal.action.initialize(h3, body, add);
924                         $modal.modal();
925                         break;
926                     case "modifyNetworkSourceAddress" :
927                         var h3 = "Set IP Source Address";
928                         var placeholder = "Source IP Address";
929                         var id = one.f.flows.id.modal.action.modifyNetworkSourceAddress;
930                         var help = "Example: 127.0.0.1";
931                         var action = 'SET_NW_SRC';
932                         var name = "Source IP";
933                         var body = function() {
934                             return one.f.flows.modal.action.body.set(h3, placeholder, id, help);
935                         };
936                         var add = function($modal) {
937                             one.f.flows.modal.action.add.set(name, id, action, $modal);
938                         };
939                         var $modal = one.f.flows.modal.action.initialize(h3, body, add);
940                         $modal.modal();
941                         break;
942                     case "modifyNetworkDestinationAddress" :
943                         var h3 = "Set IP Destination Address";
944                         var placeholder = "Destination IP Address";
945                         var id = one.f.flows.id.modal.action.modifyNetworkDestinationAddress;
946                         var help = "Example: 127.0.0.1";
947                         var action = 'SET_NW_DST';
948                         var name = "Destination IP";
949                         var body = function() {
950                             return one.f.flows.modal.action.body.set(h3, placeholder, id, help);
951                         };
952                         var add = function($modal) {
953                             one.f.flows.modal.action.add.set(name, id, action, $modal);
954                         };
955                         var $modal = one.f.flows.modal.action.initialize(h3, body, add);
956                         $modal.modal();
957                         break;
958                     case "modifyTosBits" :
959                         var h3 = "Set IPv4 ToS";
960                         var placeholder = "IPv4 ToS";
961                         var id = one.f.flows.id.modal.action.modifyTosBits;
962                         var help = "Range: 0 - 63";
963                         var action = 'SET_NW_TOS';
964                         var name = "TOS Bits";
965                         var body = function() {
966                             return one.f.flows.modal.action.body.set(h3, placeholder, id, help);
967                         };
968                         var add = function($modal) {
969                             one.f.flows.modal.action.add.set(name, id, action, $modal);
970                         };
971                         var $modal = one.f.flows.modal.action.initialize(h3, body, add);
972                         $modal.modal();
973                         break;
974                     case "modifyTransportSourcePort" :
975                         var h3 = "Set Transport Source Port";
976                         var placeholder = "Transport Source Port";
977                         var id = one.f.flows.id.modal.action.modifyTransportSourcePort;
978                         var help = "Range: 1 - 65535";
979                         var action = 'SET_TP_SRC';
980                         var name = "Source Port";
981                         var body = function() {
982                             return one.f.flows.modal.action.body.set(h3, placeholder, id, help);
983                         };
984                         var add = function($modal) {
985                             one.f.flows.modal.action.add.set(name, id, action, $modal);
986                         };
987                         var $modal = one.f.flows.modal.action.initialize(h3, body, add);
988                         $modal.modal();
989                         break;
990                     case "modifyTransportDestinationPort" :
991                         var h3 = "Set Transport Destination Port";
992                         var placeholder = "Transport Destination Port";
993                         var id = one.f.flows.id.modal.action.modifyTransportDestinationPort;
994                         var help = "Range: 1 - 65535";
995                         var action = 'SET_TP_DST';
996                         var name = "Destination Port";
997                         var body = function() {
998                             return one.f.flows.modal.action.body.set(h3, placeholder, id, help);
999                         };
1000                         var add = function($modal) {
1001                             one.f.flows.modal.action.add.set(name, id, action, $modal);
1002                         };
1003                         var $modal = one.f.flows.modal.action.initialize(h3, body, add);
1004                         $modal.modal();
1005                         break;
1006                     case "drop" :
1007                         var name = "Drop";
1008                         var action = 'DROP';
1009                         one.f.flows.modal.action.add.add(name, action);
1010                         break;
1011                     case "loopback" :
1012                         var name = "Loopback";
1013                         var action = 'LOOPBACK';
1014                         one.f.flows.modal.action.add.add(name, action);
1015                         break;
1016                     case "flood" :
1017                         var name = "Flood";
1018                         var action = 'FLOOD';
1019                         one.f.flows.modal.action.add.add(name, action);
1020                         break;
1021                     case "softwarePath" :
1022                         var name = "Software Path";
1023                         var action = 'SW_PATH';
1024                         one.f.flows.modal.action.add.add(name, action);
1025                         break;
1026                     case "hardwarePath" :
1027                         var name = "Hardware Path";
1028                         var action = 'HW_PATH';
1029                         one.f.flows.modal.action.add.add(name, action);
1030                         break;
1031                     case "controller" :
1032                         var name = "Controller";
1033                         var action = 'CONTROLLER';
1034                         one.f.flows.modal.action.add.add(name, action);
1035                         break;
1036                 }
1037             },
1038             initialize : function(h3, bodyCallback, addCallback) {
1039                 var footer = one.f.flows.modal.action.footer();
1040                 var $body = bodyCallback();
1041                 var $modal = one.lib.modal.spawn(one.f.flows.id.modal.action.modal, h3, $body, footer);
1042                 // bind close button
1043                 $('#'+one.f.flows.id.modal.action.close, $modal).click(function() {
1044                     $modal.modal('hide');
1045                 });
1046                 // bind add flow button
1047                 $('#'+one.f.flows.id.modal.action.add, $modal).click(function() {
1048                     addCallback($modal);
1049                 });
1050                 return $modal;
1051             },
1052             add : {
1053                 addOutputPorts : function($modal) {
1054                     var $options = $('#'+one.f.flows.id.modal.action.addOutputPorts).find('option:selected');
1055                     var ports = '';
1056                     var pid = '';
1057                     $options.each(function(index, value) {
1058                         ports = ports+$(value).text()+", ";
1059                         pid = pid+$(value).attr('value')+",";
1060                     });
1061                     ports = ports.slice(0,-2);
1062                     pid = pid.slice(0,-1);
1063                     var $tr = one.f.flows.modal.action.table.add("Add Output Ports", ports);
1064                     $tr.attr('id', 'addOutputPorts');
1065                     $tr.data('action', 'OUTPUT='+pid);
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                     $modal.modal('hide');
1071                 },
1072                 add : function(name, action) {
1073                     var $tr = one.f.flows.modal.action.table.add(name);
1074                     $tr.attr('id', action);
1075                     $tr.data('action', action);
1076                     $tr.click(function() {
1077                         one.f.flows.modal.action.add.modal.initialize(this);
1078                     });
1079                     one.f.flows.modal.action.table.append($tr);
1080                 },
1081                 set : function(name, id, action, $modal) {
1082                     var $input = $('#'+id);
1083                     var value = $input.val();
1084                     var $tr = one.f.flows.modal.action.table.add(name, value);
1085                     $tr.attr('id', action);
1086                     $tr.data('action', action+'='+value);
1087                     $tr.click(function() {
1088                         one.f.flows.modal.action.add.modal.initialize(this);
1089                     });
1090                     one.f.flows.modal.action.table.append($tr);
1091                     $modal.modal('hide');
1092                 },
1093                 remove : function(that) {
1094                     $(that).remove();
1095                     var $table = $('#'+one.f.flows.id.modal.action.table);
1096                     if ($table.find('tbody').find('tr').size() == 0) {
1097                         var $tr = $(document.createElement('tr'));
1098                         var $td = $(document.createElement('td'));
1099                         $td.attr('colspan', '3');
1100                         $tr.addClass('empty');
1101                         $td.text('No data available');
1102                         $tr.append($td);
1103                         $table.find('tbody').append($tr);
1104                     }
1105                 },
1106                 modal : {
1107                     initialize : function(that) {
1108                         var h3 = "Remove Action";
1109                         var footer = one.f.flows.modal.action.add.modal.footer();
1110                         var $body = one.f.flows.modal.action.add.modal.body();
1111                         var $modal = one.lib.modal.spawn(one.f.flows.id.modal.action.modal.modal, h3, $body, footer);
1112
1113                         // bind cancel button
1114                         $('#'+one.f.flows.id.modal.action.modal.cancel, $modal).click(function() {
1115                             $modal.modal('hide');
1116                         });
1117
1118                         // bind remove button
1119                         $('#'+one.f.flows.id.modal.action.modal.remove, $modal).click(function() {
1120                             one.f.flows.modal.action.add.remove(that);
1121                             $modal.modal('hide');
1122                         });
1123
1124                         $modal.modal();
1125                     },
1126                     body : function() {
1127                         var $p = $(document.createElement('p'));
1128                         $p.append("Remove this action?");
1129                         return $p;
1130                     },
1131                     footer : function() {
1132                         var footer = [];
1133
1134                         var removeButton = one.lib.dashlet.button.single("Remove Action", one.f.flows.id.modal.action.modal.remove, "btn-danger", "");
1135                         var $removeButton = one.lib.dashlet.button.button(removeButton);
1136                         footer.push($removeButton);
1137
1138                         var cancelButton = one.lib.dashlet.button.single("Cancel", one.f.flows.id.modal.action.modal.cancel, "", "");
1139                         var $cancelButton = one.lib.dashlet.button.button(cancelButton);
1140                         footer.push($cancelButton);
1141
1142                         return footer;
1143                     }
1144                 }
1145             },
1146             table : {
1147                 add : function(action, data, type) {
1148                     var $tr = $(document.createElement('tr'));
1149                     var $td = $(document.createElement('td'));
1150                     $td.append(action);
1151                     $tr.append($td);
1152                     var $td = $(document.createElement('td'));
1153                     if (data != undefined) $td.append(data);
1154                     $tr.append($td);
1155                     var $td = $(document.createElement('td'));
1156                     if (type != undefined) $td.append(type);
1157                     $tr.append($td);
1158                     return $tr;
1159                 },
1160                 append : function($tr) {
1161                     var $table = $('#'+one.f.flows.id.modal.action.table);
1162                     var $empty = $table.find('.empty').parent();
1163                     if ($empty.size() > 0) $empty.remove();
1164                     $table.append($tr);
1165                 }
1166             },
1167             body : {
1168                 common : function() {
1169                     var $form = $(document.createElement('form'));
1170                     var $fieldset = $(document.createElement('fieldset'));
1171                     return [$form, $fieldset];
1172                 },
1173                 addOutputPorts : function() {
1174                     var common = one.f.flows.modal.action.body.common();
1175                     var $form = common[0];
1176                     var $fieldset = common[1];
1177                     // output port
1178                     $label = one.lib.form.label("Select Output Ports");
1179                     var ports = one.f.flows.registry.nodeports[one.f.flows.registry.currentNode]['ports'];
1180                     $select = one.lib.form.select.create(ports, true);
1181                     $select.attr('id', one.f.flows.id.modal.action.addOutputPorts);
1182                     one.lib.form.select.prepend($select, {'':'Select a Port'});
1183                     $fieldset.append($label).append($select);
1184                     $form.append($fieldset);
1185                     return $form;
1186                 },
1187                 set : function(label, placeholder, id, help) {
1188                     var common = one.f.flows.modal.action.body.common();
1189                     var $form = common[0];
1190                     var $fieldset = common[1];
1191                     // input
1192                     $label = one.lib.form.label(label);
1193                     $input = one.lib.form.input(placeholder);
1194                     $input.attr('id', id);
1195                     $help = one.lib.form.help(help);
1196                     // append
1197                     $fieldset.append($label).append($input).append($help);
1198                     $form.append($fieldset);
1199                     return $form;
1200                 }
1201             },
1202             footer : function() {
1203                 var footer = [];
1204                 var addButton = one.lib.dashlet.button.single("Add Action", one.f.flows.id.modal.action.add, "btn-primary", "");
1205                 var $addButton = one.lib.dashlet.button.button(addButton);
1206                 footer.push($addButton);
1207
1208                 var closeButton = one.lib.dashlet.button.single("Close", one.f.flows.id.modal.action.close, "", "");
1209                 var $closeButton = one.lib.dashlet.button.button(closeButton);
1210                 footer.push($closeButton);
1211
1212                 return footer;
1213             }
1214         },
1215         footer : function() {
1216             var footer = [];
1217
1218             var installButton = one.lib.dashlet.button.single("Install Flow", one.f.flows.id.modal.install, "btn-success", "");
1219             var $installButton = one.lib.dashlet.button.button(installButton);
1220             footer.push($installButton);
1221
1222             var addButton = one.lib.dashlet.button.single("Save Flow", one.f.flows.id.modal.add, "btn-primary", "");
1223             var $addButton = one.lib.dashlet.button.button(addButton);
1224             footer.push($addButton);
1225
1226             var closeButton = one.lib.dashlet.button.single("Close", one.f.flows.id.modal.close, "", "");
1227             var $closeButton = one.lib.dashlet.button.button(closeButton);
1228             footer.push($closeButton);
1229
1230             return footer;
1231         }
1232     },
1233     ajax : {
1234         dashlet : function(callback) {
1235             $.getJSON(one.f.address.root+one.f.address.flows.main, function(data) {
1236                 one.f.flows.registry['flows'] = data.flows;
1237                 one.f.flows.registry['privilege'] = data.privilege;
1238                 callback(data);
1239             });
1240         }
1241     },
1242     data : {
1243         flowsDataGrid: function(data) {
1244             var source = new StaticDataSource({
1245                     columns: [
1246                         {
1247                             property: 'selector',
1248                             label: "<input type='checkbox' id='"+one.f.flows.id.dashlet.datagrid.selectAllFlows+"'/>",
1249                             sortable: false
1250                         },
1251                         {
1252                             property: 'name',
1253                             label: 'Flow Name',
1254                             sortable: true
1255                         },
1256                         {
1257                             property: 'node',
1258                             label: 'Node',
1259                             sortable: true
1260                         }
1261                     ],
1262                     data: data.flows,
1263                     formatter: function(items) {
1264                         $.each(items, function(index, item) {
1265                                     var $checkbox = document.createElement("input");
1266                             $checkbox.setAttribute("type", "checkbox");
1267                             $checkbox.setAttribute("name", item.name);
1268                             $checkbox.setAttribute("node", item.node);
1269                             $checkbox.setAttribute('class','flowEntry')
1270                             item.selector = $checkbox.outerHTML;
1271                                   item["name"] = '<span data-installInHw=' + item["flow"]["installInHw"] + 
1272                                 ' data-flowstatus=' + item["flow"]["status"] + 
1273                                 ' data-nodeId=' + item["nodeId"] + '>' + item["name"] + '</span>';
1274                         });
1275
1276                     },
1277                     delay: 0
1278                 });
1279             return source;
1280         },
1281         dashlet : function(data) {
1282             var body = [];
1283             $(data).each(function(index, value) {
1284                 var tr = {};
1285                 var entry = [];
1286
1287                 
1288                 entry.push(value['name']);
1289                 entry.push(value['node']);
1290                 if (value['flow']['installInHw'] == 'true' && value['flow']['status'] == 'Success')
1291                     tr['type'] = ['success'];
1292                 else if (value['flow']['installInHw'] == 'false' && value['flow']['status'] == 'Success')
1293                     tr['type'] = ['warning'];
1294                 else 
1295                     tr['type'] = ['warning'];
1296                 tr['entry'] = entry;
1297                 tr['id'] = value['nodeId'];
1298
1299                 body.push(tr);
1300             });
1301             return body;
1302         }
1303     },
1304     body : {
1305         dashlet : function(body, callback) {
1306             var attributes = ['table-striped', 'table-bordered', 'table-hover', 'table-condensed', 'table-cursor'];
1307             var $table = one.lib.dashlet.table.table(attributes);
1308
1309             var headers = ['Flow Name', 'Node'];
1310                 
1311             var $thead = one.lib.dashlet.table.header(headers);
1312             $table.append($thead);
1313
1314             var $tbody = one.lib.dashlet.table.body(body);
1315             $table.append($tbody);
1316             return $table;
1317         }
1318     }
1319 }
1320
1321 /** INIT **/
1322 // populate nav tabs
1323 $(one.f.menu.left.top).each(function(index, value) {
1324     var $nav = $(".nav", "#left-top");
1325     one.main.page.dashlet($nav, value);
1326 });
1327
1328 $(one.f.menu.left.bottom).each(function(index, value) {
1329     var $nav = $(".nav", "#left-bottom");
1330     one.main.page.dashlet($nav, value);
1331 });
1332
1333 $(one.f.menu.right.bottom).each(function(index, value) {
1334     var $nav = $(".nav", "#right-bottom");
1335     one.main.page.dashlet($nav, value);
1336 });
1337
1338 one.f.populate = function($dashlet, header) {
1339     var $h4 = one.lib.dashlet.header(header);
1340     $dashlet.append($h4);
1341 };
1342
1343 // bind dashlet nav
1344 $('.dash .nav a', '#main').click(function() {
1345     // de/activation
1346     var $li = $(this).parent();
1347     var $ul = $li.parent();
1348     one.lib.nav.unfocus($ul);
1349     $li.addClass('active');
1350     // clear respective dashlet
1351     var $dashlet = $ul.parent().find('.dashlet');
1352     one.lib.dashlet.empty($dashlet);
1353     // callback based on menu
1354     var id = $(this).attr('id');
1355     var menu = one.f.dashlet;
1356     switch (id) {
1357         case menu.flows.id:
1358             one.f.flows.dashlet($dashlet);
1359             break;
1360         case menu.nodes.id:
1361             one.f.nodes.dashlet($dashlet);
1362             break;
1363         case menu.detail.id:
1364             one.f.detail.dashlet($dashlet);
1365             break;
1366     };
1367 });
1368
1369 // activate first tab on each dashlet
1370 $('.dash .nav').each(function(index, value) {
1371     $($(value).find('li')[0]).find('a').click();
1372 });