Plugin UnivBristol by Frederic Francois
[myslice.git] / plugins / univbrisfvf / static / js / univbrisfvf.js
1 /**
2  * Description: display a query result in a datatables-powered <table>
3  * Copyright (c) 2012-2013 UPMC Sorbonne Universite - INRIA
4  * License: GPLv3
5  */ 
6
7 (function($){
8
9     var debug=false;
10     debug=true;
11     sync_query_uuid="";
12
13
14     var UnivbrisFvf = Plugin.extend({
15
16         init: function(options, element) {
17             //alert("foam init called");
18             this.classname="univbrisfvf";
19             this._super(options, element);
20                 
21             //alert(this.options.hidden_columns);
22             /* Member variables */
23             // in general we expect 2 queries here
24             // query_uuid refers to a single object (typically a slice)
25             // query_all_uuid refers to a list (typically resources or users)
26             // these can return in any order so we keep track of which has been received yet
27             //this.received_all_query = false;
28             //this.received_query = false;
29
30             // We need to remember the active filter for datatables filtering
31             this.filters = Array(); 
32
33             // an internal buffer for records that are 'in' and thus need to be checked 
34             this.buffered_records_to_check = [];
35             // an internal buffer for keeping lines and display them in one call to fnAddData
36             this.buffered_lines = [];
37
38             /* Events */
39             // xx somehow non of these triggers at all for now
40             //this.elmt().on('show', this, this.on_show);
41             //this.elmt().on('shown.bs.tab', this, this.on_show);
42             //this.elmt().on('resize', this, this.on_resize);
43
44             //var query = manifold.query_store.find_analyzed_query(this.options.query_uuid);
45             //this.object = query.object;
46
47             //// we need 2 different keys
48             // * canonical_key is the primary key as derived from metadata (typically: urn)
49             //   and is used to communicate about a given record with the other plugins
50             // * init_key is a key that both kinds of records 
51             //   (i.e. records returned by both queries) must have (typically: hrn or hostname)
52             //   in general query_all will return well populated records, but query
53             //   returns records with only the fields displayed on startup
54             var keys = manifold.metadata.get_key(this.object);
55             this.canonical_key = (keys && keys.length == 1) ? keys[0] : undefined;
56             // 
57             this.init_key = this.options.init_key;
58             // have init_key default to canonical_key
59             this.init_key = this.init_key || this.canonical_key;
60             // sanity check
61             if ( ! this.init_key ) messages.warning ("UnivbrisFvf : cannot find init_key");
62             if ( ! this.canonical_key ) messages.warning ("UnivbrisFvf : cannot find canonical_key");
63             if (debug) messages.debug("UnivbrisFvf: canonical_key="+this.canonical_key+" init_key="+this.init_key);
64
65             /* Setup query and record handlers */
66             //this.listen_query(options.query_uuid);
67             //this.listen_query(options.query_all_uuid, 'all');
68
69             /* GUI setup and event binding */
70             //this.initialize_table();
71             //alert("init fvf");
72             jQuery("#uob_fv_table_form").hide();
73         
74             $('<button id="cancel_addflowspaceform" type="button" style="height: 25px; width: 200px" onclick="fnCancel()">Cancel</button>').appendTo('#fvf_table_button');
75
76             $('<button id="addflowspaceform" type="button" style="height: 25px; width: 200px" onclick="fnAddflowspace()">Add flowspace</button>').appendTo('#fvf_table_button');
77                 
78             this._querytable_draw_callback();
79         },
80
81         /* PLUGIN EVENTS */
82
83         on_show: function(e) {
84             if (debug) messages.debug("univbrisfvf.on_show");
85             var self = e.data;
86             self.table.fnAdjustColumnSizing();
87         },        
88
89         on_resize: function(e) {
90             if (debug) messages.debug("univbrisfvf.on_resize");
91             var self = e.data;
92             self.table.fnAdjustColumnSizing();
93         },        
94
95         /* GUI EVENTS */
96
97         /* GUI MANIPULATION */
98
99         initialize_table: function() 
100         {
101             /* Transforms the table into DataTable, and keep a pointer to it */
102             var self = this;
103             var actual_options = {
104                 // Customize the position of Datatables elements (length,filter,button,...)
105                 // we use a fluid row on top and another on the bottom, making sure we take 12 grid elt's each time
106                 //sDom: "<'row'<'col-xs-5'l><'col-xs-1'r><'col-xs-6'f>>t<'row'<'col-xs-5'i><'col-xs-7'p>>",
107                 //sDom: "<'row'<'col-xs-2'l><'col-xs-9'r><'col-xs-2'f>>t<'row'<'col-xs-5'i><'col-xs-5'p>><'next'>",
108                 sDom: "<'row'<'col-xs-9'r>t<'buttons'>",
109                 // XXX as of sept. 2013, I cannot locate a bootstrap3-friendly mode for now
110                 // hopefully this would come with dataTables v1.10 ?
111                 // in any case, search for 'sPaginationType' all over the code for more comments
112                 sPaginationType: 'bootstrap',
113                 // Handle the null values & the error : Datatables warning Requested unknown parameter
114                 // http://datatables.net/forums/discussion/5331/datatables-warning-...-requested-unknown-parameter/p2
115                 aoColumnDefs: [{sDefaultContent: '',aTargets: [ '_all' ]}],
116                 // WARNING: this one causes tables in a 'tabs' that are not exposed at the time this is run to show up empty
117                 // sScrollX: '100%',       /* Horizontal scrolling */
118                 bProcessing: false,      /* Loading */
119                 fnDrawCallback: function() { self._querytable_draw_callback.call(self);}
120                 //fnFooterCallback: function() {self._univbrisfvf_footer_callback.call(self,nFoot, aData, iStart, iEnd, aiDisplay)};}
121                 // XXX use $.proxy here !
122             };
123             // the intention here is that options.datatables_options as coming from the python object take precedence
124             // xxx DISABLED by jordan: was causing errors in datatables.js
125             // xxx turned back on by Thierry - this is the code that takes python-provided options into account
126             // check your datatables_options tag instead 
127             // however, we have to accumulate in aoColumnDefs from here (above) 
128             // and from the python wrapper (checkboxes management, plus any user-provided aoColumnDefs)
129             if ( 'aoColumnDefs' in this.options.datatables_options) {
130                 actual_options['aoColumnDefs']=this.options.datatables_options['aoColumnDefs'].concat(actual_options['aoColumnDefs']);
131                 delete this.options.datatables_options['aoColumnDefs'];
132             }
133             $.extend(actual_options, this.options.datatables_options );
134             this.table = $("#univbris_flowspace_form__table").dataTable(actual_options);
135
136             //alert(this.table);
137
138             /* Setup the SelectAll button in the dataTable header */
139             /* xxx not sure this is still working */
140             var oSelectAll = $('#datatableSelectAll-'+ this.options.plugin_uuid);
141             oSelectAll.html("<span class='glyphicon glyphicon-ok' style='float:right;display:inline-block;'></span>Select All");
142             oSelectAll.button();
143             oSelectAll.css('font-size','11px');
144             oSelectAll.css('float','right');
145             oSelectAll.css('margin-right','15px');
146             oSelectAll.css('margin-bottom','5px');
147             oSelectAll.unbind('click');
148             oSelectAll.click(this._selectAll);
149
150             /* Add a filtering function to the current table 
151              * Note: we use closure to get access to the 'options'
152              */
153             $.fn.dataTableExt.afnFiltering.push(function( oSettings, aData, iDataIndex ) { 
154                 /* No filtering if the table does not match */
155                 if (oSettings.nTable.id != self.options.plugin_uuid + '__table')
156                     return true;
157                 return self._querytable_filter.call(self, oSettings, aData, iDataIndex);
158             });
159
160            //alert(this.options.hidden_columns);
161
162             /* Processing hidden_columns */
163             $.each(this.options.hidden_columns, function(i, field) {
164                 //manifold.raise_event(self.options.query_all_uuid, FIELD_REMOVED, field);
165                 //alert (field);
166                 self.hide_column(field);
167                 //self.hide_column(field);
168             });
169
170         }, // initialize_table
171
172
173         fnCancel:function(e){
174                 //var sData=$("#uob_fv_table_form").find("input").serialize();
175                 //alert("add flowspace:" + sData);
176                 //alert("cancel"); 
177                 jQuery("#uob_ofv_table_form").hide();
178                 jQuery("#uob_fv_table_form").hide();
179                 jQuery( "#univbris_foam_ports_selection" ).hide();
180                 jQuery( "#univbris_flowspace_selection" ).show();
181                 jQuery('#topo_plugin').hide();
182                 /*var port_table=$("#univbris_foam_ports_selection__table").dataTable();
183                 var nodes = $('input',port_table.fnGetNodes());
184                 for(var i=0;i<nodes.length;i++){
185                         nodes[i].checked=false;
186                         console.log(nodes[i].id);
187                 }*/
188
189         },
190
191
192         fnAddflowspace:function(e){
193                 
194                 e.stopPropagation();
195                 //if(fvf_add==1){       
196                         jQuery("#uob_ofv_table_form").hide();
197                         jQuery("#uob_fv_table_form").hide();
198
199                         if(pk_mode==1){
200                                                         
201                                 var sData=$("#uob_fv_table_form").find("input").serialize();
202                                 var form =serializeAnything("#uob_fv_table_form");
203                                 var port_table=$("#univbris_foam_ports_selection__table").dataTable();
204                                 var form2=$('input',port_table.fnGetNodes()).serialize();
205                                 var nodes = $('input',port_table.fnGetNodes());
206                 
207                                 this.table = $("#univbris_flowspace_selection__table").dataTable();
208                                 var val_status=validateFvfForm();
209                                 if (val_status == true){
210                                         pk_flowspace_index=1+pk_flowspace_index;
211                                         flowspace=sData;
212                                         var m_form=form+","+form2;
213                                         var string = "<p id='"+m_form+"'> <a onclick=\'fnPopTable(\""+form+"\",\""+form2+"\");'>"+$("#flowspace_name").val()+"</a></p>";        
214                                         if(fvf_add==1){
215                                                 this.table.fnAddData([string, '<a class="edit">Edit</a>', '<a class="delete" href="">Delete</a>']);
216                                         }
217                                         else{
218                                                 this.table.fnDeleteRow(fvf_nrow);       
219                         this.table.fnAddData([string, '<a class="edit">Edit</a>', '<a class="delete" href="">Delete</a>']);
220                                         }
221                                         jQuery( "#univbris_foam_ports_selection" ).hide();
222                                         jQuery( "#univbris_flowspace_selection" ).show();
223                                         jQuery('#topo_plugin').hide();
224                                 }
225                                 else{
226                                         alert("validation failed");
227                                         jQuery("#uob_fv_table_form").show();
228                                         jQuery("#uob_ofv_table_form").hide();
229                                         jQuery( "#univbris_foam_ports_selection" ).show();
230                                 }
231                         }
232                         else{
233                                                         
234                                 var sData=$("#uob_ofv_table_form").find("input").serialize();
235                                 var form =serializeAnything("#uob_ofv_table_form");
236                                 var port_table=$("#univbris_foam_ports_selection__table").dataTable();
237                                 var form2=$('input',port_table.fnGetNodes()).serialize();
238                                 var nodes = $('input',port_table.fnGetNodes());
239                 
240                                 this.table = $("#univbris_flowspace_selection__table").dataTable();
241                                 
242                                 var val_status=validateoFvfForm();
243                                 if (val_status == true){
244                                         opt_flowspace_index=1+opt_flowspace_index;
245                                         flowspace=sData;
246                                         var m_form=form+","+form2;
247                                         var string = "<p id='"+m_form+"'> <a onclick=\'fnPopTable(\""+form+"\",\""+form2+"\");'>"+$("#oflowspace_name").val()+"</a></p>";       
248                                         if(fvf_add==1){
249                                                 this.table.fnAddData([string, '<a class="edit">Edit</a>', '<a class="delete" href="">Delete</a>']);
250                                         }
251                                         else{
252                                                 this.table.fnDeleteRow(fvf_nrow);       
253                         this.table.fnAddData([string, '<a class="edit">Edit</a>', '<a class="delete" href="">Delete</a>']);
254                                         }
255                                         jQuery( "#univbris_foam_ports_selection" ).hide();
256                                         jQuery( "#univbris_flowspace_selection" ).show();
257                                         jQuery('#topo_plugin').hide();
258                                 }
259                                 else{
260                                         alert("validation failed");
261                                         jQuery("#uob_ofv_table_form").show();
262                                         jQuery("#uob_fv_table_form").hide();
263                                         jQuery( "#univbris_foam_ports_selection" ).show();
264                                 }
265
266                         }
267                 /*}
268                 else{
269                         jQuery("#uob_fv_table_form").hide();
270                         jQuery("#uob_ofv_table_form").hide();
271                         var sData=$("#uob_fv_table_form").find("input").serialize();
272                         var form =serializeAnything("#uob_fv_table_form");
273                         //var form2=serializeAnything("#uob_form");
274
275                         var port_table=$("#univbris_foam_ports_selection__table").dataTable();
276                         var form2=$('input',port_table.fnGetNodes()).serialize();
277                         this.table = $("#univbris_flowspace_selection__table").dataTable();
278                         flowspace=sData;
279                         var m_form=form+","+form2;
280                         var string = "<p id='"+m_form+"'> <a onclick=\'fnPopTable(\""+form+"\",\""+form2+"\");'>"+$("#flowspace_name").val()+"</a></p>";
281                         this.table.fnDeleteRow(fvf_nrow);       
282                         this.table.fnAddData([string, '<a class="edit">Edit</a>', '<a class="delete" href="">Delete</a>']);
283                         
284                         jQuery( "#univbris_foam_ports_selection" ).hide();
285                         jQuery( "#univbris_flowspace_selection" ).show();
286                         jQuery('#topo_plugin').hide();
287                 
288                 }*/
289         },
290
291
292         /**
293          * @brief Determine index of key in the table columns 
294          * @param key
295          * @param cols
296          */
297         getColIndex: function(key, cols) {
298             var tabIndex = $.map(cols, function(x, i) { if (x.sTitle == key) return i; });
299             return (tabIndex.length > 0) ? tabIndex[0] : -1;
300         }, // getColIndex
301
302         // create a checkbox <input> tag
303         // computes 'id' attribute from canonical_key
304         // computes 'init_id' from init_key for initialization phase
305         // no need to used convoluted ids with plugin-uuid or others, since
306         // we search using table.$ which looks only in this table
307         checkbox_html : function (record) {
308             var result="";
309             // Prefix id with plugin_uuid
310             result += "<input";
311             result += " class='univbrisfvf-checkbox'";
312          // compute id from canonical_key
313             var id = record[this.canonical_key]
314          // compute init_id form init_key
315             var init_id=record[this.init_key];
316          // set id - for retrieving from an id, or for posting events upon user's clicks
317             result += " id='"+record[this.canonical_key]+"'";
318          // set init_id
319             result += "init_id='" + init_id + "'";
320          // wrap up
321             result += " type='checkbox'";
322             result += " autocomplete='off'";
323             result += "></input>";
324             return result;
325         }, 
326
327          fake_checkbox_html : function (record) {
328             //alert("fake fun called");
329             var result="";
330             // Prefix id with plugin_uuid
331             result += "<input";
332             //result += " class='univbrisfvf-checkbox'";
333          // set id - for retrieving from an id, or for posting events upon user's clicks
334             result += " id='"+ record +"'";
335             result += " name='"+ record +"'";
336          // set init_id
337             result += " init_id='" + record + "'";
338          // wrap up
339             result += " type='checkbox'";
340             result += " autocomplete='off'";
341             result += "></input>";
342             ///alert(result);
343             return result;
344         }, 
345
346
347         new_record: function(record)
348         {
349            
350          // this models a line in dataTables, each element in the line describes a cell
351             line = new Array();
352      
353             // go through table headers to get column names we want
354             // in order (we have temporarily hack some adjustments in names)
355             var cols = this.table.fnSettings().aoColumns;
356             var colnames = cols.map(function(x) {return x.sTitle})
357             var nb_col = cols.length;
358             /* if we've requested checkboxes, then forget about the checkbox column for now */
359             if (this.options.checkboxes) nb_col -= 1;
360             
361             //alert(colnames);
362             /*replace production*/
363             /* fill in stuff depending on the column name */
364              var cols = this.table.fnSettings().aoColumns;
365             //alert("col "+cols);
366             var colnames = cols.map(function(x) {return x.sTitle})
367             var nb_col = cols.length;
368                         //alert("nb_col: "+ nb_col);
369             /* if we've requested checkboxes, then forget about the checkbox column for now */
370             if (this.options.checkboxes) nb_col -= 1;
371                         //alert("nb_col: "+ nb_col);
372             //alert(colnames);
373             /*replace production*/
374             /* fill in stuff depending on the column name */
375             for (var j = 0; j < nb_col; j++) {
376                 if (typeof colnames[j] == 'undefined') {
377                     line.push('...');
378                 } else if (colnames[j] == 'Flowspace Selector') {
379                     //alert("added");
380                     line.push("first");
381                 }
382                 
383             }
384     
385             // catch up with the last column if checkboxes were requested 
386             if (this.options.checkboxes) {
387                 // Use a key instead of hostname (hard coded...)
388                 line.push(this.checkbox_html(record));
389                 }
390     
391             // adding an array in one call is *much* more efficient
392                 // this.table.fnAddData(line);
393                 this.buffered_lines.push(line);
394                 this.table.fnAddData(this.buffered_lines);
395                 //this.table.redraw();
396                 //this._querytable_draw_callback();
397         },
398
399         clear_table: function()
400         {
401             this.table.fnClearTable();
402         },
403
404         redraw_table: function()
405         {
406             this.table.fnDraw();
407         },
408
409         show_column: function(field)
410         {
411             var oSettings = this.table.fnSettings();
412             var cols = oSettings.aoColumns;
413             var index = this.getColIndex(field,cols);
414             if (index != -1)
415                 this.table.fnSetColumnVis(index, true);
416         },
417
418         hide_column: function(field)
419         {
420             var oSettings = this.table.fnSettings();
421             var cols = oSettings.aoColumns;
422             var index = this.getColIndex(field,cols);
423             //index=-1;
424             //alert(field + ": index: " + index );
425             if (index != -1)
426                 //alert(field + ": hidden with index: " + index );
427                 this.table.fnSetColumnVis(index, false);
428         },
429
430         // this is used at init-time, at which point only init_key can make sense
431         // (because the argument record, if it comes from query, might not have canonical_key set
432         set_checkbox_from_record: function (record, checked) {
433             if (checked === undefined) checked = true;
434             var init_id = record[this.init_key];
435             if (debug) messages.debug("univbrisfvf.set_checkbox_from_record, init_id="+init_id);
436             // using table.$ to search inside elements that are not visible
437             var element = this.table.$('[init_id="'+init_id+'"]');
438             element.attr('checked',checked);
439         },
440
441         // id relates to canonical_key
442         set_checkbox_from_data: function (id, checked) {
443             if (checked === undefined) checked = true;
444             if (debug) messages.debug("univbrisfvf.set_checkbox_from_data, id="+id);
445             // using table.$ to search inside elements that are not visible
446             var element = this.table.$("[id='"+id+"']");
447             element.attr('checked',checked);
448         },
449
450         /*************************** QUERY HANDLER ****************************/
451
452         on_filter_added: function(filter)
453         {
454             this.filters.push(filter);
455             this.redraw_table();
456         },
457
458         on_filter_removed: function(filter)
459         {
460             // Remove corresponding filters
461             this.filters = $.grep(this.filters, function(x) {
462                 return x != filter;
463             });
464             this.redraw_table();
465         },
466         
467         on_filter_clear: function()
468         {
469             // XXX
470             this.redraw_table();
471         },
472
473         on_field_added: function(field)
474         {
475             this.show_column(field);
476         },
477
478         on_field_removed: function(field)
479         {
480             this.hide_column(field);
481         },
482
483         on_field_clear: function()
484         {
485             alert('UnivbrisFvf::clear_fields() not implemented');
486         },
487
488         /* XXX TODO: make this generic a plugin has to subscribe to a set of Queries to avoid duplicated code ! */
489         /*************************** ALL QUERY HANDLER ****************************/
490
491         on_all_filter_added: function(filter)
492         {
493             // XXX
494             this.redraw_table();
495         },
496
497         on_all_filter_removed: function(filter)
498         {
499             // XXX
500             this.redraw_table();
501         },
502         
503         on_all_filter_clear: function()
504         {
505             // XXX
506             this.redraw_table();
507         },
508
509         on_all_field_added: function(field)
510         {
511             this.show_column(field);
512         },
513
514         on_all_field_removed: function(field)
515         {
516             this.hide_column(field);
517         },
518
519         on_all_field_clear: function()
520         {
521             alert('UnivbrisFvf::clear_fields() not implemented');
522         },
523
524
525         /*************************** RECORD HANDLER ***************************/
526
527         on_new_record: function(record)
528         {
529             if (this.received_all_query) {
530                 // if the 'all' query has been dealt with already we may turn on the checkbox
531                 this.set_checkbox_from_record(record, true);
532             } else {
533                 this.buffered_records_to_check.push(record);
534             }
535         },
536
537         on_clear_records: function()
538         {
539         },
540
541         // Could be the default in parent
542         on_query_in_progress: function()
543         {
544             this.spin();
545         },
546
547         on_query_done: function()
548         {
549             this.received_query = true;
550             // unspin once we have received both
551             if (this.received_all_query && this.received_query) this.unspin();
552         },
553         
554         on_field_state_changed: function(data)
555         {
556             switch(data.request) {
557                 case FIELD_REQUEST_ADD:
558                 case FIELD_REQUEST_ADD_RESET:
559                     this.set_checkbox_from_data(data.value, true);
560                     break;
561                 case FIELD_REQUEST_REMOVE:
562                 case FIELD_REQUEST_REMOVE_RESET:
563                     this.set_checkbox_from_data(data.value, false);
564                     break;
565                 default:
566                     break;
567             }
568         },
569
570         /* XXX TODO: make this generic a plugin has to subscribe to a set of Queries to avoid duplicated code ! */
571         // all
572         on_all_field_state_changed: function(data)
573         {
574             switch(data.request) {
575                 case FIELD_REQUEST_ADD:
576                 case FIELD_REQUEST_ADD_RESET:
577                     this.set_checkboxfrom_data(data.value, true);
578                     break;
579                 case FIELD_REQUEST_REMOVE:
580                 case FIELD_REQUEST_REMOVE_RESET:
581                     this.set_checkbox_from_data(data.value, false);
582                     break;
583                 default:
584                     break;
585             }
586         },
587
588         on_all_new_record: function(record)
589         {
590             this.new_record(record);
591         },
592
593         on_all_clear_records: function()
594         {
595             this.clear_table();
596
597         },
598
599         on_all_query_in_progress: function()
600         {
601             // XXX parent
602             this.spin();
603         }, // on_all_query_in_progress
604
605         on_all_query_done: function()
606         {
607             if (debug) messages.debug("1-shot initializing dataTables content with " + this.buffered_lines.length + " lines");
608             this.table.fnAddData (this.buffered_lines);
609             this.buffered_lines=[];
610             
611             var self = this;
612             // if we've already received the slice query, we have not been able to set 
613             // checkboxes on the fly at that time (dom not yet created)
614             $.each(this.buffered_records_to_check, function(i, record) {
615                 if (debug) messages.debug ("querytable delayed turning on checkbox " + i + " record= " + record);
616                 self.set_checkbox_from_record(record, true);
617             });
618             this.buffered_records_to_check = [];
619
620             this.received_all_query = true;
621             // unspin once we have received both
622             if (this.received_all_query && this.received_query) this.unspin();
623
624         }, // on_all_query_done
625
626         /************************** PRIVATE METHODS ***************************/
627
628         /** 
629          * @brief QueryTable filtering function
630          */
631         _querytable_filter: function(oSettings, aData, iDataIndex)
632         {
633             var ret = true;
634             $.each (this.filters, function(index, filter) { 
635                 /* XXX How to manage checkbox ? */
636                 var key = filter[0]; 
637                 var op = filter[1];
638                 var value = filter[2];
639
640                 /* Determine index of key in the table columns */
641                 var col = $.map(oSettings.aoColumns, function(x, i) {if (x.sTitle == key) return i;})[0];
642
643                 /* Unknown key: no filtering */
644                 if (typeof(col) == 'undefined')
645                     return;
646
647                 col_value=unfold.get_value(aData[col]);
648                 /* Test whether current filter is compatible with the column */
649                 if (op == '=' || op == '==') {
650                     if ( col_value != value || col_value==null || col_value=="" || col_value=="n/a")
651                         ret = false;
652                 }else if (op == '!=') {
653                     if ( col_value == value || col_value==null || col_value=="" || col_value=="n/a")
654                         ret = false;
655                 } else if(op=='<') {
656                     if ( parseFloat(col_value) >= value || col_value==null || col_value=="" || col_value=="n/a")
657                         ret = false;
658                 } else if(op=='>') {
659                     if ( parseFloat(col_value) <= value || col_value==null || col_value=="" || col_value=="n/a")
660                         ret = false;
661                 } else if(op=='<=' || op=='≤') {
662                     if ( parseFloat(col_value) > value || col_value==null || col_value=="" || col_value=="n/a")
663                         ret = false;
664                 } else if(op=='>=' || op=='≥') {
665                     if ( parseFloat(col_value) < value || col_value==null || col_value=="" || col_value=="n/a")
666                         ret = false;
667                 }else{
668                     // How to break out of a loop ?
669                     alert("filter not supported");
670                     return false;
671                 }
672
673             });
674             return ret;
675         },
676
677         _querytable_draw_callback: function()
678         {
679             /* 
680              * Handle clicks on checkboxes: reassociate checkbox click every time
681              * the table is redrawn    
682              */
683             this.elts('querytable-checkbox').unbind('click').click(this, this._check_click);
684             //alert("fvf_add: "+fvf_add);
685             if(fvf_add==1){
686                 $("#addflowspaceform").unbind('click').click(this, this.fnAddflowspace);
687             }
688             else{
689                 $("[id='addflowspaceform']").unbind('click').click(this, this.fnModflowspace);
690             }
691             $("#cancel_addflowspaceform").unbind('click').click(this,this.fnCancel); 
692
693             if (!this.table)
694                 return;
695
696             /* Remove pagination if we show only a few results */
697             var wrapper = this.table; //.parent().parent().parent();
698             var rowsPerPage = this.table.fnSettings()._iDisplayLength;
699             var rowsToShow = this.table.fnSettings().fnRecordsDisplay();
700             var minRowsPerPage = this.table.fnSettings().aLengthMenu[0];
701
702             if ( rowsToShow <= rowsPerPage || rowsPerPage == -1 ) {
703                 $('.querytable_paginate', wrapper).css('visibility', 'hidden');
704             } else {
705                 $('.querytable_paginate', wrapper).css('visibility', 'visible');
706             }
707
708             if ( rowsToShow <= minRowsPerPage ) {
709                 $('.querytable_length', wrapper).css('visibility', 'hidden');
710             } else {
711                 $('.querytable_length', wrapper).css('visibility', 'visible');
712             }
713
714         },
715
716
717
718         _check_click: function(e) 
719         {
720             e.stopPropagation();
721
722             var self = e.data;
723             var id=this.id;
724
725             // this.id = key of object to be added... what about multiple keys ?
726             if (debug) messages.debug("querytable._check_click key="+this.canonical_key+"->"+id+" checked="+this.checked);
727             //manifold.raise_event(self.options.query_uuid, this.checked?SET_ADD:SET_REMOVED, id);
728             //return false; // prevent checkbox to be checked, waiting response from manifold plugin api
729             
730         },
731
732         _selectAll: function() 
733         {
734             // requires jQuery id
735             var uuid=this.id.split("-");
736             var oTable=$("#querytable-"+uuid[1]).dataTable();
737             // Function available in QueryTable 1.9.x
738             // Filter : displayed data only
739             var filterData = oTable._('tr', {"filter":"applied"});   
740             /* TODO: WARNING if too many nodes selected, use filters to reduce nuber of nodes */        
741             if(filterData.length<=100){
742                 $.each(filterData, function(index, obj) {
743                     var last=$(obj).last();
744                     var key_value=unfold.get_value(last[0]);
745                     if(typeof($(last[0]).attr('checked'))=="undefined"){
746                         $.publish('selected', 'add/'+key_value);
747                     }
748                 });
749             }
750         },
751
752     });
753
754     $.plugin('UnivbrisFvf', UnivbrisFvf);
755
756   /* define the 'dom-checkbox' type for sorting in datatables 
757      http://datatables.net/examples/plug-ins/dom_sort.html
758      using trial and error I found that the actual column number
759      was in fact given as a third argument, and not second 
760      as the various online resources had it - go figure */
761     $.fn.dataTableExt.afnSortData['dom-checkbox'] = function  ( oSettings, _, iColumn ) {
762         return $.map( oSettings.oApi._fnGetTrNodes(oSettings), function (tr, i) {
763             return result=$('td:eq('+iColumn+') input', tr).prop('checked') ? '1' : '0';
764         } );
765
766 };
767
768 })(jQuery);
769
770
771 function deserializeDT(d){
772
773         try{
774             var data = d,
775                 currentDom,
776                 $current = null,
777                 $currentSavedValue = null,
778                 $self = this,
779                 i = 0,
780                 keyValPairString = [],
781                 keyValPairObject = {},
782                 tmp = null,
783                 defaults = null;
784
785             if (data.constructor === String) {
786
787
788                 data = decodeURIComponent(data.replace(/\+/g, " "));
789
790                 keyValPairString = data.split('&');
791
792                 for (i = 0; i < keyValPairString.length; i++) {
793                     tmp = keyValPairString[i].split('=');
794                     keyValPairObject[tmp[0]] = tmp[1];
795
796                 }
797             }
798
799           var port_table=$("#univbris_foam_ports_selection__table").dataTable();
800           var nodes = $('input',port_table.fnGetNodes());
801
802
803           for(i=0;i<nodes.length;i++){
804                         $currentSavedValue = keyValPairObject[nodes[i].id];
805                         if ($currentSavedValue === undefined){
806                                 nodes[i].checked=false;
807                         }
808                         else{
809                                 nodes[i].checked=true;
810                         }
811           };
812
813         }
814         catch(err){
815                 alert(err);
816         }
817
818            
819 };
820
821
822 function fnPopTable(form1,form2){
823                 hideFvfError();
824                 jQuery("#univbris_flowspace_selection").hide();
825                 $("[id='addflowspaceform']").hide();
826                 
827                 deserializeDT(form2);
828
829
830                 //$("[name='flowspace_name']").prop("disabled", true);
831                 //$("#uob_fv_table_form :input").prop("disabled", true);
832                 //$("[id='cancel_addflowspaceform']").prop("disabled", false);
833                 //$("[id='cancel_addflowspaceform']").text('close');
834
835                 var port_table=$("#univbris_foam_ports_selection__table").dataTable();
836                 var nodes = $('input',port_table.fnGetNodes());
837                 for(var i=0;i<nodes.length;i++){
838                         nodes[i].disabled=true;
839                 }
840
841                 if (form1.search('pk_flowspace')!=-1){
842                         pk_mode=1;
843                 }
844                 else{
845                         pk_mode=0;
846                 }
847                 
848
849                 if  (pk_mode==1){
850                         try{
851                                 manifold.raise_event(sync_query_uuid,CLEAR_FILTERS);
852                                 var filter=[];
853                                 filter.push("link type");
854                                 filter.push("!=");
855                                 filter.push("optical");
856                                 manifold.raise_event(sync_query_uuid,FILTER_ADDED,filter);
857                         }
858                         catch(err){
859                                 alert("raise error:"+err);
860                         }
861                         $("#uob_fv_table_form :input").prop("disabled", false);
862                         $("#uob_fv_table_form").deserialize(form1);
863                         $("[name='flowspace_name']").prop("disabled", true);
864                         $("#uob_fv_table_form :input").prop("disabled", true);
865                         $("[id='cancel_addflowspaceform']").prop("disabled", false);
866                         $("[id='cancel_addflowspaceform']").text('close');
867                         topoviewer_state={mode:"read",link_type:"non-optical"};
868                         jQuery("#uob_fv_table_form").show();
869                 }
870                 else{
871
872                         try{
873                                 manifold.raise_event(sync_query_uuid,CLEAR_FILTERS);
874                                 var filter=[];
875                                 filter.push("link type");
876                                 filter.push("!=");
877                                 filter.push("packet");
878                                 manifold.raise_event(sync_query_uuid,FILTER_ADDED,filter);
879                                 filter=[];
880                                 filter.push("link type");
881                                 filter.push("!=");
882                                 filter.push("compute");
883                                 manifold.raise_event(sync_query_uuid,FILTER_ADDED,filter);
884                                 filter=[];
885                                 filter.push("link type");
886                                 filter.push("!=");
887                                 filter.push("federation");
888                                 manifold.raise_event(sync_query_uuid,FILTER_ADDED,filter);
889                         }
890                         catch(err){
891                                 alert("raise error:"+err);
892                         }
893                         $("#uob_ofv_table_form :input").prop("disabled", false);
894                         $("#uob_ofv_table_form").deserialize(form1);
895                         $("[name='oflowspace_name']").prop("disabled", true);
896                         $("#uob_ofv_table_form :input").prop("disabled", true);
897                         $("[id='cancel_addflowspaceform']").prop("disabled", false);
898                         $("[id='cancel_addflowspaceform']").text('close');
899                         topoviewer_state={mode:"read",link_type:"optical"};
900                         jQuery("#uob_ofv_table_form").show();
901                 }
902
903                 var port_table=$("#univbris_foam_ports_selection__table").dataTable();
904                 var nodes = $('input',port_table.fnGetNodes());
905                 var svg_links = svg.selectAll(".link");
906
907                 for(n=0;n<nodes.length;n++){
908                                 for(var i=0;i<svg_links[0].length;i++){
909                                         if(svg_links[0][i].__data__.value==nodes[n].id){
910                                                 if(nodes[n].checked==true){
911                                                         svg_links[0][i].style.stroke= 'black';
912                                                         svg_links[0][i].style.strokeWidth= '5px';
913                                                 }
914                                                 else{
915                                                         svg_links[0][i].style.stroke= '#ccc';
916                                                         svg_links[0][i].style.strokeWidth= '4px';
917                                                 }
918                                                 break;
919                                         }
920                                 }
921                                 nodes[n].disabled=false;
922                 };
923
924
925                 jQuery( "#univbris_foam_ports_selection" ).show();
926                 jQuery('#topo_plugin').show();
927 };
928
929 function macValidator (mac_str){
930         if (mac_str != ""){
931                 var mac_validator=/(^(([0-9a-fA-F]{2}[:-]){5}([0-9a-fA-F]{2}))$)|(^(([0-9a-fA-F]{2}[:-]){5}([0-9a-fA-F]{2})))$/;
932                 var result =mac_str.match(mac_validator);
933                 if (result==null){
934                         return false;
935                 }
936                 else{
937                         return true;
938                 }
939         }
940         else{
941                 return true;
942         }
943 };
944
945 function ethertypeValidator (eth_str){
946         if (eth_str != ""){
947                 var ethertype_validator=/^0x[0-9a-fA-F]{4}$/;
948                 var result = eth_str.match(ethertype_validator);
949                 if (result==null){
950                         return false;
951                 }
952                 else{
953                         return true;
954                 }
955         }
956         else{
957                 return true;
958         }
959 };
960
961
962 function vlanValidator (vlan_str){
963         if (vlan_str != ""){
964                 var vlan_validator=/(^[1-9][0-9]{0,2}|[1-3][0-9]{3}|40[0-8][0-9]|409[0-5]$)/;
965                 var result = vlan_str.match(vlan_validator);
966                 if (result==null){
967                         return false;
968                 }
969                 else{
970                         return true;
971                 }
972         }
973         else {
974                 return true;
975         }
976 };
977
978 function ipValidator(ip_str){
979         if (ip_str != ""){
980                 var ip_validator=/(^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$)/;
981                 var result = ip_str.match(ip_validator);
982                 if (result==null){
983                         return false;
984                 }
985                 else{
986                         return true;
987                 }
988         }
989         else {
990                 return true;
991         }
992 };
993
994
995 function portValidator (port_str){
996         if (port_str != ""){
997                 var port_validator=/^([1-9][0-9]{0,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])$/;
998                 var result = port_str.match(port_validator);
999                 if (result==null){
1000                         return false;
1001                 }
1002                 else{
1003                         return true;
1004                 }
1005         }
1006         else {
1007                 return true;
1008         }       
1009 }
1010
1011 function ipProtoValidator (ipproto_str){
1012         if (ipproto_str != ""){
1013                 var ipproto_validator=/(^[0-9]{1,2}|1[0-9]{2}|2[0-4][0-9]|25[0-5]$)/;
1014                 var result = ipproto_str.match(ipproto_validator);
1015                 if (result==null){
1016                         return false;
1017                 }
1018                 else{
1019                         return true;
1020                 }
1021         }
1022         else {
1023                 return true;
1024         }       
1025 }
1026
1027 function wavelengthValidator (wavelength_str){
1028                 var wavelength_validator=/^\d+.?\d*$/;
1029                 var result = wavelength_str.match(wavelength_validator);
1030                 if (result==null){
1031                         return false;
1032                 }
1033                 else{
1034                         return true;
1035                 }
1036 }
1037
1038
1039
1040
1041
1042
1043
1044
1045 function validateFvfForm(){
1046         var status = false;
1047         var checked =0;
1048
1049         //row 1 validation
1050         if (macValidator ($("#uob_fv_table_dl_src_start").val())==false){
1051                 $("#uob_fv_table_dl_src_start").addClass('error');
1052                 $("#uob_fv_table_dl_src_error").show();
1053         }
1054         else {
1055                 checked++;
1056         }
1057
1058         if (macValidator ($("#uob_fv_table_dl_src_end").val())==false){
1059                 $("#uob_fv_table_dl_src_end").addClass('error');
1060                 $("#uob_fv_table_dl_src_error").show();
1061         }
1062         else {
1063                 checked++;
1064         }
1065
1066         //row 2 validation
1067
1068         if (macValidator ($("#uob_fv_table_dl_dst_start").val())==false){
1069                 $("#uob_fv_table_dl_dst_start").addClass('error');
1070                 $("#uob_fv_table_dl_dst_error").show();
1071         }
1072         else {
1073                 checked++;
1074         }
1075
1076         if (macValidator ($("#uob_fv_table_dl_dst_end").val())==false){
1077                 $("#uob_fv_table_dl_dst_end").addClass('error');
1078                 $("#uob_fv_table_dl_dst_error").show();
1079         }
1080         else {
1081                 checked++;
1082         }
1083
1084         //row 3 validation
1085         
1086         if (ethertypeValidator ($("#uob_fv_table_dl_type_start").val())==false){
1087                 $("#uob_fv_table_dl_type_start").addClass('error');
1088                 $("#uob_fv_table_dl_type_error").show();
1089         }
1090         else {
1091                 checked++;
1092         }
1093
1094         if (ethertypeValidator ($("#uob_fv_table_dl_type_end").val())==false){
1095                 $("#uob_fv_table_dl_type_end").addClass('error');
1096                 $("#uob_fv_table_dl_type_error").show();
1097         }
1098         else {
1099                 checked++;
1100         }
1101
1102
1103         //row 4 validation
1104         if (vlanValidator ($("#uob_fv_table_vlan_id_start").val())==false){
1105                 $("#uob_fv_table_vlan_id_start").addClass('error');
1106                 $("#uob_fv_table_vlan_id_error").show();
1107         }
1108         else {
1109                 checked++;
1110         }
1111
1112         if (vlanValidator ($("#uob_fv_table_vlan_id_end").val())==false){
1113                 $("#uob_fv_table_vlan_id_end").addClass('error');
1114                 $("#uob_fv_table_vlan_id_error").show();
1115         }
1116         else {
1117                 checked++;
1118         }
1119  
1120         //row 5 validation
1121         if (ipValidator ($("#uob_fv_table_nw_src_start").val())==false){
1122                 $("#uob_fv_table_nw_src_start").addClass('error');
1123                 $("#uob_fv_table_nw_src_error").show();
1124         }
1125         else {
1126                 checked++;
1127         }
1128
1129         if (ipValidator ($("#uob_fv_table_nw_src_end").val())==false){
1130                 $("#uob_fv_table_nw_src_end").addClass('error');
1131                 $("#uob_fv_table_nw_src_error").show();
1132         }
1133         else {
1134                 checked++;
1135         }
1136
1137         //row 6 validation
1138         if (ipValidator ($("#uob_fv_table_nw_dst_start").val())==false){
1139                 $("#uob_fv_table_nw_dst_start").addClass('error');
1140                 $("#uob_fv_table_nw_dst_error").show();
1141         }
1142         else {
1143                 checked++;
1144         }
1145
1146         if (ipValidator ($("#uob_fv_table_nw_dst_end").val())==false){
1147                 $("#uob_fv_table_nw_dst_end").addClass('error');
1148                 $("#uob_fv_table_nw_dst_error").show();
1149         }
1150         else {
1151                 checked++;
1152         }
1153
1154
1155
1156         //row 7 validation
1157
1158         if (ipProtoValidator ($("#uob_fv_table_nw_proto_start").val())==false){
1159                 $("#uob_fv_table_nw_proto_start").addClass('error');
1160                 $("#uob_fv_table_nw_proto_error").show();
1161         }
1162         else {
1163                 checked++;
1164         }
1165
1166         if (ipProtoValidator ($("#uob_fv_table_nw_proto_end").val())==false){
1167                 $("#uob_fv_table_nw_proto_end").addClass('error');
1168                 $("#uob_fv_table_nw_proto_error").show();
1169         }
1170         else {
1171                 checked++;
1172         }
1173
1174         //row 8 validation
1175         if (portValidator ($("#uob_fv_table_tp_src_start").val())==false){
1176                 $("#uob_fv_table_tp_src_start").addClass('error');
1177                 $("#uob_fv_table_tp_src_error").show();
1178         }
1179         else {
1180                 checked++;
1181         }
1182
1183         if (portValidator ($("#uob_fv_table_tp_src_end").val())==false){
1184                 $("#uob_fv_table_tp_src_end").addClass('error');
1185                 $("#uob_fv_table_tp_src_error").show();
1186         }
1187         else {
1188                 checked++;
1189         }
1190
1191         //row 9 validation
1192         if (portValidator ($("#uob_fv_table_tp_dst_start").val())==false){
1193                 $("#uob_fv_table_tp_dst_start").addClass('error');
1194                 $("#uob_fv_table_tp_dst_error").show();
1195         }
1196         else {
1197                 checked++;
1198         }
1199
1200         if (portValidator ($("#uob_fv_table_tp_dst_end").val())==false){
1201                 $("#uob_fv_table_tp_dst_end").addClass('error');
1202                 $("#uob_fv_table_tp_dst_error").show();
1203         }
1204         else {
1205                 checked++;
1206         }/**/
1207
1208         //validate that at least one port is selected
1209         var port_table=$("#univbris_foam_ports_selection__table").dataTable();
1210         var nodes = $('input',port_table.fnGetNodes());
1211
1212         var port_selected=false;
1213         for(var i=0;i<nodes.length;i++){
1214                 if(nodes[i].checked==true){
1215                         checked++;
1216                         port_selected=true;
1217                         break;
1218                 }                       
1219         }
1220
1221         if (checked >= 19) {
1222                 status=true;
1223         }
1224
1225         if (port_selected==false & checked == 18){
1226                 alert("you need to select at least one port");
1227         }
1228         else if (port_selected==false & checked <= 18){
1229                 alert("you need to select at least one port and correct other flowspace parameter errors");
1230         }
1231         else if (port_selected==true & checked <= 18){
1232                 alert("you need to correct other flowspace parameter errors");
1233         }
1234         
1235         //alert("validator status:"+status+" checked:"+checked);
1236         return status;
1237 }
1238
1239 function validateoFvfForm(){
1240         var status = false;
1241         var checked =0;
1242
1243         //row 1 validation
1244         if (wavelengthValidator($('#uob_ofv_table_wavelength').val())==false){
1245                 $("#uob_ofv_table_wavelength").addClass('error');
1246                 $("#uob_ofv_table_wavelength_error").show();
1247         }
1248         else {
1249                 checked++;
1250         }
1251
1252         
1253
1254         //validate that at least one port is selected
1255         var port_table=$("#univbris_foam_ports_selection__table").dataTable();
1256         var nodes = $('input',port_table.fnGetNodes());
1257
1258         var port_selected=false;
1259         for(var i=0;i<nodes.length;i++){
1260                 if(nodes[i].checked==true){
1261                         checked++;
1262                         port_selected=true;
1263                         break;
1264                 }                       
1265         }
1266
1267         if (checked >= 2) {
1268                 status=true;
1269         }
1270
1271         if (port_selected==false & checked == 1){
1272                 alert("you need to select at least one port");
1273         }
1274         else if (port_selected==false & checked <= 1){
1275                 alert("you need to select at least one port and correct other flowspace parameter errors");
1276         }
1277         else if (port_selected==true & checked <= 1){
1278                 alert("you need to correct other flowspace parameter errors");
1279         }
1280         
1281         //alert("validator status:"+status+" checked:"+checked);
1282         return status;
1283 }
1284
1285
1286
1287 function fnGetSelected( oTableLocal )
1288 {
1289         var aReturn = new Array();
1290         var aTrs = oTableLocal.fnGetNodes();
1291         
1292         for ( var i=0 ; i<aTrs.length ; i++ )
1293         {
1294                 if ( $(aTrs[i]).hasClass('row_selected') )
1295                 {
1296                         aReturn.push( aTrs[i] );
1297                 }
1298         }
1299         return aReturn;
1300 }
1301
1302 function serializeAnything (form){
1303         var toReturn    = [];
1304         var els         = $(form).find(':input').get();
1305
1306         $.each(els, function() {                        
1307                 if (this.name && (this.checked || /select|textarea/i.test(this.nodeName) || /text|hidden|password/i.test(this.type))) {
1308                                 var val = $(this).val();
1309                                 toReturn.push( encodeURIComponent(this.name) + "=" + encodeURIComponent( val ) );
1310                         }
1311                 });
1312
1313                 return toReturn.join("&").replace(/%20/g, "+");
1314 }
1315
1316 function hideFvfError(){
1317         $("[id*=_error]").hide();
1318         console
1319         $("#uob_fv_table_form :input").each(function(){
1320                 try{
1321                         $(this).removeClass('error');
1322                 }
1323                 catch (err){
1324                 }
1325
1326         });
1327
1328         $("#uob_ofv_table_form :input").each(function(){
1329                 try{
1330                         $(this).removeClass('error');
1331                 }
1332                 catch (err){
1333                 }
1334
1335         });
1336 }
1337
1338
1339 (function ($) {
1340     $.fn.extend({
1341         deserialize : function (d, config) {
1342             var data = d,
1343                 currentDom,
1344                 $current = null,
1345                 $currentSavedValue = null,
1346                 $self = this,
1347                 i = 0,
1348                 keyValPairString = [],
1349                 keyValPairObject = {},
1350                 tmp = null,
1351                 defaults = null;
1352
1353             if (d === undefined || !$self.is('form')) {
1354                 return $self;
1355             }
1356
1357             defaults = {
1358                 overwrite : true
1359             };
1360
1361             config = $.extend(defaults, config);
1362
1363             if (d.constructor === String) {
1364
1365
1366                 d = decodeURIComponent(d.replace(/\+/g, " "));
1367
1368                 keyValPairString = d.split('&');
1369
1370                 for (i = 0; i < keyValPairString.length; i++) {
1371                     tmp = keyValPairString[i].split('=');
1372                     keyValPairObject[tmp[0]] = tmp[1];
1373
1374                 }
1375             }
1376
1377             $('input, select, textarea', $self).each(function (i) {
1378
1379                 $current = $(this);
1380                 currentDom = $current.get(0);
1381                 $currentSavedValue = keyValPairObject[$current.attr('name')];
1382
1383                 if (currentDom.disabled === true) {
1384                     //current.val($currentSavedValue);
1385                     return true;
1386                 }
1387
1388                 if ($current.is('textarea')) {
1389                     if ($currentSavedValue === undefined) {
1390                         $current.val('');
1391                     } else {
1392                         $current.val($currentSavedValue);
1393                     }
1394                     return true;
1395                 }
1396
1397                 if ($current.is('select')) {
1398                     if ($currentSavedValue === undefined) {
1399                         return true;
1400                     } else {
1401                         currentDom.selectedIndex = $currentSavedValue;
1402                     }
1403                     return true;
1404                 }
1405
1406                 if ($current.is('input:radio')) {
1407                     if ($currentSavedValue !== undefined) {
1408
1409                         $current.each(function () {
1410                             if ($(this).val() === $currentSavedValue) {
1411                                 $(this).get(0).checked = true;
1412                             }
1413                         });
1414                     }
1415
1416                     return true;
1417                 }
1418
1419                 if ($current.is('input:checkbox')) {
1420                     currentDom.checked = ($current.val() === $currentSavedValue);
1421                     return true;
1422                 }
1423
1424                 if ($current.is('input:text, input:hidden')) {
1425                     if ($currentSavedValue === undefined) {
1426                         $current.val('');
1427                     } else {
1428                         $current.val($currentSavedValue);
1429                         return true;
1430                     }
1431
1432                 }
1433
1434             });
1435
1436             return $self;
1437         }
1438
1439     });
1440
1441
1442 }(jQuery));
1443
1444