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