PageRenderTime 46ms CodeModel.GetById 3ms app.highlight 34ms RepoModel.GetById 1ms app.codeStats 0ms

/hudson-war/src/main/webapp/scripts/yui/tabview/tabview-debug.js

http://github.com/hudson/hudson
JavaScript | 897 lines | 494 code | 130 blank | 273 comment | 110 complexity | 473a916ad17cb22b42e295411e773e87 MD5 | raw file
  1/*
  2Copyright (c) 2008, Yahoo! Inc. All rights reserved.
  3Code licensed under the BSD License:
  4http://developer.yahoo.net/yui/license.txt
  5version: 2.5.1
  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     * A widget to control tabbed views.
 17     * @namespace YAHOO.widget
 18     * @class TabView
 19     * @extends YAHOO.util.Element
 20     * @constructor
 21     * @param {HTMLElement | String | Object} el(optional) The html 
 22     * element that represents the TabView, or the attribute object to use. 
 23     * An element will be created if none provided.
 24     * @param {Object} attr (optional) A key map of the tabView's 
 25     * initial attributes.  Ignored if first arg is attributes object.
 26     */
 27    YAHOO.widget.TabView = function(el, attr) {
 28        attr = attr || {};
 29        if (arguments.length == 1 && !YAHOO.lang.isString(el) && !el.nodeName) {
 30            attr = el; // treat first arg as attr object
 31            el = attr.element || null;
 32        }
 33        
 34        if (!el && !attr.element) { // create if we dont have one
 35            el = _createTabViewElement.call(this, attr);
 36        }
 37    	YAHOO.widget.TabView.superclass.constructor.call(this, el, attr); 
 38    };
 39
 40    YAHOO.extend(YAHOO.widget.TabView, YAHOO.util.Element);
 41    
 42    var proto = YAHOO.widget.TabView.prototype;
 43    var Dom = YAHOO.util.Dom;
 44    var Event = YAHOO.util.Event;
 45    var Tab = YAHOO.widget.Tab;
 46    
 47    
 48    /**
 49     * The className to add when building from scratch. 
 50     * @property CLASSNAME
 51     * @default "navset"
 52     */
 53    proto.CLASSNAME = 'yui-navset';
 54    
 55    /**
 56     * The className of the HTMLElement containing the TabView's tab elements
 57     * to look for when building from existing markup, or to add when building
 58     * from scratch. 
 59     * All childNodes of the tab container are treated as Tabs when building
 60     * from existing markup.
 61     * @property TAB_PARENT_CLASSNAME
 62     * @default "nav"
 63     */
 64    proto.TAB_PARENT_CLASSNAME = 'yui-nav';
 65    
 66    /**
 67     * The className of the HTMLElement containing the TabView's label elements
 68     * to look for when building from existing markup, or to add when building
 69     * from scratch. 
 70     * All childNodes of the content container are treated as content elements when
 71     * building from existing markup.
 72     * @property CONTENT_PARENT_CLASSNAME
 73     * @default "nav-content"
 74     */
 75    proto.CONTENT_PARENT_CLASSNAME = 'yui-content';
 76    
 77    proto._tabParent = null;
 78    proto._contentParent = null; 
 79    
 80    /**
 81     * Adds a Tab to the TabView instance.  
 82     * If no index is specified, the tab is added to the end of the tab list.
 83     * @method addTab
 84     * @param {YAHOO.widget.Tab} tab A Tab instance to add.
 85     * @param {Integer} index The position to add the tab. 
 86     * @return void
 87     */
 88    proto.addTab = function(tab, index) {
 89        var tabs = this.get('tabs');
 90        if (!tabs) { // not ready yet
 91            this._queue[this._queue.length] = ['addTab', arguments];
 92            return false;
 93        }
 94        
 95        index = (index === undefined) ? tabs.length : index;
 96        
 97        var before = this.getTab(index);
 98        
 99        var self = this;
100        var el = this.get('element');
101        var tabParent = this._tabParent;
102        var contentParent = this._contentParent;
103
104        var tabElement = tab.get('element');
105        var contentEl = tab.get('contentEl');
106
107        if ( before ) {
108            tabParent.insertBefore(tabElement, before.get('element'));
109        } else {
110            tabParent.appendChild(tabElement);
111        }
112
113        if ( contentEl && !Dom.isAncestor(contentParent, contentEl) ) {
114            contentParent.appendChild(contentEl);
115        }
116        
117        if ( !tab.get('active') ) {
118            tab.set('contentVisible', false, true); /* hide if not active */
119        } else {
120            this.set('activeTab', tab, true);
121            
122        }
123
124        var activate = function(e) {
125            YAHOO.util.Event.preventDefault(e);
126            var silent = false;
127
128            if (this == self.get('activeTab')) {
129                silent = true; // dont fire activeTabChange if already active
130            }
131            self.set('activeTab', this, silent);
132        };
133        
134        tab.addListener( tab.get('activationEvent'), activate);
135        
136        tab.addListener('activationEventChange', function(e) {
137            if (e.prevValue != e.newValue) {
138                tab.removeListener(e.prevValue, activate);
139                tab.addListener(e.newValue, activate);
140            }
141        });
142        
143        tabs.splice(index, 0, tab);
144    };
145
146    /**
147     * Routes childNode events.
148     * @method DOMEventHandler
149     * @param {event} e The Dom event that is being handled.
150     * @return void
151     */
152    proto.DOMEventHandler = function(e) {
153        var el = this.get('element');
154        var target = YAHOO.util.Event.getTarget(e);
155        var tabParent = this._tabParent;
156        
157        if (Dom.isAncestor(tabParent, target) ) {
158            var tabEl;
159            var tab = null;
160            var contentEl;
161            var tabs = this.get('tabs');
162
163            for (var i = 0, len = tabs.length; i < len; i++) {
164                tabEl = tabs[i].get('element');
165                contentEl = tabs[i].get('contentEl');
166
167                if ( target == tabEl || Dom.isAncestor(tabEl, target) ) {
168                    tab = tabs[i];
169                    break; // note break
170                }
171            } 
172            
173            if (tab) {
174                tab.fireEvent(e.type, e);
175            }
176        }
177    };
178    
179    /**
180     * Returns the Tab instance at the specified index.
181     * @method getTab
182     * @param {Integer} index The position of the Tab.
183     * @return YAHOO.widget.Tab
184     */
185    proto.getTab = function(index) {
186    	return this.get('tabs')[index];
187    };
188    
189    /**
190     * Returns the index of given tab.
191     * @method getTabIndex
192     * @param {YAHOO.widget.Tab} tab The tab whose index will be returned.
193     * @return int
194     */
195    proto.getTabIndex = function(tab) {
196        var index = null;
197        var tabs = this.get('tabs');
198    	for (var i = 0, len = tabs.length; i < len; ++i) {
199            if (tab == tabs[i]) {
200                index = i;
201                break;
202            }
203        }
204        
205        return index;
206    };
207    
208    /**
209     * Removes the specified Tab from the TabView.
210     * @method removeTab
211     * @param {YAHOO.widget.Tab} item The Tab instance to be removed.
212     * @return void
213     */
214    proto.removeTab = function(tab) {
215        var tabCount = this.get('tabs').length;
216
217        var index = this.getTabIndex(tab);
218        var nextIndex = index + 1;
219        if ( tab == this.get('activeTab') ) { // select next tab
220            if (tabCount > 1) {
221                if (index + 1 == tabCount) {
222                    this.set('activeIndex', index - 1);
223                } else {
224                    this.set('activeIndex', index + 1);
225                }
226            }
227        }
228        
229        this._tabParent.removeChild( tab.get('element') );
230        this._contentParent.removeChild( tab.get('contentEl') );
231        this._configs.tabs.value.splice(index, 1);
232    	
233    };
234    
235    /**
236     * Provides a readable name for the TabView instance.
237     * @method toString
238     * @return String
239     */
240    proto.toString = function() {
241        var name = this.get('id') || this.get('tagName');
242        return "TabView " + name; 
243    };
244    
245    /**
246     * The transiton to use when switching between tabs.
247     * @method contentTransition
248     */
249    proto.contentTransition = function(newTab, oldTab) {
250        newTab.set('contentVisible', true);
251        oldTab.set('contentVisible', false);
252    };
253    
254    /**
255     * setAttributeConfigs TabView specific properties.
256     * @method initAttributes
257     * @param {Object} attr Hash of initial attributes
258     */
259    proto.initAttributes = function(attr) {
260        YAHOO.widget.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 (!YAHOO.util.Dom.hasClass(el, this.CLASSNAME)) {
269            YAHOO.util.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] || _createTabParent.call(this);
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] ||  _createContentParent.call(this);
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                switch(value) {
319                    case 'bottom':
320                    this.appendChild(this._tabParent);
321                    break;
322                }
323            }
324        });
325        
326        /**
327         * The index of the tab currently active.
328         * @attribute activeIndex
329         * @type Int
330         */
331        this.setAttributeConfig('activeIndex', {
332            value: attr.activeIndex,
333            method: function(value) {
334                this.set('activeTab', this.getTab(value));
335            },
336            validator: function(value) {
337                return !this.getTab(value).get('disabled'); // cannot activate if disabled
338            }
339        });
340        
341        /**
342         * The tab currently active.
343         * @attribute activeTab
344         * @type YAHOO.widget.Tab
345         */
346        this.setAttributeConfig('activeTab', {
347            value: attr.activeTab,
348            method: function(tab) {
349                var activeTab = this.get('activeTab');
350                
351                if (tab) {  
352                    tab.set('active', true);
353                    this._configs['activeIndex'].value = this.getTabIndex(tab); // keep in sync
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                return !value.get('disabled'); // cannot activate if disabled
368            }
369        });
370
371        YAHOO.log('attributes initialized', 'info', 'TabView');
372        if ( this._tabParent ) {
373            _initTabs.call(this);
374        }
375        
376        // Due to delegation we add all DOM_EVENTS to the TabView container
377        // but IE will leak when unsupported events are added, so remove these
378        this.DOM_EVENTS.submit = false;
379        this.DOM_EVENTS.focus = false;
380        this.DOM_EVENTS.blur = false;
381
382        for (var type in this.DOM_EVENTS) {
383            if ( YAHOO.lang.hasOwnProperty(this.DOM_EVENTS, type) ) {
384                this.addListener.call(this, type, this.DOMEventHandler);
385            }
386        }
387    };
388    
389    /**
390     * Creates Tab instances from a collection of HTMLElements.
391     * @method initTabs
392     * @private
393     * @return void
394     */
395    var _initTabs = function() {
396        var tab,
397            attr,
398            contentEl;
399            
400        var el = this.get('element');   
401        var tabs = _getChildNodes(this._tabParent);
402        var contentElements = _getChildNodes(this._contentParent);
403
404        for (var i = 0, len = tabs.length; i < len; ++i) {
405            attr = {};
406            
407            if (contentElements[i]) {
408                attr.contentEl = contentElements[i];
409            }
410
411            tab = new YAHOO.widget.Tab(tabs[i], attr);
412            this.addTab(tab);
413            
414            if (tab.hasClass(tab.ACTIVE_CLASSNAME) ) {
415                this._configs.activeTab.value = tab; // dont invoke method
416                this._configs.activeIndex.value = this.getTabIndex(tab);
417            }
418        }
419    };
420    
421    var _createTabViewElement = function(attr) {
422        var el = document.createElement('div');
423
424        if ( this.CLASSNAME ) {
425            el.className = this.CLASSNAME;
426        }
427        
428        YAHOO.log('TabView Dom created', 'info', 'TabView');
429        return el;
430    };
431    
432    var _createTabParent = function(attr) {
433        var el = document.createElement('ul');
434
435        if ( this.TAB_PARENT_CLASSNAME ) {
436            el.className = this.TAB_PARENT_CLASSNAME;
437        }
438        
439        this.get('element').appendChild(el);
440        
441        return el;
442    };
443    
444    var _createContentParent = function(attr) {
445        var el = document.createElement('div');
446
447        if ( this.CONTENT_PARENT_CLASSNAME ) {
448            el.className = this.CONTENT_PARENT_CLASSNAME;
449        }
450        
451        this.get('element').appendChild(el);
452        
453        return el;
454    };
455    
456    var _getChildNodes = function(el) {
457        var nodes = [];
458        var childNodes = el.childNodes;
459        
460        for (var i = 0, len = childNodes.length; i < len; ++i) {
461            if (childNodes[i].nodeType == 1) {
462                nodes[nodes.length] = childNodes[i];
463            }
464        }
465        
466        return nodes;
467    };
468})();
469
470(function() {
471    var Dom = YAHOO.util.Dom,
472        Event = YAHOO.util.Event;
473    
474    /**
475     * A representation of a Tab's label and content.
476     * @namespace YAHOO.widget
477     * @class Tab
478     * @extends YAHOO.util.Element
479     * @constructor
480     * @param element {HTMLElement | String} (optional) The html element that 
481     * represents the TabView. An element will be created if none provided.
482     * @param {Object} properties A key map of initial properties
483     */
484    var Tab = function(el, attr) {
485        attr = attr || {};
486        if (arguments.length == 1 && !YAHOO.lang.isString(el) && !el.nodeName) {
487            attr = el;
488            el = attr.element;
489        }
490
491        if (!el && !attr.element) {
492            el = _createTabElement.call(this, attr);
493        }
494
495        this.loadHandler =  {
496            success: function(o) {
497                this.set('content', o.responseText);
498            },
499            failure: function(o) {
500            }
501        };
502        
503        Tab.superclass.constructor.call(this, el, attr);
504        
505        this.DOM_EVENTS = {}; // delegating to tabView
506    };
507
508    YAHOO.extend(Tab, YAHOO.util.Element);
509    var proto = Tab.prototype;
510    
511    /**
512     * The default tag name for a Tab's inner element.
513     * @property LABEL_INNER_TAGNAME
514     * @type String
515     * @default "em"
516     */
517    proto.LABEL_TAGNAME = 'em';
518    
519    /**
520     * The class name applied to active tabs.
521     * @property ACTIVE_CLASSNAME
522     * @type String
523     * @default "selected"
524     */
525    proto.ACTIVE_CLASSNAME = 'selected';
526    
527    /**
528     * The title applied to active tabs.
529     * @property ACTIVE_TITLE
530     * @type String
531     * @default "active"
532     */
533    proto.ACTIVE_TITLE = 'active';
534
535    /**
536     * The class name applied to disabled tabs.
537     * @property DISABLED_CLASSNAME
538     * @type String
539     * @default "disabled"
540     */
541    proto.DISABLED_CLASSNAME = 'disabled';
542    
543    /**
544     * The class name applied to dynamic tabs while loading.
545     * @property LOADING_CLASSNAME
546     * @type String
547     * @default "disabled"
548     */
549    proto.LOADING_CLASSNAME = 'loading';
550
551    /**
552     * Provides a reference to the connection request object when data is
553     * loaded dynamically.
554     * @property dataConnection
555     * @type Object
556     */
557    proto.dataConnection = null;
558    
559    /**
560     * Object containing success and failure callbacks for loading data.
561     * @property loadHandler
562     * @type object
563     */
564    proto.loadHandler = null;
565
566    proto._loading = false;
567    
568    /**
569     * Provides a readable name for the tab.
570     * @method toString
571     * @return String
572     */
573    proto.toString = function() {
574        var el = this.get('element');
575        var id = el.id || el.tagName;
576        return "Tab " + id; 
577    };
578    
579    /**
580     * setAttributeConfigs TabView specific properties.
581     * @method initAttributes
582     * @param {Object} attr Hash of initial attributes
583     */
584    proto.initAttributes = function(attr) {
585        attr = attr || {};
586        Tab.superclass.initAttributes.call(this, attr);
587        
588        var el = this.get('element');
589        
590        /**
591         * The event that triggers the tab's activation.
592         * @attribute activationEvent
593         * @type String
594         */
595        this.setAttributeConfig('activationEvent', {
596            value: attr.activationEvent || 'click'
597        });        
598
599        /**
600         * The element that contains the tab's label.
601         * @attribute labelEl
602         * @type HTMLElement
603         */
604        this.setAttributeConfig('labelEl', {
605            value: attr.labelEl || _getlabelEl.call(this),
606            method: function(value) {
607                var current = this.get('labelEl');
608
609                if (current) {
610                    if (current == value) {
611                        return false; // already set
612                    }
613                    
614                    this.replaceChild(value, current);
615                } else if (el.firstChild) { // ensure label is firstChild by default
616                    this.insertBefore(value, el.firstChild);
617                } else {
618                    this.appendChild(value);
619                }  
620            } 
621        });
622
623        /**
624         * The tab's label text (or innerHTML).
625         * @attribute label
626         * @type String
627         */
628        this.setAttributeConfig('label', {
629            value: attr.label || _getLabel.call(this),
630            method: function(value) {
631                var labelEl = this.get('labelEl');
632                if (!labelEl) { // create if needed
633                    this.set('labelEl', _createlabelEl.call(this));
634                }
635                
636                _setLabel.call(this, value);
637            }
638        });
639        
640        /**
641         * The HTMLElement that contains the tab's content.
642         * @attribute contentEl
643         * @type HTMLElement
644         */
645        this.setAttributeConfig('contentEl', {
646            value: attr.contentEl || document.createElement('div'),
647            method: function(value) {
648                var current = this.get('contentEl');
649
650                if (current) {
651                    if (current == value) {
652                        return false; // already set
653                    }
654                    this.replaceChild(value, current);
655                }
656            }
657        });
658        
659        /**
660         * The tab's content.
661         * @attribute content
662         * @type String
663         */
664        this.setAttributeConfig('content', {
665            value: attr.content,
666            method: function(value) {
667                this.get('contentEl').innerHTML = value;
668            }
669        });
670
671        var _dataLoaded = false;
672        
673        /**
674         * The tab's data source, used for loading content dynamically.
675         * @attribute dataSrc
676         * @type String
677         */
678        this.setAttributeConfig('dataSrc', {
679            value: attr.dataSrc
680        });
681        
682        /**
683         * Whether or not content should be reloaded for every view.
684         * @attribute cacheData
685         * @type Boolean
686         * @default false
687         */
688        this.setAttributeConfig('cacheData', {
689            value: attr.cacheData || false,
690            validator: YAHOO.lang.isBoolean
691        });
692        
693        /**
694         * The method to use for the data request.
695         * @attribute loadMethod
696         * @type String
697         * @default "GET"
698         */
699        this.setAttributeConfig('loadMethod', {
700            value: attr.loadMethod || 'GET',
701            validator: YAHOO.lang.isString
702        });
703
704        /**
705         * Whether or not any data has been loaded from the server.
706         * @attribute dataLoaded
707         * @type Boolean
708         */        
709        this.setAttributeConfig('dataLoaded', {
710            value: false,
711            validator: YAHOO.lang.isBoolean,
712            writeOnce: true
713        });
714        
715        /**
716         * Number if milliseconds before aborting and calling failure handler.
717         * @attribute dataTimeout
718         * @type Number
719         * @default null
720         */
721        this.setAttributeConfig('dataTimeout', {
722            value: attr.dataTimeout || null,
723            validator: YAHOO.lang.isNumber
724        });
725        
726        /**
727         * Whether or not the tab is currently active.
728         * If a dataSrc is set for the tab, the content will be loaded from
729         * the given source.
730         * @attribute active
731         * @type Boolean
732         */
733        this.setAttributeConfig('active', {
734            value: attr.active || this.hasClass(this.ACTIVE_CLASSNAME),
735            method: function(value) {
736                if (value === true) {
737                    this.addClass(this.ACTIVE_CLASSNAME);
738                    this.set('title', this.ACTIVE_TITLE);
739                } else {
740                    this.removeClass(this.ACTIVE_CLASSNAME);
741                    this.set('title', '');
742                }
743            },
744            validator: function(value) {
745                return YAHOO.lang.isBoolean(value) && !this.get('disabled') ;
746            }
747        });
748        
749        /**
750         * Whether or not the tab is disabled.
751         * @attribute disabled
752         * @type Boolean
753         */
754        this.setAttributeConfig('disabled', {
755            value: attr.disabled || this.hasClass(this.DISABLED_CLASSNAME),
756            method: function(value) {
757                if (value === true) {
758                    Dom.addClass(this.get('element'), this.DISABLED_CLASSNAME);
759                } else {
760                    Dom.removeClass(this.get('element'), this.DISABLED_CLASSNAME);
761                }
762            },
763            validator: YAHOO.lang.isBoolean
764        });
765        
766        /**
767         * The href of the tab's anchor element.
768         * @attribute href
769         * @type String
770         * @default '#'
771         */
772        this.setAttributeConfig('href', {
773            value: attr.href ||
774                    this.getElementsByTagName('a')[0].getAttribute('href', 2) || '#',
775            method: function(value) {
776                this.getElementsByTagName('a')[0].href = value;
777            },
778            validator: YAHOO.lang.isString
779        });
780        
781        /**
782         * The Whether or not the tab's content is visible.
783         * @attribute contentVisible
784         * @type Boolean
785         * @default false
786         */
787        this.setAttributeConfig('contentVisible', {
788            value: attr.contentVisible,
789            method: function(value) {
790                if (value) {
791                    this.get('contentEl').style.display = 'block';
792                    
793                    if ( this.get('dataSrc') ) {
794                     // load dynamic content unless already loading or loaded and caching
795                        if ( !this._loading && !(this.get('dataLoaded') && this.get('cacheData')) ) {
796                            _dataConnect.call(this);
797                        }
798                    }
799                } else {
800                    this.get('contentEl').style.display = 'none';
801                }
802            },
803            validator: YAHOO.lang.isBoolean
804        });
805        YAHOO.log('attributes initialized', 'info', 'Tab');
806    };
807    
808    var _createTabElement = function(attr) {
809        var el = document.createElement('li');
810        var a = document.createElement('a');
811        
812        a.href = attr.href || '#';
813        
814        el.appendChild(a);
815        
816        var label = attr.label || null;
817        var labelEl = attr.labelEl || null;
818        
819        if (labelEl) { // user supplied labelEl
820            if (!label) { // user supplied label
821                label = _getLabel.call(this, labelEl);
822            }
823        } else {
824            labelEl = _createlabelEl.call(this);
825        }
826        
827        a.appendChild(labelEl);
828        
829        YAHOO.log('creating Tab Dom', 'info', 'Tab');
830        return el;
831    };
832    
833    var _getlabelEl = function() {
834        return this.getElementsByTagName(this.LABEL_TAGNAME)[0];
835    };
836    
837    var _createlabelEl = function() {
838        var el = document.createElement(this.LABEL_TAGNAME);
839        return el;
840    };
841    
842    var _setLabel = function(label) {
843        var el = this.get('labelEl');
844        el.innerHTML = label;
845    };
846    
847    var _getLabel = function() {
848        var label,
849            el = this.get('labelEl');
850            
851            if (!el) {
852                return undefined;
853            }
854        
855        return el.innerHTML;
856    };
857    
858    var _dataConnect = function() {
859        if (!YAHOO.util.Connect) {
860            YAHOO.log('YAHOO.util.Connect dependency not met',
861                    'error', 'Tab');
862            return false;
863        }
864
865        Dom.addClass(this.get('contentEl').parentNode, this.LOADING_CLASSNAME);
866        this._loading = true; 
867        this.dataConnection = YAHOO.util.Connect.asyncRequest(
868            this.get('loadMethod'),
869            this.get('dataSrc'), 
870            {
871                success: function(o) {
872                    YAHOO.log('content loaded successfully', 'info', 'Tab');
873                    this.loadHandler.success.call(this, o);
874                    this.set('dataLoaded', true);
875                    this.dataConnection = null;
876                    Dom.removeClass(this.get('contentEl').parentNode,
877                            this.LOADING_CLASSNAME);
878                    this._loading = false;
879                },
880                failure: function(o) {
881                    YAHOO.log('loading failed: ' + o.statusText, 'error', 'Tab');
882                    this.loadHandler.failure.call(this, o);
883                    this.dataConnection = null;
884                    Dom.removeClass(this.get('contentEl').parentNode,
885                            this.LOADING_CLASSNAME);
886                    this._loading = false;
887                },
888                scope: this,
889                timeout: this.get('dataTimeout')
890            }
891        );
892    };
893    
894    YAHOO.widget.Tab = Tab;
895})();
896
897YAHOO.register("tabview", YAHOO.widget.TabView, {version: "2.5.1", build: "984"});