| /* |
| Copyright (c) 2007, Caridy Patino. All rights reserved. |
| Portions Copyright (c) 2007, Yahoo!, Inc. All rights reserved. |
| Code licensed under the BSD License: |
| http://www.bubbling-library.com/eng/licence |
| version: 1.5.0 |
| */ |
| (function() { |
| |
| var $B = YAHOO.Bubbling, |
| $L = YAHOO.lang, |
| $E = YAHOO.util.Event, |
| $D = YAHOO.util.Dom; |
| |
| /** |
| * @singleton Accordion Manager - Creating accordion controls based on the markup. |
| * Apply visual enhanced to an area |
| * @constructor |
| */ |
| YAHOO.widget.AccordionManager = function() { |
| var obj = {}, |
| _selector = 'selected', |
| _sliding = 'sliding', |
| _anims = {}; |
| |
| // on click action behaviors... |
| $B.addDefaultAction('accordionToggleItem', function (layer, args) { |
| if (!args[1].decrepitate) { |
| // switching the slidable area and reclaiming the behavior |
| return obj.toggle(args[1].target); |
| } |
| }); |
| $B.addDefaultAction('accordionRemoveItem', function (layer, args) { |
| if (!args[1].decrepitate) { |
| // removing an item from the accordion and reclaiming the behavior |
| return obj.remove(args[1].target); |
| } |
| }); |
| |
| // on event arrive |
| // behaviors for the second accordion (ADVANCED AJAX APPLICATION) |
| // Tagline: One behavior that will rule them all (based on the slide's rel attribute) |
| $B.on('accordionOpenItem', function (layer, args) { |
| var reLink = /.*#/; |
| // if can be loaded thru AJAX |
| if ($D.hasClass(args[1].slide, 'ajax') && $L.isObject(YAHOO.plugin.Dispatcher)) { |
| var trigger = $D.getElementsByClassName('accordionToggleItem','*',args[1].el); |
| trigger = (trigger.length>0?trigger[0]:null); |
| if (trigger && (trigger = trigger.getAttribute('href',2))) { |
| YAHOO.plugin.Dispatcher.fetch ( args[1].slide, trigger.replace(reLink,''), { |
| onLoad: function (el) { |
| $D.removeClass(args[1].slide, 'ajax'); |
| } |
| }); |
| } |
| } |
| }); |
| |
| // on keyboad action behavior... |
| $B.on('key', function (layer, args) { |
| var o = args[1], item = null, result = false; |
| if (!o.decrepitate && (o.type == 'keyup')) { |
| if (((o.keyCode === 39) && obj.open (o.target)) || |
| ((o.keyCode === 37) && obj.close (o.target))) { // Shortcut: cursor -> or cursor <- |
| // reclaiming the event & stoping the event propagation |
| o.decrepitate = true; |
| o.stop = true; |
| } |
| } |
| }); |
| |
| // on rollover action behavior... |
| $B.on('rollover', function (layer, args) { |
| var list, item, onWayOut; |
| if (item = _getItem(args[1].target)) { |
| if ((list = _getList(item)) && list.rollover) { |
| if (!list.selected) { |
| $D.addClass(list.el, _selector); |
| onWayOut = function (e) { |
| var l = _getList ({el:$E.getTarget(e)}); |
| if (l && !$B.virtualTarget(e, l.el) && !l.persistent) { |
| _reset(l, {force:true}); |
| } |
| }; |
| if (!list.persistent) { |
| $E.removeListener ( list.el, 'mouseout', onWayOut ); |
| $E.addListener ( list.el, 'mouseout', onWayOut, obj, true ); |
| } |
| } |
| if (!item.selected) { |
| // is over a new item... |
| _openItem(item, list); |
| } |
| } |
| } |
| }); |
| |
| // creating the most common message (behavior layer) |
| $B.addLayer (['accordionOpenItem', 'accordionCloseItem', 'accordionRemoveItem'], obj); |
| |
| function _getEffect ( el ) { |
| var effect = el.getAttribute('rel') || null; |
| if (effect) { |
| effect = YAHOO.util.Easing[effect] || null; |
| } |
| return effect; |
| } |
| function _getTimer ( el ) { |
| var t = ($D.hasClass(el, 'fast')?0.1:null) || ($D.hasClass(el, 'slow')?0.6:null) || 0.4; |
| return t; |
| } |
| function _getItem ( elem ) { |
| if (elem && ($L.isObject(elem) || (elem = $D.get (elem)))) { |
| var item, el = $B.getOwnerByClassName (elem, 'yui-cms-item'); |
| if ($L.isObject(el)) { |
| item = { |
| el: el, |
| triger: elem, |
| selected: $D.hasClass(el, _selector), |
| sliding: $D.hasClass(el, _sliding), |
| size: {width:0, Height: 0} |
| }; |
| // getting the slidable element |
| var slide = $D.getElementsByClassName('bd','*',el); |
| slide = (slide.length>0?slide[0]:null); |
| item.slide = slide; |
| var h = parseInt($D.getStyle(slide, 'height'), 10); |
| var w = parseInt($D.getStyle(slide, 'width'), 10); |
| // forcing to number... to avoid misbehavior on "auto" height/width... |
| if (!$L.isNumber(h)) { |
| $D.setStyle(slide, 'height', slide.scrollHeight+'px'); |
| } |
| if (!$L.isNumber(w)) { |
| $D.setStyle(slide, 'width', slide.scrollWidth+'px'); |
| } |
| item.size.height = slide.scrollHeight; |
| item.size.width = slide.scrollWidth; |
| } |
| return item; |
| } |
| } |
| function _getList ( item ) { |
| var list = null, el = item.el; |
| if (el && ($L.isObject(el) || (el = $D.get (el)))) { |
| if (el = $B.getOwnerByClassName (el, 'yui-cms-accordion')) { |
| // creating the list literal based on the classnames defined for the accordion wrapper |
| list = { |
| el: el, |
| effect: _getEffect(el), |
| orientation: ($D.hasClass(el, 'vertical')?'width':'height'), |
| selected: $D.hasClass(el, _selector), |
| fade: $D.hasClass(el, 'fade'), |
| manually: $D.hasClass(el, 'manually'), |
| fixIE: ($E.isIE && $D.hasClass(el, 'fixIE')), // hack for IE and quirk mode... |
| multiple: $D.hasClass(el, 'multiple'), |
| rollover: $D.hasClass(el, 'rollover'), |
| persistent: $D.hasClass(el, 'persistent'), |
| dispatcher: $D.hasClass(el, 'dispatcher'), |
| wizard: $D.hasClass(el, 'wizard'), |
| timer: _getTimer(el), |
| items: [] |
| }; |
| // searching for items childs... |
| $D.batch ($D.getElementsByClassName('bd','*',el), function(elem){ |
| // adding an item to the list |
| list.items.push (_getItem(elem)); |
| }); |
| } |
| return list; |
| } |
| } |
| function _reset ( list, params ) { |
| params = params || {}; |
| var conf = [], i, |
| force = params.force || false, |
| item = params.item || null; |
| if (list) { |
| if (!list.multiple || force) { |
| // closing all the selected items |
| for (i=0; i<list.items.length; i++) { |
| // is the element is not equal to item, or if the item is under an animation... |
| if ((!item || (list.items[i].el !== item.el)) && (list.items[i].selected || list.items[i].sliding || params.expand)) { |
| if (params.expand) { |
| _openItem (list.items[i], list, params.grouping); |
| } else { |
| _closeItem (list.items[i], list, params.grouping); |
| if (params.mirror) { |
| // hack for get the mirror element in persistent and !mutiples accordions |
| params.mirror.push(list.items[i]); |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| function _openItem ( item, list ) { |
| var conf = [], anim, i, g = [], m = [], fs, onFinish; |
| if (list || (list = _getList (item))) { |
| // if the item is not already opened |
| if (!item.selected) { |
| // closing all the selected items if neccesary |
| if (!list.multiple) { |
| _reset ( list, {item: item, grouping: g, mirror: m} ); |
| } |
| // if the animation is underway: we need to stop it... |
| anim = _anims[$E.generateId(item.slide)]; |
| if ((anim) && (anim.isAnimated())) {anim.stop();} |
| // opening the selected element, based on the list's orientation, timer and effect attribute... |
| conf[list.orientation] = {to: item.size[list.orientation]}; |
| // scrolling effect |
| if (!list.manually) { |
| conf['scroll'] = {from: (list.orientation=='width'?[item.size[list.orientation],0]:[0,item.size[list.orientation]]), to: [0,0]}; |
| } |
| if (list.fade) { // appliying fadeIn |
| conf['opacity'] = {to: 1}; |
| } |
| anim = new YAHOO.util.Scroll(item.slide, conf, list.timer, list.effect); |
| $D.addClass(item.el, _sliding); |
| onFinish = function() { |
| $D.removeClass(item.el, _sliding); |
| $D.addClass(item.el, _selector); |
| // broadcasting the corresponding event... |
| $B.fire ('accordionOpenItem', item); |
| }; |
| anim.onComplete.subscribe(onFinish); |
| _anims[$E.generateId(item.slide)] = anim; |
| if (list.manually) { |
| // manually animation... |
| m = m[0] || null; |
| // getting the desired dimension from the mirror or from the current item |
| fs = (m?m.size[list.orientation]:item.size[list.orientation]); |
| for (i=1;i<=fs;i++){ |
| if (m) { |
| $D.setStyle (m.slide, list.orientation, (fs-i)+'px'); |
| } |
| $D.setStyle (item.slide, list.orientation, i+'px'); |
| } |
| onFinish(); |
| } else { |
| // creating an animation thread |
| for (i=0; i<g.length; i++) { |
| YAHOO.util.AnimMgr.registerElement(g[i]); |
| } |
| YAHOO.util.AnimMgr.registerElement(anim); |
| } |
| } |
| return true; |
| } |
| return false; |
| } |
| function _closeItem ( item, list, grouping ) { |
| var conf = [], anim, fs; |
| if (item && (list || (list = _getList (item)))) { |
| // closing the item, based on the list's orientation, timer and effect attribute... |
| conf[list.orientation] = {to: ((list.orientation=='width'||list.fixIE)?1:0)}; // hack for vertical accordion issue on Safari and Opera |
| if (list.fade) { // appliying fadeIn |
| conf['opacity'] = {to: 0}; |
| } |
| // scrolling effect |
| if (!list.manually) { |
| conf['scroll'] = {to: (list.orientation=='width'?[item.size[list.orientation],0]:[0,item.size[list.orientation]])}; |
| } |
| // if the animation is underway: we need to stop it... |
| anim = _anims[$E.generateId(item.slide)]; |
| if ((anim) && (anim.isAnimated())) {anim.stop();} |
| anim = new YAHOO.util.Scroll(item.slide, conf, list.timer, list.effect); |
| $D.addClass(item.el, _sliding); |
| onFinish = function() { |
| $D.removeClass(item.el, _sliding); |
| $D.removeClass(item.el, _selector); |
| // broadcasting the corresponding event... |
| $B.fire ('accordionOpenItem', item); |
| }; |
| anim.onComplete.subscribe(onFinish); |
| if ($L.isArray(grouping)) { |
| grouping.push(anim); |
| } else { |
| anim.animate(); |
| } |
| if (list.manually) { |
| // animation manually |
| fs = item.size[list.orientation]; |
| for (i=fs;i>=conf[list.orientation].to;i--){ |
| $D.setStyle (item.slide, list.orientation, i+'px'); |
| } |
| onFinish(); |
| } |
| _anims[$E.generateId(item.slide)] = anim; |
| return true; |
| } |
| return false; |
| } |
| function _removeItem ( item, list ) { |
| if (item && (list || (list = _getList (item)))) { |
| // closing element |
| _closeItem (item, list); |
| // removing listeners... |
| $E.purgeElement ( item.el, true ); |
| // hack, removing the element after close it... |
| window.setTimeout (function(){ |
| item.el.parentNode.removeChild(item.el); |
| $B.fire ('accordionRemoveItem', item); |
| }, list.timer+0.1); |
| return true; |
| } |
| return false; |
| } |
| |
| // public vars |
| // public methods |
| /** |
| * * Expanding all the elements in the accordion... |
| * @public |
| * @param {object} el DOM reference |
| * @return boolean |
| */ |
| obj.expand = function ( el ) { |
| var list; |
| if (list = _getList ({el:el})) { |
| return _reset (list, {force:true, expand:true}); |
| } |
| }; |
| /** |
| * * Collapsing all the elements in the accordion... |
| * @public |
| * @param {object} el DOM reference |
| * @return boolean |
| */ |
| obj.collapse = function ( el ) { |
| var list; |
| if (list = _getList ({el:el})) { |
| return _reset (list, {force:true}); |
| } |
| }; |
| /** |
| * * Open a certain item inside an area... |
| * @public |
| * @param {object} el DOM reference |
| * @return boolean |
| */ |
| obj.open = function ( el ) { |
| var item; |
| if (item = _getItem(el)) { |
| return _openItem (item); |
| } |
| }; |
| /** |
| * * Close a certain item inside an area... |
| * @public |
| * @param {object} el DOM reference |
| * @return boolean |
| */ |
| obj.close = function ( el ) { |
| var item, list; |
| if (item = _getItem(el)) { |
| if (list = _getList (item)) { |
| // if the item is already opened, and is multiple and not persistent |
| return ((item.selected && (list.multiple || !list.persistent))?_closeItem (item, list):false); |
| } |
| } |
| }; |
| /** |
| * * toggle a certain item inside an area... |
| * @public |
| * @param {object} el DOM reference |
| * @return boolean |
| */ |
| obj.toggle = function ( el ) { |
| var item, list; |
| if (item = _getItem(el)) { |
| if (list = _getList (item)) { |
| // if the item is already opened, and is multiple and not persistent |
| return ((item.selected && (list.multiple || !list.persistent))?_closeItem (item, list):_openItem (item, list)); |
| } |
| } |
| }; |
| /** |
| * * remove a certain item from the area... |
| * @public |
| * @param {object} el DOM reference |
| * @return boolean |
| */ |
| obj.remove = function ( el ) { |
| var item, list; |
| if (item = _getItem(el)) { |
| if (list = _getList (item)) { |
| return _removeItem (item, list); |
| } |
| } |
| }; |
| return obj; |
| }(); |
| })(); |
| YAHOO.register("accordion", YAHOO.widget.AccordionManager, {version: "1.5.0", build: "203"}); |