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