summaryrefslogtreecommitdiff
path: root/frontend/beta/js/YUI/tabview.js
Unidiff
Diffstat (limited to 'frontend/beta/js/YUI/tabview.js') (more/less context) (show whitespace changes)
-rw-r--r--frontend/beta/js/YUI/tabview.js1950
1 files changed, 1950 insertions, 0 deletions
diff --git a/frontend/beta/js/YUI/tabview.js b/frontend/beta/js/YUI/tabview.js
new file mode 100644
index 0000000..34a09bb
--- a/dev/null
+++ b/frontend/beta/js/YUI/tabview.js
@@ -0,0 +1,1950 @@
1/*
2Copyright (c) 2006, Yahoo! Inc. All rights reserved.
3Code licensed under the BSD License:
4http://developer.yahoo.net/yui/license.txt
5version: 0.12.0
6*/
7(function() {
8
9 YAHOO.util.Lang = {
10 isArray: function(val) { // frames lose type, so test constructor string
11 if (val.constructor && val.constructor.toString().indexOf('Array') > -1) {
12 return true;
13 } else {
14 return YAHOO.util.Lang.isObject(val) && val.constructor == Array;
15 }
16 },
17
18 isBoolean: function(val) {
19 return typeof val == 'boolean';
20 },
21
22 isFunction: function(val) {
23 return typeof val == 'function';
24 },
25
26 isNull: function(val) {
27 return val === null;
28 },
29
30 isNumber: function(val) {
31 return !isNaN(val);
32 },
33
34 isObject: function(val) {
35 return typeof val == 'object' || YAHOO.util.Lang.isFunction(val);
36 },
37
38 isString: function(val) {
39 return typeof val == 'string';
40 },
41
42 isUndefined: function(val) {
43 return typeof val == 'undefined';
44 }
45 };
46})();/**
47 * Provides Attribute configurations.
48 * @namespace YAHOO.util
49 * @class Attribute
50 * @constructor
51 * @param hash {Object} The intial Attribute.
52 * @param {YAHOO.util.AttributeProvider} The owner of the Attribute instance.
53 */
54
55YAHOO.util.Attribute = function(hash, owner) {
56 if (owner) {
57 this.owner = owner;
58 this.configure(hash, true);
59 }
60};
61
62YAHOO.util.Attribute.prototype = {
63 /**
64 * The name of the attribute.
65 * @property name
66 * @type String
67 */
68 name: undefined,
69
70 /**
71 * The value of the attribute.
72 * @property value
73 * @type String
74 */
75 value: null,
76
77 /**
78 * The owner of the attribute.
79 * @property owner
80 * @type YAHOO.util.AttributeProvider
81 */
82 owner: null,
83
84 /**
85 * Whether or not the attribute is read only.
86 * @property readOnly
87 * @type Boolean
88 */
89 readOnly: false,
90
91 /**
92 * Whether or not the attribute can only be written once.
93 * @property writeOnce
94 * @type Boolean
95 */
96 writeOnce: false,
97
98 /**
99 * The attribute's initial configuration.
100 * @private
101 * @property _initialConfig
102 * @type Object
103 */
104 _initialConfig: null,
105
106 /**
107 * Whether or not the attribute's value has been set.
108 * @private
109 * @property _written
110 * @type Boolean
111 */
112 _written: false,
113
114 /**
115 * The method to use when setting the attribute's value.
116 * The method recieves the new value as the only argument.
117 * @property method
118 * @type Function
119 */
120 method: null,
121
122 /**
123 * The validator to use when setting the attribute's value.
124 * @property validator
125 * @type Function
126 * @return Boolean
127 */
128 validator: null,
129
130 /**
131 * Retrieves the current value of the attribute.
132 * @method getValue
133 * @return {any} The current value of the attribute.
134 */
135 getValue: function() {
136 return this.value;
137 },
138
139 /**
140 * Sets the value of the attribute and fires beforeChange and change events.
141 * @method setValue
142 * @param {Any} value The value to apply to the attribute.
143 * @param {Boolean} silent If true the change events will not be fired.
144 * @return {Boolean} Whether or not the value was set.
145 */
146 setValue: function(value, silent) {
147 var beforeRetVal;
148 var owner = this.owner;
149 var name = this.name;
150
151 var event = {
152 type: name,
153 prevValue: this.getValue(),
154 newValue: value
155 };
156
157 if (this.readOnly || ( this.writeOnce && this._written) ) {
158 return false; // write not allowed
159 }
160
161 if (this.validator && !this.validator.call(owner, value) ) {
162 return false; // invalid value
163 }
164
165 if (!silent) {
166 beforeRetVal = owner.fireBeforeChangeEvent(event);
167 if (beforeRetVal === false) {
168 YAHOO.log('setValue ' + name +
169 'cancelled by beforeChange event', 'info', 'Attribute');
170 return false;
171 }
172 }
173
174 if (this.method) {
175 this.method.call(owner, value);
176 }
177
178 this.value = value;
179 this._written = true;
180
181 event.type = name;
182
183 if (!silent) {
184 this.owner.fireChangeEvent(event);
185 }
186
187 return true;
188 },
189
190 /**
191 * Allows for configuring the Attribute's properties.
192 * @method configure
193 * @param {Object} map A key-value map of Attribute properties.
194 * @param {Boolean} init Whether or not this should become the initial config.
195 */
196 configure: function(map, init) {
197 map = map || {};
198 this._written = false; // reset writeOnce
199 this._initialConfig = this._initialConfig || {};
200
201 for (var key in map) {
202 if ( key && map.hasOwnProperty(key) ) {
203 this[key] = map[key];
204 if (init) {
205 this._initialConfig[key] = map[key];
206 }
207 }
208 }
209 },
210
211 /**
212 * Resets the value to the initial config value.
213 * @method resetValue
214 * @return {Boolean} Whether or not the value was set.
215 */
216 resetValue: function() {
217 return this.setValue(this._initialConfig.value);
218 },
219
220 /**
221 * Resets the attribute config to the initial config state.
222 * @method resetConfig
223 */
224 resetConfig: function() {
225 this.configure(this._initialConfig);
226 },
227
228 /**
229 * Resets the value to the current value.
230 * Useful when values may have gotten out of sync with actual properties.
231 * @method refresh
232 * @return {Boolean} Whether or not the value was set.
233 */
234 refresh: function(silent) {
235 this.setValue(this.value, silent);
236 }
237};(function() {
238 var Lang = YAHOO.util.Lang;
239
240 /*
241 Copyright (c) 2006, Yahoo! Inc. All rights reserved.
242 Code licensed under the BSD License:
243 http://developer.yahoo.net/yui/license.txt
244 */
245
246 /**
247 * Provides and manages YAHOO.util.Attribute instances
248 * @namespace YAHOO.util
249 * @class AttributeProvider
250 * @uses YAHOO.util.EventProvider
251 */
252 YAHOO.util.AttributeProvider = function() {};
253
254 YAHOO.util.AttributeProvider.prototype = {
255
256 /**
257 * A key-value map of Attribute configurations
258 * @property _configs
259 * @protected (may be used by subclasses and augmentors)
260 * @private
261 * @type {Object}
262 */
263 _configs: null,
264 /**
265 * Returns the current value of the attribute.
266 * @method get
267 * @param {String} key The attribute whose value will be returned.
268 */
269 get: function(key){
270 var configs = this._configs || {};
271 var config = configs[key];
272
273 if (!config) {
274 YAHOO.log(key + ' not found', 'error', 'AttributeProvider');
275 return undefined;
276 }
277
278 return config.value;
279 },
280
281 /**
282 * Sets the value of a config.
283 * @method set
284 * @param {String} key The name of the attribute
285 * @param {Any} value The value to apply to the attribute
286 * @param {Boolean} silent Whether or not to suppress change events
287 * @return {Boolean} Whether or not the value was set.
288 */
289 set: function(key, value, silent){
290 var configs = this._configs || {};
291 var config = configs[key];
292
293 if (!config) {
294 YAHOO.log('set failed: ' + key + ' not found',
295 'error', 'AttributeProvider');
296 return false;
297 }
298
299 return config.setValue(value, silent);
300 },
301
302 /**
303 * Returns an array of attribute names.
304 * @method getAttributeKeys
305 * @return {Array} An array of attribute names.
306 */
307 getAttributeKeys: function(){
308 var configs = this._configs;
309 var keys = [];
310 var config;
311 for (var key in configs) {
312 config = configs[key];
313 if ( configs.hasOwnProperty(key) &&
314 !Lang.isUndefined(config) ) {
315 keys[keys.length] = key;
316 }
317 }
318
319 return keys;
320 },
321
322 /**
323 * Sets multiple attribute values.
324 * @method setAttributes
325 * @param {Object} map A key-value map of attributes
326 * @param {Boolean} silent Whether or not to suppress change events
327 */
328 setAttributes: function(map, silent){
329 for (var key in map) {
330 if ( map.hasOwnProperty(key) ) {
331 this.set(key, map[key], silent);
332 }
333 }
334 },
335
336 /**
337 * Resets the specified attribute's value to its initial value.
338 * @method resetValue
339 * @param {String} key The name of the attribute
340 * @param {Boolean} silent Whether or not to suppress change events
341 * @return {Boolean} Whether or not the value was set
342 */
343 resetValue: function(key, silent){
344 var configs = this._configs || {};
345 if (configs[key]) {
346 this.set(key, configs[key]._initialConfig.value, silent);
347 return true;
348 }
349 return false;
350 },
351
352 /**
353 * Sets the attribute's value to its current value.
354 * @method refresh
355 * @param {String | Array} key The attribute(s) to refresh
356 * @param {Boolean} silent Whether or not to suppress change events
357 */
358 refresh: function(key, silent){
359 var configs = this._configs;
360
361 key = ( ( Lang.isString(key) ) ? [key] : key ) ||
362 this.getAttributeKeys();
363
364 for (var i = 0, len = key.length; i < len; ++i) {
365 if ( // only set if there is a value and not null
366 configs[key[i]] &&
367 ! Lang.isUndefined(configs[key[i]].value) &&
368 ! Lang.isNull(configs[key[i]].value) ) {
369 configs[key[i]].refresh(silent);
370 }
371 }
372 },
373
374 /**
375 * Adds an Attribute to the AttributeProvider instance.
376 * @method register
377 * @param {String} key The attribute's name
378 * @param {Object} map A key-value map containing the
379 * attribute's properties.
380 */
381 register: function(key, map) {
382 this._configs = this._configs || {};
383
384 if (this._configs[key]) { // dont override
385 return false;
386 }
387
388 map.name = key;
389 this._configs[key] = new YAHOO.util.Attribute(map, this);
390 return true;
391 },
392
393 /**
394 * Returns the attribute's properties.
395 * @method getAttributeConfig
396 * @param {String} key The attribute's name
397 * @private
398 * @return {object} A key-value map containing all of the
399 * attribute's properties.
400 */
401 getAttributeConfig: function(key) {
402 var configs = this._configs || {};
403 var config = configs[key] || {};
404 var map = {}; // returning a copy to prevent overrides
405
406 for (key in config) {
407 if ( config.hasOwnProperty(key) ) {
408 map[key] = config[key];
409 }
410 }
411
412 return map;
413 },
414
415 /**
416 * Sets or updates an Attribute instance's properties.
417 * @method configureAttribute
418 * @param {String} key The attribute's name.
419 * @param {Object} map A key-value map of attribute properties
420 * @param {Boolean} init Whether or not this should become the intial config.
421 */
422 configureAttribute: function(key, map, init) {
423 var configs = this._configs || {};
424
425 if (!configs[key]) {
426 YAHOO.log('unable to configure, ' + key + ' not found',
427 'error', 'AttributeProvider');
428 return false;
429 }
430
431 configs[key].configure(map, init);
432 },
433
434 /**
435 * Resets an attribute to its intial configuration.
436 * @method resetAttributeConfig
437 * @param {String} key The attribute's name.
438 * @private
439 */
440 resetAttributeConfig: function(key){
441 var configs = this._configs || {};
442 configs[key].resetConfig();
443 },
444
445 /**
446 * Fires the attribute's beforeChange event.
447 * @method fireBeforeChangeEvent
448 * @param {String} key The attribute's name.
449 * @param {Obj} e The event object to pass to handlers.
450 */
451 fireBeforeChangeEvent: function(e) {
452 var type = 'before';
453 type += e.type.charAt(0).toUpperCase() + e.type.substr(1) + 'Change';
454 e.type = type;
455 return this.fireEvent(e.type, e);
456 },
457
458 /**
459 * Fires the attribute's change event.
460 * @method fireChangeEvent
461 * @param {String} key The attribute's name.
462 * @param {Obj} e The event object to pass to the handlers.
463 */
464 fireChangeEvent: function(e) {
465 e.type += 'Change';
466 return this.fireEvent(e.type, e);
467 }
468 };
469
470 YAHOO.augment(YAHOO.util.AttributeProvider, YAHOO.util.EventProvider);
471})();(function() {
472// internal shorthand
473var Dom = YAHOO.util.Dom,
474 Lang = YAHOO.util.Lang,
475 EventPublisher = YAHOO.util.EventPublisher,
476 AttributeProvider = YAHOO.util.AttributeProvider;
477
478/**
479 * Element provides an interface to an HTMLElement's attributes and common
480 * methods. Other commonly used attributes are added as well.
481 * @namespace YAHOO.util
482 * @class Element
483 * @uses YAHOO.util.AttributeProvider
484 * @constructor
485 * @param el {HTMLElement | String} The html element that
486 * represents the Element.
487 * @param {Object} map A key-value map of initial config names and values
488 */
489YAHOO.util.Element = function(el, map) {
490 if (arguments.length) {
491 this.init(el, map);
492 }
493};
494
495YAHOO.util.Element.prototype = {
496 /**
497 * Dom events supported by the Element instance.
498 * @property DOM_EVENTS
499 * @type Object
500 */
501 DOM_EVENTS: null,
502
503 /**
504 * Wrapper for HTMLElement method.
505 * @method appendChild
506 * @param {Boolean} deep Whether or not to do a deep clone
507 */
508 appendChild: function(child) {
509 child = child.get ? child.get('element') : child;
510 this.get('element').appendChild(child);
511 },
512
513 /**
514 * Wrapper for HTMLElement method.
515 * @method getElementsByTagName
516 * @param {String} tag The tagName to collect
517 */
518 getElementsByTagName: function(tag) {
519 return this.get('element').getElementsByTagName(tag);
520 },
521
522 /**
523 * Wrapper for HTMLElement method.
524 * @method hasChildNodes
525 * @return {Boolean} Whether or not the element has childNodes
526 */
527 hasChildNodes: function() {
528 return this.get('element').hasChildNodes();
529 },
530
531 /**
532 * Wrapper for HTMLElement method.
533 * @method insertBefore
534 * @param {HTMLElement} element The HTMLElement to insert
535 * @param {HTMLElement} before The HTMLElement to insert
536 * the element before.
537 */
538 insertBefore: function(element, before) {
539 element = element.get ? element.get('element') : element;
540 before = (before && before.get) ? before.get('element') : before;
541
542 this.get('element').insertBefore(element, before);
543 },
544
545 /**
546 * Wrapper for HTMLElement method.
547 * @method removeChild
548 * @param {HTMLElement} child The HTMLElement to remove
549 */
550 removeChild: function(child) {
551 child = child.get ? child.get('element') : child;
552 this.get('element').removeChild(child);
553 return true;
554 },
555
556 /**
557 * Wrapper for HTMLElement method.
558 * @method replaceChild
559 * @param {HTMLElement} newNode The HTMLElement to insert
560 * @param {HTMLElement} oldNode The HTMLElement to replace
561 */
562 replaceChild: function(newNode, oldNode) {
563 newNode = newNode.get ? newNode.get('element') : newNode;
564 oldNode = oldNode.get ? oldNode.get('element') : oldNode;
565 return this.get('element').replaceChild(newNode, oldNode);
566 },
567
568
569 /**
570 * Registers Element specific attributes.
571 * @method initAttributes
572 * @param {Object} map A key-value map of initial attribute configs
573 */
574 initAttributes: function(map) {
575 map = map || {};
576 var element = Dom.get(map.element) || null;
577
578 /**
579 * The HTMLElement the Element instance refers to.
580 * @config element
581 * @type HTMLElement
582 */
583 this.register('element', {
584 value: element,
585 readOnly: true
586 });
587 },
588
589 /**
590 * Adds a listener for the given event. These may be DOM or
591 * customEvent listeners. Any event that is fired via fireEvent
592 * can be listened for. All handlers receive an event object.
593 * @method addListener
594 * @param {String} type The name of the event to listen for
595 * @param {Function} fn The handler to call when the event fires
596 * @param {Any} obj A variable to pass to the handler
597 * @param {Object} scope The object to use for the scope of the handler
598 */
599 addListener: function(type, fn, obj, scope) {
600 var el = this.get('element');
601 var scope = scope || this;
602
603 el = this.get('id') || el;
604
605 if (!this._events[type]) { // create on the fly
606 if ( this.DOM_EVENTS[type] ) {
607 YAHOO.util.Event.addListener(el, type, function(e) {
608 if (e.srcElement && !e.target) { // supplement IE with target
609 e.target = e.srcElement;
610 }
611 this.fireEvent(type, e);
612 }, obj, scope);
613 }
614
615 this.createEvent(type, this);
616 this._events[type] = true;
617 }
618
619 this.subscribe.apply(this, arguments); // notify via customEvent
620 },
621
622
623 /**
624 * Alias for addListener
625 * @method on
626 * @param {String} type The name of the event to listen for
627 * @param {Function} fn The function call when the event fires
628 * @param {Any} obj A variable to pass to the handler
629 * @param {Object} scope The object to use for the scope of the handler
630 */
631 on: function() { this.addListener.apply(this, arguments); },
632
633
634 /**
635 * Remove an event listener
636 * @method removeListener
637 * @param {String} type The name of the event to listen for
638 * @param {Function} fn The function call when the event fires
639 */
640 removeListener: function(type, fn) {
641 this.unsubscribe.apply(this, arguments);
642 },
643
644 /**
645 * Wrapper for Dom method.
646 * @method addClass
647 * @param {String} className The className to add
648 */
649 addClass: function(className) {
650 Dom.addClass(this.get('element'), className);
651 },
652
653 /**
654 * Wrapper for Dom method.
655 * @method getElementsByClassName
656 * @param {String} className The className to collect
657 * @param {String} tag (optional) The tag to use in
658 * conjunction with class name
659 * @return {Array} Array of HTMLElements
660 */
661 getElementsByClassName: function(className, tag) {
662 return Dom.getElementsByClassName(className, tag,
663 this.get('element') );
664 },
665
666 /**
667 * Wrapper for Dom method.
668 * @method hasClass
669 * @param {String} className The className to add
670 * @return {Boolean} Whether or not the element has the class name
671 */
672 hasClass: function(className) {
673 return Dom.hasClass(this.get('element'), className);
674 },
675
676 /**
677 * Wrapper for Dom method.
678 * @method removeClass
679 * @param {String} className The className to remove
680 */
681 removeClass: function(className) {
682 return Dom.removeClass(this.get('element'), className);
683 },
684
685 /**
686 * Wrapper for Dom method.
687 * @method replaceClass
688 * @param {String} oldClassName The className to replace
689 * @param {String} newClassName The className to add
690 */
691 replaceClass: function(oldClassName, newClassName) {
692 return Dom.replaceClass(this.get('element'),
693 oldClassName, newClassName);
694 },
695
696 /**
697 * Wrapper for Dom method.
698 * @method setStyle
699 * @param {String} property The style property to set
700 * @param {String} value The value to apply to the style property
701 */
702 setStyle: function(property, value) {
703 return Dom.setStyle(this.get('element'), property, value);
704 },
705
706 /**
707 * Wrapper for Dom method.
708 * @method getStyle
709 * @param {String} property The style property to retrieve
710 * @return {String} The current value of the property
711 */
712 getStyle: function(property) {
713 return Dom.getStyle(this.get('element'), property);
714 },
715
716 /**
717 * Apply any queued set calls.
718 * @method fireQueue
719 */
720 fireQueue: function() {
721 var queue = this._queue;
722 for (var i = 0, len = queue.length; i < len; ++i) {
723 this[queue[i][0]].apply(this, queue[i][1]);
724 }
725 },
726
727 /**
728 * Appends the HTMLElement into either the supplied parentNode.
729 * @method appendTo
730 * @param {HTMLElement | Element} parentNode The node to append to
731 * @param {HTMLElement | Element} before An optional node to insert before
732 */
733 appendTo: function(parent, before) {
734 parent = (parent.get) ? parent.get('element') : Dom.get(parent);
735
736 before = (before && before.get) ?
737 before.get('element') : Dom.get(before);
738 var element = this.get('element');
739
740 var newAddition = !Dom.inDocument(element);
741
742 if (!element) {
743 YAHOO.log('appendTo failed: element not available',
744 'error', 'Element');
745 return false;
746 }
747
748 if (!parent) {
749 YAHOO.log('appendTo failed: parent not available',
750 'error', 'Element');
751 return false;
752 }
753
754 if (element.parent != parent) {
755 if (before) {
756 parent.insertBefore(element, before);
757 } else {
758 parent.appendChild(element);
759 }
760 }
761
762 YAHOO.log(element + 'appended to ' + parent);
763
764 if (!newAddition) {
765 return false; // note return; no refresh if in document
766 }
767
768 // if a new addition, refresh HTMLElement any applied attributes
769 var keys = this.getAttributeKeys();
770
771 for (var key in keys) { // only refresh HTMLElement attributes
772 if ( !Lang.isUndefined(element[key]) ) {
773 this.refresh(key);
774 }
775 }
776 },
777
778 get: function(key) {
779 var configs = this._configs || {};
780 var el = configs.element; // avoid loop due to 'element'
781 if (el && !configs[key] && !Lang.isUndefined(el.value[key]) ) {
782 return el.value[key];
783 }
784
785 return AttributeProvider.prototype.get.call(this, key);
786 },
787
788 set: function(key, value, silent) {
789 var el = this.get('element');
790 if (!el) {
791 this._queue[key] = ['set', arguments];
792 return false;
793 }
794
795 // set it on the element if not a property
796 if ( !this._configs[key] && !Lang.isUndefined(el[key]) ) {
797 _registerHTMLAttr(this, key);
798 }
799
800 return AttributeProvider.prototype.set.apply(this, arguments);
801 },
802
803 register: function(key) { // protect html attributes
804 var configs = this._configs || {};
805 var element = this.get('element') || null;
806
807 if ( element && !Lang.isUndefined(element[key]) ) {
808 YAHOO.log(key + ' is reserved for ' + element,
809 'error', 'Element');
810 return false;
811 }
812
813 return AttributeProvider.prototype.register.apply(this, arguments);
814 },
815
816 configureAttribute: function(property, map, init) { // protect html attributes
817 if (!this._configs[property] && this._configs.element &&
818 !Lang.isUndefined(this._configs.element[property]) ) {
819 _registerHTMLAttr(this, property, map);
820 return false;
821 }
822
823 return AttributeProvider.prototype.configure.apply(this, arguments);
824 },
825
826 getAttributeKeys: function() {
827 var el = this.get('element');
828 var keys = AttributeProvider.prototype.getAttributeKeys.call(this);
829
830 //add any unconfigured element keys
831 for (var key in el) {
832 if (!this._configs[key]) {
833 keys[key] = keys[key] || el[key];
834 }
835 }
836
837 return keys;
838 },
839
840 init: function(el, attr) {
841 this._queue = this._queue || [];
842 this._events = this._events || {};
843 this._configs = this._configs || {};
844 attr = attr || {};
845 attr.element = attr.element || el || null;
846
847 this.DOM_EVENTS = {
848 'click': true,
849 'keydown': true,
850 'keypress': true,
851 'keyup': true,
852 'mousedown': true,
853 'mousemove': true,
854 'mouseout': true,
855 'mouseover': true,
856 'mouseup': true
857 };
858
859 var readyHandler = function() {
860 this.initAttributes(attr);
861
862 this.setAttributes(attr, true);
863 this.fireQueue();
864 this.fireEvent('contentReady', {
865 type: 'contentReady',
866 target: attr.element
867 });
868 };
869
870 if ( Lang.isString(el) ) {
871 _registerHTMLAttr(this, 'id', { value: el });
872 YAHOO.util.Event.onAvailable(el, function() {
873 attr.element = Dom.get(el);
874 this.fireEvent('available', {
875 type: 'available',
876 target: attr.element
877 });
878 }, this, true);
879
880 YAHOO.util.Event.onContentReady(el, function() {
881 readyHandler.call(this);
882 }, this, true);
883 } else {
884 readyHandler.call(this);
885 }
886 }
887};
888
889/**
890 * Sets the value of the property and fires beforeChange and change events.
891 * @private
892 * @method _registerHTMLAttr
893 * @param {YAHOO.util.Element} element The Element instance to
894 * register the config to.
895 * @param {String} key The name of the config to register
896 * @param {Object} map A key-value map of the config's params
897 */
898var _registerHTMLAttr = function(self, key, map) {
899 var el = self.get('element');
900 map = map || {};
901 map.name = key;
902 map.method = map.method || function(value) {
903 el[key] = value;
904 };
905 map.value = map.value || el[key];
906 self._configs[key] = new YAHOO.util.Attribute(map, self);
907};
908
909/**
910 * Fires when the Element's HTMLElement can be retrieved by Id.
911 * <p>See: <a href="#addListener">Element.addListener</a></p>
912 * <p><strong>Event fields:</strong><br>
913 * <code>&lt;String&gt; type</code> available<br>
914 * <code>&lt;HTMLElement&gt;
915 * target</code> the HTMLElement bound to this Element instance<br>
916 * <p><strong>Usage:</strong><br>
917 * <code>var handler = function(e) {var target = e.target};<br>
918 * myTabs.addListener('available', handler);</code></p>
919 * @event available
920 */
921
922/**
923 * Fires when the Element's HTMLElement subtree is rendered.
924 * <p>See: <a href="#addListener">Element.addListener</a></p>
925 * <p><strong>Event fields:</strong><br>
926 * <code>&lt;String&gt; type</code> contentReady<br>
927 * <code>&lt;HTMLElement&gt;
928 * target</code> the HTMLElement bound to this Element instance<br>
929 * <p><strong>Usage:</strong><br>
930 * <code>var handler = function(e) {var target = e.target};<br>
931 * myTabs.addListener('contentReady', handler);</code></p>
932 * @event contentReady
933 */
934
935YAHOO.augment(YAHOO.util.Element, AttributeProvider);
936})();(function() {
937 var Dom = YAHOO.util.Dom,
938 Event = YAHOO.util.Event,
939 Lang = YAHOO.util.Lang;
940
941 /**
942 * A representation of a Tab's label and content.
943 * @namespace YAHOO.widget
944 * @class Tab
945 * @extends YAHOO.util.Element
946 * @constructor
947 * @param element {HTMLElement | String} (optional) The html element that
948 * represents the TabView. An element will be created if none provided.
949 * @param {Object} properties A key map of initial properties
950 */
951 Tab = function(el, attr) {
952 attr = attr || {};
953 if (arguments.length == 1 && !Lang.isString(el) && !el.nodeName) {
954 attr = el;
955 el = attr.element;
956 }
957
958 if (!el && !attr.element) {
959 el = _createTabElement.call(this, attr);
960 }
961
962 this.loadHandler = {
963 success: function(o) {
964 this.set('content', o.responseText);
965 },
966 failure: function(o) {
967 YAHOO.log('loading failed: ' + o.statusText,
968 'error', 'Tab');
969 }
970 };
971
972 Tab.superclass.constructor.call(this, el, attr);
973
974 this.DOM_EVENTS = {}; // delegating to tabView
975 };
976
977 YAHOO.extend(Tab, YAHOO.util.Element);
978 var proto = Tab.prototype;
979
980 /**
981 * The default tag name for a Tab's inner element.
982 * @property LABEL_INNER_TAGNAME
983 * @type String
984 * @default "em"
985 */
986 proto.LABEL_TAGNAME = 'em';
987
988 /**
989 * The class name applied to active tabs.
990 * @property ACTIVE_CLASSNAME
991 * @type String
992 * @default "on"
993 */
994 proto.ACTIVE_CLASSNAME = 'selected';
995
996 /**
997 * The class name applied to disabled tabs.
998 * @property DISABLED_CLASSNAME
999 * @type String
1000 * @default "disabled"
1001 */
1002 proto.DISABLED_CLASSNAME = 'disabled';
1003
1004 /**
1005 * The class name applied to dynamic tabs while loading.
1006 * @property LOADING_CLASSNAME
1007 * @type String
1008 * @default "disabled"
1009 */
1010 proto.LOADING_CLASSNAME = 'loading';
1011
1012 /**
1013 * Provides a reference to the connection request object when data is
1014 * loaded dynamically.
1015 * @property dataConnection
1016 * @type Object
1017 */
1018 proto.dataConnection = null;
1019
1020 /**
1021 * Object containing success and failure callbacks for loading data.
1022 * @property loadHandler
1023 * @type object
1024 */
1025 proto.loadHandler = null;
1026
1027 /**
1028 * Provides a readable name for the tab.
1029 * @method toString
1030 * @return String
1031 */
1032 proto.toString = function() {
1033 var el = this.get('element');
1034 var id = el.id || el.tagName;
1035 return "Tab " + id;
1036 };
1037
1038 /**
1039 * Registers TabView specific properties.
1040 * @method initAttributes
1041 * @param {Object} attr Hash of initial attributes
1042 */
1043 proto.initAttributes = function(attr) {
1044 attr = attr || {};
1045 Tab.superclass.initAttributes.call(this, attr);
1046
1047 var el = this.get('element');
1048
1049 /**
1050 * The event that triggers the tab's activation.
1051 * @config activationEvent
1052 * @type String
1053 */
1054 this.register('activationEvent', {
1055 value: attr.activationEvent || 'click'
1056 });
1057
1058 /**
1059 * The element that contains the tab's label.
1060 * @config labelEl
1061 * @type HTMLElement
1062 */
1063 this.register('labelEl', {
1064 value: attr.labelEl || _getlabelEl.call(this),
1065 method: function(value) {
1066 var current = this.get('labelEl');
1067
1068 if (current) {
1069 if (current == value) {
1070 return false; // already set
1071 }
1072
1073 this.replaceChild(value, current);
1074 } else if (el.firstChild) { // ensure label is firstChild by default
1075 this.insertBefore(value, el.firstChild);
1076 } else {
1077 this.appendChild(value);
1078 }
1079 }
1080 });
1081
1082 /**
1083 * The tab's label text (or innerHTML).
1084 * @config label
1085 * @type String
1086 */
1087 this.register('label', {
1088 value: attr.label || _getLabel.call(this),
1089 method: function(value) {
1090 var labelEl = this.get('labelEl');
1091 if (!labelEl) { // create if needed
1092 this.set('labelEl', _createlabelEl.call(this));
1093 }
1094
1095 _setLabel.call(this, value);
1096 }
1097 });
1098
1099 /**
1100 * The HTMLElement that contains the tab's content.
1101 * @config contentEl
1102 * @type HTMLElement
1103 */
1104 this.register('contentEl', { // TODO: apply className?
1105 value: attr.contentEl || document.createElement('div'),
1106 method: function(value) {
1107 var current = this.get('contentEl');
1108
1109 if (current) {
1110 if (current == value) {
1111 return false; // already set
1112 }
1113 this.replaceChild(value, current);
1114 }
1115 }
1116 });
1117
1118 /**
1119 * The tab's content.
1120 * @config content
1121 * @type String
1122 */
1123 this.register('content', {
1124 value: attr.content, // TODO: what about existing?
1125 method: function(value) {
1126 this.get('contentEl').innerHTML = value;
1127 }
1128 });
1129
1130 var _dataLoaded = false;
1131
1132 /**
1133 * The tab's data source, used for loading content dynamically.
1134 * @config dataSrc
1135 * @type String
1136 */
1137 this.register('dataSrc', {
1138 value: attr.dataSrc
1139 });
1140
1141 /**
1142 * Whether or not content should be reloaded for every view.
1143 * @config cacheData
1144 * @type Boolean
1145 * @default false
1146 */
1147 this.register('cacheData', {
1148 value: attr.cacheData || false,
1149 validator: Lang.isBoolean
1150 });
1151
1152 /**
1153 * The method to use for the data request.
1154 * @config loadMethod
1155 * @type String
1156 * @default "GET"
1157 */
1158 this.register('loadMethod', {
1159 value: attr.loadMethod || 'GET',
1160 validator: Lang.isString
1161 });
1162
1163 /**
1164 * Whether or not any data has been loaded from the server.
1165 * @config dataLoaded
1166 * @type Boolean
1167 */
1168 this.register('dataLoaded', {
1169 value: false,
1170 validator: Lang.isBoolean,
1171 writeOnce: true
1172 });
1173
1174 /**
1175 * Number if milliseconds before aborting and calling failure handler.
1176 * @config dataTimeout
1177 * @type Number
1178 * @default null
1179 */
1180 this.register('dataTimeout', {
1181 value: attr.dataTimeout || null,
1182 validator: Lang.isNumber
1183 });
1184
1185 /**
1186 * Whether or not the tab is currently active.
1187 * If a dataSrc is set for the tab, the content will be loaded from
1188 * the given source.
1189 * @config active
1190 * @type Boolean
1191 */
1192 this.register('active', {
1193 value: attr.active || this.hasClass(this.ACTIVE_CLASSNAME),
1194 method: function(value) {
1195 if (value === true) {
1196 this.addClass(this.ACTIVE_CLASSNAME);
1197 this.set('title', 'active');
1198 } else {
1199 this.removeClass(this.ACTIVE_CLASSNAME);
1200 this.set('title', '');
1201 }
1202 },
1203 validator: function(value) {
1204 return Lang.isBoolean(value) && !this.get('disabled') ;
1205 }
1206 });
1207
1208 /**
1209 * Whether or not the tab is disabled.
1210 * @config disabled
1211 * @type Boolean
1212 */
1213 this.register('disabled', {
1214 value: attr.disabled || this.hasClass(this.DISABLED_CLASSNAME),
1215 method: function(value) {
1216 if (value === true) {
1217 Dom.addClass(this.get('element'), this.DISABLED_CLASSNAME);
1218 } else {
1219 Dom.removeClass(this.get('element'), this.DISABLED_CLASSNAME);
1220 }
1221 },
1222 validator: Lang.isBoolean
1223 });
1224
1225 /**
1226 * The href of the tab's anchor element.
1227 * @config href
1228 * @type String
1229 * @default '#'
1230 */
1231 this.register('href', {
1232 value: attr.href || '#',
1233 method: function(value) {
1234 this.getElementsByTagName('a')[0].href = value;
1235 },
1236 validator: Lang.isString
1237 });
1238
1239 /**
1240 * The Whether or not the tab's content is visible.
1241 * @config contentVisible
1242 * @type Boolean
1243 * @default false
1244 */
1245 this.register('contentVisible', {
1246 value: attr.contentVisible,
1247 method: function(value) {
1248 if (value == true) {
1249 this.get('contentEl').style.display = 'block';
1250
1251 if ( this.get('dataSrc') ) {
1252 // load dynamic content unless already loaded and caching
1253 if ( !this.get('dataLoaded') || !this.get('cacheData') ) {
1254 _dataConnect.call(this);
1255 }
1256 }
1257 } else {
1258 this.get('contentEl').style.display = 'none';
1259 }
1260 },
1261 validator: Lang.isBoolean
1262 });
1263 };
1264
1265 var _createTabElement = function(attr) {
1266 var el = document.createElement('li');
1267 var a = document.createElement('a');
1268
1269 a.href = attr.href || '#';
1270
1271 el.appendChild(a);
1272
1273 var label = attr.label || null;
1274 var labelEl = attr.labelEl || null;
1275
1276 if (labelEl) { // user supplied labelEl
1277 if (!label) { // user supplied label
1278 label = _getLabel.call(this, labelEl);
1279 }
1280 } else {
1281 labelEl = _createlabelEl.call(this);
1282 }
1283
1284 a.appendChild(labelEl);
1285
1286 return el;
1287 };
1288
1289 var _getlabelEl = function() {
1290 return this.getElementsByTagName(this.LABEL_TAGNAME)[0];
1291 };
1292
1293 var _createlabelEl = function() {
1294 var el = document.createElement(this.LABEL_TAGNAME);
1295 return el;
1296 };
1297
1298 var _setLabel = function(label) {
1299 var el = this.get('labelEl');
1300 el.innerHTML = label;
1301 };
1302
1303 var _getLabel = function() {
1304 var label,
1305 el = this.get('labelEl');
1306
1307 if (!el) {
1308 return undefined;
1309 }
1310
1311 return el.innerHTML;
1312 };
1313
1314 var _dataConnect = function() {
1315 if (!YAHOO.util.Connect) {
1316 YAHOO.log('YAHOO.util.Connect dependency not met',
1317 'error', 'Tab');
1318 return false;
1319 }
1320
1321 Dom.addClass(this.get('contentEl').parentNode, this.LOADING_CLASSNAME);
1322
1323 this.dataConnection = YAHOO.util.Connect.asyncRequest(
1324 this.get('loadMethod'),
1325 this.get('dataSrc'),
1326 {
1327 success: function(o) {
1328 this.loadHandler.success.call(this, o);
1329 this.set('dataLoaded', true);
1330 this.dataConnection = null;
1331 Dom.removeClass(this.get('contentEl').parentNode,
1332 this.LOADING_CLASSNAME);
1333 },
1334 failure: function(o) {
1335 this.loadHandler.failure.call(this, o);
1336 this.dataConnection = null;
1337 Dom.removeClass(this.get('contentEl').parentNode,
1338 this.LOADING_CLASSNAME);
1339 },
1340 scope: this,
1341 timeout: this.get('dataTimeout')
1342 }
1343 );
1344 };
1345
1346 YAHOO.widget.Tab = Tab;
1347
1348 /**
1349 * Fires before the active state is changed.
1350 * <p>See: <a href="YAHOO.util.Element.html#addListener">Element.addListener</a></p>
1351 * <p>If handler returns false, the change will be cancelled, and the value will not
1352 * be set.</p>
1353 * <p><strong>Event fields:</strong><br>
1354 * <code>&lt;String&gt; type</code> beforeActiveChange<br>
1355 * <code>&lt;Boolean&gt;
1356 * prevValue</code> the current value<br>
1357 * <code>&lt;Boolean&gt;
1358 * newValue</code> the new value</p>
1359 * <p><strong>Usage:</strong><br>
1360 * <code>var handler = function(e) {var previous = e.prevValue};<br>
1361 * myTabs.addListener('beforeActiveChange', handler);</code></p>
1362 * @event beforeActiveChange
1363 */
1364
1365 /**
1366 * Fires after the active state is changed.
1367 * <p>See: <a href="YAHOO.util.Element.html#addListener">Element.addListener</a></p>
1368 * <p><strong>Event fields:</strong><br>
1369 * <code>&lt;String&gt; type</code> activeChange<br>
1370 * <code>&lt;Boolean&gt;
1371 * prevValue</code> the previous value<br>
1372 * <code>&lt;Boolean&gt;
1373 * newValue</code> the updated value</p>
1374 * <p><strong>Usage:</strong><br>
1375 * <code>var handler = function(e) {var previous = e.prevValue};<br>
1376 * myTabs.addListener('activeChange', handler);</code></p>
1377 * @event activeChange
1378 */
1379
1380 /**
1381 * Fires before the tab label is changed.
1382 * <p>See: <a href="YAHOO.util.Element.html#addListener">Element.addListener</a></p>
1383 * <p>If handler returns false, the change will be cancelled, and the value will not
1384 * be set.</p>
1385 * <p><strong>Event fields:</strong><br>
1386 * <code>&lt;String&gt; type</code> beforeLabelChange<br>
1387 * <code>&lt;String&gt;
1388 * prevValue</code> the current value<br>
1389 * <code>&lt;String&gt;
1390 * newValue</code> the new value</p>
1391 * <p><strong>Usage:</strong><br>
1392 * <code>var handler = function(e) {var previous = e.prevValue};<br>
1393 * myTabs.addListener('beforeLabelChange', handler);</code></p>
1394 * @event beforeLabelChange
1395 */
1396
1397 /**
1398 * Fires after the tab label is changed.
1399 * <p>See: <a href="YAHOO.util.Element.html#addListener">Element.addListener</a></p>
1400 * <p><strong>Event fields:</strong><br>
1401 * <code>&lt;String&gt; type</code> labelChange<br>
1402 * <code>&lt;String&gt;
1403 * prevValue</code> the previous value<br>
1404 * <code>&lt;String&gt;
1405 * newValue</code> the updated value</p>
1406 * <p><strong>Usage:</strong><br>
1407 * <code>var handler = function(e) {var previous = e.prevValue};<br>
1408 * myTabs.addListener('labelChange', handler);</code></p>
1409 * @event labelChange
1410 */
1411
1412 /**
1413 * Fires before the tab content is changed.
1414 * <p>See: <a href="YAHOO.util.Element.html#addListener">Element.addListener</a></p>
1415 * <p>If handler returns false, the change will be cancelled, and the value will not
1416 * be set.</p>
1417 * <p><strong>Event fields:</strong><br>
1418 * <code>&lt;String&gt; type</code> beforeContentChange<br>
1419 * <code>&lt;String&gt;
1420 * prevValue</code> the current value<br>
1421 * <code>&lt;String&gt;
1422 * newValue</code> the new value</p>
1423 * <p><strong>Usage:</strong><br>
1424 * <code>var handler = function(e) {var previous = e.prevValue};<br>
1425 * myTabs.addListener('beforeContentChange', handler);</code></p>
1426 * @event beforeContentChange
1427 */
1428
1429 /**
1430 * Fires after the tab content is changed.
1431 * <p>See: <a href="YAHOO.util.Element.html#addListener">Element.addListener</a></p>
1432 * <p><strong>Event fields:</strong><br>
1433 * <code>&lt;String&gt; type</code> contentChange<br>
1434 * <code>&lt;String&gt;
1435 * prevValue</code> the previous value<br>
1436 * <code>&lt;Boolean&gt;
1437 * newValue</code> the updated value</p>
1438 * <p><strong>Usage:</strong><br>
1439 * <code>var handler = function(e) {var previous = e.prevValue};<br>
1440 * myTabs.addListener('contentChange', handler);</code></p>
1441 * @event contentChange
1442 */
1443})();(function() {
1444
1445 /**
1446 * The tabview module provides a widget for managing content bound to tabs.
1447 * @module tabview
1448 *
1449 */
1450 /**
1451 * A widget to control tabbed views.
1452 * @namespace YAHOO.widget
1453 * @class TabView
1454 * @extends YAHOO.util.Element
1455 * @constructor
1456 * @param {HTMLElement | String | Object} el(optional) The html
1457 * element that represents the TabView, or the attribute object to use.
1458 * An element will be created if none provided.
1459 * @param {Object} attr (optional) A key map of the tabView's
1460 * initial attributes. Ignored if first arg is attributes object.
1461 */
1462 YAHOO.widget.TabView = function(el, attr) {
1463 attr = attr || {};
1464 if (arguments.length == 1 && !Lang.isString(el) && !el.nodeName) {
1465 attr = el; // treat first arg as attr object
1466 el = attr.element || null;
1467 }
1468
1469 if (!el && !attr.element) { // create if we dont have one
1470 el = _createTabViewElement.call(this, attr);
1471 }
1472 YAHOO.widget.TabView.superclass.constructor.call(this, el, attr);
1473 };
1474
1475 YAHOO.extend(YAHOO.widget.TabView, YAHOO.util.Element);
1476
1477 var proto = YAHOO.widget.TabView.prototype;
1478 var Dom = YAHOO.util.Dom;
1479 var Lang = YAHOO.util.Lang;
1480 var Event = YAHOO.util.Event;
1481 var Tab = YAHOO.widget.Tab;
1482
1483
1484 /**
1485 * The className to add when building from scratch.
1486 * @property CLASSNAME
1487 * @default "navset"
1488 */
1489 proto.CLASSNAME = 'yui-navset';
1490
1491 /**
1492 * The className of the HTMLElement containing the TabView's tab elements
1493 * to look for when building from existing markup, or to add when building
1494 * from scratch.
1495 * All childNodes of the tab container are treated as Tabs when building
1496 * from existing markup.
1497 * @property TAB_PARENT_CLASSNAME
1498 * @default "nav"
1499 */
1500 proto.TAB_PARENT_CLASSNAME = 'yui-nav';
1501
1502 /**
1503 * The className of the HTMLElement containing the TabView's label elements
1504 * to look for when building from existing markup, or to add when building
1505 * from scratch.
1506 * All childNodes of the content container are treated as content elements when
1507 * building from existing markup.
1508 * @property CONTENT_PARENT_CLASSNAME
1509 * @default "nav-content"
1510 */
1511 proto.CONTENT_PARENT_CLASSNAME = 'yui-content';
1512
1513 proto._tabParent = null;
1514 proto._contentParent = null;
1515
1516 /**
1517 * Adds a Tab to the TabView instance.
1518 * If no index is specified, the tab is added to the end of the tab list.
1519 * @method addTab
1520 * @param {YAHOO.widget.Tab} tab A Tab instance to add.
1521 * @param {Integer} index The position to add the tab.
1522 * @return void
1523 */
1524 proto.addTab = function(tab, index) {
1525 var tabs = this.get('tabs');
1526 if (!tabs) { // not ready yet
1527 this._queue[this._queue.length] = ['addTab', arguments];
1528 return false;
1529 }
1530
1531 index = (index === undefined) ? tabs.length : index;
1532
1533 var before = this.getTab(index);
1534
1535 var self = this;
1536 var el = this.get('element');
1537 var tabParent = this._tabParent;
1538 var contentParent = this._contentParent;
1539
1540 var tabElement = tab.get('element');
1541 var contentEl = tab.get('contentEl');
1542
1543 if ( before ) {
1544 tabParent.insertBefore(tabElement, before.get('element'));
1545 } else {
1546 tabParent.appendChild(tabElement);
1547 }
1548
1549 if ( contentEl && !Dom.isAncestor(contentParent, contentEl) ) {
1550 contentParent.appendChild(contentEl);
1551 }
1552
1553 if ( !tab.get('active') ) {
1554 tab.set('contentVisible', false, true); /* hide if not active */
1555 } else {
1556 this.set('activeTab', tab, true);
1557
1558 }
1559
1560 var activate = function(e) {
1561 YAHOO.util.Event.preventDefault(e);
1562 self.set('activeTab', this);
1563 };
1564
1565 tab.addListener( tab.get('activationEvent'), activate);
1566
1567 tab.addListener('activationEventChange', function(e) {
1568 if (e.prevValue != e.newValue) {
1569 tab.removeListener(e.prevValue, activate);
1570 tab.addListener(e.newValue, activate);
1571 }
1572 });
1573
1574 tabs.splice(index, 0, tab);
1575 };
1576
1577 /**
1578 * Routes childNode events.
1579 * @method DOMEventHandler
1580 * @param {event} e The Dom event that is being handled.
1581 * @return void
1582 */
1583 proto.DOMEventHandler = function(e) {
1584 var el = this.get('element');
1585 var target = YAHOO.util.Event.getTarget(e);
1586 var tabParent = this._tabParent;
1587
1588 if (Dom.isAncestor(tabParent, target) ) {
1589 var tabEl;
1590 var tab = null;
1591 var contentEl;
1592 var tabs = this.get('tabs');
1593
1594 for (var i = 0, len = tabs.length; i < len; i++) {
1595 tabEl = tabs[i].get('element');
1596 contentEl = tabs[i].get('contentEl');
1597
1598 if ( target == tabEl || Dom.isAncestor(tabEl, target) ) {
1599 tab = tabs[i];
1600 break; // note break
1601 }
1602 }
1603
1604 if (tab) {
1605 tab.fireEvent(e.type, e);
1606 }
1607 }
1608 };
1609
1610 /**
1611 * Returns the Tab instance at the specified index.
1612 * @method getTab
1613 * @param {Integer} index The position of the Tab.
1614 * @return YAHOO.widget.Tab
1615 */
1616 proto.getTab = function(index) {
1617 return this.get('tabs')[index];
1618 };
1619
1620 /**
1621 * Returns the index of given tab.
1622 * @method getTabIndex
1623 * @param {YAHOO.widget.Tab} tab The tab whose index will be returned.
1624 * @return int
1625 */
1626 proto.getTabIndex = function(tab) {
1627 var index = null;
1628 var tabs = this.get('tabs');
1629 for (var i = 0, len = tabs.length; i < len; ++i) {
1630 if (tab == tabs[i]) {
1631 index = i;
1632 break;
1633 }
1634 }
1635
1636 return index;
1637 };
1638
1639 /**
1640 * Removes the specified Tab from the TabView.
1641 * @method removeTab
1642 * @param {YAHOO.widget.Tab} item The Tab instance to be removed.
1643 * @return void
1644 */
1645 proto.removeTab = function(tab) {
1646 var tabCount = this.get('tabs').length;
1647
1648 var index = this.getTabIndex(tab);
1649 var nextIndex = index + 1;
1650 if ( tab == this.get('activeTab') ) { // select next tab
1651 if (tabCount > 1) {
1652 if (index + 1 == tabCount) {
1653 this.set('activeIndex', index - 1);
1654 } else {
1655 this.set('activeIndex', index + 1);
1656 }
1657 }
1658 }
1659
1660 this._tabParent.removeChild( tab.get('element') );
1661 this._contentParent.removeChild( tab.get('contentEl') );
1662 this._configs.tabs.value.splice(index, 1);
1663
1664 };
1665
1666 /**
1667 * Provides a readable name for the TabView instance.
1668 * @method toString
1669 * @return String
1670 */
1671 proto.toString = function() {
1672 var name = this.get('id') || this.get('tagName');
1673 return "TabView " + name;
1674 };
1675
1676 /**
1677 * The transiton to use when switching between tabs.
1678 * @method contentTransition
1679 */
1680 proto.contentTransition = function(newTab, oldTab) {
1681 newTab.set('contentVisible', true);
1682 oldTab.set('contentVisible', false);
1683 };
1684
1685 /**
1686 * Registers TabView specific properties.
1687 * @method initAttributes
1688 * @param {Object} attr Hash of initial attributes
1689 */
1690 proto.initAttributes = function(attr) {
1691 YAHOO.widget.TabView.superclass.initAttributes.call(this, attr);
1692
1693 if (!attr.orientation) {
1694 attr.orientation = 'top';
1695 }
1696
1697 var el = this.get('element');
1698
1699 /**
1700 * The Tabs belonging to the TabView instance.
1701 * @config tabs
1702 * @type Array
1703 */
1704 this.register('tabs', {
1705 value: [],
1706 readOnly: true
1707 });
1708
1709 /**
1710 * The container of the tabView's label elements.
1711 * @property _tabParent
1712 * @private
1713 * @type HTMLElement
1714 */
1715 this._tabParent =
1716 this.getElementsByClassName(this.TAB_PARENT_CLASSNAME,
1717 'ul' )[0] || _createTabParent.call(this);
1718
1719 /**
1720 * The container of the tabView's content elements.
1721 * @property _contentParent
1722 * @type HTMLElement
1723 * @private
1724 */
1725 this._contentParent =
1726 this.getElementsByClassName(this.CONTENT_PARENT_CLASSNAME,
1727 'div')[0] || _createContentParent.call(this);
1728
1729 /**
1730 * How the Tabs should be oriented relative to the TabView.
1731 * @config orientation
1732 * @type String
1733 * @default "top"
1734 */
1735 this.register('orientation', {
1736 value: attr.orientation,
1737 method: function(value) {
1738 var current = this.get('orientation');
1739 this.addClass('yui-navset-' + value);
1740
1741 if (current != value) {
1742 this.removeClass('yui-navset-' + current);
1743 }
1744
1745 switch(value) {
1746 case 'bottom':
1747 this.appendChild(this._tabParent);
1748 break;
1749 }
1750 }
1751 });
1752
1753 /**
1754 * The index of the tab currently active.
1755 * @config activeIndex
1756 * @type Int
1757 */
1758 this.register('activeIndex', {
1759 value: attr.activeIndex,
1760 method: function(value) {
1761 this.set('activeTab', this.getTab(value));
1762 },
1763 validator: function(value) {
1764 return !this.getTab(value).get('disabled'); // cannot activate if disabled
1765 }
1766 });
1767
1768 /**
1769 * The tab currently active.
1770 * @config activeTab
1771 * @type YAHOO.widget.Tab
1772 */
1773 this.register('activeTab', {
1774 value: attr.activeTab,
1775 method: function(tab) {
1776 var activeTab = this.get('activeTab');
1777
1778 if (tab) {
1779 tab.set('active', true);
1780 }
1781
1782 if (activeTab && activeTab != tab) {
1783 activeTab.set('active', false);
1784 }
1785
1786 if (activeTab && tab != activeTab) { // no transition if only 1
1787 this.contentTransition(tab, activeTab);
1788 } else if (tab) {
1789 tab.set('contentVisible', true);
1790 }
1791 },
1792 validator: function(value) {
1793 return !value.get('disabled'); // cannot activate if disabled
1794 }
1795 });
1796
1797 if ( this._tabParent ) {
1798 _initTabs.call(this);
1799 }
1800
1801 for (var type in this.DOM_EVENTS) {
1802 if ( this.DOM_EVENTS.hasOwnProperty(type) ) {
1803 this.addListener.call(this, type, this.DOMEventHandler);
1804 }
1805 }
1806 };
1807
1808 /**
1809 * Creates Tab instances from a collection of HTMLElements.
1810 * @method createTabs
1811 * @private
1812 * @param {Array|HTMLCollection} elements The elements to use for Tabs.
1813 * @return void
1814 */
1815 var _initTabs = function() {
1816 var tab,
1817 attr,
1818 contentEl;
1819
1820 var el = this.get('element');
1821 var tabs = _getChildNodes(this._tabParent);
1822 var contentElements = _getChildNodes(this._contentParent);
1823
1824 for (var i = 0, len = tabs.length; i < len; ++i) {
1825 attr = {};
1826
1827 if (contentElements[i]) {
1828 attr.contentEl = contentElements[i];
1829 }
1830
1831 tab = new YAHOO.widget.Tab(tabs[i], attr);
1832 this.addTab(tab);
1833
1834 if (tab.hasClass(tab.ACTIVE_CLASSNAME) ) {
1835 this._configs.activeTab.value = tab; // dont invoke method
1836 }
1837 }
1838 };
1839
1840 var _createTabViewElement = function(attr) {
1841 var el = document.createElement('div');
1842
1843 if ( this.CLASSNAME ) {
1844 el.className = this.CLASSNAME;
1845 }
1846
1847 return el;
1848 };
1849
1850 var _createTabParent = function(attr) {
1851 var el = document.createElement('ul');
1852
1853 if ( this.TAB_PARENT_CLASSNAME ) {
1854 el.className = this.TAB_PARENT_CLASSNAME;
1855 }
1856
1857 this.get('element').appendChild(el);
1858
1859 return el;
1860 };
1861
1862 var _createContentParent = function(attr) {
1863 var el = document.createElement('div');
1864
1865 if ( this.CONTENT_PARENT_CLASSNAME ) {
1866 el.className = this.CONTENT_PARENT_CLASSNAME;
1867 }
1868
1869 this.get('element').appendChild(el);
1870
1871 return el;
1872 };
1873
1874 var _getChildNodes = function(el) {
1875 var nodes = [];
1876 var childNodes = el.childNodes;
1877
1878 for (var i = 0, len = childNodes.length; i < len; ++i) {
1879 if (childNodes[i].nodeType == 1) {
1880 nodes[nodes.length] = childNodes[i];
1881 }
1882 }
1883
1884 return nodes;
1885 };
1886
1887/**
1888 * Fires before the activeTab is changed.
1889 * <p>See: <a href="YAHOO.util.Element.html#addListener">Element.addListener</a></p>
1890 * <p>If handler returns false, the change will be cancelled, and the value will not
1891 * be set.</p>
1892 * <p><strong>Event fields:</strong><br>
1893 * <code>&lt;String&gt; type</code> beforeActiveTabChange<br>
1894 * <code>&lt;<a href="YAHOO.widget.Tab.html">YAHOO.widget.Tab</a>&gt;
1895 * prevValue</code> the currently active tab<br>
1896 * <code>&lt;<a href="YAHOO.widget.Tab.html">YAHOO.widget.Tab</a>&gt;
1897 * newValue</code> the tab to be made active</p>
1898 * <p><strong>Usage:</strong><br>
1899 * <code>var handler = function(e) {var previous = e.prevValue};<br>
1900 * myTabs.addListener('beforeActiveTabChange', handler);</code></p>
1901 * @event beforeActiveTabChange
1902 */
1903
1904/**
1905 * Fires after the activeTab is changed.
1906 * <p>See: <a href="YAHOO.util.Element.html#addListener">Element.addListener</a></p>
1907 * <p><strong>Event fields:</strong><br>
1908 * <code>&lt;String&gt; type</code> activeTabChange<br>
1909 * <code>&lt;<a href="YAHOO.widget.Tab.html">YAHOO.widget.Tab</a>&gt;
1910 * prevValue</code> the formerly active tab<br>
1911 * <code>&lt;<a href="YAHOO.widget.Tab.html">YAHOO.widget.Tab</a>&gt;
1912 * newValue</code> the new active tab</p>
1913 * <p><strong>Usage:</strong><br>
1914 * <code>var handler = function(e) {var previous = e.prevValue};<br>
1915 * myTabs.addListener('activeTabChange', handler);</code></p>
1916 * @event activeTabChange
1917 */
1918
1919/**
1920 * Fires before the orientation is changed.
1921 * <p>See: <a href="YAHOO.util.Element.html#addListener">Element.addListener</a></p>
1922 * <p>If handler returns false, the change will be cancelled, and the value will not
1923 * be set.</p>
1924 * <p><strong>Event fields:</strong><br>
1925 * <code>&lt;String&gt; type</code> beforeOrientationChange<br>
1926 * <code>&lt;String&gt;
1927 * prevValue</code> the current orientation<br>
1928 * <code>&lt;String&gt;
1929 * newValue</code> the new orientation to be applied</p>
1930 * <p><strong>Usage:</strong><br>
1931 * <code>var handler = function(e) {var previous = e.prevValue};<br>
1932 * myTabs.addListener('beforeOrientationChange', handler);</code></p>
1933 * @event beforeOrientationChange
1934 */
1935
1936/**
1937 * Fires after the orientation is changed.
1938 * <p>See: <a href="YAHOO.util.Element.html#addListener">Element.addListener</a></p>
1939 * <p><strong>Event fields:</strong><br>
1940 * <code>&lt;String&gt; type</code> orientationChange<br>
1941 * <code>&lt;String&gt;
1942 * prevValue</code> the former orientation<br>
1943 * <code>&lt;String&gt;
1944 * newValue</code> the new orientation</p>
1945 * <p><strong>Usage:</strong><br>
1946 * <code>var handler = function(e) {var previous = e.prevValue};<br>
1947 * myTabs.addListener('orientationChange', handler);</code></p>
1948 * @event orientationChange
1949 */
1950})(); \ No newline at end of file