]> git.sur5r.net Git - bacula/bacula/blob - gui/baculum/framework/Web/Javascripts/source/prado/scriptaculous-adapter.js
baculum: New Baculum API and Baculum Web
[bacula/bacula] / gui / baculum / framework / Web / Javascripts / source / prado / scriptaculous-adapter.js
1 /**
2  * Utilities and extions to Prototype/Scriptaculous
3  * @file scriptaculous-adapter.js
4  */
5  
6 /**
7  * Extension to 
8  * <a href="http://www.prototypejs.org/api/function" target="_blank">Prototype's Function</a>
9  * @namespace Function
10  */
11 /**
12  * Similar to bindAsEventLister, but takes additional arguments.
13  * @function Function.bindEvent
14  */
15 Function.prototype.bindEvent = function()
16 {
17         var __method = this, args = $A(arguments), object = args.shift();
18         return function(event)
19         {
20                 return __method.apply(object, [event || window.event].concat(args));
21         }
22 };
23
24 /**
25  * Extension to 
26  * <a href="http://www.prototypejs.org/api/class" target="_blank">Prototype's Class</a>
27  * @namespace Class
28  */
29  
30 /**
31  * Creates a new class by copying class definition from
32  * the <tt>base</tt> and optional <tt>definition</tt>.
33  * @function {Class} Class.extend
34  * @param {function} base - Base class to copy from.
35  * @param {optional Array} - Additional definition 
36  * @returns Constructor for the extended class
37  */
38 Class.extend = function(base, definition)
39 {
40                 var component = Class.create();
41                 Object.extend(component.prototype, base.prototype);
42                 if(definition)
43                         Object.extend(component.prototype, definition);
44                 return component;
45 };
46
47 /**
48  * Base, version 1.0.2
49  * Copyright 2006, Dean Edwards
50  * License: http://creativecommons.org/licenses/LGPL/2.1/
51  * @class Base
52  */
53 var Base = function() {
54         if (arguments.length) {
55                 if (this == window) { // cast an object to this class
56                         Base.prototype.extend.call(arguments[0], arguments.callee.prototype);
57                 } else {
58                         this.extend(arguments[0]);
59                 }
60         }
61 };
62
63 Base.version = "1.0.2";
64
65 Base.prototype = {
66         extend: function(source, value) {
67                 var extend = Base.prototype.extend;
68                 if (arguments.length == 2) {
69                         var ancestor = this[source];
70                         // overriding?
71                         if ((ancestor instanceof Function) && (value instanceof Function) &&
72                                 ancestor.valueOf() != value.valueOf() && /\bbase\b/.test(value)) {
73                                 var method = value;
74                         //      var _prototype = this.constructor.prototype;
75                         //      var fromPrototype = !Base._prototyping && _prototype[source] == ancestor;
76                                 value = function() {
77                                         var previous = this.base;
78                                 //      this.base = fromPrototype ? _prototype[source] : ancestor;
79                                         this.base = ancestor;
80                                         var returnValue = method.apply(this, arguments);
81                                         this.base = previous;
82                                         return returnValue;
83                                 };
84                                 // point to the underlying method
85                                 value.valueOf = function() {
86                                         return method;
87                                 };
88                                 value.toString = function() {
89                                         return String(method);
90                                 };
91                         }
92                         return this[source] = value;
93                 } else if (source) {
94                         var _prototype = {toSource: null};
95                         // do the "toString" and other methods manually
96                         var _protected = ["toString", "valueOf"];
97                         // if we are prototyping then include the constructor
98                         if (Base._prototyping) _protected[2] = "constructor";
99                         var name;
100                         for (var i = 0; (name = _protected[i]); i++) {
101                                 if (source[name] != _prototype[name]) {
102                                         extend.call(this, name, source[name]);
103                                 }
104                         }
105                         // copy each of the source object's properties to this object
106                         for (var name in source) {
107                                 if (!_prototype[name]) {
108                                         extend.call(this, name, source[name]);
109                                 }
110                         }
111                 }
112                 return this;
113         },
114
115         base: function() {
116                 // call this method from any other method to invoke that method's ancestor
117         }
118 };
119
120 Base.extend = function(_instance, _static) {
121         var extend = Base.prototype.extend;
122         if (!_instance) _instance = {};
123         // build the prototype
124         Base._prototyping = true;
125         var _prototype = new this;
126         extend.call(_prototype, _instance);
127         var constructor = _prototype.constructor;
128         _prototype.constructor = this;
129         delete Base._prototyping;
130         // create the wrapper for the constructor function
131         var klass = function() {
132                 if (!Base._prototyping) constructor.apply(this, arguments);
133                 this.constructor = klass;
134         };
135         klass.prototype = _prototype;
136         // build the class interface
137         klass.extend = this.extend;
138         klass.implement = this.implement;
139         klass.toString = function() {
140                 return String(constructor);
141         };
142         extend.call(klass, _static);
143         // single instance
144         var object = constructor ? klass : _prototype;
145         // class initialisation
146         if (object.init instanceof Function) object.init();
147         return object;
148 };
149
150 Base.implement = function(_interface) {
151         if (_interface instanceof Function) _interface = _interface.prototype;
152         this.prototype.extend(_interface);
153 };
154
155 /**
156  * Performs a PostBack using javascript.
157  * @function Prado.PostBack
158  * @param event - Event that triggered this postback
159  * @param options - Postback options
160  * @... {string} FormID - Form that should be posted back
161  * @... {optional boolean} CausesValidation - Validate before PostBack if true
162  * @... {optional string} ValidationGroup - Group to Validate 
163  * @... {optional string} ID - Validation ID 
164  * @... {optional string} PostBackUrl - Postback URL
165  * @... {optional boolean} TrackFocus - Keep track of focused element if true
166  * @... {string} EventTarget - Id of element that triggered PostBack
167  * @... {string} EventParameter - EventParameter for PostBack
168  */
169 Prado.PostBack = function(event,options)
170 {
171         var form = $(options['FormID']);
172         var canSubmit = true;
173
174         if(options['CausesValidation'] && typeof(Prado.Validation) != "undefined")
175         {
176                 if(!Prado.Validation.validate(options['FormID'], options['ValidationGroup'], $(options['ID'])))
177                         return Event.stop(event);
178         }
179
180         if(options['PostBackUrl'] && options['PostBackUrl'].length > 0)
181                 form.action = options['PostBackUrl'];
182
183         if(options['TrackFocus'])
184         {
185                 var lastFocus = $('PRADO_LASTFOCUS');
186                 if(lastFocus)
187                 {
188                         var active = document.activeElement; //where did this come from
189                         if(active)
190                                 lastFocus.value = active.id;
191                         else
192                                 lastFocus.value = options['EventTarget'];
193                 }
194         }
195
196         $('PRADO_POSTBACK_TARGET').value = options['EventTarget'];
197         $('PRADO_POSTBACK_PARAMETER').value = options['EventParameter'];
198         /**
199          * Since google toolbar prevents browser default action,
200          * we will always disable default client-side browser action
201          */
202         /*if(options['StopEvent']) */
203                 Event.stop(event);
204         Event.fireEvent(form,"submit");
205
206         $('PRADO_POSTBACK_TARGET').value = '';
207         $('PRADO_POSTBACK_PARAMETER').value = '';
208 };
209
210 /**
211  * Prado utilities to manipulate DOM elements.
212  * @object Prado.Element
213  */
214 Prado.Element =
215 {
216         /**
217          * Set the value of a particular element.
218          * @function ?
219          * @param {string} element - Element id
220          * @param {string} value - New element value
221          */
222         setValue : function(element, value)
223         {
224                 var el = $(element);
225                 if(el && typeof(el.value) != "undefined")
226                         el.value = value;
227         },
228
229         /**
230          * Select options from a selectable element.
231          * @function ?
232          * @param {string} element - Element id
233          * @param {string} method - Name of any {@link Prado.Element.Selection} method
234          * @param {array|boolean|string} value - Values that should be selected
235          * @param {int} total - Number of elements 
236          */
237         select : function(element, method, value, total)
238         {
239                 var el = $(element);
240                 if(!el) return;
241                 var selection = Prado.Element.Selection;
242                 if(typeof(selection[method]) == "function")
243                 {
244                         var control = selection.isSelectable(el) ? [el] : selection.getListElements(element,total);
245                         selection[method](control, value);
246                 }
247         },
248
249         /**
250          * Trigger a click event on a DOM element.
251          * @function ?
252          * @param {string} element - Element id
253          */
254         click : function(element)
255         {
256                 var el = $(element);
257                 if(el)
258                         el.click();
259         },
260         
261         /**
262          * Check if an DOM element is disabled.
263          * @function {boolean} ?
264          * @param {string} element - Element id
265          * @returns true if element is disabled
266          */
267         isDisabled : function(element)
268         {
269                 if(!element.attributes['disabled']) //FF
270                         return false;
271                 var value = element.attributes['disabled'].nodeValue;
272                 if(typeof(value)=="string")
273                         return value.toLowerCase() == "disabled";
274                 else
275                         return value == true;
276         },
277
278         /**
279          * Sets an attribute of a DOM element.
280          * @function ?
281          * @param {string} element - Element id
282          * @param {string} attribute - Name of attribute
283          * @param {string} value - Value of attribute
284          */
285         setAttribute : function(element, attribute, value)
286         {
287                 var el = $(element);
288                 if(!el) return;
289                 if((attribute == "disabled" || attribute == "multiple" || attribute == "readonly" || attribute == "href") && value==false)
290                         el.removeAttribute(attribute);
291                 else if(attribute.match(/^on/i)) //event methods
292                 {
293                         try
294                         {
295                                 eval("(func = function(event){"+value+"})");
296                                 el[attribute] = func;
297                         }
298                         catch(e)
299                         {
300                                 debugger;
301                                 throw "Error in evaluating '"+value+"' for attribute "+attribute+" for element "+element.id;
302                         }
303                 }
304                 else
305                         el.setAttribute(attribute, value);
306         },
307
308         /**
309          * Sets the options for a select element. 
310          * @function ?
311          * @param {string} element - Element id
312          * @param {array[]} options - Array of options, each an array of structure 
313          *   [ "optionText" , "optionValue" , "optionGroup" ]
314          */
315         setOptions : function(element, options)
316         {
317                 var el = $(element);
318                 if(!el) return;
319                 var previousGroup = null;
320                 var optGroup=null;
321                 if(el && el.tagName.toLowerCase() == "select")
322                 {
323                         while(el.childNodes.length > 0)
324                                 el.removeChild(el.lastChild);
325
326                         var optDom = Prado.Element.createOptions(options);
327                         for(var i = 0; i < optDom.length; i++)
328                                 el.appendChild(optDom[i]);
329                 }
330         },
331
332         /**
333          * Create opt-group options from an array of options. 
334          * @function {array} ?
335          * @param {array[]} options - Array of options, each an array of structure 
336          *   [ "optionText" , "optionValue" , "optionGroup" ]
337          * @returns Array of option DOM elements
338          */
339         createOptions : function(options)
340         {
341                 var previousGroup = null;
342                 var optgroup=null;
343                 var result = [];
344                 for(var i = 0; i<options.length; i++)
345                 {
346                         var option = options[i];
347                         if(option.length > 2)
348                         {
349                                 var group = option[2];
350                                 if(group!=previousGroup)
351                                 {
352                                         if(previousGroup!=null && optgroup!=null)
353                                         {
354                                                 result.push(optgroup);
355                                                 previousGroup=null;
356                                                 optgroup=null;
357                                         }
358                                         optgroup = document.createElement('optgroup');
359                                         optgroup.label = group;
360                                         previousGroup = group;
361                                 }
362                         }
363                         var opt = document.createElement('option');
364                         opt.text = option[0];
365                         opt.innerHTML = option[0];
366                         opt.value = option[1];
367                         if(optgroup!=null)
368                                 optgroup.appendChild(opt);
369                         else
370                                 result.push(opt);
371                 }
372                 if(optgroup!=null)
373                         result.push(optgroup);
374                 return result;
375         },
376
377         /**
378          * Set focus (delayed) on a particular element.
379          * @function ?
380          * @param {string} element - Element id
381          */
382         focus : function(element)
383         {
384                 var obj = $(element);
385                 if(typeof(obj) != "undefined" && typeof(obj.focus) != "undefined")
386                         setTimeout(function(){ obj.focus(); }, 100);
387                 return false;
388         },
389
390         /**
391          * Replace a DOM element either with given content or
392          * with content from a CallBack response boundary
393          * using a replacement method.
394          * @function ?
395          * @param {string|element} element - DOM element or element id
396          * @param {string} method - Name of method to use for replacement
397          * @param {optional string} content - New content of element
398          * @param {optional string} boundary - Boundary of new content
399          */
400         replace : function(element, method, content, boundary)
401         {
402                 if(boundary)
403                 {
404                         var result = Prado.Element.extractContent(this.transport.responseText, boundary);
405                         if(result != null)
406                                 content = result;
407                 }
408                 if(typeof(element) == "string")
409                 {
410                         if($(element))
411                                 method.toFunction().apply(this,[element,""+content]);
412                 }
413                 else
414                 {
415                         method.toFunction().apply(this,[""+content]);
416                 }
417         },
418
419         /**
420          * Appends a javascript block to the document.
421          * @function ?
422          * @param {string} boundary - Boundary containing the javascript code
423          */
424         appendScriptBlock : function(boundary)
425         {
426                 var content = Prado.Element.extractContent(this.transport.responseText, boundary);
427                 if(content == null)
428                         return;
429
430                 var el   = document.createElement("script");
431                 el.type  = "text/javascript";
432                 el.id    = 'inline_' + boundary;
433                 el.text  = content;
434
435                 (document.getElementsByTagName('head')[0] || document.documentElement).appendChild(el);
436                 el.parentNode.removeChild(el);
437         },
438
439         /**
440          * Extract content from a text by its boundary id.
441          * Boundaries have this form:
442          * <pre>
443          * &lt;!--123456--&gt;Democontent&lt;!--//123456--&gt;
444          * </pre>
445          * @function {string} ?
446          * @param {string} text - Text that contains boundaries
447          * @param {string} boundary - Boundary id
448          * @returns Content from given boundaries
449          */
450         extractContent : function(text, boundary)
451         {
452                 var tagStart = '<!--'+boundary+'-->';
453                 var tagEnd = '<!--//'+boundary+'-->';
454                 var start = text.indexOf(tagStart);
455                 if(start > -1)
456                 {
457                         start += tagStart.length;
458                         var end = text.indexOf(tagEnd,start);
459                         if(end > -1)
460                                 return text.substring(start,end);
461                 }
462                 return null;
463                 /*var f = RegExp('(?:<!--'+boundary+'-->)((?:.|\n|\r)+?)(?:<!--//'+boundary+'-->)',"m");
464                 var result = text.match(f);
465                 if(result && result.length >= 2)
466                         return result[1];
467                 else
468                         return null;*/
469         },
470
471         /**
472          * Evaluate a javascript snippet from a string.
473          * @function ?
474          * @param {string} content - String containing the script
475          */
476         evaluateScript : function(content)
477         {
478                 try
479                 {
480                         content.evalScripts();
481                 }
482                 catch(e)
483                 {
484                         if(typeof(Logger) != "undefined")
485                                 Logger.error('Error during evaluation of script "'+content+'"');
486                         else
487                                 debugger;
488                         throw e;
489                 }
490         },
491         
492         /**
493          * Set CSS style with Camelized keys.
494          * See <a href="http://www.prototypejs.org/api/element/setstyle" target="_blank">Prototype's 
495          * Element.setStyle</a> for details.
496          * @function ?
497          * @param {string|element} element - DOM element or element id
498          * @param {object} styles - Object with style properties/values
499          */
500         setStyle : function (element, styles)
501         {
502                 var s = {}
503                 // Camelize all styles keys
504                 for (var property in styles)
505                 {
506                         s[property.camelize()]=styles[property].camelize();
507                 }
508                 Element.setStyle(element, s);
509         }
510 };
511
512 /**
513  * Utilities for selections.
514  * @object Prado.Element.Selection
515  */
516 Prado.Element.Selection =
517 {
518         /**
519          * Check if an DOM element can be selected.
520          * @function {boolean} ?
521          * @param {element} el - DOM elemet
522          * @returns true if element is selectable
523          */
524         isSelectable : function(el)
525         {
526                 if(el && el.type)
527                 {
528                         switch(el.type.toLowerCase())
529                         {
530                                 case 'checkbox':
531                                 case 'radio':
532                                 case 'select':
533                                 case 'select-multiple':
534                                 case 'select-one':
535                                 return true;
536                         }
537                 }
538                 return false;
539         },
540
541         /**
542          * Set checked attribute of a checkbox or radiobutton to value.
543          * @function {boolean} ?
544          * @param {element} el - DOM element
545          * @param {boolean} value - New value of checked attribute
546          * @returns New value of checked attribute
547          */
548         inputValue : function(el, value)
549         {
550                 switch(el.type.toLowerCase())
551                 {
552                         case 'checkbox':
553                         case 'radio':
554                         return el.checked = value;
555                 }
556         },
557
558         /**
559          * Set selected attribute for elements options by value.
560          * If value is boolean, all elements options selected attribute will be set
561          * to value. Otherwhise all options that have the given value will be selected. 
562          * @function ?
563          * @param {element[]} elements - Array of selectable DOM elements
564          * @param {boolean|string} value - Value of options that should be selected or boolean value of selection status
565          */
566         selectValue : function(elements, value)
567         {
568                 elements.each(function(el)
569                 {
570                         $A(el.options).each(function(option)
571                         {
572                                 if(typeof(value) == "boolean")
573                                         option.selected = value;
574                                 else if(option.value == value)
575                                         option.selected = true;
576                         });
577                 })
578         },
579
580         /**
581          * Set selected attribute for elements options by array of values.
582          * @function ?
583          * @param {element[]} elements - Array of selectable DOM elements
584          * @param {string[]} value - Array of values to select
585          */
586         selectValues : function(elements, values)
587         {
588                 var selection = this;
589                 values.each(function(value)
590                 {
591                         selection.selectValue(elements,value);
592                 })
593         },
594
595         /**
596          * Set selected attribute for elements options by option index.
597          * @function ?
598          * @param {element[]} elements - Array of selectable DOM elements
599          * @param {int} index - Index of option to select
600          */
601         selectIndex : function(elements, index)
602         {
603                 elements.each(function(el)
604                 {
605                         if(el.type.toLowerCase() == 'select-one')
606                                 el.selectedIndex = index;
607                         else
608                         {
609                                 for(var i = 0; i<el.length; i++)
610                                 {
611                                         if(i == index)
612                                                 el.options[i].selected = true;
613                                 }
614                         }
615                 })
616         },
617
618         /**
619          * Set selected attribute to true for all elements options.
620          * @function ?
621          * @param {element[]} elements - Array of selectable DOM elements
622          */
623         selectAll : function(elements)
624         {
625                 elements.each(function(el)
626                 {
627                         if(el.type.toLowerCase() != 'select-one')
628                         {
629                                 $A(el.options).each(function(option)
630                                 {
631                                         option.selected = true;
632                                 })
633                         }
634                 })
635         },
636
637         /**
638          * Toggle the selected attribute for elements options.
639          * @function ?
640          * @param {element[]} elements - Array of selectable DOM elements
641          */
642         selectInvert : function(elements)
643         {
644                 elements.each(function(el)
645                 {
646                         if(el.type.toLowerCase() != 'select-one')
647                         {
648                                 $A(el.options).each(function(option)
649                                 {
650                                         option.selected = !options.selected;
651                                 })
652                         }
653                 })
654         },
655
656         /**
657          * Set selected attribute for elements options by array of option indices.
658          * @function ?
659          * @param {element[]} elements - Array of selectable DOM elements
660          * @param {int[]} indices - Array of option indices to select
661          */
662         selectIndices : function(elements, indices)
663         {
664                 var selection = this;
665                 indices.each(function(index)
666                 {
667                         selection.selectIndex(elements,index);
668                 })
669         },
670
671         /**
672          * Unselect elements.
673          * @function ?
674          * @param {element[]} elements - Array of selectable DOM elements
675          */
676         selectClear : function(elements)
677         {
678                 elements.each(function(el)
679                 {
680                         el.selectedIndex = -1;
681                 })
682         },
683
684         /**
685          * Get list elements of an element.
686          * @function {element[]} ?
687          * @param {element[]} elements - Array of selectable DOM elements
688          * @param {int} total - Number of list elements to return
689          * @returns Array of list DOM elements
690          */
691         getListElements : function(element, total)
692         {
693                 var elements = new Array();
694                 var el;
695                 for(var i = 0; i < total; i++)
696                 {
697                         el = $(element+"_c"+i);
698                         if(el)
699                                 elements.push(el);
700                 }
701                 return elements;
702         },
703
704         /**
705          * Set checked attribute of elements by value.
706          * If value is boolean, checked attribute will be set to value. 
707          * Otherwhise all elements that have the given value will be checked. 
708          * @function ?
709          * @param {element[]} elements - Array of checkable DOM elements
710          * @param {boolean|String} value - Value that should be checked or boolean value of checked status
711          *       
712          */
713         checkValue : function(elements, value)
714         {
715                 elements.each(function(el)
716                 {
717                         if(typeof(value) == "boolean")
718                                 el.checked = value;
719                         else if(el.value == value)
720                                 el.checked = true;
721                 });
722         },
723
724         /**
725          * Set checked attribute of elements by array of values.
726          * @function ?
727          * @param {element[]} elements - Array of checkable DOM elements
728          * @param {string[]} values - Values that should be checked
729          *       
730          */
731         checkValues : function(elements, values)
732         {
733                 var selection = this;
734                 values.each(function(value)
735                 {
736                         selection.checkValue(elements, value);
737                 })
738         },
739
740         /**
741          * Set checked attribute of elements by list index.
742          * @function ?
743          * @param {element[]} elements - Array of checkable DOM elements
744          * @param {int} index - Index of element to set checked
745          */
746         checkIndex : function(elements, index)
747         {
748                 for(var i = 0; i<elements.length; i++)
749                 {
750                         if(i == index)
751                                 elements[i].checked = true;
752                 }
753         },
754
755         /**
756          * Set checked attribute of elements by array of list indices.
757          * @function ?
758          * @param {element[]} elements - Array of selectable DOM elements
759          * @param {int[]} indices - Array of list indices to set checked
760          */
761         checkIndices : function(elements, indices)
762         {
763                 var selection = this;
764                 indices.each(function(index)
765                 {
766                         selection.checkIndex(elements, index);
767                 })
768         },
769
770         /**
771          * Uncheck elements.
772          * @function ?
773          * @param {element[]} elements - Array of checkable DOM elements
774          */
775         checkClear : function(elements)
776         {
777                 elements.each(function(el)
778                 {
779                         el.checked = false;
780                 });
781         },
782
783         /**
784          * Set checked attribute of all elements to true.
785          * @function ?
786          * @param {element[]} elements - Array of checkable DOM elements
787          */
788         checkAll : function(elements)
789         {
790                 elements.each(function(el)
791                 {
792                         el.checked = true;
793                 })
794         },
795
796         /**
797          * Toggle the checked attribute of elements.
798          * @function ?
799          * @param {element[]} elements - Array of selectable DOM elements
800          */
801         checkInvert : function(elements)
802         {
803                 elements.each(function(el)
804                 {
805                         el.checked != el.checked;
806                 })
807         }
808 };
809
810
811 /**
812  * Utilities for insertion.
813  * @object Prado.Element.Insert
814  */
815 Prado.Element.Insert =
816 {
817         /**
818          * Append content to element
819          * @function ?
820          * @param {element} element - DOM element that content should be appended to
821          * @param {element} content - DOM element to append
822          */
823         append: function(element, content)
824         {
825                 $(element).insert(content);
826         },
827
828         /**
829          * Prepend content to element
830          * @function ?
831          * @param {element} element - DOM element that content should be prepended to
832          * @param {element} content - DOM element to prepend
833          */
834         prepend: function(element, content)
835         {
836                 $(element).insert({top:content});
837         },
838
839         /**
840          * Insert content after element
841          * @function ?
842          * @param {element} element - DOM element that content should be inserted after
843          * @param {element} content - DOM element to insert
844          */
845         after: function(element, content)
846         {
847                 $(element).insert({after:content});
848         },
849
850         /**
851          * Insert content before element
852          * @function ?
853          * @param {element} element - DOM element that content should be inserted before
854          * @param {element} content - DOM element to insert
855          */
856         before: function(element, content)
857         {
858                 $(element).insert({before:content});
859         }
860 };
861
862
863 /**
864  * Extension to 
865  * <a href="http://wiki.script.aculo.us/scriptaculous/show/builder" target="_blank">Scriptaculous' Builder</a>
866  * @namespace Builder
867  */
868
869 Object.extend(Builder,
870 {
871         /**
872          * Export scriptaculous builder utilities as window[functions]
873          * @function ?
874          */
875         exportTags:function()
876         {
877                 var tags=["BUTTON","TT","PRE","H1","H2","H3","BR","CANVAS","HR","LABEL","TEXTAREA","FORM","STRONG","SELECT","OPTION","OPTGROUP","LEGEND","FIELDSET","P","UL","OL","LI","TD","TR","THEAD","TBODY","TFOOT","TABLE","TH","INPUT","SPAN","A","DIV","IMG", "CAPTION"];
878                 tags.each(function(tag)
879                 {
880                         window[tag]=function()
881                         {
882                                 var args=$A(arguments);
883                                 if(args.length==0)
884                                         return Builder.node(tag,null);
885                                 if(args.length==1)
886                                         return Builder.node(tag,args[0]);
887                                 if(args.length>1)
888                                         return Builder.node(tag,args.shift(),args);
889
890                         };
891                 });
892         }
893 });
894 Builder.exportTags();
895
896 /**
897  * Extension to 
898  * <a href="http://www.prototypejs.org/api/string" target="_blank">Prototype's String</a>
899  * @namespace String
900  */
901 Object.extend(String.prototype, {
902
903         /**
904          * Add padding to string
905          * @function {string} ?
906          * @param {string} side - "left" to pad the string on the left, "right" to pad right.
907          * @param {int} len - Minimum string length.
908          * @param {string} chr - Character(s) to pad
909          * @returns Padded string
910          */
911         pad : function(side, len, chr) {
912                 if (!chr) chr = ' ';
913                 var s = this;
914                 var left = side.toLowerCase()=='left';
915                 while (s.length<len) s = left? chr + s : s + chr;
916                 return s;
917         },
918
919         /**
920          * Add left padding to string
921          * @function {string} ?
922          * @param {int} len - Minimum string length.
923          * @param {string} chr - Character(s) to pad
924          * @returns Padded string
925          */
926         padLeft : function(len, chr) {
927                 return this.pad('left',len,chr);
928         },
929
930         /**
931          * Add right padding to string
932          * @function {string} ?
933          * @param {int} len - Minimum string length.
934          * @param {string} chr - Character(s) to pad
935          * @returns Padded string
936          */
937         padRight : function(len, chr) {
938                 return this.pad('right',len,chr);
939         },
940
941         /**
942          * Add zeros to the right of string
943          * @function {string} ?
944          * @param {int} len - Minimum string length.
945          * @returns Padded string
946          */
947         zerofill : function(len) {
948                 return this.padLeft(len,'0');
949         },
950
951         /**
952          * Remove white spaces from both ends of string.
953          * @function {string} ?
954          * @returns Trimmed string
955          */
956         trim : function() {
957                 return this.replace(/^\s+|\s+$/g,'');
958         },
959
960         /**
961          * Remove white spaces from the left side of string.
962          * @function {string} ?
963          * @returns Trimmed string
964          */
965         trimLeft : function() {
966                 return this.replace(/^\s+/,'');
967         },
968
969         /**
970          * Remove white spaces from the right side of string.
971          * @function {string} ?
972          * @returns Trimmed string
973          */
974         trimRight : function() {
975                 return this.replace(/\s+$/,'');
976         },
977
978         /**
979          * Convert period separated function names into a function reference.
980          * <br />Example:
981          * <pre> 
982          * "Prado.AJAX.Callback.Action.setValue".toFunction()
983          * </pre>
984          * @function {function} ?
985          * @returns Reference to the corresponding function
986          */
987         toFunction : function()
988         {
989                 var commands = this.split(/\./);
990                 var command = window;
991                 commands.each(function(action)
992                 {
993                         if(command[new String(action)])
994                                 command=command[new String(action)];
995                 });
996                 if(typeof(command) == "function")
997                         return command;
998                 else
999                 {
1000                         if(typeof Logger != "undefined")
1001                                 Logger.error("Missing function", this);
1002
1003                         throw new Error ("Missing function '"+this+"'");
1004                 }
1005         },
1006
1007         /**
1008          * Convert string into integer, returns null if not integer.
1009          * @function {int} ?
1010          * @returns Integer, null if string does not represent an integer.
1011          */
1012         toInteger : function()
1013         {
1014                 var exp = /^\s*[-\+]?\d+\s*$/;
1015                 if (this.match(exp) == null)
1016                         return null;
1017                 var num = parseInt(this, 10);
1018                 return (isNaN(num) ? null : num);
1019         },
1020
1021         /**
1022          * Convert string into a double/float value. <b>Internationalization
1023          * is not supported</b>
1024          * @function {double} ?
1025          * @param {string} decimalchar - Decimal character, defaults to "."
1026          * @returns Double, null if string does not represent a float value
1027          */
1028         toDouble : function(decimalchar)
1029         {
1030                 if(this.length <= 0) return null;
1031                 decimalchar = decimalchar || ".";
1032                 var exp = new RegExp("^\\s*([-\\+])?(\\d+)?(\\" + decimalchar + "(\\d+))?\\s*$");
1033                 var m = this.match(exp);
1034
1035                 if (m == null)
1036                         return null;
1037                 m[1] = m[1] || "";
1038                 m[2] = m[2] || "0";
1039                 m[4] = m[4] || "0";
1040
1041                 var cleanInput = m[1] + (m[2].length>0 ? m[2] : "0") + "." + m[4];
1042                 var num = parseFloat(cleanInput);
1043                 return (isNaN(num) ? null : num);
1044         },
1045
1046         /**
1047          * Convert strings that represent a currency value to float.
1048          * E.g. "10,000.50" will become "10000.50". The number
1049          * of dicimal digits, grouping and decimal characters can be specified.
1050          * <i>The currency input format is <b>very</b> strict, null will be returned if
1051          * the pattern does not match</i>.
1052          * @function {double} ?
1053          * @param {string} groupchar - Grouping character, defaults to ","
1054          * @param {int} digits - Number of decimal digits
1055          * @param {string} decimalchar - Decimal character, defaults to "."
1056          * @returns Double, null if string does not represent a currency value
1057          */
1058         toCurrency : function(groupchar, digits, decimalchar)
1059         {
1060                 groupchar = groupchar || ",";
1061                 decimalchar = decimalchar || ".";
1062                 digits = typeof(digits) == "undefined" ? 2 : digits;
1063
1064                 var exp = new RegExp("^\\s*([-\\+])?(((\\d+)\\" + groupchar + ")*)(\\d+)"
1065                         + ((digits > 0) ? "(\\" + decimalchar + "(\\d{1," + digits + "}))?" : "")
1066                         + "\\s*$");
1067                 var m = this.match(exp);
1068                 if (m == null)
1069                         return null;
1070                 var intermed = m[2] + m[5] ;
1071                 var cleanInput = m[1] + intermed.replace(
1072                                 new RegExp("(\\" + groupchar + ")", "g"), "")
1073                                                                 + ((digits > 0) ? "." + m[7] : "");
1074                 var num = parseFloat(cleanInput);
1075                 return (isNaN(num) ? null : num);
1076         },
1077
1078         /**
1079          * Converts the string to a date by finding values that matches the
1080          * date format pattern.
1081          * @function {Date} ?
1082          * @param {string} format - Date format pattern, e.g. MM-dd-yyyy
1083          * @returns Date extracted from the string
1084          */
1085         toDate : function(format)
1086         {
1087                 return Date.SimpleParse(this, format);
1088         }
1089 });
1090
1091 /**
1092  * Extension to 
1093  * <a href="http://www.prototypejs.org/api/event" target="_blank">Prototype's Event</a>
1094  * @namespace Event
1095  */
1096 Object.extend(Event,
1097 {
1098         /**
1099          * Register a function to be executed when the page is loaded.
1100          * Note that the page is only loaded if all resources (e.g. images)
1101          * are loaded.
1102          * <br />Example: 
1103          * <br />Show an alert box with message "Page Loaded!" when the
1104          * page finished loading.
1105          * <pre>
1106          * Event.OnLoad(function(){ alert("Page Loaded!"); });
1107          * </pre>
1108          * @function ?
1109          * @param {function} fn - Function to execute when page is loaded.
1110          */
1111         OnLoad : function (fn)
1112         {
1113                 // opera onload is in document, not window
1114                 var w = document.addEventListener &&
1115                                         !window.addEventListener ? document : window;
1116                 Event.observe(w,'load',fn);
1117         },
1118
1119         /**
1120          * Returns the unicode character generated by key.
1121          * @param {event} e - Keyboard event
1122          * @function {int} ?
1123          * @returns Unicode character code generated by the key that was struck.
1124          */
1125         keyCode : function(e)
1126         {
1127            return e.keyCode != null ? e.keyCode : e.charCode
1128         },
1129
1130         /**
1131          * Checks if an Event is of type HTMLEvent.
1132          * @function {boolean} ?
1133          * @param {string} type - Event type or event name.
1134          * @return true if event is of type HTMLEvent.
1135          */
1136         isHTMLEvent : function(type)
1137         {
1138                 var events = ['abort', 'blur', 'change', 'error', 'focus',
1139                                         'load', 'reset', 'resize', 'scroll', 'select',
1140                                         'submit', 'unload'];
1141                 return events.include(type);
1142         },
1143
1144         /**
1145          * Checks if an Event is a mouse event.
1146          * @function {boolean} ?
1147          * @param {string} type - Event type or event name
1148          * @return true if event is of type MouseEvent.
1149          */
1150         isMouseEvent : function(type)
1151         {
1152                 var events = ['click', 'mousedown', 'mousemove', 'mouseout',
1153                                         'mouseover', 'mouseup'];
1154                 return events.include(type);
1155         },
1156
1157         /**
1158          * Dispatch the DOM event of a given <tt>type</tt> on a DOM
1159          * <tt>element</tt>. Only HTMLEvent and MouseEvent can be
1160          * dispatched, keyboard events or UIEvent can not be dispatch
1161          * via javascript consistently.
1162          * For the "submit" event the submit() method is called.
1163          * @function ?
1164          * @param {element|string} element - Element id string or DOM element.
1165          * @param {string} type - Event type to dispatch.
1166          */
1167         fireEvent : function(element,type)
1168         {
1169                 element = $(element);
1170                 if(type == "submit")
1171                         return element.submit();
1172                 if(document.createEvent)
1173         {
1174                         if(Event.isHTMLEvent(type))
1175                         {
1176                                 var event = document.createEvent('HTMLEvents');
1177                     event.initEvent(type, true, true);
1178                         }
1179                         else if(Event.isMouseEvent(type))
1180                         {
1181                                 var event = document.createEvent('MouseEvents');
1182                                 if (event.initMouseEvent)
1183                         {
1184                                         event.initMouseEvent(type,true,true,
1185                                                 document.defaultView, 1, 0, 0, 0, 0, false,
1186                                                                 false, false, false, 0, null);
1187                         }
1188                         else
1189                         {
1190                             // Safari
1191                             // TODO we should be initialising other mouse-event related attributes here
1192                             event.initEvent(type, true, true);
1193                         }
1194                         }
1195             element.dispatchEvent(event);
1196         }
1197         else if(document.createEventObject)
1198         {
1199                 var evObj = document.createEventObject();
1200             element.fireEvent('on'+type, evObj);
1201         }
1202         else if(typeof(element['on'+type]) == "function")
1203             element['on'+type]();
1204         }
1205 });
1206
1207
1208 /**
1209  * Extension to 
1210  * <a href="http://www.prototypejs.org/api/date" target="_blank">Prototype's Date</a>
1211  * @namespace Date
1212  */
1213 Object.extend(Date.prototype,
1214 {
1215         /**
1216          * SimpleFormat
1217          * @function ?
1218          * @param {string} format - TODO
1219          * @param {string} data - TODO
1220          * @returns TODO
1221          */
1222         SimpleFormat: function(format, data)
1223         {
1224                 data = data || {};
1225                 var bits = new Array();
1226                 bits['d'] = this.getDate();
1227                 bits['dd'] = String(this.getDate()).zerofill(2);
1228
1229                 bits['M'] = this.getMonth()+1;
1230                 bits['MM'] = String(this.getMonth()+1).zerofill(2);
1231                 if(data.AbbreviatedMonthNames)
1232                         bits['MMM'] = data.AbbreviatedMonthNames[this.getMonth()];
1233                 if(data.MonthNames)
1234                         bits['MMMM'] = data.MonthNames[this.getMonth()];
1235                 var yearStr = "" + this.getFullYear();
1236                 yearStr = (yearStr.length == 2) ? '19' + yearStr: yearStr;
1237                 bits['yyyy'] = yearStr;
1238                 bits['yy'] = bits['yyyy'].toString().substr(2,2);
1239
1240                 // do some funky regexs to replace the format string
1241                 // with the real values
1242                 var frm = new String(format);
1243                 for (var sect in bits)
1244                 {
1245                         var reg = new RegExp("\\b"+sect+"\\b" ,"g");
1246                         frm = frm.replace(reg, bits[sect]);
1247                 }
1248                 return frm;
1249         },
1250
1251         /**
1252          * toISODate
1253          * @function {string} ?
1254          * @returns TODO
1255          */
1256         toISODate : function()
1257         {
1258                 var y = this.getFullYear();
1259                 var m = String(this.getMonth() + 1).zerofill(2);
1260                 var d = String(this.getDate()).zerofill(2);
1261                 return String(y) + String(m) + String(d);
1262         }
1263 });
1264
1265 Object.extend(Date,
1266 {
1267         /**
1268          * SimpleParse
1269          * @function ?
1270          * @param {string} format - TODO
1271          * @param {string} data - TODO
1272          * @returns TODO
1273          */
1274         SimpleParse: function(value, format)
1275         {
1276                 var val=String(value);
1277                 format=String(format);
1278
1279                 if(val.length <= 0) return null;
1280
1281                 if(format.length <= 0) return new Date(value);
1282
1283                 var isInteger = function (val)
1284                 {
1285                         var digits="1234567890";
1286                         for (var i=0; i < val.length; i++)
1287                         {
1288                                 if (digits.indexOf(val.charAt(i))==-1) { return false; }
1289                         }
1290                         return true;
1291                 };
1292
1293                 var getInt = function(str,i,minlength,maxlength)
1294                 {
1295                         for (var x=maxlength; x>=minlength; x--)
1296                         {
1297                                 var token=str.substring(i,i+x);
1298                                 if (token.length < minlength) { return null; }
1299                                 if (isInteger(token)) { return token; }
1300                         }
1301                         return null;
1302                 };
1303
1304                 var i_val=0;
1305                 var i_format=0;
1306                 var c="";
1307                 var token="";
1308                 var token2="";
1309                 var x,y;
1310                 var now=new Date();
1311                 var year=now.getFullYear();
1312                 var month=now.getMonth()+1;
1313                 var date=1;
1314
1315                 while (i_format < format.length)
1316                 {
1317                         // Get next token from format string
1318                         c=format.charAt(i_format);
1319                         token="";
1320                         while ((format.charAt(i_format)==c) && (i_format < format.length))
1321                         {
1322                                 token += format.charAt(i_format++);
1323                         }
1324
1325                         // Extract contents of value based on format token
1326                         if (token=="yyyy" || token=="yy" || token=="y")
1327                         {
1328                                 if (token=="yyyy") { x=4;y=4; }
1329                                 if (token=="yy")   { x=2;y=2; }
1330                                 if (token=="y")    { x=2;y=4; }
1331                                 year=getInt(val,i_val,x,y);
1332                                 if (year==null) { return null; }
1333                                 i_val += year.length;
1334                                 if (year.length==2)
1335                                 {
1336                                         if (year > 70) { year=1900+(year-0); }
1337                                         else { year=2000+(year-0); }
1338                                 }
1339                         }
1340
1341                         else if (token=="MM"||token=="M")
1342                         {
1343                                 month=getInt(val,i_val,token.length,2);
1344                                 if(month==null||(month<1)||(month>12)){return null;}
1345                                 i_val+=month.length;
1346                         }
1347                         else if (token=="dd"||token=="d")
1348                         {
1349                                 date=getInt(val,i_val,token.length,2);
1350                                 if(date==null||(date<1)||(date>31)){return null;}
1351                                 i_val+=date.length;
1352                         }
1353                         else
1354                         {
1355                                 if (val.substring(i_val,i_val+token.length)!=token) {return null;}
1356                                 else {i_val+=token.length;}
1357                         }
1358                 }
1359
1360                 // If there are any trailing characters left in the value, it doesn't match
1361                 if (i_val != val.length) { return null; }
1362
1363                 // Is date valid for month?
1364                 if (month==2)
1365                 {
1366                         // Check for leap year
1367                         if ( ( (year%4==0)&&(year%100 != 0) ) || (year%400==0) ) { // leap year
1368                                 if (date > 29){ return null; }
1369                         }
1370                         else { if (date > 28) { return null; } }
1371                 }
1372
1373                 if ((month==4)||(month==6)||(month==9)||(month==11))
1374                 {
1375                         if (date > 30) { return null; }
1376                 }
1377
1378                 var newdate=new Date(year,month-1,date, 0, 0, 0);
1379                 return newdate;
1380         }
1381 });
1382
1383 /**
1384  * Prado utilities for effects.
1385  * @object Prado.Effect
1386  */
1387 Prado.Effect = 
1388 {
1389         /**
1390          * Highlights an element
1391          * @function ?
1392          * @param {element} element - DOM element to highlight
1393          * @param {optional object} options - Highlight options
1394          */
1395         Highlight : function (element,options)
1396         {
1397                 new Effect.Highlight(element,options);
1398         }
1399 };