]> git.koha-community.org Git - koha.git/blob - koha-tt/intranet-tmpl/prog/en/lib/yui/tabview/tabview-debug.js
Bug 5917 / Bug 6085 : Fixing not being able to change language
[koha.git] / koha-tt / intranet-tmpl / prog / en / lib / yui / tabview / tabview-debug.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 (function() {
8
9     /**
10      * The tabview module provides a widget for managing content bound to tabs.
11      * @module tabview
12      * @requires yahoo, dom, event, element
13      *
14      */
15
16     var Y = YAHOO.util,
17         Dom = Y.Dom,
18         Event = Y.Event,
19         document = window.document,
20     
21         // STRING CONSTANTS
22         ACTIVE = 'active',
23         ACTIVE_INDEX = 'activeIndex',
24         ACTIVE_TAB = 'activeTab',
25         CONTENT_EL = 'contentEl',
26         ELEMENT = 'element',
27     
28     /**
29      * A widget to control tabbed views.
30      * @namespace YAHOO.widget
31      * @class TabView
32      * @extends YAHOO.util.Element
33      * @constructor
34      * @param {HTMLElement | String | Object} el(optional) The html 
35      * element that represents the TabView, or the attribute object to use. 
36      * An element will be created if none provided.
37      * @param {Object} attr (optional) A key map of the tabView's 
38      * initial attributes.  Ignored if first arg is attributes object.
39      */
40     TabView = function(el, attr) {
41         attr = attr || {};
42         if (arguments.length == 1 && !YAHOO.lang.isString(el) && !el.nodeName) {
43             attr = el; // treat first arg as attr object
44             el = attr.element || null;
45         }
46         
47         if (!el && !attr.element) { // create if we dont have one
48             el = this._createTabViewElement(attr);
49         }
50         TabView.superclass.constructor.call(this, el, attr); 
51     };
52
53     YAHOO.extend(TabView, Y.Element, {
54         /**
55          * The className to add when building from scratch. 
56          * @property CLASSNAME
57          * @default "navset"
58          */
59         CLASSNAME: 'yui-navset',
60         
61         /**
62          * The className of the HTMLElement containing the TabView's tab elements
63          * to look for when building from existing markup, or to add when building
64          * from scratch. 
65          * All childNodes of the tab container are treated as Tabs when building
66          * from existing markup.
67          * @property TAB_PARENT_CLASSNAME
68          * @default "nav"
69          */
70         TAB_PARENT_CLASSNAME: 'yui-nav',
71         
72         /**
73          * The className of the HTMLElement containing the TabView's label elements
74          * to look for when building from existing markup, or to add when building
75          * from scratch. 
76          * All childNodes of the content container are treated as content elements when
77          * building from existing markup.
78          * @property CONTENT_PARENT_CLASSNAME
79          * @default "nav-content"
80          */
81         CONTENT_PARENT_CLASSNAME: 'yui-content',
82         
83         _tabParent: null,
84         _contentParent: null,
85         
86         /**
87          * Adds a Tab to the TabView instance.  
88          * If no index is specified, the tab is added to the end of the tab list.
89          * @method addTab
90          * @param {YAHOO.widget.Tab} tab A Tab instance to add.
91          * @param {Integer} index The position to add the tab. 
92          * @return void
93          */
94         addTab: function(tab, index) {
95             var tabs = this.get('tabs'),
96                 before = this.getTab(index),
97                 tabParent = this._tabParent,
98                 contentParent = this._contentParent,
99                 tabElement = tab.get(ELEMENT),
100                 contentEl = tab.get(CONTENT_EL);
101
102             if (!tabs) { // not ready yet
103                 this._queue[this._queue.length] = ['addTab', arguments];
104                 return false;
105             }
106             
107             index = (index === undefined) ? tabs.length : index;
108             
109             tabs.splice(index, 0, tab);
110
111             if ( before ) {
112                 tabParent.insertBefore(tabElement, before.get(ELEMENT));
113             } else {
114                 tabParent.appendChild(tabElement);
115             }
116
117             if ( contentEl && !Dom.isAncestor(contentParent, contentEl) ) {
118                 contentParent.appendChild(contentEl);
119             }
120             
121             if ( !tab.get(ACTIVE) ) {
122                 tab.set('contentVisible', false, true); /* hide if not active */
123             } else {
124                 this.set(ACTIVE_TAB, tab, true);
125                 this.set('activeIndex', index, true);
126             }
127
128             this._initTabEvents(tab);
129         },
130
131         _initTabEvents: function(tab) {
132             tab.addListener( tab.get('activationEvent'), tab._onActivate, this, tab);
133             tab.addListener( tab.get('activationEventChange'), tab._onActivationEventChange, this, tab);
134         },
135
136         _removeTabEvents: function(tab) {
137             tab.removeListener(tab.get('activationEvent'), tab._onActivate, this, tab);
138             tab.removeListener('activationEventChange', tab._onActivationEventChange, this, tab);
139         },
140
141         /**
142          * Routes childNode events.
143          * @method DOMEventHandler
144          * @param {event} e The Dom event that is being handled.
145          * @return void
146          */
147         DOMEventHandler: function(e) {
148             var target = Event.getTarget(e),
149                 tabParent = this._tabParent,
150                 tabs = this.get('tabs'),
151                 tab,
152                 tabEl,
153                 contentEl;
154
155             
156             if (Dom.isAncestor(tabParent, target) ) {
157                 for (var i = 0, len = tabs.length; i < len; i++) {
158                     tabEl = tabs[i].get(ELEMENT);
159                     contentEl = tabs[i].get(CONTENT_EL);
160
161                     if ( target == tabEl || Dom.isAncestor(tabEl, target) ) {
162                         tab = tabs[i];
163                         break; // note break
164                     }
165                 } 
166                 
167                 if (tab) {
168                     tab.fireEvent(e.type, e);
169                 }
170             }
171         },
172         
173         /**
174          * Returns the Tab instance at the specified index.
175          * @method getTab
176          * @param {Integer} index The position of the Tab.
177          * @return YAHOO.widget.Tab
178          */
179         getTab: function(index) {
180             return this.get('tabs')[index];
181         },
182         
183         /**
184          * Returns the index of given tab.
185          * @method getTabIndex
186          * @param {YAHOO.widget.Tab} tab The tab whose index will be returned.
187          * @return int
188          */
189         getTabIndex: function(tab) {
190             var index = null,
191                 tabs = this.get('tabs');
192             for (var i = 0, len = tabs.length; i < len; ++i) {
193                 if (tab == tabs[i]) {
194                     index = i;
195                     break;
196                 }
197             }
198             
199             return index;
200         },
201         
202         /**
203          * Removes the specified Tab from the TabView.
204          * @method removeTab
205          * @param {YAHOO.widget.Tab} item The Tab instance to be removed.
206          * @return void
207          */
208         removeTab: function(tab) {
209             var tabCount = this.get('tabs').length,
210                 index = this.getTabIndex(tab);
211
212             if ( tab === this.get(ACTIVE_TAB) ) { 
213                 if (tabCount > 1) { // select another tab
214                     if (index + 1 === tabCount) { // if last, activate previous
215                         this.set(ACTIVE_INDEX, index - 1);
216                     } else { // activate next tab
217                         this.set(ACTIVE_INDEX, index + 1);
218                     }
219                 } else { // no more tabs
220                     this.set(ACTIVE_TAB, null);
221                 }
222             }
223             
224             this._removeTabEvents(tab);
225             this._tabParent.removeChild( tab.get(ELEMENT) );
226             this._contentParent.removeChild( tab.get(CONTENT_EL) );
227             this._configs.tabs.value.splice(index, 1);
228
229             tab.fireEvent('remove', { type: 'remove', tabview: this });
230         },
231         
232         /**
233          * Provides a readable name for the TabView instance.
234          * @method toString
235          * @return String
236          */
237         toString: function() {
238             var name = this.get('id') || this.get('tagName');
239             return "TabView " + name; 
240         },
241         
242         /**
243          * The transiton to use when switching between tabs.
244          * @method contentTransition
245          */
246         contentTransition: function(newTab, oldTab) {
247             if (newTab) {
248                 newTab.set('contentVisible', true);
249             }
250             if (oldTab) {
251                 oldTab.set('contentVisible', false);
252             }
253         },
254         
255         /**
256          * setAttributeConfigs TabView specific properties.
257          * @method initAttributes
258          * @param {Object} attr Hash of initial attributes
259          */
260         initAttributes: function(attr) {
261             TabView.superclass.initAttributes.call(this, attr);
262             
263             if (!attr.orientation) {
264                 attr.orientation = 'top';
265             }
266             
267             var el = this.get(ELEMENT);
268
269             if (!Dom.hasClass(el, this.CLASSNAME)) {
270                 Dom.addClass(el, this.CLASSNAME);        
271             }
272             
273             /**
274              * The Tabs belonging to the TabView instance.
275              * @attribute tabs
276              * @type Array
277              */
278             this.setAttributeConfig('tabs', {
279                 value: [],
280                 readOnly: true
281             });
282
283             /**
284              * The container of the tabView's label elements.
285              * @property _tabParent
286              * @private
287              * @type HTMLElement
288              */
289             this._tabParent = 
290                     this.getElementsByClassName(this.TAB_PARENT_CLASSNAME,
291                             'ul' )[0] || this._createTabParent();
292                 
293             /**
294              * The container of the tabView's content elements.
295              * @property _contentParent
296              * @type HTMLElement
297              * @private
298              */
299             this._contentParent = 
300                     this.getElementsByClassName(this.CONTENT_PARENT_CLASSNAME,
301                             'div')[0] ||  this._createContentParent();
302             
303             /**
304              * How the Tabs should be oriented relative to the TabView.
305              * @attribute orientation
306              * @type String
307              * @default "top"
308              */
309             this.setAttributeConfig('orientation', {
310                 value: attr.orientation,
311                 method: function(value) {
312                     var current = this.get('orientation');
313                     this.addClass('yui-navset-' + value);
314                     
315                     if (current != value) {
316                         this.removeClass('yui-navset-' + current);
317                     }
318                     
319                     if (value === 'bottom') {
320                         this.appendChild(this._tabParent);
321                     }
322                 }
323             });
324             
325             /**
326              * The index of the tab currently active.
327              * @attribute activeIndex
328              * @type Int
329              */
330             this.setAttributeConfig(ACTIVE_INDEX, {
331                 value: attr.activeIndex,
332                 validator: function(value) {
333                     var ret = true;
334                     if (value && this.getTab(value).get('disabled')) { // cannot activate if disabled
335                         ret = false;
336                     }
337                     return ret;
338                 }
339             });
340             
341             /**
342              * The tab currently active.
343              * @attribute activeTab
344              * @type YAHOO.widget.Tab
345              */
346             this.setAttributeConfig(ACTIVE_TAB, {
347                 value: attr.activeTab,
348                 method: function(tab) {
349                     var activeTab = this.get(ACTIVE_TAB);
350                     
351                     if (tab) {
352                         tab.set(ACTIVE, true);
353                     }
354                     
355                     if (activeTab && activeTab !== tab) {
356                         activeTab.set(ACTIVE, false);
357                     }
358                     
359                     if (activeTab && tab !== activeTab) { // no transition if only 1
360                         this.contentTransition(tab, activeTab);
361                     } else if (tab) {
362                         tab.set('contentVisible', true);
363                     }
364                 },
365                 validator: function(value) {
366                     var ret = true;
367                     if (value && value.get('disabled')) { // cannot activate if disabled
368                         ret = false;
369                     }
370                     return ret;
371                 }
372             });
373
374             this.on('activeTabChange', this._onActiveTabChange);
375             this.on('activeIndexChange', this._onActiveIndexChange);
376
377             YAHOO.log('attributes initialized', 'info', 'TabView');
378             if ( this._tabParent ) {
379                 this._initTabs();
380             }
381             
382             // Due to delegation we add all DOM_EVENTS to the TabView container
383             // but IE will leak when unsupported events are added, so remove these
384             this.DOM_EVENTS.submit = false;
385             this.DOM_EVENTS.focus = false;
386             this.DOM_EVENTS.blur = false;
387
388             for (var type in this.DOM_EVENTS) {
389                 if ( YAHOO.lang.hasOwnProperty(this.DOM_EVENTS, type) ) {
390                     this.addListener.call(this, type, this.DOMEventHandler);
391                 }
392             }
393         },
394
395         /**
396          * Removes selected state from the given tab if it is the activeTab
397          * @method deselectTab
398          * @param {Int} index The tab index to deselect 
399          */
400         deselectTab: function(index) {
401             if (this.getTab(index) === this.get('activeTab')) {
402                 this.set('activeTab', null);
403             }
404         },
405
406         /**
407          * Makes the tab at the given index the active tab
408          * @method selectTab
409          * @param {Int} index The tab index to be made active
410          */
411         selectTab: function(index) {
412             this.set('activeTab', this.getTab(index));
413         },
414
415         _onActiveTabChange: function(e) {
416             var activeIndex = this.get(ACTIVE_INDEX),
417                 newIndex = this.getTabIndex(e.newValue);
418
419             if (activeIndex !== newIndex) {
420                 if (!(this.set(ACTIVE_INDEX, newIndex)) ) { // NOTE: setting
421                      // revert if activeIndex update fails (cancelled via beforeChange) 
422                     this.set(ACTIVE_TAB, e.prevValue);
423                 }
424             }
425         },
426         
427         _onActiveIndexChange: function(e) {
428             // no set if called from ActiveTabChange event
429             if (e.newValue !== this.getTabIndex(this.get(ACTIVE_TAB))) {
430                 if (!(this.set(ACTIVE_TAB, this.getTab(e.newValue))) ) { // NOTE: setting
431                      // revert if activeTab update fails (cancelled via beforeChange) 
432                     this.set(ACTIVE_INDEX, e.prevValue);
433                 }
434             }
435         },
436
437         /**
438          * Creates Tab instances from a collection of HTMLElements.
439          * @method _initTabs
440          * @private
441          * @return void
442          */
443         _initTabs: function() {
444             var tabs = Dom.getChildren(this._tabParent),
445                 contentElements = Dom.getChildren(this._contentParent),
446                 activeIndex = this.get(ACTIVE_INDEX),
447                 tab,
448                 attr,
449                 active;
450
451             for (var i = 0, len = tabs.length; i < len; ++i) {
452                 attr = {};
453                 
454                 if (contentElements[i]) {
455                     attr.contentEl = contentElements[i];
456                 }
457
458                 tab = new YAHOO.widget.Tab(tabs[i], attr);
459                 this.addTab(tab);
460                 
461                 if (tab.hasClass(tab.ACTIVE_CLASSNAME) ) {
462                     active = tab;
463                 }
464             }
465             if (activeIndex) {
466                 this.set(ACTIVE_TAB, this.getTab(activeIndex));
467             } else {
468                 this._configs.activeTab.value = active; // dont invoke method
469                 this._configs.activeIndex.value = this.getTabIndex(active);
470             }
471         },
472
473         _createTabViewElement: function(attr) {
474             var el = document.createElement('div');
475
476             if ( this.CLASSNAME ) {
477                 el.className = this.CLASSNAME;
478             }
479             
480             YAHOO.log('TabView Dom created', 'info', 'TabView');
481             return el;
482         },
483
484         _createTabParent: function(attr) {
485             var el = document.createElement('ul');
486
487             if ( this.TAB_PARENT_CLASSNAME ) {
488                 el.className = this.TAB_PARENT_CLASSNAME;
489             }
490             
491             this.get(ELEMENT).appendChild(el);
492             
493             return el;
494         },
495         
496         _createContentParent: function(attr) {
497             var el = document.createElement('div');
498
499             if ( this.CONTENT_PARENT_CLASSNAME ) {
500                 el.className = this.CONTENT_PARENT_CLASSNAME;
501             }
502             
503             this.get(ELEMENT).appendChild(el);
504             
505             return el;
506         }
507     });
508     
509     
510     YAHOO.widget.TabView = TabView;
511 })();
512
513 (function() {
514     var Y = YAHOO.util, 
515         Dom = Y.Dom,
516         Lang = YAHOO.lang,
517     
518
519     // STRING CONSTANTS
520         ACTIVE_TAB = 'activeTab',
521         LABEL = 'label',
522         LABEL_EL = 'labelEl',
523         CONTENT = 'content',
524         CONTENT_EL = 'contentEl',
525         ELEMENT = 'element',
526         CACHE_DATA = 'cacheData',
527         DATA_SRC = 'dataSrc',
528         DATA_LOADED = 'dataLoaded',
529         DATA_TIMEOUT = 'dataTimeout',
530         LOAD_METHOD = 'loadMethod',
531         POST_DATA = 'postData',
532         DISABLED = 'disabled',
533     
534     /**
535      * A representation of a Tab's label and content.
536      * @namespace YAHOO.widget
537      * @class Tab
538      * @extends YAHOO.util.Element
539      * @constructor
540      * @param element {HTMLElement | String} (optional) The html element that 
541      * represents the Tab. An element will be created if none provided.
542      * @param {Object} properties A key map of initial properties
543      */
544     Tab = function(el, attr) {
545         attr = attr || {};
546         if (arguments.length == 1 && !Lang.isString(el) && !el.nodeName) {
547             attr = el;
548             el = attr.element;
549         }
550
551         if (!el && !attr.element) {
552             el = this._createTabElement(attr);
553         }
554
555         this.loadHandler =  {
556             success: function(o) {
557                 this.set(CONTENT, o.responseText);
558             },
559             failure: function(o) {
560             }
561         };
562         
563         Tab.superclass.constructor.call(this, el, attr);
564         
565         this.DOM_EVENTS = {}; // delegating to tabView
566     };
567
568     YAHOO.extend(Tab, YAHOO.util.Element, {
569         /**
570          * The default tag name for a Tab's inner element.
571          * @property LABEL_INNER_TAGNAME
572          * @type String
573          * @default "em"
574          */
575         LABEL_TAGNAME: 'em',
576         
577         /**
578          * The class name applied to active tabs.
579          * @property ACTIVE_CLASSNAME
580          * @type String
581          * @default "selected"
582          */
583         ACTIVE_CLASSNAME: 'selected',
584         
585         /**
586          * The class name applied to active tabs.
587          * @property HIDDEN_CLASSNAME
588          * @type String
589          * @default "yui-hidden"
590          */
591         HIDDEN_CLASSNAME: 'yui-hidden',
592         
593         /**
594          * The title applied to active tabs.
595          * @property ACTIVE_TITLE
596          * @type String
597          * @default "active"
598          */
599         ACTIVE_TITLE: 'active',
600
601         /**
602          * The class name applied to disabled tabs.
603          * @property DISABLED_CLASSNAME
604          * @type String
605          * @default "disabled"
606          */
607         DISABLED_CLASSNAME: DISABLED,
608         
609         /**
610          * The class name applied to dynamic tabs while loading.
611          * @property LOADING_CLASSNAME
612          * @type String
613          * @default "disabled"
614          */
615         LOADING_CLASSNAME: 'loading',
616
617         /**
618          * Provides a reference to the connection request object when data is
619          * loaded dynamically.
620          * @property dataConnection
621          * @type Object
622          */
623         dataConnection: null,
624         
625         /**
626          * Object containing success and failure callbacks for loading data.
627          * @property loadHandler
628          * @type object
629          */
630         loadHandler: null,
631
632         _loading: false,
633         
634         /**
635          * Provides a readable name for the tab.
636          * @method toString
637          * @return String
638          */
639         toString: function() {
640             var el = this.get(ELEMENT),
641                 id = el.id || el.tagName;
642             return "Tab " + id; 
643         },
644         
645         /**
646          * setAttributeConfigs Tab specific properties.
647          * @method initAttributes
648          * @param {Object} attr Hash of initial attributes
649          */
650         initAttributes: function(attr) {
651             attr = attr || {};
652             Tab.superclass.initAttributes.call(this, attr);
653             
654             /**
655              * The event that triggers the tab's activation.
656              * @attribute activationEvent
657              * @type String
658              */
659             this.setAttributeConfig('activationEvent', {
660                 value: attr.activationEvent || 'click'
661             });        
662
663             /**
664              * The element that contains the tab's label.
665              * @attribute labelEl
666              * @type HTMLElement
667              */
668             this.setAttributeConfig(LABEL_EL, {
669                 value: attr[LABEL_EL] || this._getLabelEl(),
670                 method: function(value) {
671                     value = Dom.get(value);
672                     var current = this.get(LABEL_EL);
673
674                     if (current) {
675                         if (current == value) {
676                             return false; // already set
677                         }
678                         
679                         current.parentNode.replaceChild(value, current);
680                         this.set(LABEL, value.innerHTML);
681                     }
682                 } 
683             });
684
685             /**
686              * The tab's label text (or innerHTML).
687              * @attribute label
688              * @type String
689              */
690             this.setAttributeConfig(LABEL, {
691                 value: attr.label || this._getLabel(),
692                 method: function(value) {
693                     var labelEl = this.get(LABEL_EL);
694                     if (!labelEl) { // create if needed
695                         this.set(LABEL_EL, this._createLabelEl());
696                     }
697                     
698                     labelEl.innerHTML = value;
699                 }
700             });
701             
702             /**
703              * The HTMLElement that contains the tab's content.
704              * @attribute contentEl
705              * @type HTMLElement
706              */
707             this.setAttributeConfig(CONTENT_EL, {
708                 value: attr[CONTENT_EL] || document.createElement('div'),
709                 method: function(value) {
710                     value = Dom.get(value);
711                     var current = this.get(CONTENT_EL);
712
713                     if (current) {
714                         if (current === value) {
715                             return false; // already set
716                         }
717                         if (!this.get('selected')) {
718                             Dom.addClass(value, this.HIDDEN_CLASSNAME);
719                         }
720                         current.parentNode.replaceChild(value, current);
721                         this.set(CONTENT, value.innerHTML);
722                     }
723                 }
724             });
725             
726             /**
727              * The tab's content.
728              * @attribute content
729              * @type String
730              */
731             this.setAttributeConfig(CONTENT, {
732                 value: attr[CONTENT],
733                 method: function(value) {
734                     this.get(CONTENT_EL).innerHTML = value;
735                 }
736             });
737
738             /**
739              * The tab's data source, used for loading content dynamically.
740              * @attribute dataSrc
741              * @type String
742              */
743             this.setAttributeConfig(DATA_SRC, {
744                 value: attr.dataSrc
745             });
746             
747             /**
748              * Whether or not content should be reloaded for every view.
749              * @attribute cacheData
750              * @type Boolean
751              * @default false
752              */
753             this.setAttributeConfig(CACHE_DATA, {
754                 value: attr.cacheData || false,
755                 validator: Lang.isBoolean
756             });
757             
758             /**
759              * The method to use for the data request.
760              * @attribute loadMethod
761              * @type String
762              * @default "GET"
763              */
764             this.setAttributeConfig(LOAD_METHOD, {
765                 value: attr.loadMethod || 'GET',
766                 validator: Lang.isString
767             });
768
769             /**
770              * Whether or not any data has been loaded from the server.
771              * @attribute dataLoaded
772              * @type Boolean
773              */        
774             this.setAttributeConfig(DATA_LOADED, {
775                 value: false,
776                 validator: Lang.isBoolean,
777                 writeOnce: true
778             });
779             
780             /**
781              * Number if milliseconds before aborting and calling failure handler.
782              * @attribute dataTimeout
783              * @type Number
784              * @default null
785              */
786             this.setAttributeConfig(DATA_TIMEOUT, {
787                 value: attr.dataTimeout || null,
788                 validator: Lang.isNumber
789             });
790             
791             /**
792              * Arguments to pass when POST method is used 
793              * @attribute postData
794              * @default null
795              */
796             this.setAttributeConfig(POST_DATA, {
797                 value: attr.postData || null
798             });
799
800             /**
801              * Whether or not the tab is currently active.
802              * If a dataSrc is set for the tab, the content will be loaded from
803              * the given source.
804              * @attribute active
805              * @type Boolean
806              */
807             this.setAttributeConfig('active', {
808                 value: attr.active || this.hasClass(this.ACTIVE_CLASSNAME),
809                 method: function(value) {
810                     if (value === true) {
811                         this.addClass(this.ACTIVE_CLASSNAME);
812                         this.set('title', this.ACTIVE_TITLE);
813                     } else {
814                         this.removeClass(this.ACTIVE_CLASSNAME);
815                         this.set('title', '');
816                     }
817                 },
818                 validator: function(value) {
819                     return Lang.isBoolean(value) && !this.get(DISABLED) ;
820                 }
821             });
822             
823             /**
824              * Whether or not the tab is disabled.
825              * @attribute disabled
826              * @type Boolean
827              */
828             this.setAttributeConfig(DISABLED, {
829                 value: attr.disabled || this.hasClass(this.DISABLED_CLASSNAME),
830                 method: function(value) {
831                     if (value === true) {
832                         Dom.addClass(this.get(ELEMENT), this.DISABLED_CLASSNAME);
833                     } else {
834                         Dom.removeClass(this.get(ELEMENT), this.DISABLED_CLASSNAME);
835                     }
836                 },
837                 validator: Lang.isBoolean
838             });
839             
840             /**
841              * The href of the tab's anchor element.
842              * @attribute href
843              * @type String
844              * @default '#'
845              */
846             this.setAttributeConfig('href', {
847                 value: attr.href ||
848                         this.getElementsByTagName('a')[0].getAttribute('href', 2) || '#',
849                 method: function(value) {
850                     this.getElementsByTagName('a')[0].href = value;
851                 },
852                 validator: Lang.isString
853             });
854             
855             /**
856              * The Whether or not the tab's content is visible.
857              * @attribute contentVisible
858              * @type Boolean
859              * @default false
860              */
861             this.setAttributeConfig('contentVisible', {
862                 value: attr.contentVisible,
863                 method: function(value) {
864                     if (value) {
865                         Dom.removeClass(this.get(CONTENT_EL), this.HIDDEN_CLASSNAME);
866                         
867                         if ( this.get(DATA_SRC) ) {
868                          // load dynamic content unless already loading or loaded and caching
869                             if ( !this._loading && !(this.get(DATA_LOADED) && this.get(CACHE_DATA)) ) {
870                                 this._dataConnect();
871                             }
872                         }
873                     } else {
874                         Dom.addClass(this.get(CONTENT_EL), this.HIDDEN_CLASSNAME);
875                     }
876                 },
877                 validator: Lang.isBoolean
878             });
879             YAHOO.log('attributes initialized', 'info', 'Tab');
880         },
881         
882         _dataConnect: function() {
883             if (!Y.Connect) {
884                 YAHOO.log('YAHOO.util.Connect dependency not met',
885                         'error', 'Tab');
886                 return false;
887             }
888
889             Dom.addClass(this.get(CONTENT_EL).parentNode, this.LOADING_CLASSNAME);
890             this._loading = true; 
891             this.dataConnection = Y.Connect.asyncRequest(
892                 this.get(LOAD_METHOD),
893                 this.get(DATA_SRC), 
894                 {
895                     success: function(o) {
896                         YAHOO.log('content loaded successfully', 'info', 'Tab');
897                         this.loadHandler.success.call(this, o);
898                         this.set(DATA_LOADED, true);
899                         this.dataConnection = null;
900                         Dom.removeClass(this.get(CONTENT_EL).parentNode,
901                                 this.LOADING_CLASSNAME);
902                         this._loading = false;
903                     },
904                     failure: function(o) {
905                         YAHOO.log('loading failed: ' + o.statusText, 'error', 'Tab');
906                         this.loadHandler.failure.call(this, o);
907                         this.dataConnection = null;
908                         Dom.removeClass(this.get(CONTENT_EL).parentNode,
909                                 this.LOADING_CLASSNAME);
910                         this._loading = false;
911                     },
912                     scope: this,
913                     timeout: this.get(DATA_TIMEOUT)
914                 },
915
916                 this.get(POST_DATA)
917             );
918         },
919         _createTabElement: function(attr) {
920             var el = document.createElement('li'),
921                 a = document.createElement('a'),
922                 label = attr.label || null,
923                 labelEl = attr.labelEl || null;
924             
925             a.href = attr.href || '#'; // TODO: Use Dom.setAttribute?
926             el.appendChild(a);
927             
928             if (labelEl) { // user supplied labelEl
929                 if (!label) { // user supplied label
930                     label = this._getLabel();
931                 }
932             } else {
933                 labelEl = this._createLabelEl();
934             }
935             
936             a.appendChild(labelEl);
937             
938             YAHOO.log('creating Tab Dom', 'info', 'Tab');
939             return el;
940         },
941
942         _getLabelEl: function() {
943             return this.getElementsByTagName(this.LABEL_TAGNAME)[0];
944         },
945
946         _createLabelEl: function() {
947             var el = document.createElement(this.LABEL_TAGNAME);
948             return el;
949         },
950     
951         
952         _getLabel: function() {
953             var el = this.get(LABEL_EL);
954                 
955                 if (!el) {
956                     return undefined;
957                 }
958             
959             return el.innerHTML;
960         },
961
962         _onActivate: function(e, tabview) {
963             var tab = this,
964                 silent = false;
965
966             Y.Event.preventDefault(e);
967             if (tab === tabview.get(ACTIVE_TAB)) {
968                 silent = true; // dont fire activeTabChange if already active
969             }
970             tabview.set(ACTIVE_TAB, tab, silent);
971         },
972
973         _onActivationEventChange: function(e) {
974             var tab = this;
975
976             if (e.prevValue != e.newValue) {
977                 tab.removeListener(e.prevValue, tab._onActivate);
978                 tab.addListener(e.newValue, tab._onActivate, this, tab);
979             }
980         }
981     });
982     
983     
984     /**
985      * Fires when a tab is removed from the tabview
986      * @event remove
987      * @type CustomEvent
988      * @param {Event} An event object with fields for "type" ("remove")
989      * and "tabview" (the tabview instance it was removed from) 
990      */
991     
992     YAHOO.widget.Tab = Tab;
993 })();
994
995 YAHOO.register("tabview", YAHOO.widget.TabView, {version: "2.8.0r4", build: "2449"});