]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - include/javascript/yui/build/element/element.js
Release 6.2.0beta4
[Github/sugarcrm.git] / include / javascript / yui / build / element / element.js
1 /*
2 Copyright (c) 2009, Yahoo! Inc. All rights reserved.
3 Code licensed under the BSD License:
4 http://developer.yahoo.net/yui/license.txt
5 version: 2.8.0r4
6 */
7 /**
8  * Provides Attribute configurations.
9  * @namespace YAHOO.util
10  * @class Attribute
11  * @constructor
12  * @param hash {Object} The intial Attribute.
13  * @param {YAHOO.util.AttributeProvider} The owner of the Attribute instance.
14  */
15
16 YAHOO.util.Attribute = function(hash, owner) {
17     if (owner) { 
18         this.owner = owner;
19         this.configure(hash, true);
20     }
21 };
22
23 YAHOO.util.Attribute.prototype = {
24     /**
25      * The name of the attribute.
26      * @property name
27      * @type String
28      */
29     name: undefined,
30     
31     /**
32      * The value of the attribute.
33      * @property value
34      * @type String
35      */
36     value: null,
37     
38     /**
39      * The owner of the attribute.
40      * @property owner
41      * @type YAHOO.util.AttributeProvider
42      */
43     owner: null,
44     
45     /**
46      * Whether or not the attribute is read only.
47      * @property readOnly
48      * @type Boolean
49      */
50     readOnly: false,
51     
52     /**
53      * Whether or not the attribute can only be written once.
54      * @property writeOnce
55      * @type Boolean
56      */
57     writeOnce: false,
58
59     /**
60      * The attribute's initial configuration.
61      * @private
62      * @property _initialConfig
63      * @type Object
64      */
65     _initialConfig: null,
66     
67     /**
68      * Whether or not the attribute's value has been set.
69      * @private
70      * @property _written
71      * @type Boolean
72      */
73     _written: false,
74     
75     /**
76      * A function to call when setting the attribute's value.
77      * The method receives the new value as the first arg and the attribute name as the 2nd
78      * @property method
79      * @type Function
80      */
81     method: null,
82     
83     /**
84      * The function to use when setting the attribute's value.
85      * The setter receives the new value as the first arg and the attribute name as the 2nd
86      * The return value of the setter replaces the value passed to set(). 
87      * @property setter
88      * @type Function
89      */
90     setter: null,
91     
92     /**
93      * The function to use when getting the attribute's value.
94      * The getter receives the new value as the first arg and the attribute name as the 2nd
95      * The return value of the getter will be used as the return from get().
96      * @property getter
97      * @type Function
98      */
99     getter: null,
100
101     /**
102      * The validator to use when setting the attribute's value.
103      * @property validator
104      * @type Function
105      * @return Boolean
106      */
107     validator: null,
108     
109     /**
110      * Retrieves the current value of the attribute.
111      * @method getValue
112      * @return {any} The current value of the attribute.
113      */
114     getValue: function() {
115         var val = this.value;
116
117         if (this.getter) {
118             val = this.getter.call(this.owner, this.name, val);
119         }
120
121         return val;
122     },
123     
124     /**
125      * Sets the value of the attribute and fires beforeChange and change events.
126      * @method setValue
127      * @param {Any} value The value to apply to the attribute.
128      * @param {Boolean} silent If true the change events will not be fired.
129      * @return {Boolean} Whether or not the value was set.
130      */
131     setValue: function(value, silent) {
132         var beforeRetVal,
133             owner = this.owner,
134             name = this.name;
135         
136         var event = {
137             type: name, 
138             prevValue: this.getValue(),
139             newValue: value
140         };
141         
142         if (this.readOnly || ( this.writeOnce && this._written) ) {
143             return false; // write not allowed
144         }
145         
146         if (this.validator && !this.validator.call(owner, value) ) {
147             return false; // invalid value
148         }
149
150         if (!silent) {
151             beforeRetVal = owner.fireBeforeChangeEvent(event);
152             if (beforeRetVal === false) {
153                 return false;
154             }
155         }
156
157         if (this.setter) {
158             value = this.setter.call(owner, value, this.name);
159             if (value === undefined) {
160             }
161         }
162         
163         if (this.method) {
164             this.method.call(owner, value, this.name);
165         }
166         
167         this.value = value; // TODO: set before calling setter/method?
168         this._written = true;
169         
170         event.type = name;
171         
172         if (!silent) {
173             this.owner.fireChangeEvent(event);
174         }
175         
176         return true;
177     },
178     
179     /**
180      * Allows for configuring the Attribute's properties.
181      * @method configure
182      * @param {Object} map A key-value map of Attribute properties.
183      * @param {Boolean} init Whether or not this should become the initial config.
184      */
185     configure: function(map, init) {
186         map = map || {};
187
188         if (init) {
189             this._written = false; // reset writeOnce
190         }
191
192         this._initialConfig = this._initialConfig || {};
193         
194         for (var key in map) {
195             if ( map.hasOwnProperty(key) ) {
196                 this[key] = map[key];
197                 if (init) {
198                     this._initialConfig[key] = map[key];
199                 }
200             }
201         }
202     },
203     
204     /**
205      * Resets the value to the initial config value.
206      * @method resetValue
207      * @return {Boolean} Whether or not the value was set.
208      */
209     resetValue: function() {
210         return this.setValue(this._initialConfig.value);
211     },
212     
213     /**
214      * Resets the attribute config to the initial config state.
215      * @method resetConfig
216      */
217     resetConfig: function() {
218         this.configure(this._initialConfig, true);
219     },
220     
221     /**
222      * Resets the value to the current value.
223      * Useful when values may have gotten out of sync with actual properties.
224      * @method refresh
225      * @return {Boolean} Whether or not the value was set.
226      */
227     refresh: function(silent) {
228         this.setValue(this.value, silent);
229     }
230 };
231
232 (function() {
233     var Lang = YAHOO.util.Lang;
234
235     /*
236     Copyright (c) 2006, Yahoo! Inc. All rights reserved.
237     Code licensed under the BSD License:
238     http://developer.yahoo.net/yui/license.txt
239     */
240     
241     /**
242      * Provides and manages YAHOO.util.Attribute instances
243      * @namespace YAHOO.util
244      * @class AttributeProvider
245      * @uses YAHOO.util.EventProvider
246      */
247     YAHOO.util.AttributeProvider = function() {};
248
249     YAHOO.util.AttributeProvider.prototype = {
250         
251         /**
252          * A key-value map of Attribute configurations
253          * @property _configs
254          * @protected (may be used by subclasses and augmentors)
255          * @private
256          * @type {Object}
257          */
258         _configs: null,
259         /**
260          * Returns the current value of the attribute.
261          * @method get
262          * @param {String} key The attribute whose value will be returned.
263          * @return {Any} The current value of the attribute.
264          */
265         get: function(key){
266             this._configs = this._configs || {};
267             var config = this._configs[key];
268             
269             if (!config || !this._configs.hasOwnProperty(key)) {
270                 return null;
271             }
272             
273             return config.getValue();
274         },
275         
276         /**
277          * Sets the value of a config.
278          * @method set
279          * @param {String} key The name of the attribute
280          * @param {Any} value The value to apply to the attribute
281          * @param {Boolean} silent Whether or not to suppress change events
282          * @return {Boolean} Whether or not the value was set.
283          */
284         set: function(key, value, silent){
285             this._configs = this._configs || {};
286             var config = this._configs[key];
287             
288             if (!config) {
289                 return false;
290             }
291             
292             return config.setValue(value, silent);
293         },
294     
295         /**
296          * Returns an array of attribute names.
297          * @method getAttributeKeys
298          * @return {Array} An array of attribute names.
299          */
300         getAttributeKeys: function(){
301             this._configs = this._configs;
302             var keys = [], key;
303
304             for (key in this._configs) {
305                 if ( Lang.hasOwnProperty(this._configs, key) && 
306                         !Lang.isUndefined(this._configs[key]) ) {
307                     keys[keys.length] = key;
308                 }
309             }
310             
311             return keys;
312         },
313         
314         /**
315          * Sets multiple attribute values.
316          * @method setAttributes
317          * @param {Object} map  A key-value map of attributes
318          * @param {Boolean} silent Whether or not to suppress change events
319          */
320         setAttributes: function(map, silent){
321             for (var key in map) {
322                 if ( Lang.hasOwnProperty(map, key) ) {
323                     this.set(key, map[key], silent);
324                 }
325             }
326         },
327     
328         /**
329          * Resets the specified attribute's value to its initial value.
330          * @method resetValue
331          * @param {String} key The name of the attribute
332          * @param {Boolean} silent Whether or not to suppress change events
333          * @return {Boolean} Whether or not the value was set
334          */
335         resetValue: function(key, silent){
336             this._configs = this._configs || {};
337             if (this._configs[key]) {
338                 this.set(key, this._configs[key]._initialConfig.value, silent);
339                 return true;
340             }
341             return false;
342         },
343     
344         /**
345          * Sets the attribute's value to its current value.
346          * @method refresh
347          * @param {String | Array} key The attribute(s) to refresh
348          * @param {Boolean} silent Whether or not to suppress change events
349          */
350         refresh: function(key, silent) {
351             this._configs = this._configs || {};
352             var configs = this._configs;
353             
354             key = ( ( Lang.isString(key) ) ? [key] : key ) || 
355                     this.getAttributeKeys();
356             
357             for (var i = 0, len = key.length; i < len; ++i) { 
358                 if (configs.hasOwnProperty(key[i])) {
359                     this._configs[key[i]].refresh(silent);
360                 }
361             }
362         },
363     
364         /**
365          * Adds an Attribute to the AttributeProvider instance. 
366          * @method register
367          * @param {String} key The attribute's name
368          * @param {Object} map A key-value map containing the
369          * attribute's properties.
370          * @deprecated Use setAttributeConfig
371          */
372         register: function(key, map) {
373             this.setAttributeConfig(key, map);
374         },
375         
376         
377         /**
378          * Returns the attribute's properties.
379          * @method getAttributeConfig
380          * @param {String} key The attribute's name
381          * @private
382          * @return {object} A key-value map containing all of the
383          * attribute's properties.
384          */
385         getAttributeConfig: function(key) {
386             this._configs = this._configs || {};
387             var config = this._configs[key] || {};
388             var map = {}; // returning a copy to prevent overrides
389             
390             for (key in config) {
391                 if ( Lang.hasOwnProperty(config, key) ) {
392                     map[key] = config[key];
393                 }
394             }
395     
396             return map;
397         },
398         
399         /**
400          * Sets or updates an Attribute instance's properties. 
401          * @method setAttributeConfig
402          * @param {String} key The attribute's name.
403          * @param {Object} map A key-value map of attribute properties
404          * @param {Boolean} init Whether or not this should become the intial config.
405          */
406         setAttributeConfig: function(key, map, init) {
407             this._configs = this._configs || {};
408             map = map || {};
409             if (!this._configs[key]) {
410                 map.name = key;
411                 this._configs[key] = this.createAttribute(map);
412             } else {
413                 this._configs[key].configure(map, init);
414             }
415         },
416         
417         /**
418          * Sets or updates an Attribute instance's properties. 
419          * @method configureAttribute
420          * @param {String} key The attribute's name.
421          * @param {Object} map A key-value map of attribute properties
422          * @param {Boolean} init Whether or not this should become the intial config.
423          * @deprecated Use setAttributeConfig
424          */
425         configureAttribute: function(key, map, init) {
426             this.setAttributeConfig(key, map, init);
427         },
428         
429         /**
430          * Resets an attribute to its intial configuration. 
431          * @method resetAttributeConfig
432          * @param {String} key The attribute's name.
433          * @private
434          */
435         resetAttributeConfig: function(key){
436             this._configs = this._configs || {};
437             this._configs[key].resetConfig();
438         },
439         
440         // wrapper for EventProvider.subscribe
441         // to create events on the fly
442         subscribe: function(type, callback) {
443             this._events = this._events || {};
444
445             if ( !(type in this._events) ) {
446                 this._events[type] = this.createEvent(type);
447             }
448
449             YAHOO.util.EventProvider.prototype.subscribe.apply(this, arguments);
450         },
451
452         on: function() {
453             this.subscribe.apply(this, arguments);
454         },
455
456         addListener: function() {
457             this.subscribe.apply(this, arguments);
458         },
459
460         /**
461          * Fires the attribute's beforeChange event. 
462          * @method fireBeforeChangeEvent
463          * @param {String} key The attribute's name.
464          * @param {Obj} e The event object to pass to handlers.
465          */
466         fireBeforeChangeEvent: function(e) {
467             var type = 'before';
468             type += e.type.charAt(0).toUpperCase() + e.type.substr(1) + 'Change';
469             e.type = type;
470             return this.fireEvent(e.type, e);
471         },
472         
473         /**
474          * Fires the attribute's change event. 
475          * @method fireChangeEvent
476          * @param {String} key The attribute's name.
477          * @param {Obj} e The event object to pass to the handlers.
478          */
479         fireChangeEvent: function(e) {
480             e.type += 'Change';
481             return this.fireEvent(e.type, e);
482         },
483
484         createAttribute: function(map) {
485             return new YAHOO.util.Attribute(map, this);
486         }
487     };
488     
489     YAHOO.augment(YAHOO.util.AttributeProvider, YAHOO.util.EventProvider);
490 })();
491
492 (function() {
493 // internal shorthand
494 var Dom = YAHOO.util.Dom,
495     AttributeProvider = YAHOO.util.AttributeProvider,
496         specialTypes = {
497                 mouseenter: true,
498                 mouseleave: true
499         };
500
501 /**
502  * Element provides an wrapper object to simplify adding
503  * event listeners, using dom methods, and managing attributes. 
504  * @module element
505  * @namespace YAHOO.util
506  * @requires yahoo, dom, event
507  */
508
509 /**
510  * Element provides an wrapper object to simplify adding
511  * event listeners, using dom methods, and managing attributes. 
512  * @class Element
513  * @uses YAHOO.util.AttributeProvider
514  * @constructor
515  * @param el {HTMLElement | String} The html element that 
516  * represents the Element.
517  * @param {Object} map A key-value map of initial config names and values
518  */
519 var Element = function(el, map) {
520     this.init.apply(this, arguments);
521 };
522
523 Element.DOM_EVENTS = {
524     'click': true,
525     'dblclick': true,
526     'keydown': true,
527     'keypress': true,
528     'keyup': true,
529     'mousedown': true,
530     'mousemove': true,
531     'mouseout': true, 
532     'mouseover': true, 
533     'mouseup': true,
534     'mouseenter': true, 
535     'mouseleave': true,
536     'focus': true,
537     'blur': true,
538     'submit': true,
539     'change': true
540 };
541
542 Element.prototype = {
543     /**
544      * Dom events supported by the Element instance.
545      * @property DOM_EVENTS
546      * @type Object
547      */
548     DOM_EVENTS: null,
549
550     DEFAULT_HTML_SETTER: function(value, key) {
551         var el = this.get('element');
552         
553         if (el) {
554             el[key] = value;
555         }
556
557                 return value;
558
559     },
560
561     DEFAULT_HTML_GETTER: function(key) {
562         var el = this.get('element'),
563             val;
564
565         if (el) {
566             val = el[key];
567         }
568
569         return val;
570     },
571
572     /**
573      * Wrapper for HTMLElement method.
574      * @method appendChild
575      * @param {YAHOO.util.Element || HTMLElement} child The element to append. 
576      * @return {HTMLElement} The appended DOM element. 
577      */
578     appendChild: function(child) {
579         child = child.get ? child.get('element') : child;
580         return this.get('element').appendChild(child);
581     },
582     
583     /**
584      * Wrapper for HTMLElement method.
585      * @method getElementsByTagName
586      * @param {String} tag The tagName to collect
587      * @return {HTMLCollection} A collection of DOM elements. 
588      */
589     getElementsByTagName: function(tag) {
590         return this.get('element').getElementsByTagName(tag);
591     },
592     
593     /**
594      * Wrapper for HTMLElement method.
595      * @method hasChildNodes
596      * @return {Boolean} Whether or not the element has childNodes
597      */
598     hasChildNodes: function() {
599         return this.get('element').hasChildNodes();
600     },
601     
602     /**
603      * Wrapper for HTMLElement method.
604      * @method insertBefore
605      * @param {HTMLElement} element The HTMLElement to insert
606      * @param {HTMLElement} before The HTMLElement to insert
607      * the element before.
608      * @return {HTMLElement} The inserted DOM element. 
609      */
610     insertBefore: function(element, before) {
611         element = element.get ? element.get('element') : element;
612         before = (before && before.get) ? before.get('element') : before;
613         
614         return this.get('element').insertBefore(element, before);
615     },
616     
617     /**
618      * Wrapper for HTMLElement method.
619      * @method removeChild
620      * @param {HTMLElement} child The HTMLElement to remove
621      * @return {HTMLElement} The removed DOM element. 
622      */
623     removeChild: function(child) {
624         child = child.get ? child.get('element') : child;
625         return this.get('element').removeChild(child);
626     },
627     
628     /**
629      * Wrapper for HTMLElement method.
630      * @method replaceChild
631      * @param {HTMLElement} newNode The HTMLElement to insert
632      * @param {HTMLElement} oldNode The HTMLElement to replace
633      * @return {HTMLElement} The replaced DOM element. 
634      */
635     replaceChild: function(newNode, oldNode) {
636         newNode = newNode.get ? newNode.get('element') : newNode;
637         oldNode = oldNode.get ? oldNode.get('element') : oldNode;
638         return this.get('element').replaceChild(newNode, oldNode);
639     },
640
641     
642     /**
643      * Registers Element specific attributes.
644      * @method initAttributes
645      * @param {Object} map A key-value map of initial attribute configs
646      */
647     initAttributes: function(map) {
648     },
649
650     /**
651      * Adds a listener for the given event.  These may be DOM or 
652      * customEvent listeners.  Any event that is fired via fireEvent
653      * can be listened for.  All handlers receive an event object. 
654      * @method addListener
655      * @param {String} type The name of the event to listen for
656      * @param {Function} fn The handler to call when the event fires
657      * @param {Any} obj A variable to pass to the handler
658      * @param {Object} scope The object to use for the scope of the handler 
659      */
660     addListener: function(type, fn, obj, scope) {
661
662         scope = scope || this;
663
664         var Event = YAHOO.util.Event,
665                         el = this.get('element') || this.get('id'),
666                 self = this;
667
668
669                 if (specialTypes[type] && !Event._createMouseDelegate) {
670                 return false;   
671                 }
672
673
674         if (!this._events[type]) { // create on the fly
675
676             if (el && this.DOM_EVENTS[type]) {
677                                 Event.on(el, type, function(e, matchedEl) {
678
679                                         // Supplement IE with target, currentTarget relatedTarget
680
681                         if (e.srcElement && !e.target) { 
682                             e.target = e.srcElement;
683                         }
684
685                                         if ((e.toElement && !e.relatedTarget) || (e.fromElement && !e.relatedTarget)) {
686                                                 e.relatedTarget = Event.getRelatedTarget(e);
687                                         }
688                                         
689                                         if (!e.currentTarget) {
690                                                 e.currentTarget = el;
691                                         }
692
693                                         //      Note: matchedEl el is passed back for delegated listeners
694                             self.fireEvent(type, e, matchedEl);
695
696                         }, obj, scope);
697             }
698             this.createEvent(type, {scope: this});
699         }
700         
701         return YAHOO.util.EventProvider.prototype.subscribe.apply(this, arguments); // notify via customEvent
702     },
703
704
705     /**
706      * Alias for addListener
707      * @method on
708      * @param {String} type The name of the event to listen for
709      * @param {Function} fn The function call when the event fires
710      * @param {Any} obj A variable to pass to the handler
711      * @param {Object} scope The object to use for the scope of the handler 
712      */
713     on: function() {
714         return this.addListener.apply(this, arguments);
715     },
716     
717     /**
718      * Alias for addListener
719      * @method subscribe
720      * @param {String} type The name of the event to listen for
721      * @param {Function} fn The function call when the event fires
722      * @param {Any} obj A variable to pass to the handler
723      * @param {Object} scope The object to use for the scope of the handler 
724      */
725     subscribe: function() {
726         return this.addListener.apply(this, arguments);
727     },
728     
729     /**
730      * Remove an event listener
731      * @method removeListener
732      * @param {String} type The name of the event to listen for
733      * @param {Function} fn The function call when the event fires
734      */
735     removeListener: function(type, fn) {
736         return this.unsubscribe.apply(this, arguments);
737     },
738     
739     /**
740      * Wrapper for Dom method.
741      * @method addClass
742      * @param {String} className The className to add
743      */
744     addClass: function(className) {
745         Dom.addClass(this.get('element'), className);
746     },
747     
748     /**
749      * Wrapper for Dom method.
750      * @method getElementsByClassName
751      * @param {String} className The className to collect
752      * @param {String} tag (optional) The tag to use in
753      * conjunction with class name
754      * @return {Array} Array of HTMLElements
755      */
756     getElementsByClassName: function(className, tag) {
757         return Dom.getElementsByClassName(className, tag,
758                 this.get('element') );
759     },
760     
761     /**
762      * Wrapper for Dom method.
763      * @method hasClass
764      * @param {String} className The className to add
765      * @return {Boolean} Whether or not the element has the class name
766      */
767     hasClass: function(className) {
768         return Dom.hasClass(this.get('element'), className); 
769     },
770     
771     /**
772      * Wrapper for Dom method.
773      * @method removeClass
774      * @param {String} className The className to remove
775      */
776     removeClass: function(className) {
777         return Dom.removeClass(this.get('element'), className);
778     },
779     
780     /**
781      * Wrapper for Dom method.
782      * @method replaceClass
783      * @param {String} oldClassName The className to replace
784      * @param {String} newClassName The className to add
785      */
786     replaceClass: function(oldClassName, newClassName) {
787         return Dom.replaceClass(this.get('element'), 
788                 oldClassName, newClassName);
789     },
790     
791     /**
792      * Wrapper for Dom method.
793      * @method setStyle
794      * @param {String} property The style property to set
795      * @param {String} value The value to apply to the style property
796      */
797     setStyle: function(property, value) {
798         return Dom.setStyle(this.get('element'),  property, value); // TODO: always queuing?
799     },
800     
801     /**
802      * Wrapper for Dom method.
803      * @method getStyle
804      * @param {String} property The style property to retrieve
805      * @return {String} The current value of the property
806      */
807     getStyle: function(property) {
808         return Dom.getStyle(this.get('element'),  property);
809     },
810     
811     /**
812      * Apply any queued set calls.
813      * @method fireQueue
814      */
815     fireQueue: function() {
816         var queue = this._queue;
817         for (var i = 0, len = queue.length; i < len; ++i) {
818             this[queue[i][0]].apply(this, queue[i][1]);
819         }
820     },
821     
822     /**
823      * Appends the HTMLElement into either the supplied parentNode.
824      * @method appendTo
825      * @param {HTMLElement | Element} parentNode The node to append to
826      * @param {HTMLElement | Element} before An optional node to insert before
827      * @return {HTMLElement} The appended DOM element. 
828      */
829     appendTo: function(parent, before) {
830         parent = (parent.get) ?  parent.get('element') : Dom.get(parent);
831         
832         this.fireEvent('beforeAppendTo', {
833             type: 'beforeAppendTo',
834             target: parent
835         });
836         
837         
838         before = (before && before.get) ? 
839                 before.get('element') : Dom.get(before);
840         var element = this.get('element');
841         
842         if (!element) {
843             return false;
844         }
845         
846         if (!parent) {
847             return false;
848         }
849         
850         if (element.parent != parent) {
851             if (before) {
852                 parent.insertBefore(element, before);
853             } else {
854                 parent.appendChild(element);
855             }
856         }
857         
858         
859         this.fireEvent('appendTo', {
860             type: 'appendTo',
861             target: parent
862         });
863
864         return element;
865     },
866     
867     get: function(key) {
868         var configs = this._configs || {},
869             el = configs.element; // avoid loop due to 'element'
870
871         if (el && !configs[key] && !YAHOO.lang.isUndefined(el.value[key]) ) {
872             this._setHTMLAttrConfig(key);
873         }
874
875         return AttributeProvider.prototype.get.call(this, key);
876     },
877
878     setAttributes: function(map, silent) {
879         // set based on configOrder
880         var done = {},
881             configOrder = this._configOrder;
882
883         // set based on configOrder
884         for (var i = 0, len = configOrder.length; i < len; ++i) {
885             if (map[configOrder[i]] !== undefined) {
886                 done[configOrder[i]] = true;
887                 this.set(configOrder[i], map[configOrder[i]], silent);
888             }
889         }
890
891         // unconfigured (e.g. Dom attributes)
892         for (var att in map) {
893             if (map.hasOwnProperty(att) && !done[att]) {
894                 this.set(att, map[att], silent);
895             }
896         }
897     },
898
899     set: function(key, value, silent) {
900         var el = this.get('element');
901         if (!el) {
902             this._queue[this._queue.length] = ['set', arguments];
903             if (this._configs[key]) {
904                 this._configs[key].value = value; // so "get" works while queueing
905             
906             }
907             return;
908         }
909         
910         // set it on the element if not configured and is an HTML attribute
911         if ( !this._configs[key] && !YAHOO.lang.isUndefined(el[key]) ) {
912             this._setHTMLAttrConfig(key);
913         }
914
915         return AttributeProvider.prototype.set.apply(this, arguments);
916     },
917     
918     setAttributeConfig: function(key, map, init) {
919         this._configOrder.push(key);
920         AttributeProvider.prototype.setAttributeConfig.apply(this, arguments);
921     },
922
923     createEvent: function(type, config) {
924         this._events[type] = true;
925         return AttributeProvider.prototype.createEvent.apply(this, arguments);
926     },
927     
928     init: function(el, attr) {
929         this._initElement(el, attr); 
930     },
931
932     destroy: function() {
933         var el = this.get('element');
934         YAHOO.util.Event.purgeElement(el, true); // purge DOM listeners recursively
935         this.unsubscribeAll(); // unsubscribe all custom events
936
937         if (el && el.parentNode) {
938             el.parentNode.removeChild(el); // pull from the DOM
939         }
940
941         // revert initial configs
942         this._queue = [];
943         this._events = {};
944         this._configs = {};
945         this._configOrder = []; 
946     },
947
948     _initElement: function(el, attr) {
949         this._queue = this._queue || [];
950         this._events = this._events || {};
951         this._configs = this._configs || {};
952         this._configOrder = []; 
953         attr = attr || {};
954         attr.element = attr.element || el || null;
955
956         var isReady = false;  // to determine when to init HTMLElement and content
957
958         var DOM_EVENTS = Element.DOM_EVENTS;
959         this.DOM_EVENTS = this.DOM_EVENTS || {};
960
961         for (var event in DOM_EVENTS) {
962             if (DOM_EVENTS.hasOwnProperty(event)) {
963                 this.DOM_EVENTS[event] = DOM_EVENTS[event];
964             }
965         }
966
967         if (typeof attr.element === 'string') { // register ID for get() access
968             this._setHTMLAttrConfig('id', { value: attr.element });
969         }
970
971         if (Dom.get(attr.element)) {
972             isReady = true;
973             this._initHTMLElement(attr);
974             this._initContent(attr);
975         }
976
977         YAHOO.util.Event.onAvailable(attr.element, function() {
978             if (!isReady) { // otherwise already done
979                 this._initHTMLElement(attr);
980             }
981
982             this.fireEvent('available', { type: 'available', target: Dom.get(attr.element) });  
983         }, this, true);
984         
985         YAHOO.util.Event.onContentReady(attr.element, function() {
986             if (!isReady) { // otherwise already done
987                 this._initContent(attr);
988             }
989             this.fireEvent('contentReady', { type: 'contentReady', target: Dom.get(attr.element) });  
990         }, this, true);
991     },
992
993     _initHTMLElement: function(attr) {
994         /**
995          * The HTMLElement the Element instance refers to.
996          * @attribute element
997          * @type HTMLElement
998          */
999         this.setAttributeConfig('element', {
1000             value: Dom.get(attr.element),
1001             readOnly: true
1002          });
1003     },
1004
1005     _initContent: function(attr) {
1006         this.initAttributes(attr);
1007         this.setAttributes(attr, true);
1008         this.fireQueue();
1009
1010     },
1011
1012     /**
1013      * Sets the value of the property and fires beforeChange and change events.
1014      * @private
1015      * @method _setHTMLAttrConfig
1016      * @param {YAHOO.util.Element} element The Element instance to
1017      * register the config to.
1018      * @param {String} key The name of the config to register
1019      * @param {Object} map A key-value map of the config's params
1020      */
1021     _setHTMLAttrConfig: function(key, map) {
1022         var el = this.get('element');
1023         map = map || {};
1024         map.name = key;
1025
1026         map.setter = map.setter || this.DEFAULT_HTML_SETTER;
1027         map.getter = map.getter || this.DEFAULT_HTML_GETTER;
1028
1029         map.value = map.value || el[key];
1030         this._configs[key] = new YAHOO.util.Attribute(map, this);
1031     }
1032 };
1033
1034 /**
1035  * Fires when the Element's HTMLElement can be retrieved by Id.
1036  * <p>See: <a href="#addListener">Element.addListener</a></p>
1037  * <p><strong>Event fields:</strong><br>
1038  * <code>&lt;String&gt; type</code> available<br>
1039  * <code>&lt;HTMLElement&gt;
1040  * target</code> the HTMLElement bound to this Element instance<br>
1041  * <p><strong>Usage:</strong><br>
1042  * <code>var handler = function(e) {var target = e.target};<br>
1043  * myTabs.addListener('available', handler);</code></p>
1044  * @event available
1045  */
1046  
1047 /**
1048  * Fires when the Element's HTMLElement subtree is rendered.
1049  * <p>See: <a href="#addListener">Element.addListener</a></p>
1050  * <p><strong>Event fields:</strong><br>
1051  * <code>&lt;String&gt; type</code> contentReady<br>
1052  * <code>&lt;HTMLElement&gt;
1053  * target</code> the HTMLElement bound to this Element instance<br>
1054  * <p><strong>Usage:</strong><br>
1055  * <code>var handler = function(e) {var target = e.target};<br>
1056  * myTabs.addListener('contentReady', handler);</code></p>
1057  * @event contentReady
1058  */
1059
1060 /**
1061  * Fires before the Element is appended to another Element.
1062  * <p>See: <a href="#addListener">Element.addListener</a></p>
1063  * <p><strong>Event fields:</strong><br>
1064  * <code>&lt;String&gt; type</code> beforeAppendTo<br>
1065  * <code>&lt;HTMLElement/Element&gt;
1066  * target</code> the HTMLElement/Element being appended to 
1067  * <p><strong>Usage:</strong><br>
1068  * <code>var handler = function(e) {var target = e.target};<br>
1069  * myTabs.addListener('beforeAppendTo', handler);</code></p>
1070  * @event beforeAppendTo
1071  */
1072
1073 /**
1074  * Fires after the Element is appended to another Element.
1075  * <p>See: <a href="#addListener">Element.addListener</a></p>
1076  * <p><strong>Event fields:</strong><br>
1077  * <code>&lt;String&gt; type</code> appendTo<br>
1078  * <code>&lt;HTMLElement/Element&gt;
1079  * target</code> the HTMLElement/Element being appended to 
1080  * <p><strong>Usage:</strong><br>
1081  * <code>var handler = function(e) {var target = e.target};<br>
1082  * myTabs.addListener('appendTo', handler);</code></p>
1083  * @event appendTo
1084  */
1085
1086 YAHOO.augment(Element, AttributeProvider);
1087 YAHOO.util.Element = Element;
1088 })();
1089
1090 YAHOO.register("element", YAHOO.util.Element, {version: "2.8.0r4", build: "2449"});