]> git.sur5r.net Git - bacula/bacula/blob - gui/baculum/framework/Web/Javascripts/source/prado/prado.js
baculum: New Baculum API and Baculum Web
[bacula/bacula] / gui / baculum / framework / Web / Javascripts / source / prado / prado.js
1 /*
2  * Polyfill for ECMAScript5's bind() function.
3  * ----------
4  * Adds compatible .bind() function; needed for Internet Explorer < 9
5  * Source: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind
6  */
7
8 if (!Function.prototype.bind) {
9   Function.prototype.bind = function (oThis) {
10     if (typeof this !== "function") {
11       // closest thing possible to the ECMAScript 5 internal IsCallable function
12       throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");
13     }
14
15     var aArgs = Array.prototype.slice.call(arguments, 1),
16         fToBind = this,
17         fNOP = function () {},
18         fBound = function () {
19           return fToBind.apply(this instanceof fNOP && oThis
20                                  ? this
21                                  : oThis,
22                                aArgs.concat(Array.prototype.slice.call(arguments)));
23         };
24
25     fNOP.prototype = this.prototype;
26     fBound.prototype = new fNOP();
27
28     return fBound;
29   };
30 }
31
32 /*
33  * Low Pro JQ
34  * ----------
35  *
36  * Author: Dan Webb (dan@danwebb.net)
37  * GIT: github.com:danwrong/low-pro-for-jquery.git
38  * Download: http://github.com/danwrong/low-pro-for-jquery/tree/master/src/lowpro.jquery.js?raw=true
39  *
40  * A jQuery port of the Low Pro behavior framework that was originally written for Prototype.
41  *
42  * Prado actually uses it as a base to emulate OOP subclassing, inheritance and contructor events.
43  * The "behaviour" and the "Remote" bits are not used and have been commented out.
44  */
45
46 (function($) {
47
48   var addMethods = function(source) {
49     var ancestor   = this.superclass && this.superclass.prototype;
50     var properties = $.keys(source);
51
52     if (!$.keys({ toString: true }).length) properties.push("toString", "valueOf");
53
54     for (var i = 0, length = properties.length; i < length; i++) {
55       var property = properties[i], value = source[property];
56       if (ancestor && $.isFunction(value) && $.argumentNames(value)[0] == "$super") {
57
58         var method = value, value = $.extend($.wrap((function(m) {
59           return function() { return ancestor[m].apply(this, arguments) };
60         })(property), method), {
61           valueOf:  function() { return method },
62           toString: function() { return method.toString() }
63         });
64       }
65       this.prototype[property] = value;
66     }
67
68     return this;
69   };
70
71   $.extend({
72     keys: function(obj) {
73       var keys = [];
74       for (var key in obj) keys.push(key);
75       return keys;
76     },
77
78     argumentNames: function(func) {
79       var names = func.toString().match(/^[\s\(]*function[^(]*\((.*?)\)/)[1].split(/, ?/);
80       return names.length == 1 && !names[0] ? [] : names;
81     },
82
83     bind: function(func, scope) {
84       return function() {
85         return func.apply(scope, $.makeArray(arguments));
86       };
87     },
88
89     wrap: function(func, wrapper) {
90       var __method = func;
91       return function() {
92         return wrapper.apply(this, [$.bind(__method, this)].concat($.makeArray(arguments)));
93       };
94     },
95
96     klass: function() {
97       var parent = null, properties = $.makeArray(arguments);
98       if ($.isFunction(properties[0])) parent = properties.shift();
99
100       var klass = function() {
101         this.initialize.apply(this, arguments);
102       };
103
104       klass.superclass = parent;
105       klass.subclasses = [];
106       klass.addMethods = addMethods;
107
108       if (parent) {
109         var subclass = function() { };
110         subclass.prototype = parent.prototype;
111         klass.prototype = new subclass;
112         parent.subclasses.push(klass);
113       }
114
115       for (var i = 0; i < properties.length; i++)
116         klass.addMethods(properties[i]);
117
118       if (!klass.prototype.initialize)
119         klass.prototype.initialize = function() {};
120
121       klass.prototype.constructor = klass;
122
123       return klass;
124     },
125     delegate: function(rules) {
126       return function(e) {
127         var target = $(e.target), parent = null;
128         for (var selector in rules) {
129           if (target.is(selector) || ((parent = target.parents(selector)) && parent.length > 0)) {
130             return rules[selector].apply(this, [parent || target].concat($.makeArray(arguments)));
131           }
132           parent = null;
133         }
134       };
135     }
136   });
137 /*
138   var bindEvents = function(instance) {
139     for (var member in instance) {
140       if (member.match(/^on(.+)/) && typeof instance[member] == 'function') {
141         instance.element.live(RegExp.$1, {'behavior': instance}, instance[member]);
142       }
143     }
144   };
145
146   var behaviorWrapper = function(behavior) {
147     return $.klass(behavior, {
148       initialize: function($super, element, args) {
149         this.element = element;
150         if ($super) $super.apply(this, args);
151       },
152       trigger: function(eventType, extraParameters) {
153         var parameters = [this].concat(extraParameters);
154         this.element.trigger(eventType, parameters);
155       }
156     });
157   };
158
159   var attachBehavior = function(el, behavior, args) {
160       var wrapper = behaviorWrapper(behavior);
161       var instance = new wrapper(el, args);
162
163       bindEvents(instance);
164
165       if (!behavior.instances) behavior.instances = [];
166
167       behavior.instances.push(instance);
168
169       return instance;
170   };
171
172
173   $.fn.extend({
174     attach: function() {
175       var args = $.makeArray(arguments), behavior = args.shift();
176       attachBehavior(this, behavior, args);
177       return this;
178     },
179     delegate: function(type, rules) {
180       return this.bind(type, $.delegate(rules));
181     },
182     attached: function(behavior) {
183       var instances = [];
184
185       if (!behavior.instances) return instances;
186
187       this.each(function(i, element) {
188         $.each(behavior.instances, function(i, instance) {
189           if (instance.element.get(0) == element) instances.push(instance);
190         });
191       });
192
193       return instances;
194     },
195     firstAttached: function(behavior) {
196       return this.attached(behavior)[0];
197     }
198   });
199
200   Remote = $.klass({
201     initialize: function(options) {
202       if (this.element.attr('nodeName') == 'FORM') this.element.attach(Remote.Form, options);
203       else this.element.attach(Remote.Link, options);
204     }
205   });
206
207   Remote.Base = $.klass({
208     initialize : function(options) {
209       this.options = $.extend(true, {}, options || {});
210     },
211     _makeRequest : function(options) {
212       $.ajax(options);
213       return false;
214     }
215   });
216
217   Remote.Link = $.klass(Remote.Base, {
218     onclick: function(e) {
219       var options = $.extend({
220         url: $(this).attr('href'),
221         type: 'GET'
222       }, this.options);
223       return e.data.behavior._makeRequest(e.data.behavior.options);
224     }
225   });
226
227   Remote.Form = $.klass(Remote.Base, {
228     onclick: function(e) {
229       var target = e.target;
230
231       if ($.inArray(target.nodeName.toLowerCase(), ['input', 'button']) >= 0 && target.type.match(/submit|image/))
232         e.data.behavior._submitButton = target;
233     },
234     onsubmit: function(e) {
235       var elm = $(this), data = elm.serializeArray();
236
237       if (e.data.behavior._submitButton) data.push({
238         name: e.data.behavior._submitButton.name,
239         value: e.data.behavior._submitButton.value
240       });
241
242       var options = $.extend({
243         url : elm.attr('action'),
244         type : elm.attr('method') || 'GET',
245         data : data
246       }, e.data.behavior.options);
247
248       e.data.behavior._makeRequest(options);
249
250       return false;
251     }
252   });
253
254   $.ajaxSetup({
255     beforeSend: function(xhr) {
256       if (!this.dataType)
257         xhr.setRequestHeader("Accept", "text/javascript, text/html, application/xml, text/xml, *\/*");
258     }
259   });
260 */
261 })(jQuery);
262
263
264 /**
265  * Prado base namespace
266  * @namespace Prado
267  */
268 var Prado =
269 {
270         /**
271          * Version of Prado clientscripts
272          * @var Version
273          */
274         Version: '3.3.2',
275
276         /**
277          * Registry for Prado components
278          * @var Registry
279          */
280         Registry: {}
281 };
282
283 Prado.RequestManager =
284 {
285         FIELD_POSTBACK_TARGET : 'PRADO_POSTBACK_TARGET',
286
287         FIELD_POSTBACK_PARAMETER : 'PRADO_POSTBACK_PARAMETER'
288 };
289 /**
290  * Performs a PostBack using javascript.
291  * @function Prado.PostBack
292  * @param options - Postback options
293  * @param event - Event that triggered this postback
294  * @... {string} FormID - Form that should be posted back
295  * @... {optional boolean} CausesValidation - Validate before PostBack if true
296  * @... {optional string} ValidationGroup - Group to Validate
297  * @... {optional string} ID - Validation ID
298  * @... {optional string} PostBackUrl - Postback URL
299  * @... {optional boolean} TrackFocus - Keep track of focused element if true
300  * @... {string} EventTarget - Id of element that triggered PostBack
301  * @... {string} EventParameter - EventParameter for PostBack
302  */
303 Prado.PostBack = jQuery.klass(
304 {
305         options : {},
306
307         initialize: function(options, event)
308         {
309                 jQuery.extend(this.options, options || {});
310                 this.event = event;
311                 this.doPostBack();
312         },
313
314         getForm : function()
315         {
316                 return jQuery("#" + this.options['FormID']).get(0);
317         },
318
319         doPostBack : function()
320         {
321                 var form = this.getForm();
322                 if(this.options['CausesValidation'] && typeof(Prado.Validation) != "undefined")
323                 {
324                         if(!Prado.Validation.validate(this.options['FormID'], this.options['ValidationGroup'], jQuery("#" + this.options['ID'])))
325                                 return this.event.preventDefault();
326                 }
327
328                 if(this.options['PostBackUrl'] && this.options['PostBackUrl'].length > 0)
329                         form.action = this.options['PostBackUrl'];
330
331                 if(this.options['TrackFocus'])
332                 {
333                         var lastFocus = jQuery('#PRADO_LASTFOCUS');
334                         if(lastFocus)
335                         {
336                                 var active = document.activeElement; //where did this come from
337                                 if(active)
338                                         lastFocus.value = active.id;
339                                 else
340                                         lastFocus.value = this.options['EventTarget'];
341                         }
342                 }
343
344                 var input=null;
345                 if(this.options.EventTarget)
346                 {
347                         input = document.createElement("input");
348                         input.setAttribute("type", "hidden");
349                         input.setAttribute("name", Prado.RequestManager.FIELD_POSTBACK_TARGET);
350                         input.setAttribute("value", this.options.EventTarget);
351                         form.appendChild(input);
352                 }
353                 if(this.options.EventParameter)
354                 {
355                         input = document.createElement("input");
356                         input.setAttribute("type", "hidden");
357                         input.setAttribute("name", Prado.RequestManager.FIELD_POSTBACK_PARAMETER);
358                         input.setAttribute("value", this.options.EventParameter);
359                         form.appendChild(input);
360                 }
361
362                 jQuery(form).trigger('submit');
363         }
364 });
365
366 /**
367  * Prado utilities to manipulate DOM elements.
368  * @object Prado.Element
369  */
370 Prado.Element =
371 {
372         /**
373          * Executes a jQuery method on a particular element.
374          * @function ?
375          * @param {string} element - Element id
376          * @param {string} method - method name
377          * @param {array} value - method parameters
378          */
379         j: function(element, method, params)
380         {
381                 var obj=jQuery("#" + element);
382                 obj[method].apply(obj, params);
383         },
384
385         /**
386          * Select options from a selectable element.
387          * @function ?
388          * @param {string} element - Element id
389          * @param {string} method - Name of any {@link Prado.Element.Selection} method
390          * @param {array|boolean|string} value - Values that should be selected
391          * @param {int} total - Number of elements
392          */
393         select : function(element, method, value, total)
394         {
395                 var el = jQuery("#" + element).get(0);
396                 if(!el) return;
397                 var selection = Prado.Element.Selection;
398                 if(typeof(selection[method]) == "function")
399                 {
400                         var control = selection.isSelectable(el) ? [el] : selection.getListElements(element,total);
401                         selection[method](control, value);
402                 }
403         },
404
405         /**
406          * Sets an attribute of a DOM element.
407          * @function ?
408          * @param {string} element - Element id
409          * @param {string} attribute - Name of attribute
410          * @param {string} value - Value of attribute
411          */
412         setAttribute : function(element, attribute, value)
413         {
414                 var el = jQuery("#" + element);
415                 if(!el) return;
416                 if((attribute == "disabled" || attribute == "multiple" || attribute == "readonly" || attribute == "href") && value==false)
417                         el.removeAttr(attribute);
418                 else if(attribute.match(/^on/i)) //event methods
419                 {
420                         try
421                         {
422                                 eval("(func = function(event){"+value+"})");
423                                 el.get(0)[attribute] = func;
424                         }
425                         catch(e)
426                         {
427                                 debugger;
428                                 throw "Error in evaluating '"+value+"' for attribute "+attribute+" for element "+element;
429                         }
430                 }
431                 else
432                         el.attr(attribute, value);
433         },
434
435         scrollTo : function(element, options)
436         {
437                 var op = {
438                         duration : 500,
439                         offset : 50
440                 };
441                 jQuery.extend(op, options || {});
442                 jQuery('html, body').animate({
443                         scrollTop: jQuery("#"+element).offset().top - op.offset
444                 }, op.duration);
445         },
446
447         focus : function(element)
448         {
449                 jQuery(document).ajaxStop(function () {
450                         setTimeout(function(){
451                                 jQuery("#"+element).focus();
452                         }, 100);
453                 });
454         },
455
456         /**
457          * Sets the options for a select element.
458          * @function ?
459          * @param {string} element - Element id
460          * @param {array[]} options - Array of options, each an array of structure
461          *   [ "optionText" , "optionValue" , "optionGroup" ]
462          */
463         setOptions : function(element, options)
464         {
465                 var el = jQuery("#" + element).get(0);
466                 var previousGroup = null;
467                 var optGroup=null;
468                 if(el && el.tagName.toLowerCase() == "select")
469                 {
470                         while(el.childNodes.length > 0)
471                                 el.removeChild(el.lastChild);
472
473                         var optDom = Prado.Element.createOptions(options);
474                         for(var i = 0; i < optDom.length; i++)
475                                 el.appendChild(optDom[i]);
476                 }
477         },
478
479         /**
480          * Create opt-group options from an array of options.
481          * @function {array} ?
482          * @param {array[]} options - Array of options, each an array of structure
483          *   [ "optionText" , "optionValue" , "optionGroup" ]
484          * @returns Array of option DOM elements
485          */
486         createOptions : function(options)
487         {
488                 var previousGroup = null;
489                 var optgroup=null;
490                 var result = [];
491                 for(var i = 0; i<options.length; i++)
492                 {
493                         var option = options[i];
494                         if(option.length > 2)
495                         {
496                                 var group = option[2];
497                                 if(group!=previousGroup)
498                                 {
499                                         if(previousGroup!=null && optgroup!=null)
500                                         {
501                                                 result.push(optgroup);
502                                                 previousGroup=null;
503                                                 optgroup=null;
504                                         }
505                                         optgroup = document.createElement('optgroup');
506                                         optgroup.label = group;
507                                         previousGroup = group;
508                                 }
509                         }
510                         var opt = document.createElement('option');
511                         opt.text = option[0];
512                         opt.innerHTML = option[0];
513                         opt.value = option[1];
514                         if(optgroup!=null)
515                                 optgroup.appendChild(opt);
516                         else
517                                 result.push(opt);
518                 }
519                 if(optgroup!=null)
520                         result.push(optgroup);
521                 return result;
522         },
523
524         /**
525          * Replace a DOM element either with given content or
526          * with content from a CallBack response boundary
527          * using a replacement method.
528          * @function ?
529          * @param {string|element} element - DOM element or element id
530          * @param {optional string} content - New content of element
531          * @param {optional string} boundary - Boundary of new content
532          * @param {optional boolean} self - Whether to replace itself or just the inner content
533          */
534         replace : function(element, content, boundary, self)
535         {
536                 if(boundary)
537                 {
538                         var result = this.extractContent(boundary);
539                         if(result != null)
540                                 content = result;
541                 }
542                 if(self)
543                   jQuery('#'+element).replaceWith(content);
544                 else 
545                   jQuery('#'+element).html(content);
546         },
547
548         /**
549          * Appends a javascript block to the document.
550          * @function ?
551          * @param {string} boundary - Boundary containing the javascript code
552          */
553         appendScriptBlock : function(boundary)
554         {
555                 var content = this.extractContent(boundary);
556                 if(content == null)
557                         return;
558
559                 var el   = document.createElement("script");
560                 el.type  = "text/javascript";
561                 el.id    = 'inline_' + boundary;
562                 el.text  = content;
563
564                 (document.getElementsByTagName('head')[0] || document.documentElement).appendChild(el);
565                 el.parentNode.removeChild(el);
566         },
567
568         /**
569          * Evaluate a javascript snippet from a string.
570          * @function ?
571          * @param {string} content - String containing the script
572          * @param {string} boundary - Boundary containing the script
573          */
574         evaluateScript : function(content, boundary)
575         {
576                 if(boundary)
577                 {
578                         var result = this.extractContent(boundary);
579                         if(result != null)
580                                 content = result;
581                 }
582
583                 try
584                 {
585                         jQuery.globalEval(content);
586                 }
587                 catch(e)
588                 {
589                         if(typeof(Logger) != "undefined")
590                                 Logger.error('Error during evaluation of script "'+content+'"');
591                         else
592                                 debugger;
593                         throw e;
594                 }
595         }
596 };
597
598 /**
599  * Utilities for selections.
600  * @object Prado.Element.Selection
601  */
602 Prado.Element.Selection =
603 {
604         /**
605          * Check if an DOM element can be selected.
606          * @function {boolean} ?
607          * @param {element} el - DOM elemet
608          * @returns true if element is selectable
609          */
610         isSelectable : function(el)
611         {
612                 if(el && el.type)
613                 {
614                         switch(el.type.toLowerCase())
615                         {
616                                 case 'checkbox':
617                                 case 'radio':
618                                 case 'select':
619                                 case 'select-multiple':
620                                 case 'select-one':
621                                 return true;
622                         }
623                 }
624                 return false;
625         },
626
627         /**
628          * Set checked attribute of a checkbox or radiobutton to value.
629          * @function {boolean} ?
630          * @param {element} el - DOM element
631          * @param {boolean} value - New value of checked attribute
632          * @returns New value of checked attribute
633          */
634         inputValue : function(el, value)
635         {
636                 switch(el.type.toLowerCase())
637                 {
638                         case 'checkbox':
639                         case 'radio':
640                         return el.checked = value;
641                 }
642         },
643
644         /**
645          * Set selected attribute for elements options by value.
646          * If value is boolean, all elements options selected attribute will be set
647          * to value. Otherwhise all options that have the given value will be selected.
648          * @function ?
649          * @param {element[]} elements - Array of selectable DOM elements
650          * @param {boolean|string} value - Value of options that should be selected or boolean value of selection status
651          */
652         selectValue : function(elements, value)
653         {
654                 jQuery.each(elements, function(idx, el)
655                 {
656                         jQuery.each(el.options, function(idx, option)
657                         {
658                                 if(typeof(value) == "boolean")
659                                         option.selected = value;
660                                 else if(option.value == value)
661                                         option.selected = true;
662                         });
663                 })
664         },
665
666         /**
667          * Set selected attribute for elements options by array of values.
668          * @function ?
669          * @param {element[]} elements - Array of selectable DOM elements
670          * @param {string[]} value - Array of values to select
671          */
672         selectValues : function(elements, values)
673         {
674                 var selection = this;
675                 jQuery.each(values, function(idx, value)
676                 {
677                         selection.selectValue(elements,value);
678                 })
679         },
680
681         /**
682          * Set selected attribute for elements options by option index.
683          * @function ?
684          * @param {element[]} elements - Array of selectable DOM elements
685          * @param {int} index - Index of option to select
686          */
687         selectIndex : function(elements, index)
688         {
689                 jQuery.each(elements, function(idx, el)
690                 {
691                         if(el.type.toLowerCase() == 'select-one')
692                                 el.selectedIndex = index;
693                         else
694                         {
695                                 for(var i = 0; i<el.length; i++)
696                                 {
697                                         if(i == index)
698                                                 el.options[i].selected = true;
699                                 }
700                         }
701                 })
702         },
703
704         /**
705          * Set selected attribute to true for all elements options.
706          * @function ?
707          * @param {element[]} elements - Array of selectable DOM elements
708          */
709         selectAll : function(elements)
710         {
711                 jQuery.each(elements, function(idx, el)
712                 {
713                         if(el.type.toLowerCase() != 'select-one')
714                         {
715                                 jQuery.each(el.options, function(idx, option)
716                                 {
717                                         option.selected = true;
718                                 })
719                         }
720                 })
721         },
722
723         /**
724          * Toggle the selected attribute for elements options.
725          * @function ?
726          * @param {element[]} elements - Array of selectable DOM elements
727          */
728         selectInvert : function(elements)
729         {
730                 jQuery.each(elements, function(idx, el)
731                 {
732                         if(el.type.toLowerCase() != 'select-one')
733                         {
734                                 jQuery.each(el.options, function(idx, option)
735                                 {
736                                         option.selected = !option.selected;
737                                 })
738                         }
739                 })
740         },
741
742         /**
743          * Set selected attribute for elements options by array of option indices.
744          * @function ?
745          * @param {element[]} elements - Array of selectable DOM elements
746          * @param {int[]} indices - Array of option indices to select
747          */
748         selectIndices : function(elements, indices)
749         {
750                 var selection = this;
751                 jQuery.each(indices, function(idx, index)
752                 {
753                         selection.selectIndex(elements,index);
754                 })
755         },
756
757         /**
758          * Unselect elements.
759          * @function ?
760          * @param {element[]} elements - Array of selectable DOM elements
761          */
762         selectClear : function(elements)
763         {
764                 jQuery.each(elements, function(idx, el)
765                 {
766                         el.selectedIndex = -1;
767                 })
768         },
769
770         /**
771          * Get list elements of an element.
772          * @function {element[]} ?
773          * @param {element[]} elements - Array of selectable DOM elements
774          * @param {int} total - Number of list elements to return
775          * @returns Array of list DOM elements
776          */
777         getListElements : function(element, total)
778         {
779                 var elements = new Array();
780                 var el;
781                 for(var i = 0; i < total; i++)
782                 {
783                         el = jQuery("#"+element+"_c"+i).get(0);
784                         if(el)
785                                 elements.push(el);
786                 }
787                 return elements;
788         },
789
790         /**
791          * Set checked attribute of elements by value.
792          * If value is boolean, checked attribute will be set to value.
793          * Otherwhise all elements that have the given value will be checked.
794          * @function ?
795          * @param {element[]} elements - Array of checkable DOM elements
796          * @param {boolean|String} value - Value that should be checked or boolean value of checked status
797          *
798          */
799         checkValue : function(elements, value)
800         {
801                 jQuery.each(elements, function(idx, el)
802                 {
803                         if(typeof(value) == "boolean")
804                                 el.checked = value;
805                         else if(el.value == value)
806                                 el.checked = true;
807                 });
808         },
809
810         /**
811          * Set checked attribute of elements by array of values.
812          * @function ?
813          * @param {element[]} elements - Array of checkable DOM elements
814          * @param {string[]} values - Values that should be checked
815          *
816          */
817         checkValues : function(elements, values)
818         {
819                 var selection = this;
820                 jQuery(values).each(function(idx, value)
821                 {
822                         selection.checkValue(elements, value);
823                 })
824         },
825
826         /**
827          * Set checked attribute of elements by list index.
828          * @function ?
829          * @param {element[]} elements - Array of checkable DOM elements
830          * @param {int} index - Index of element to set checked
831          */
832         checkIndex : function(elements, index)
833         {
834                 for(var i = 0; i<elements.length; i++)
835                 {
836                         if(i == index)
837                                 elements[i].checked = true;
838                 }
839         },
840
841         /**
842          * Set checked attribute of elements by array of list indices.
843          * @function ?
844          * @param {element[]} elements - Array of selectable DOM elements
845          * @param {int[]} indices - Array of list indices to set checked
846          */
847         checkIndices : function(elements, indices)
848         {
849                 var selection = this;
850                 jQuery.each(indices, function(idx, index)
851                 {
852                         selection.checkIndex(elements, index);
853                 })
854         },
855
856         /**
857          * Uncheck elements.
858          * @function ?
859          * @param {element[]} elements - Array of checkable DOM elements
860          */
861         checkClear : function(elements)
862         {
863                 jQuery.each(elements, function(idx, el)
864                 {
865                         el.checked = false;
866                 });
867         },
868
869         /**
870          * Set checked attribute of all elements to true.
871          * @function ?
872          * @param {element[]} elements - Array of checkable DOM elements
873          */
874         checkAll : function(elements)
875         {
876                 jQuery.each(elements, function(idx, el)
877                 {
878                         el.checked = true;
879                 })
880         },
881
882         /**
883          * Toggle the checked attribute of elements.
884          * @function ?
885          * @param {element[]} elements - Array of selectable DOM elements
886          */
887         checkInvert : function(elements)
888         {
889                 jQuery.each(elements, function(idx, el)
890                 {
891                         el.checked = !el.checked;
892                 })
893         }
894 };
895
896 jQuery.extend(String.prototype, {
897
898         /**
899          * Add padding to string
900          * @function {string} ?
901          * @param {string} side - "left" to pad the string on the left, "right" to pad right.
902          * @param {int} len - Minimum string length.
903          * @param {string} chr - Character(s) to pad
904          * @returns Padded string
905          */
906         pad : function(side, len, chr) {
907                 if (!chr) chr = ' ';
908                 var s = this;
909                 var left = side.toLowerCase()=='left';
910                 while (s.length<len) s = left? chr + s : s + chr;
911                 return s;
912         },
913
914         /**
915          * Add left padding to string
916          * @function {string} ?
917          * @param {int} len - Minimum string length.
918          * @param {string} chr - Character(s) to pad
919          * @returns Padded string
920          */
921         padLeft : function(len, chr) {
922                 return this.pad('left',len,chr);
923         },
924
925         /**
926          * Add right padding to string
927          * @function {string} ?
928          * @param {int} len - Minimum string length.
929          * @param {string} chr - Character(s) to pad
930          * @returns Padded string
931          */
932         padRight : function(len, chr) {
933                 return this.pad('right',len,chr);
934         },
935
936         /**
937          * Add zeros to the right of string
938          * @function {string} ?
939          * @param {int} len - Minimum string length.
940          * @returns Padded string
941          */
942         zerofill : function(len) {
943                 return this.padLeft(len,'0');
944         },
945
946         /**
947          * Remove white spaces from both ends of string.
948          * @function {string} ?
949          * @returns Trimmed string
950          */
951         trim : function() {
952                 return this.replace(/^\s+|\s+$/g,'');
953         },
954
955         /**
956          * Remove white spaces from the left side of string.
957          * @function {string} ?
958          * @returns Trimmed string
959          */
960         trimLeft : function() {
961                 return this.replace(/^\s+/,'');
962         },
963
964         /**
965          * Remove white spaces from the right side of string.
966          * @function {string} ?
967          * @returns Trimmed string
968          */
969         trimRight : function() {
970                 return this.replace(/\s+$/,'');
971         },
972
973         /**
974          * Convert period separated function names into a function reference.
975          * <br />Example:
976          * <pre>
977          * "Prado.AJAX.Callback.Action.setValue".toFunction()
978          * </pre>
979          * @function {function} ?
980          * @returns Reference to the corresponding function
981          */
982         toFunction : function()
983         {
984                 var commands = this.split(/\./);
985                 var command = window;
986                 jQuery(commands).each(function(idx, action)
987                 {
988                         if(command[new String(action)])
989                                 command=command[new String(action)];
990                 });
991                 if(typeof(command) == "function")
992                         return command;
993                 else
994                 {
995                         if(typeof Logger != "undefined")
996                                 Logger.error("Missing function", this);
997
998                         throw new Error ("Missing function '"+this+"'");
999                 }
1000         },
1001
1002         /**
1003          * Convert string into integer, returns null if not integer.
1004          * @function {int} ?
1005          * @returns Integer, null if string does not represent an integer.
1006          */
1007         toInteger : function()
1008         {
1009                 var exp = /^\s*[-\+]?\d+\s*$/;
1010                 if (this.match(exp) == null)
1011                         return null;
1012                 var num = parseInt(this, 10);
1013                 return (isNaN(num) ? null : num);
1014         },
1015
1016         /**
1017          * Convert string into a double/float value. <b>Internationalization
1018          * is not supported</b>
1019          * @function {double} ?
1020          * @param {string} decimalchar - Decimal character, defaults to "."
1021          * @returns Double, null if string does not represent a float value
1022          */
1023         toDouble : function(decimalchar)
1024         {
1025                 if(this.length <= 0) return null;
1026                 decimalchar = decimalchar || ".";
1027                 var exp = new RegExp("^\\s*([-\\+])?(\\d+)?(\\" + decimalchar + "(\\d+))?\\s*$");
1028                 var m = this.match(exp);
1029
1030                 if (m == null)
1031                         return null;
1032                 m[1] = m[1] || "";
1033                 m[2] = m[2] || "0";
1034                 m[4] = m[4] || "0";
1035
1036                 var cleanInput = m[1] + (m[2].length>0 ? m[2] : "0") + "." + m[4];
1037                 var num = parseFloat(cleanInput);
1038                 return (isNaN(num) ? null : num);
1039         },
1040
1041         /**
1042          * Convert strings that represent a currency value to float.
1043          * E.g. "10,000.50" will become "10000.50". The number
1044          * of dicimal digits, grouping and decimal characters can be specified.
1045          * <i>The currency input format is <b>very</b> strict, null will be returned if
1046          * the pattern does not match</i>.
1047          * @function {double} ?
1048          * @param {string} groupchar - Grouping character, defaults to ","
1049          * @param {int} digits - Number of decimal digits
1050          * @param {string} decimalchar - Decimal character, defaults to "."
1051          * @returns Double, null if string does not represent a currency value
1052          */
1053         toCurrency : function(groupchar, digits, decimalchar)
1054         {
1055                 groupchar = groupchar || ",";
1056                 decimalchar = decimalchar || ".";
1057                 digits = typeof(digits) == "undefined" ? 2 : digits;
1058
1059                 var exp = new RegExp("^\\s*([-\\+])?(((\\d+)\\" + groupchar + ")*)(\\d+)"
1060                         + ((digits > 0) ? "(\\" + decimalchar + "(\\d{1," + digits + "}))?" : "")
1061                         + "\\s*$");
1062                 var m = this.match(exp);
1063                 if (m == null)
1064                         return null;
1065                 var intermed = m[2] + m[5] ;
1066                 var cleanInput = m[1] + intermed.replace(
1067                                 new RegExp("(\\" + groupchar + ")", "g"), "")
1068                                                                 + ((digits > 0) ? "." + m[7] : "");
1069                 var num = parseFloat(cleanInput);
1070                 return (isNaN(num) ? null : num);
1071         }
1072 });
1073
1074 jQuery.extend(Date.prototype,
1075 {
1076         /**
1077          * SimpleFormat
1078          * @function ?
1079          * @param {string} format - TODO
1080          * @param {string} data - TODO
1081          * @returns TODO
1082          */
1083         SimpleFormat: function(format, data)
1084         {
1085                 data = data || {};
1086                 var bits = new Array();
1087                 bits['d'] = this.getDate();
1088                 bits['dd'] = String(this.getDate()).zerofill(2);
1089
1090                 bits['M'] = this.getMonth()+1;
1091                 bits['MM'] = String(this.getMonth()+1).zerofill(2);
1092                 if(data.AbbreviatedMonthNames)
1093                         bits['MMM'] = data.AbbreviatedMonthNames[this.getMonth()];
1094                 if(data.MonthNames)
1095                         bits['MMMM'] = data.MonthNames[this.getMonth()];
1096                 var yearStr = "" + this.getFullYear();
1097                 yearStr = (yearStr.length == 2) ? '19' + yearStr: yearStr;
1098                 bits['yyyy'] = yearStr;
1099                 bits['yy'] = bits['yyyy'].toString().substr(2,2);
1100
1101                 // do some funky regexs to replace the format string
1102                 // with the real values
1103                 var frm = new String(format);
1104                 for (var sect in bits)
1105                 {
1106                         var reg = new RegExp("\\b"+sect+"\\b" ,"g");
1107                         frm = frm.replace(reg, bits[sect]);
1108                 }
1109                 return frm;
1110         },
1111
1112         /**
1113          * toISODate
1114          * @function {string} ?
1115          * @returns TODO
1116          */
1117         toISODate : function()
1118         {
1119                 var y = this.getFullYear();
1120                 var m = String(this.getMonth() + 1).zerofill(2);
1121                 var d = String(this.getDate()).zerofill(2);
1122                 return String(y) + String(m) + String(d);
1123         }
1124 });
1125
1126 jQuery.extend(Date,
1127 {
1128         /**
1129          * SimpleParse
1130          * @function ?
1131          * @param {string} format - TODO
1132          * @param {string} data - TODO
1133          * @returns TODO
1134          */
1135         SimpleParse: function(value, format)
1136         {
1137                 var val=String(value);
1138                 format=String(format);
1139
1140                 if(val.length <= 0) return null;
1141
1142                 if(format.length <= 0) return new Date(value);
1143
1144                 var isInteger = function (val)
1145                 {
1146                         var digits="1234567890";
1147                         for (var i=0; i < val.length; i++)
1148                         {
1149                                 if (digits.indexOf(val.charAt(i))==-1) { return false; }
1150                         }
1151                         return true;
1152                 };
1153
1154                 var getInt = function(str,i,minlength,maxlength)
1155                 {
1156                         for (var x=maxlength; x>=minlength; x--)
1157                         {
1158                                 var token=str.substring(i,i+x);
1159                                 if (token.length < minlength) { return null; }
1160                                 if (isInteger(token)) { return token; }
1161                         }
1162                         return null;
1163                 };
1164
1165                 var i_val=0;
1166                 var i_format=0;
1167                 var c="";
1168                 var token="";
1169                 var token2="";
1170                 var x,y;
1171                 var now=new Date();
1172                 var year=now.getFullYear();
1173                 var month=now.getMonth()+1;
1174                 var date=1;
1175
1176                 while (i_format < format.length)
1177                 {
1178                         // Get next token from format string
1179                         c=format.charAt(i_format);
1180                         token="";
1181                         while ((format.charAt(i_format)==c) && (i_format < format.length))
1182                         {
1183                                 token += format.charAt(i_format++);
1184                         }
1185
1186                         // Extract contents of value based on format token
1187                         if (token=="yyyy" || token=="yy" || token=="y")
1188                         {
1189                                 if (token=="yyyy") { x=4;y=4; }
1190                                 if (token=="yy")   { x=2;y=2; }
1191                                 if (token=="y")    { x=2;y=4; }
1192                                 year=getInt(val,i_val,x,y);
1193                                 if (year==null) { return null; }
1194                                 i_val += year.length;
1195                                 if (year.length==2)
1196                                 {
1197                                         if (year > 70) { year=1900+(year-0); }
1198                                         else { year=2000+(year-0); }
1199                                 }
1200                         }
1201
1202                         else if (token=="MM"||token=="M")
1203                         {
1204                                 month=getInt(val,i_val,token.length,2);
1205                                 if(month==null||(month<1)||(month>12)){return null;}
1206                                 i_val+=month.length;
1207                         }
1208                         else if (token=="dd"||token=="d")
1209                         {
1210                                 date=getInt(val,i_val,token.length,2);
1211                                 if(date==null||(date<1)||(date>31)){return null;}
1212                                 i_val+=date.length;
1213                         }
1214                         else
1215                         {
1216                                 if (val.substring(i_val,i_val+token.length)!=token) {return null;}
1217                                 else {i_val+=token.length;}
1218                         }
1219                 }
1220
1221                 // If there are any trailing characters left in the value, it doesn't match
1222                 if (i_val != val.length) { return null; }
1223
1224                 // Is date valid for month?
1225                 if (month==2)
1226                 {
1227                         // Check for leap year
1228                         if ( ( (year%4==0)&&(year%100 != 0) ) || (year%400==0) ) { // leap year
1229                                 if (date > 29){ return null; }
1230                         }
1231                         else { if (date > 28) { return null; } }
1232                 }
1233
1234                 if ((month==4)||(month==6)||(month==9)||(month==11))
1235                 {
1236                         if (date > 30) { return null; }
1237                 }
1238
1239                 var newdate=new Date(year,month-1,date, 0, 0, 0);
1240                 return newdate;
1241         }
1242 });