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