← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] lp:~bac/launchpad/add-gallery-accordion into lp:launchpad

 

Brad Crittenden has proposed merging lp:~bac/launchpad/add-gallery-accordion into lp:launchpad.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~bac/launchpad/add-gallery-accordion/+merge/49786

= Summary =

Adding the code for an accordion widget and update the tools to include
the JavaScript and assets.

== Proposed fix ==

Created lib/lp/contrib as a repository for this code.  The code may
eventually move out of Launchpad into lazr-js.

== Pre-implementation notes ==

Discussions with Deryck and others.
-- 
https://code.launchpad.net/~bac/launchpad/add-gallery-accordion/+merge/49786
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~bac/launchpad/add-gallery-accordion into lp:launchpad.
=== modified file 'buildout-templates/bin/combine-css.in'
--- buildout-templates/bin/combine-css.in	2011-02-09 21:09:32 +0000
+++ buildout-templates/bin/combine-css.in	2011-02-15 11:27:17 +0000
@@ -35,6 +35,7 @@
     'lazr/build/picker/assets/skins/sam/picker.css',
     'lazr/build/activator/assets/skins/sam/activator.css',
     'lazr/build/choiceedit/assets/choiceedit-core.css',
+    'yui3-gallery/gallery-accordion/assets/skins/sam/gallery-accordion.css',
     # This one goes at the end because it's our main stylesheet and should
     # take precedence over the others.
     'build/style-3-0.css']

=== added symlink 'lib/canonical/launchpad/icing/yui3-gallery'
=== target is u'../../../lp/contrib/javascript/yui3-gallery'
=== added directory 'lib/lp/contrib'
=== added directory 'lib/lp/contrib/javascript'
=== added directory 'lib/lp/contrib/javascript/yui3-gallery'
=== added directory 'lib/lp/contrib/javascript/yui3-gallery/gallery-accordion'
=== added directory 'lib/lp/contrib/javascript/yui3-gallery/gallery-accordion/assets'
=== added file 'lib/lp/contrib/javascript/yui3-gallery/gallery-accordion/assets/gallery-accordion-core.css'
--- lib/lp/contrib/javascript/yui3-gallery/gallery-accordion/assets/gallery-accordion-core.css	1970-01-01 00:00:00 +0000
+++ lib/lp/contrib/javascript/yui3-gallery/gallery-accordion/assets/gallery-accordion-core.css	2011-02-15 11:27:17 +0000
@@ -0,0 +1,59 @@
+.yui3-accordion {
+    width: 100%;
+    height: 100%;
+    overflow: hidden;
+    position: relative;
+}
+
+.yui3-accordion-item {
+    position: relative;
+    cursor: pointer;
+    width: 100%;
+}
+
+.yui3-accordion-item .yui3-widget-hd {
+    overflow: hidden;
+}
+
+.yui3-accordion-item .yui3-widget-bd {
+    cursor: default;
+    overflow: hidden;
+    position: relative;
+}
+
+.yui3-accordion-item-icons {
+    position: relative;
+    float: right;
+    overflow: hidden;
+    padding: 1px;
+    height: 25px;
+}
+
+.yui3-accordion-item-icon,
+.yui3-accordion-item-iconexpanded,
+.yui3-accordion-item-iconalwaysvisible,
+.yui3-accordion-item-iconclose {
+    width: 22px;
+    height: 22px;
+}
+
+.yui3-accordion-item-icon,
+.yui3-accordion-item-label {
+    float: left;
+}
+
+.yui3-accordion-item-label{
+    position: relative;
+    top: 4px;
+    _height: 22px;
+}
+
+.yui3-accordion-item-iconexpanded,
+.yui3-accordion-item-iconalwaysvisible,
+.yui3-accordion-item-iconclose {
+    float: left;
+}
+
+.yui3-accordion-item-iconclose-hidden {
+    display: none;
+}

=== added directory 'lib/lp/contrib/javascript/yui3-gallery/gallery-accordion/assets/skins'
=== added directory 'lib/lp/contrib/javascript/yui3-gallery/gallery-accordion/assets/skins/sam'
=== added file 'lib/lp/contrib/javascript/yui3-gallery/gallery-accordion/assets/skins/sam/accordion_sprite.png'
Binary files lib/lp/contrib/javascript/yui3-gallery/gallery-accordion/assets/skins/sam/accordion_sprite.png	1970-01-01 00:00:00 +0000 and lib/lp/contrib/javascript/yui3-gallery/gallery-accordion/assets/skins/sam/accordion_sprite.png	2011-02-15 11:27:17 +0000 differ
=== added file 'lib/lp/contrib/javascript/yui3-gallery/gallery-accordion/assets/skins/sam/gallery-accordion-skin.css'
--- lib/lp/contrib/javascript/yui3-gallery/gallery-accordion/assets/skins/sam/gallery-accordion-skin.css	1970-01-01 00:00:00 +0000
+++ lib/lp/contrib/javascript/yui3-gallery/gallery-accordion/assets/skins/sam/gallery-accordion-skin.css	2011-02-15 11:27:17 +0000
@@ -0,0 +1,104 @@
+.yui3-skin-sam .yui3-accordion {
+    border: 1px solid #93B2CC;
+}
+
+.yui3-skin-sam .yui3-accordion-item .yui3-widget-hd {
+    background-image: url( accordion_sprite.png );
+    background-position: 0px 0px;
+    border: 1px solid #93B2CC;
+    height: 25px;
+}
+
+.yui3-skin-sam .yui3-accordion-item-icon,
+.yui3-skin-sam .yui3-accordion-item-iconexpanded,
+.yui3-skin-sam .yui3-accordion-item-iconalwaysvisible,
+.yui3-skin-sam .yui3-accordion-item-iconclose {
+    background-repeat: no-repeat;
+}
+    
+.yui3-skin-sam .yui3-accordion-item-icon {
+    background-image: url( accordion_sprite.png );
+    background-position: center -25px;
+    _background-position: center -27px;
+}
+
+.yui3-skin-sam .yui3-accordion-item-label{
+    color: #444444;
+}
+
+.yui3-skin-sam .yui3-accordion-item-label {
+    text-decoration: none;
+    background: transparent;
+    overflow: hidden;
+    color: #444444;
+    font-weight: bold;
+}
+
+.yui3-skin-sam .yui3-accordion-item-label:hover{
+    text-decoration: underline;
+}
+
+.yui3-skin-sam .yui3-accordion-item-iconalwaysvisible,
+.yui3-skin-sam .yui3-accordion-item-iconalwaysvisible-off {
+    background-image: url( accordion_sprite.png );
+    background-position: 0px -85px;
+    _background-position: 0px -87px;
+}
+
+.yui3-skin-sam .yui3-accordion-item-iconalwaysvisible-on {
+    background-image: url( accordion_sprite.png );
+    background-position: 0px -55px;
+    _background-position: 0px -57px;
+}
+
+.yui3-skin-sam .yui3-accordion-item-iconexpanded,
+.yui3-skin-sam .yui3-accordion-item-iconexpanded-off {
+    background-image: url( accordion_sprite.png );
+    background-position: 0px -175px;
+    _background-position: 0px -177px;
+}
+
+.yui3-skin-sam .yui3-accordion-item-iconexpanded-off:hover{
+    background-image: url( accordion_sprite.png );
+    background-position: 0px -205px;
+}
+
+.yui3-skin-sam .yui3-accordion-item-iconexpanded-on {
+    background-image: url( accordion_sprite.png );
+    background-position: 0px -115px;
+    _background-position: 0px -117px;
+}
+
+
+.yui3-skin-sam .yui3-accordion-item-iconexpanded-on:hover {
+    background-image: url( accordion_sprite.png );
+    background-position: 0px -145px;
+}
+
+
+.yui3-skin-sam .yui3-accordion-item-iconexpanded-expanding {
+    background-image: url( wait_expand.gif );
+    background-position: 0px center;
+}
+
+
+.yui3-skin-sam .yui3-accordion-item-iconexpanded-collapsing {
+    background-image: url( wait_collapse.gif );
+    background-position: 0px center;
+}
+
+.yui3-skin-sam .yui3-accordion-item-iconclose {
+    background-image: url( accordion_sprite.png );
+    background-position: 0px -235px;
+    _background-position: 0px -237px;
+}
+
+
+.yui3-skin-sam .yui3-accordion-proxyel-visible {
+    border-color : blue;
+    color : white;
+    font-weight : bold;
+    background-color : red;
+    opacity : 0.7;
+    filter: alpha(opacity = 70);
+} 

=== added file 'lib/lp/contrib/javascript/yui3-gallery/gallery-accordion/assets/skins/sam/gallery-accordion.css'
--- lib/lp/contrib/javascript/yui3-gallery/gallery-accordion/assets/skins/sam/gallery-accordion.css	1970-01-01 00:00:00 +0000
+++ lib/lp/contrib/javascript/yui3-gallery/gallery-accordion/assets/skins/sam/gallery-accordion.css	2011-02-15 11:27:17 +0000
@@ -0,0 +1,1 @@
+.yui3-accordion{width:100%;height:100%;overflow:hidden;position:relative;}.yui3-accordion-item{position:relative;cursor:pointer;width:100%;}.yui3-accordion-item .yui3-widget-hd{overflow:hidden;}.yui3-accordion-item .yui3-widget-bd{cursor:default;overflow:hidden;position:relative;}.yui3-accordion-item-icons{position:relative;float:right;overflow:hidden;padding:1px;height:25px;}.yui3-accordion-item-icon,.yui3-accordion-item-iconexpanded,.yui3-accordion-item-iconalwaysvisible,.yui3-accordion-item-iconclose{width:22px;height:22px;}.yui3-accordion-item-icon,.yui3-accordion-item-label{float:left;}.yui3-accordion-item-label{position:relative;top:4px;_height:22px;}.yui3-accordion-item-iconexpanded,.yui3-accordion-item-iconalwaysvisible,.yui3-accordion-item-iconclose{float:left;}.yui3-accordion-item-iconclose-hidden{display:none;}.yui3-skin-sam .yui3-accordion{border:1px solid #93B2CC;}.yui3-skin-sam .yui3-accordion-item .yui3-widget-hd{background-image:url(accordion_sprite.png);background-position:0 0;border:1px solid #93B2CC;height:25px;}.yui3-skin-sam .yui3-accordion-item-icon,.yui3-skin-sam .yui3-accordion-item-iconexpanded,.yui3-skin-sam .yui3-accordion-item-iconalwaysvisible,.yui3-skin-sam .yui3-accordion-item-iconclose{background-repeat:no-repeat;}.yui3-skin-sam .yui3-accordion-item-icon{background-image:url(accordion_sprite.png);background-position:center -25px;_background-position:center -27px;}.yui3-skin-sam .yui3-accordion-item-label{color:#444;}.yui3-skin-sam .yui3-accordion-item-label{text-decoration:none;background:transparent;overflow:hidden;color:#444;font-weight:bold;}.yui3-skin-sam .yui3-accordion-item-label:hover{text-decoration:underline;}.yui3-skin-sam .yui3-accordion-item-iconalwaysvisible,.yui3-skin-sam .yui3-accordion-item-iconalwaysvisible-off{background-image:url(accordion_sprite.png);background-position:0 -85px;_background-position:0 -87px;}.yui3-skin-sam .yui3-accordion-item-iconalwaysvisible-on{background-image:url(accordion_sprite.png);background-position:0 -55px;_background-position:0 -57px;}.yui3-skin-sam .yui3-accordion-item-iconexpanded,.yui3-skin-sam .yui3-accordion-item-iconexpanded-off{background-image:url(accordion_sprite.png);background-position:0 -175px;_background-position:0 -177px;}.yui3-skin-sam .yui3-accordion-item-iconexpanded-off:hover{background-image:url(accordion_sprite.png);background-position:0 -205px;}.yui3-skin-sam .yui3-accordion-item-iconexpanded-on{background-image:url(accordion_sprite.png);background-position:0 -115px;_background-position:0 -117px;}.yui3-skin-sam .yui3-accordion-item-iconexpanded-on:hover{background-image:url(accordion_sprite.png);background-position:0 -145px;}.yui3-skin-sam .yui3-accordion-item-iconexpanded-expanding{background-image:url(wait_expand.gif);background-position:0 center;}.yui3-skin-sam .yui3-accordion-item-iconexpanded-collapsing{background-image:url(wait_collapse.gif);background-position:0 center;}.yui3-skin-sam .yui3-accordion-item-iconclose{background-image:url(accordion_sprite.png);background-position:0 -235px;_background-position:0 -237px;}.yui3-skin-sam .yui3-accordion-proxyel-visible{border-color:blue;color:white;font-weight:bold;background-color:red;opacity:.7;filter:alpha(opacity = 70);}

=== added file 'lib/lp/contrib/javascript/yui3-gallery/gallery-accordion/assets/skins/sam/wait_collapse.gif'
Binary files lib/lp/contrib/javascript/yui3-gallery/gallery-accordion/assets/skins/sam/wait_collapse.gif	1970-01-01 00:00:00 +0000 and lib/lp/contrib/javascript/yui3-gallery/gallery-accordion/assets/skins/sam/wait_collapse.gif	2011-02-15 11:27:17 +0000 differ
=== added file 'lib/lp/contrib/javascript/yui3-gallery/gallery-accordion/assets/skins/sam/wait_expand.gif'
Binary files lib/lp/contrib/javascript/yui3-gallery/gallery-accordion/assets/skins/sam/wait_expand.gif	1970-01-01 00:00:00 +0000 and lib/lp/contrib/javascript/yui3-gallery/gallery-accordion/assets/skins/sam/wait_expand.gif	2011-02-15 11:27:17 +0000 differ
=== added file 'lib/lp/contrib/javascript/yui3-gallery/gallery-accordion/gallery-accordion-debug.js'
--- lib/lp/contrib/javascript/yui3-gallery/gallery-accordion/gallery-accordion-debug.js	1970-01-01 00:00:00 +0000
+++ lib/lp/contrib/javascript/yui3-gallery/gallery-accordion/gallery-accordion-debug.js	2011-02-15 11:27:17 +0000
@@ -0,0 +1,2890 @@
+YUI.add('gallery-accordion', function(Y) {
+
+/**
+ * Provides Accordion widget
+ *
+ * @module gallery-accordion
+ */
+
+(function(){
+
+// Local constants
+var Lang = Y.Lang,
+    Node = Y.Node,
+    Anim = Y.Anim,
+    Easing = Y.Easing,
+    AccName = "accordion",
+    WidgetStdMod = Y.WidgetStdMod,
+    QuirksMode = document.compatMode == "BackCompat",
+    IEQuirksMode = QuirksMode && Y.UA.ie > 0,
+    COLLAPSE_HEIGHT = IEQuirksMode ? 1 : 0,
+    getCN = Y.ClassNameManager.getClassName,
+    
+    C_ITEM = "yui3-accordion-item",
+    C_PROXY_VISIBLE = getCN( AccName, "proxyel", "visible" ),
+    DRAGGROUP = getCN( AccName, "graggroup" ),
+
+    BEFOREITEMADD = "beforeItemAdd",
+    ITEMADDED = "itemAdded",
+    BEFOREITEMREMOVE = "beforeItemRemove",
+    ITEMREMOVED = "itemRemoved",
+    BEFOREITEMERESIZED = "beforeItemResized",
+    ITEMERESIZED = "itemResized",
+
+    BEFOREITEMEXPAND  = "beforeItemExpand",
+    BEFOREITEMCOLLAPSE = "beforeItemCollapse",
+    ITEMEXPANDED = "itemExpanded",
+    ITEMCOLLAPSED = "itemCollapsed",
+
+    BEFOREITEMREORDER = "beforeItemReorder",
+    BEFOREENDITEMREORDER = "beforeEndItemReorder",
+    ITEMREORDERED = "itemReordered",
+    
+    DEFAULT = "default",
+    ANIMATION = "animation",
+    ALWAYSVISIBLE = "alwaysVisible",
+    EXPANDED = "expanded",
+    COLLAPSEOTHERSONEXPAND = "collapseOthersOnExpand",
+    ITEMS = "items",
+    CONTENT_HEIGHT = "contentHeight",
+    ICON_CLOSE = "iconClose",
+    ICON_ALWAYSVISIBLE = "iconAlwaysVisible",
+    STRETCH = "stretch",
+    PX = "px",
+    CONTENT_BOX = "contentBox",
+    BOUNDING_BOX = "boundingBox",
+    SRCNODE = "srcNode",
+    RENDERED = "rendered",
+    BODYCONTENT = "bodyContent",
+    CHILDREN = "children",
+    PARENT_NODE = "parentNode",
+    NODE = "node",
+    DATA = "data";
+
+
+/**
+ * Accordion creates an widget, consists of one or more items, which can be collapsed, expanded,
+ * set as always visible and reordered by using Drag&Drop. Collapsing/expanding might be animated.
+ *
+ * @class Accordion
+ * @extends Widget
+ */
+
+Y.Accordion = Y.Base.create( AccName, Y.Widget, [], {
+
+    /**
+     * Signals the beginning of adding an item to the Accordion.
+     *
+     * @event beforeItemAdd
+     * @param event {Event.Facade} An Event Facade object with the following attribute specific properties added:
+     *  <dl>
+     *      <dt>item</dt>
+     *          <dd>An <code>AccordionItem</code> instance of the item being added</dd>
+     *  </dl>
+     */
+
+
+    /**
+     * Signals an item has been added to the Accordion.
+     *
+     * @event itemAdded
+     * @param event {Event.Facade} An Event Facade object with the following attribute specific properties added:
+     *  <dl>
+     *      <dt>item</dt>
+     *          <dd>An <code>AccordionItem</code> instance of the item that has been added</dd>
+     *  </dl>
+     */
+
+
+    /**
+     * Signals the beginning of removing an item.
+     *
+     * @event beforeItemRemove
+     * @param event {Event.Facade} An Event Facade object with the following attribute specific properties added:
+     *  <dl>
+     *      <dt>item</dt>
+     *          <dd>An <code>AccordionItem</code> instance of the item being removed</dd>
+     *  </dl>
+     */
+
+
+    /**
+     * Signals an item has been removed from Accordion.
+     *
+     * @event itemRemoved
+     * @param event {Event.Facade} An Event Facade object with the following attribute specific properties added:
+     *  <dl>
+     *      <dt>item</dt>
+     *          <dd>An <code>AccordionItem</code> instance of the item that has been removed</dd>
+     *  </dl>
+     */
+
+
+    /**
+     * Signals the beginning of resizing an item.
+     *
+     * @event beforeItemResized
+     * @param event {Event.Facade} An Event Facade object with the following attribute specific properties added:
+     *  <dl>
+     *      <dt>item</dt>
+     *          <dd>An <code>AccordionItem</code> instance of the item being resized</dd>
+     *  </dl>
+     */
+
+
+    /**
+     * Signals an item has been resized.
+     *
+     * @event itemResized
+     * @param event {Event.Facade} An Event Facade object with the following attribute specific properties added:
+     *  <dl>
+     *      <dt>item</dt>
+     *          <dd>An <code>AccordionItem</code> instance of the item that has been resized</dd>
+     *  </dl>
+     */
+
+
+    /**
+     * Signals the beginning of expanding an item
+     *
+     * @event beforeItemExpand
+     * @param event {Event.Facade} An Event Facade object with the following attribute specific properties added:
+     *  <dl>
+     *      <dt>item</dt>
+     *          <dd>An <code>AccordionItem</code> instance of the item being expanded</dd>
+     *  </dl>
+     */
+
+
+    /**
+     * Signals the beginning of collapsing an item
+     *
+     * @event beforeItemCollapse
+     * @param event {Event.Facade} An Event Facade object with the following attribute specific properties added:
+     *  <dl>
+     *      <dt>item</dt>
+     *          <dd>An <code>AccordionItem</code> instance of the item being collapsed</dd>
+     *  </dl>
+     */
+
+
+    /**
+     * Signals an item has been expanded
+     *
+     * @event itemExpanded
+     * @param event {Event.Facade} An Event Facade object with the following attribute specific properties added:
+     *  <dl>
+     *      <dt>item</dt>
+     *          <dd>An <code>AccordionItem</code> instance of the item that has been expanded</dd>
+     *  </dl>
+     */
+
+
+    /**
+     * Signals an item has been collapsed
+     *
+     * @event itemCollapsed
+     * @param event {Event.Facade} An Event Facade object with the following attribute specific properties added:
+     *  <dl>
+     *      <dt>item</dt>
+     *          <dd>An <code>AccordionItem</code> instance of the item that has been collapsed</dd>
+     *  </dl>
+     */
+
+
+    /**
+     * Signals the beginning of reordering an item
+     *
+     * @event beforeItemReorder
+     * @param event {Event.Facade} An Event Facade object with the following attribute specific properties added:
+     *  <dl>
+     *      <dt>item</dt>
+     *          <dd>An <code>AccordionItem</code> instance of the item being reordered</dd>
+     *  </dl>
+     */
+
+
+    /**
+     * Fires before the end of item reordering
+     *
+     * @event beforeEndItemReorder
+     * @param event {Event.Facade} An Event Facade object with the following attribute specific properties added:
+     *  <dl>
+     *      <dt>item</dt>
+     *          <dd>An <code>AccordionItem</code> instance of the item being reordered</dd>
+     *  </dl>
+     */
+
+
+    /**
+     * Signals an item has been reordered
+     *
+     * @event itemReordered
+     * @param event {Event.Facade} An Event Facade object with the following attribute specific properties added:
+     *  <dl>
+     *      <dt>item</dt>
+     *          <dd>An <code>AccordionItem</code> instance of the item that has been reordered</dd>
+     *  </dl>
+     */
+
+
+    /**
+     * Initializer lifecycle implementation for the Accordion class. Publishes events,
+     * initializes internal properties and subscribes for resize event.
+     *
+     * @method initializer
+     * @protected
+     * @param config {Object} Configuration object literal for the Accordion
+     */
+    initializer: function( config ) {
+        this.after( "render", Y.bind( this._afterRender, this ) );
+    },
+
+
+    /**
+     * Destructor lifecycle implementation for the Accordion class.
+     * Removes and destroys all registered items.
+     *
+     * @method destructor
+     * @protected
+     */
+    destructor: function() {
+        var items, item, i, length;
+
+        items = this.get( ITEMS );
+        length = items.length;
+
+        for( i = length - 1; i >= 0; i-- ){
+            item = items[ i ];
+
+            items.splice( i, 1 );
+
+            this._removeItemHandles( item );
+
+            item.destroy();
+        }
+    },
+
+
+    /**
+     * Contains items for collapsing
+     * @property _forCollapsing
+     * @protected
+     * @type Object
+     */
+    _forCollapsing : {},
+
+
+    /**
+     * Contains items for expanding
+     * @property _forExpanding
+     * @protected
+     * @type Object
+     */
+    _forExpanding : {},
+
+
+    /**
+    * Contains currently running animations
+    * @property _animations
+    * @protected
+    * @type Object
+    */
+    _animations   : {},
+
+
+    /**
+     * Collection of items handles.
+     * Keeps track of each items's event handle, as returned from <code>Y.on</code> or <code>Y.after</code>.
+     * @property _itemHandles
+     * @private
+     * @type Object
+     */
+    _itemsHandles: {},
+
+
+    /**
+     * Removes all handles, attched to given item
+     *
+     * @method _removeItemHandles
+     * @protected
+     * @param item {Y.AccordionItem} The item, which handles to remove
+     */
+    _removeItemHandles: function( item ){
+        var itemHandles, itemHandle;
+
+        itemHandles = this._itemsHandles[ item ];
+
+        for( itemHandle in itemHandles ){
+            if( itemHandles.hasOwnProperty( itemHandle ) ){
+                itemHandle = itemHandles[ itemHandle ];
+                itemHandle.detach();
+            }
+        }
+
+        delete this._itemsHandles[ item ];
+    },
+
+    /**
+     * Obtains the precise height of the node provided, including padding and border.
+     *
+     * @method _getNodeOffsetHeight
+     * @protected
+     * @param node {Node|HTMLElement} The node to gather the height from
+     * @return {Number} The calculated height or zero in case of failure
+     */
+    _getNodeOffsetHeight: function( node ){
+        var height, preciseRegion;
+
+        if( node instanceof Node ){
+            if( node.hasMethod( "getBoundingClientRect" ) ){
+                preciseRegion = node.invoke( "getBoundingClientRect" );
+
+                if( preciseRegion ){
+                    height = preciseRegion.bottom - preciseRegion.top;
+
+                    return height;
+                }
+            } else {
+                height = node.get( "offsetHeight" );
+                return Y.Lang.isValue( height ) ? height : 0;
+            }
+        } else if( node ){
+            height = node.offsetHeight;
+            return Y.Lang.isValue( height ) ? height : 0;
+        }
+
+        return 0;
+    },
+
+
+    /**
+     * Updates expand and alwaysVisible properties of given item with the values provided.
+     * The properties will be updated only if needed.
+     *
+     * @method _setItemProperties
+     * @protected
+     * @param item {Y.AccordionItem} The item, which properties should be updated
+     * @param expanding {Boolean} The new value of "expanded" property
+     * @param alwaysVisible {Boolean} The new value of "alwaysVisible" property
+     */
+    _setItemProperties: function( item, expanding, alwaysVisible ){
+        var curAlwaysVisible, curExpanded;
+
+        curAlwaysVisible = item.get( ALWAYSVISIBLE );
+        curExpanded = item.get( EXPANDED );
+
+        if( expanding != curExpanded ){
+            item.set( EXPANDED, expanding, {
+                internalCall: true
+            });
+        }
+
+        if( alwaysVisible !== curAlwaysVisible ){
+            item.set( ALWAYSVISIBLE, alwaysVisible, {
+                internalCall: true
+            });
+        }
+    },
+
+
+    /**
+     * Updates user interface of an item and marks it as expanded, alwaysVisible or both
+     *
+     * @method _setItemUI
+     * @protected
+     * @param item {Y.AccordionItem} The item, which user interface should be updated
+     * @param expanding {Boolean} If true, the item will be marked as expanded.
+     * If false, the item will be marked as collapsed
+     * @param alwaysVisible {Boolean} If true, the item will be marked as always visible.
+     * If false, the always visible mark will be removed
+     */
+    _setItemUI: function( item, expanding, alwaysVisible ){
+        item.markAsExpanded( expanding );
+        item.markAsAlwaysVisible( alwaysVisible );
+    },
+
+
+    /**
+     * Sets listener to resize event
+     *
+     * @method _afterRender
+     * @protected
+     * @param e {Event} after render custom event
+     */
+    _afterRender: function( e ){
+        var resizeEvent;
+
+        resizeEvent = this.get( "resizeEvent" );
+
+        this._setUpResizing( resizeEvent );
+
+        this.after( "resizeEventChange", Y.bind( this._afterResizeEventChange, this ) );
+    },
+
+
+    /**
+     * Set up resizing with the new value provided
+     *
+     * @method _afterResizeEventChange
+     * @protected
+     * @param params {Event} after resizeEventChange custom event
+     */
+    _afterResizeEventChange: function( params ){
+        this._setUpResizing( params.newVal );
+    },
+
+
+    /**
+     * Distributes the involved items as result of user interaction on item header.
+     * Some items might be stored in the list for collapsing, other in the list for expanding.
+     * Finally, invokes <code>_processItems</code> function, except if item has been expanded and
+     * user has clicked on always visible icon.
+     * If the user clicked on close icon, the item will be closed.
+     *
+     * @method _onItemChosen
+     * @protected
+     * @param item {Y.AccordionItem} The item on which user has clicked or pressed key
+     * @param srcIconAlwaysVisible {Boolean} True if the user has clicked on always visible icon
+     * @param srcIconClose {Boolean} True if the user has clicked on close icon
+     */
+    _onItemChosen: function( item, srcIconAlwaysVisible, srcIconClose ){
+        var toBeExcluded, alwaysVisible, expanded, collapseOthersOnExpand;
+
+        toBeExcluded = {};
+        collapseOthersOnExpand = this.get( COLLAPSEOTHERSONEXPAND );
+        alwaysVisible = item.get( ALWAYSVISIBLE );
+        expanded      = item.get( EXPANDED );
+
+        if( srcIconClose ){
+            this.removeItem( item );
+            return;
+        } else if( srcIconAlwaysVisible ){
+            if( expanded ){
+                alwaysVisible = !alwaysVisible;
+                expanded = alwaysVisible ? true : expanded;
+
+                this._setItemProperties( item, expanded, alwaysVisible );
+                this._setItemUI( item, expanded, alwaysVisible );
+
+                return;
+            } else {
+                this._forExpanding[ item ] = {
+                    'item': item,
+                    alwaysVisible: true
+                };
+
+                if( collapseOthersOnExpand ){
+                    toBeExcluded[ item ] = {
+                        'item': item
+                    };
+
+                    this._storeItemsForCollapsing( toBeExcluded );
+                }
+            }
+        } else {
+            /*
+             * Do the opposite
+             */
+            if( expanded ){
+                this._forCollapsing[ item ] = {
+                    'item': item
+                };
+            } else {
+                this._forExpanding[ item ] = {
+                    'item': item,
+                    'alwaysVisible': alwaysVisible
+                };
+
+                if( collapseOthersOnExpand ){
+                    toBeExcluded[ item ] = {
+                        'item': item
+                    };
+
+                    this._storeItemsForCollapsing( toBeExcluded );
+                }
+            }
+        }
+
+        this._processItems();
+    },
+
+
+    /**
+     * Helper method to adjust the height of all items, which <code>contentHeight</code> property is set as "stretch".
+     * If some item has animation running, it will be stopped before running another one.
+     *
+     * @method adjustStretchItems
+     * @protected
+     * @return {Number} The calculated height per strech item
+     */
+    _adjustStretchItems: function(){
+        var items = this.get( ITEMS ), heightPerStretchItem, forExpanding;
+
+        heightPerStretchItem = this._getHeightPerStretchItem();
+        forExpanding = this._forExpanding;
+
+        Y.Array.each( items, function( item, index, items ){
+            var body, bodyHeight, anim, heightSettings, expanded;
+
+            heightSettings = item.get( CONTENT_HEIGHT );
+            expanded      = item.get( EXPANDED );
+
+            if( !forExpanding[ item ] && heightSettings.method === STRETCH && expanded ){
+                anim = this._animations[ item ];
+
+                // stop waiting animation
+                if( anim ){
+                    anim.stop();
+                }
+
+                body = item.getStdModNode( WidgetStdMod.BODY );
+                bodyHeight = this._getNodeOffsetHeight( body );
+
+                if( heightPerStretchItem < bodyHeight ){
+                    this._processCollapsing( item, heightPerStretchItem );
+                } else if( heightPerStretchItem > bodyHeight ){
+                    this._processExpanding( item, heightPerStretchItem );
+                }
+            }
+        }, this );
+
+        return heightPerStretchItem;
+    },
+
+    /**
+     * Calculates the height per strech item.
+     *
+     * @method _getHeightPerStretchItem
+     * @protected
+     * @return {Number} The calculated height per strech item
+     */
+    _getHeightPerStretchItem: function(){
+        var height, items, stretchCounter = 0;
+
+        items = this.get( ITEMS );
+        height = this.get( BOUNDING_BOX ).get( "clientHeight" );
+
+        Y.Array.each( items, function( item, index, items ){
+            var collapsed, itemContentHeight, header, heightSettings, headerHeight;
+
+            header = item.getStdModNode( WidgetStdMod.HEADER );
+            heightSettings = item.get( CONTENT_HEIGHT );
+
+            headerHeight = this._getNodeOffsetHeight( header );
+
+            height -= headerHeight;
+            collapsed = !item.get( EXPANDED );
+
+            if( collapsed ){
+                height -= COLLAPSE_HEIGHT;
+                return;
+            }
+
+            if( heightSettings.method === STRETCH ){
+                stretchCounter++;
+            } else {
+                itemContentHeight = this._getItemContentHeight( item );
+                height -= itemContentHeight;
+            }
+        }, this );
+
+        if( stretchCounter > 0 ){
+            height /= stretchCounter;
+        }
+
+        if( height < 0 ){
+            height = 0;
+        }
+
+        return height;
+    },
+
+
+    /**
+     * Calculates the height of given item depending on its "contentHeight" property.
+     *
+     * @method _getItemContentHeight
+     * @protected
+     * @param item {Y.AccordionItem} The item, which height should be calculated
+     * @return {Number} The calculated item's height
+     */
+    _getItemContentHeight: function( item ){
+        var heightSettings, height = 0, body, bodyContent;
+
+        heightSettings = item.get( CONTENT_HEIGHT );
+
+        if( heightSettings.method === "auto" ){
+            body = item.getStdModNode( WidgetStdMod.BODY );
+            bodyContent = body.get( CHILDREN ).item(0);
+            height = bodyContent ? this._getNodeOffsetHeight( bodyContent ) : 0;
+        } else if( heightSettings.method === "fixed" ) {
+            height = heightSettings.height;
+        } else {
+            height = this._getHeightPerStretchItem();
+        }
+
+        return height;
+    },
+
+
+    /**
+     * Stores all items, which are expanded and not set as always visible in list
+     * in order to be collapsed later.
+     *
+     * @method _storeItemsForCollapsing
+     * @protected
+     * @param itemsToBeExcluded {Object} (optional) Contains one or more <code>Y.AccordionItem</code> instances,
+     * which should be not included in the list
+     */
+    _storeItemsForCollapsing: function( itemsToBeExcluded ){
+        var items;
+
+        itemsToBeExcluded = itemsToBeExcluded || {};
+        items = this.get( ITEMS );
+
+        Y.Array.each( items, function( item, index, items ){
+            var expanded, alwaysVisible;
+
+            expanded = item.get( EXPANDED );
+            alwaysVisible = item.get( ALWAYSVISIBLE );
+
+            if( expanded && !alwaysVisible && !itemsToBeExcluded[ item ] ){
+                this._forCollapsing[ item ] = {
+                    'item': item
+                };
+            }
+        }, this );
+    },
+
+
+    /**
+     * Expands an item to given height. This includes also an update to item's user interface
+     *
+     * @method _expandItem
+     * @protected
+     * @param item {Y.AccordionItem} The item, which should be expanded.
+     * @param height {Number} The height to which we should expand the item
+     */
+    _expandItem: function( item, height ){
+        var alwaysVisible = item.get( ALWAYSVISIBLE );
+
+        this._processExpanding( item, height );
+        this._setItemUI( item, true, alwaysVisible );
+    },
+
+
+    /**
+     * Expands an item to given height. Depending on the <code>useAnimation</code> setting,
+     * the process of expanding might be animated. This setting will be ignored, if <code>forceSkipAnimation</code> param
+     * is <code>true</code>.
+     *
+     * @method _processExpanding
+     * @protected
+     * @param item {Y.AccordionItem} An <code>Y.AccordionItem</code> instance to be expanded
+     * @param forceSkipAnimation {Boolean} If true, the animation will be skipped,
+     * without taking in consideration Accordion's <code>useAnimation</code> setting
+     * @param height {Number} The height to which item should be expanded
+     */
+    _processExpanding: function( item, height, forceSkipAnimation ){
+        var anim, curAnim, animSettings, notifyOthers = false,
+            accAnimationSettings, body;
+
+        body = item.getStdModNode( WidgetStdMod.BODY );
+
+        this.fire( BEFOREITEMERESIZED, {
+            'item': item
+        });
+
+        if( body.get( "clientHeight" ) <= COLLAPSE_HEIGHT ){
+            notifyOthers = true;
+            this.fire( BEFOREITEMEXPAND, {
+                'item': item
+            });
+        }
+
+        if( !forceSkipAnimation && this.get( "useAnimation" ) ){
+            animSettings = item.get( ANIMATION ) || {};
+
+            anim = new Anim( {
+                node: body,
+                to: {
+                    'height': height
+                }
+            });
+
+            anim.on( "end", Y.bind( this._onExpandComplete, this, item, notifyOthers ) );
+
+            accAnimationSettings = this.get( ANIMATION );
+
+            anim.set( "duration", animSettings.duration || accAnimationSettings.duration );
+            anim.set( "easing"  , animSettings.easing   || accAnimationSettings.easing   );
+
+            curAnim = this._animations[ item ];
+
+            if( curAnim ){
+                curAnim.stop();
+            }
+
+            item.markAsExpanding( true );
+
+            this._animations[ item ] = anim;
+
+            anim.run();
+        } else {
+            body.setStyle( "height", height + PX );
+
+            this.fire( ITEMERESIZED, {
+                'item': item
+            });
+
+            if( notifyOthers ){
+                this.fire( ITEMEXPANDED, {
+                    'item': item
+                });
+            }
+        }
+    },
+
+
+    /**
+     * Executes when animated expanding completes
+     *
+     * @method _onExpandComplete
+     * @protected
+     * @param item {Y.AccordionItem} An <code>Y.AccordionItem</code> instance which has been expanded
+     * @param notifyOthers {Boolean} If true, itemExpanded event will be fired
+     */
+    _onExpandComplete: function( item, notifyOthers ){
+        delete this._animations[ item ];
+
+        item.markAsExpanding( false );
+
+        this.fire( ITEMERESIZED, {
+            'item': item
+        });
+
+        if( notifyOthers ){
+            this.fire( ITEMEXPANDED, {
+                'item': item
+            });
+        }
+    },
+
+
+    /**
+     * Collapse an item and update its user interface
+     *
+     * @method _collapseItem
+     * @protected
+     * @param item {Y.AccordionItem} The item, which should be collapsed
+     */
+    _collapseItem: function( item ){
+        this._processCollapsing( item, COLLAPSE_HEIGHT );
+        this._setItemUI( item, false, false );
+    },
+
+
+    /**
+     * Collapse an item to given height. Depending on the <code>useAnimation</code> setting,
+     * the process of collapsing might be animated. This setting will be ignored, if <code>forceSkipAnimation</code> param
+     * is <code>true</code>.
+     *
+     * @method _processCollapsing
+     * @protected
+     * @param item {Y.AccordionItem} An <code>Y.AccordionItem</code> instance to be collapsed
+     * @param height {Number} The height to which item should be collapsed
+     * @param forceSkipAnimation {Boolean} If true, the animation will be skipped,
+     * without taking in consideration Accordion's <code>useAnimation</code> setting
+     */
+    _processCollapsing: function( item, height, forceSkipAnimation ){
+        var anim, curAnim, animSettings, accAnimationSettings, body,
+            notifyOthers = (height === COLLAPSE_HEIGHT);
+
+        body = item.getStdModNode( WidgetStdMod.BODY );
+
+
+        this.fire( BEFOREITEMERESIZED, {
+            'item': item
+        });
+
+        if( notifyOthers ){
+            this.fire( BEFOREITEMCOLLAPSE, {
+                'item': item
+            });
+        }
+
+        if( !forceSkipAnimation && this.get( "useAnimation" ) ){
+            animSettings = item.get( ANIMATION ) || {};
+
+            anim = new Anim( {
+                node: body,
+                to: {
+                    'height': height
+                }
+            });
+
+            anim.on( "end", Y.bind( this._onCollapseComplete, this, item, notifyOthers ) );
+
+            accAnimationSettings = this.get( ANIMATION );
+
+            anim.set( "duration", animSettings.duration || accAnimationSettings.duration );
+            anim.set( "easing"  , animSettings.easing   || accAnimationSettings.easing );
+
+            curAnim = this._animations[ item ];
+
+            if( curAnim ){
+                curAnim.stop();
+            }
+
+            item.markAsCollapsing( true );
+
+            this._animations[ item ] = anim;
+
+            anim.run();
+        } else {
+            body.setStyle( "height", height + PX );
+
+            this.fire( ITEMERESIZED, {
+                'item': item
+            });
+
+            if( notifyOthers ){
+                this.fire( ITEMCOLLAPSED, {
+                    'item': item
+                });
+            }
+        }
+    },
+
+
+    /**
+     * Executes when animated collapsing completes
+     *
+     * @method _onCollapseComplete
+     * @protected
+     * @param item {Y.AccordionItem} An <code>Y.AccordionItem</code> instance which has been collapsed
+     * @param notifyOthers {Boolean} If true, itemCollapsed event will be fired
+     */
+    _onCollapseComplete: function( item, notifyOthers ){
+        delete this._animations[ item ];
+
+        item.markAsCollapsing( false );
+
+        this.fire( ITEMERESIZED, {
+            item: item
+        });
+
+        if( notifyOthers ){
+            this.fire( ITEMCOLLAPSED, {
+                'item': item
+            });
+        }
+    },
+
+
+    /**
+     * Make an item draggable. The item can be reordered later.
+     *
+     * @method _initItemDragDrop
+     * @protected
+     * @param item {Y.AccordionItem} An <code>Y.AccordionItem</code> instance to be set as draggable
+     */
+    _initItemDragDrop: function( item ){
+        var itemHeader, dd, bb, itemBB, ddrop;
+
+        itemHeader = item.getStdModNode( WidgetStdMod.HEADER );
+
+        if( itemHeader.dd ){
+            return;
+        }
+
+        bb = this.get( BOUNDING_BOX );
+        itemBB = item.get( BOUNDING_BOX );
+
+        dd = new Y.DD.Drag({
+            node: itemHeader,
+            groups: [ DRAGGROUP ]
+        }).plug(Y.Plugin.DDProxy, {
+            moveOnEnd: false
+        }).plug(Y.Plugin.DDConstrained, {
+            constrain2node: bb
+        });
+
+        ddrop = new Y.DD.Drop({
+            node: itemBB,
+            groups: [ DRAGGROUP ]
+        });
+
+        dd.on   ( "drag:start",   Y.bind( this._onDragStart,  this, dd ) );
+        dd.on   ( "drag:end"  ,   Y.bind( this._onDragEnd,    this, dd ) );
+        dd.after( "drag:end"  ,   Y.bind( this._afterDragEnd, this, dd ) );
+        dd.on   ( "drag:drophit", Y.bind( this._onDropHit,    this, dd ) );
+    },
+
+
+    /**
+     * Sets the label of the item being dragged on the drag proxy.
+     * Fires beforeItemReorder event - returning false will cancel reordering
+     *
+     * @method _onDragStart
+     * @protected
+     * @param dd {Y.DD.Drag} The drag instance of the item
+     * @param e {Event} the DD instance's drag:start custom event
+     */
+    _onDragStart: function( dd, e ){
+        var dragNode, item;
+
+        item = this.getItem( dd.get( NODE ).get( PARENT_NODE ) );
+        dragNode = dd.get( "dragNode" );
+
+        dragNode.addClass( C_PROXY_VISIBLE );
+        dragNode.set( "innerHTML", item.get( "label" ) );
+
+        return this.fire( BEFOREITEMREORDER, { 'item': item } );
+    },
+
+
+    /**
+     * Restores HTML structure of the drag proxy.
+     * Fires beforeEndItemReorder event - returning false will cancel reordering
+     *
+     * @method _onDragEnd
+     * @protected
+     * @param dd {Y.DD.Drag} The drag instance of the item
+     * @param e {Event} the DD instance's drag:end custom event
+     */
+    _onDragEnd: function( dd, e ){
+        var dragNode, item;
+
+        dragNode = dd.get( "dragNode" );
+
+        dragNode.removeClass( C_PROXY_VISIBLE );
+        dragNode.set( "innerHTML", "" );
+
+        item = this.getItem( dd.get( NODE ).get( PARENT_NODE ) );
+        return this.fire( BEFOREENDITEMREORDER, { 'item': item } );
+    },
+
+
+    /**
+     * Set drophit to false in dragdrop instance's custom value (if there has been drophit) and fires itemReordered event
+     *
+     * @method _afterDragEnd
+     * @protected
+     * @param dd {Y.DD.Drag} The drag instance of the item
+     * @param e {Event} the DD instance's drag:end custom event
+     */
+    _afterDragEnd: function( dd, e ){
+        var item, data;
+
+        data = dd.get( DATA );
+
+        if( data.drophit ){
+            item = this.getItem( dd.get( NODE ).get( PARENT_NODE ) );
+
+            dd.set( DATA, {
+                drophit: false
+            } );
+
+            return this.fire( ITEMREORDERED, { 'item': item } );
+        }
+
+        return true;
+    },
+
+
+    /**
+     * Moves the source item before or after target item.
+     *
+     * @method _onDropHit
+     * @protected
+     * @param dd {Y.DD.Drag} The drag instance of the item
+     * @param e {Event} the DD instance's drag:drophit custom event
+     */
+    _onDropHit: function( dd, e) {
+        var mineIndex, targetItemIndex, targetItemBB, itemBB, cb,
+            goingUp, items, targetItem, item;
+
+        item = this.getItem( dd.get( NODE ).get( PARENT_NODE ) );
+        targetItem = this.getItem( e.drop.get( NODE ) );
+
+        if( targetItem === item ){
+            return false;
+        }
+
+        mineIndex = this.getItemIndex( item );
+        targetItemIndex = this.getItemIndex( targetItem );
+        targetItemBB = targetItem.get( BOUNDING_BOX );
+        itemBB = item.get( BOUNDING_BOX );
+        cb = this.get( CONTENT_BOX );
+        goingUp = false;
+        items = this.get( ITEMS );
+
+        if( targetItemIndex < mineIndex ){
+            goingUp = true;
+        }
+
+        cb.removeChild( itemBB );
+
+        if( goingUp ){
+            cb. insertBefore( itemBB, targetItemBB );
+            items.splice( mineIndex, 1 );
+            items.splice( targetItemIndex, 0, item );
+        } else {
+            cb. insertBefore( itemBB, targetItemBB.next( C_ITEM ) );
+            items.splice( targetItemIndex + 1, 0, item );
+            items.splice( mineIndex, 1 );
+        }
+
+        dd.set( DATA, {
+            drophit: true
+        });
+
+        return true;
+    },
+
+
+    /**
+     * Process items as result of user interaction or properties change.
+     * This includes four steps:
+     * 1. Update the properties of the items
+     * 2. Collapse all items stored in the list for collapsing
+     * 3. Adjust all stretch items
+     * 4. Expand items stored in the list for expanding
+     *
+     * @method _processItems
+     * @protected
+     */
+    _processItems: function(){
+        var forCollapsing, forExpanding, itemCont, heightPerStretchItem,
+            height, heightSettings, item;
+
+        forCollapsing = this._forCollapsing;
+        forExpanding = this._forExpanding;
+
+        this._setItemsProperties();
+
+        for( item in forCollapsing ){
+            if( forCollapsing.hasOwnProperty( item ) ){
+                itemCont = forCollapsing[ item ];
+
+                this._collapseItem( itemCont.item );
+            }
+        }
+
+        heightPerStretchItem = this._adjustStretchItems();
+
+        for( item in forExpanding ){
+            if( forExpanding.hasOwnProperty( item ) ){
+                itemCont = forExpanding[ item ];
+                item = itemCont.item;
+                height = heightPerStretchItem;
+                heightSettings = item.get( CONTENT_HEIGHT );
+
+                if( heightSettings.method !== STRETCH ){
+                    height = this._getItemContentHeight( item );
+                }
+
+                this._expandItem( item, height );
+            }
+        }
+
+        this._forCollapsing = {};
+        this._forExpanding = {};
+    },
+
+
+    /**
+     * Update properties of items, which were stored in the lists for collapsing or expanding
+     *
+     * @method _setItemsProperties
+     * @protected
+     */
+    _setItemsProperties: function (){
+        var forCollapsing, forExpanding, itemData;
+
+        forCollapsing = this._forCollapsing;
+        forExpanding = this._forExpanding;
+
+        for( itemData in forCollapsing ){
+            if( forCollapsing.hasOwnProperty( itemData ) ){
+                itemData = forCollapsing[ itemData ];
+                this._setItemProperties( itemData.item, false, false );
+            }
+        }
+
+        for( itemData in forExpanding ){
+            if( forExpanding.hasOwnProperty( itemData ) ){
+                itemData = forExpanding[ itemData ];
+                this._setItemProperties( itemData.item, true, itemData.alwaysVisible );
+            }
+        }
+    },
+
+
+    /**
+     * Handles the change of "expand" property of given item
+     *
+     * @method _afterItemExpand
+     * @protected
+     * @param params {EventFacade} The event facade for the attribute change
+     */
+    _afterItemExpand: function( params ){
+        var expanded, item, alwaysVisible, collapseOthersOnExpand;
+
+        if( params.internalCall ){
+            return;
+        }
+
+        expanded = params.newVal;
+        item    = params.currentTarget;
+        alwaysVisible = item.get( ALWAYSVISIBLE );
+        collapseOthersOnExpand = this.get( COLLAPSEOTHERSONEXPAND );
+
+        if( expanded ){
+            this._forExpanding[ item ] = {
+                'item': item,
+                'alwaysVisible': alwaysVisible
+            };
+
+            if( collapseOthersOnExpand ){
+                this._storeItemsForCollapsing();
+            }
+        } else {
+            this._forCollapsing[ item ] = {
+                'item': item
+            };
+        }
+
+        this._processItems();
+    },
+
+    /**
+     * Handles the change of "alwaysVisible" property of given item
+     *
+     * @method _afterItemAlwaysVisible
+     * @protected
+     * @param params {EventFacade} The event facade for the attribute change
+     */
+    _afterItemAlwaysVisible: function( params ){
+        var item, alwaysVisible, expanded;
+
+        if( params.internalCall ){
+            return;
+        }
+
+        alwaysVisible = params.newVal;
+        item         = params.currentTarget;
+        expanded     = item.get( EXPANDED );
+
+        if( alwaysVisible ){
+            if( expanded ){
+                this._setItemProperties( item, true, true );
+                this._setItemUI( item, true, true );
+                return;
+            } else {
+                this._forExpanding[ item ] = {
+                    'item': item,
+                    'alwaysVisible': true
+                };
+
+                this._storeItemsForCollapsing();
+            }
+        } else {
+            if( expanded ){
+                this._setItemUI( item, true, false );
+                return;
+            } else {
+                return;
+            }
+        }
+
+        this._processItems();
+    },
+
+
+    /**
+     * Handles the change of "contentHeight" property of given item
+     *
+     * @method _afterContentHeight
+     * @protected
+     * @param params {EventFacade} The event facade for the attribute change
+     */
+    _afterContentHeight: function( params ){
+        var item, itemContentHeight, body, bodyHeight, expanded;
+
+        item = params.currentTarget;
+
+        this._adjustStretchItems();
+
+        if( params.newVal.method !== STRETCH ){
+            expanded = item.get( EXPANDED );
+            itemContentHeight = this._getItemContentHeight( item );
+
+            body = item.getStdModNode( WidgetStdMod.BODY );
+            bodyHeight = this._getNodeOffsetHeight( body );
+
+            if( itemContentHeight < bodyHeight ){
+                this._processCollapsing( item, itemContentHeight, !expanded );
+            } else if( itemContentHeight > bodyHeight ){
+                this._processExpanding( item, itemContentHeight, !expanded );
+            }
+        }
+    },
+
+
+    /**
+     * Handles the change of "contentUpdate" property of given item
+     *
+     * @method _afterContentUpdate
+     * @protected
+     * @param params {EventFacade} The event facade for the attribute change
+     */
+    _afterContentUpdate : function( params ){
+        var item, body, bodyHeight, expanded, auto, anim;
+
+        item = params.currentTarget;
+        auto = item.get( "contentHeight" ).method === "auto";
+        expanded = item.get( EXPANDED );
+
+        body = item.getStdModNode( WidgetStdMod.BODY );
+        bodyHeight = this._getNodeOffsetHeight( body );
+
+        if( auto && expanded && params.src !== Y.Widget.UI_SRC ){
+            Y.later( 0, this, function(){
+                var itemContentHeight = this._getItemContentHeight( item );
+
+                if( itemContentHeight !== bodyHeight ){
+                    anim = this._animations[ item ];
+
+                    // stop waiting animation
+                    if( anim ){
+                        anim.stop();
+                    }
+
+                    this._adjustStretchItems();
+
+                    if( itemContentHeight < bodyHeight ){
+                        this._processCollapsing( item, itemContentHeight, !expanded );
+                    } else if( itemContentHeight > bodyHeight ){
+                        this._processExpanding( item, itemContentHeight, !expanded );
+                    }
+                }
+            } );
+        }
+    },
+
+
+    /**
+     * Subscribe for resize event, which could be provided from the browser or from an arbitrary object.
+     * For example, if there is LayoutManager in the page, it is preferable to subscribe to its resize event,
+     * instead to those, which browser provides.
+     *
+     * @method _setUpResizing
+     * @protected
+     * @param value {String|Object} String "default" or object with the following properties:
+     *  <dl>
+     *      <dt>sourceObject</dt>
+     *          <dd>An abbitrary object</dd>
+     *      <dt>resizeEvent</dt>
+     *          <dd>The name of its resize event</dd>
+     *  </dl>
+     */
+    _setUpResizing: function( value ){
+        if( this._resizeEventHandle ){
+            this._resizeEventHandle.detach();
+        }
+
+        if( value === DEFAULT ){
+            this._resizeEventHandle = Y.on( 'windowresize', Y.bind( this._adjustStretchItems, this ) );
+        } else {
+            this._resizeEventHandle = value.sourceObject.on( value.resizeEvent, Y.bind( this._adjustStretchItems, this ) );
+        }
+    },
+
+
+    /**
+     * Creates one or more items found in Accordion's <code>contentBox</code>
+     *
+     * @method renderUI
+     * @protected
+     */
+    renderUI: function(){
+        var srcNode, itemsDom, contentBox, srcNodeId;
+
+        srcNode = this.get( SRCNODE );
+        contentBox = this.get( CONTENT_BOX );
+        srcNodeId = srcNode.get( "id" );
+
+        /*
+         * Widget 3.1 workaround - the Id of contentBox is generated by YUI, instead to keep srcNode's Id, so we set it manually
+         */
+        contentBox.set( "id", srcNodeId );
+
+        itemsDom = srcNode.all( "> ." + C_ITEM );
+
+        itemsDom.each( function( itemNode, index, itemsDom ){
+            var newItem;
+
+            if( !this.getItem( itemNode ) ){
+                newItem = new Y.AccordionItem({
+                    srcNode: itemNode,
+                    id : itemNode.get( "id" )
+                });
+
+                this.addItem( newItem );
+            }
+        }, this );
+    },
+
+
+    /**
+     * Add listener to <code>itemChosen</code> event in Accordion's content box
+     *
+     * @method bindUI
+     * @protected
+     */
+    bindUI: function(){
+        var contentBox, itemChosenEvent;
+
+        contentBox = this.get( CONTENT_BOX );
+        itemChosenEvent = this.get( 'itemChosen' );
+
+        contentBox.delegate( itemChosenEvent, Y.bind( this._onItemChosenEvent, this ), '.yui3-widget-hd' );
+    },
+
+
+    /**
+     * Listening for itemChosen event, determines the source (is that iconClose, iconAlwaysVisisble, etc.) and
+     * invokes this._onItemChosen for further processing
+     *
+     * @method _onItemChosenEvent
+     * @protected
+     *
+     * @param e {Event} The itemChosen event
+     */
+    _onItemChosenEvent: function(e){
+        var header, itemNode, item, iconAlwaysVisible,
+            iconClose, srcIconAlwaysVisible, srcIconClose;
+
+        header = e.currentTarget;
+        itemNode = header.get( PARENT_NODE );
+        item = this.getItem( itemNode );
+        iconAlwaysVisible = item.get( ICON_ALWAYSVISIBLE );
+        iconClose = item.get( ICON_CLOSE );
+        srcIconAlwaysVisible = (iconAlwaysVisible === e.target);
+        srcIconClose = (iconClose === e.target);
+
+        this._onItemChosen( item, srcIconAlwaysVisible, srcIconClose );
+    },
+
+
+    /**
+     * Add an item to Accordion. Items could be added/removed multiple times and they
+     * will be rendered in the process of adding, if not.
+     * The item will be expanded, collapsed, or set as always visible depending on the
+     * settings. Item's properties will be also updated, if they are incomplete.
+     * For example, if <code>alwaysVisible</code> is true, but <code>expanded</code>
+     * property is false, it will be set to true also.
+     *
+     * If the second param, <code>parentItem</code> is an <code>Y.AccordionItem</code> instance,
+     * registered in Accordion, the item will be added as child of the <code>parentItem</code>
+     *
+     * @method addItem
+     * @param item {Y.AccordionItem} The item to be added in Accordion
+     * @param parentItem {Y.AccordionItem} (optional) This item will be the parent of the item being added
+     *
+     * @return {Boolean} True in case of successfully added item, false otherwise
+     */
+    addItem: function( item, parentItem ){
+        var expanded, alwaysVisible, itemBody, itemBodyContent, itemIndex, items, contentBox,
+            itemHandles, itemContentBox, res, children;
+
+        res = this.fire( BEFOREITEMADD, {
+            'item': item
+        });
+
+        if( !res ){
+            return false;
+        }
+
+        items = this.get( ITEMS );
+        contentBox = this.get( CONTENT_BOX );
+
+        itemContentBox = item.get( CONTENT_BOX );
+
+        if( !itemContentBox.inDoc() ){
+            if( parentItem ){
+                itemIndex = this.getItemIndex( parentItem );
+
+                if( itemIndex < 0 ){
+                    return false;
+                }
+
+                items.splice( itemIndex, 0, item );
+                contentBox.insertBefore( itemContentBox, parentItem.get( BOUNDING_BOX ) );
+            } else {
+                items.push( item );
+                contentBox.insertBefore( itemContentBox, null );
+            }
+        } else {
+            children = contentBox.get( CHILDREN );
+
+            res = children.some( function( node, index, nodeList ){
+                if( node === itemContentBox ){
+                    items.splice( index, 0, item );
+                    return true;
+                } else {
+                    return false;
+                }
+            }, this );
+
+            if( !res ){
+                return false;
+            }
+        }
+
+        itemBody = item.getStdModNode( WidgetStdMod.BODY );
+        itemBodyContent = item.get( BODYCONTENT );
+
+        if( !itemBody && !itemBodyContent  ){
+            item.set( BODYCONTENT, "" );
+        }
+
+        if( !item.get( RENDERED ) ){
+            item.render();
+        }
+
+        expanded = item.get( EXPANDED );
+        alwaysVisible = item.get( ALWAYSVISIBLE );
+
+        expanded = expanded || alwaysVisible;
+
+        if( expanded ){
+            this._forExpanding[ item ] = {
+                'item': item,
+                'alwaysVisible': alwaysVisible
+            };
+        } else {
+            this._forCollapsing[ item ] = {
+                'item': item
+            };
+        }
+
+        this._processItems();
+
+        if( this.get( "reorderItems" ) ){
+            this._initItemDragDrop( item );
+        }
+
+        itemHandles = this._itemsHandles[ item ];
+
+        if( !itemHandles ){
+            itemHandles = {};
+        }
+
+        itemHandles = {
+            "expandedChange" : item.after( "expandedChange", Y.bind( this._afterItemExpand, this ) ),
+            "alwaysVisibleChange" : item.after( "alwaysVisibleChange", Y.bind( this._afterItemAlwaysVisible, this ) ),
+            "contentHeightChange" : item.after( "contentHeightChange", Y.bind( this._afterContentHeight, this ) ),
+            "contentUpdate" : item.after( "contentUpdate", Y.bind( this._afterContentUpdate, this ) )
+        };
+
+        this._itemsHandles[ item ] = itemHandles;
+
+        this.fire( ITEMADDED, {
+            'item': item
+        });
+
+        return true;
+    },
+
+
+    /**
+     * Removes an previously registered item in Accordion
+     *
+     * @method removeItem
+     * @param p_item {Y.AccordionItem|Number} The item to be removed, or its index
+     * @return {Y.AccordionItem} The removed item or null if not found
+     */
+    removeItem: function( p_item ){
+        var items, bb, item = null, itemIndex;
+
+        items = this.get( ITEMS );
+
+        if( Lang.isNumber( p_item ) ){
+            itemIndex = p_item;
+        } else if( p_item instanceof Y.AccordionItem ){
+            itemIndex = this.getItemIndex( p_item );
+        } else {
+            return null;
+        }
+
+        if( itemIndex >= 0 ){
+
+            this.fire( BEFOREITEMREMOVE, {
+                item: p_item
+            });
+
+            item = items.splice( itemIndex, 1 )[0];
+
+            this._removeItemHandles( item );
+
+            bb = item.get( BOUNDING_BOX );
+            bb.remove();
+
+            this._adjustStretchItems();
+
+            this.fire( ITEMREMOVED, {
+                item: p_item
+            });
+        }
+
+        return item;
+    },
+
+
+    /**
+     * Searching for item, previously registered in Accordion
+     *
+     * @method getItem
+     * @param param {Number|Y.Node} If number, this must be item's index.
+     * If Node, it should be the value of item's <code>contentBox</code> or <code>boundingBox</code> properties
+     *
+     * @return {Y.AccordionItem} The found item or null
+     */
+    getItem: function( param ){
+        var items = this.get( ITEMS ), item = null;
+
+        if( Lang.isNumber( param ) ){
+            item = items[ param ];
+            return (item instanceof Y.AccordionItem) ? item : null;
+        } else if( param instanceof Node ){
+            Y.Array.some( items, function( tmpItem, index, items ){
+                var contentBox = tmpItem.get( CONTENT_BOX );
+
+                /*
+                 * Both contentBox and boundingBox point to same node, so it is safe to check only one of them
+                 */
+                if( contentBox === param ){
+                    item = tmpItem;
+                    return true;
+                } else {
+                    return false;
+                }
+            }, this );
+        }
+
+        return item;
+    },
+
+
+    /**
+     * Looking for the index of previously registered item
+     *
+     * @method getItemIndex
+     * @param item {Y.AccordionItem} The item which index should be returned
+     * @return {Number} Item index or <code>-1</code> if item has been not found
+     */
+    getItemIndex: function( item ){
+        var res = -1, items;
+
+        if( item instanceof Y.AccordionItem ){
+            items = this.get( ITEMS );
+
+            Y.Array.some( items, function( tmpItem, index, items ){
+                if( tmpItem === item ){
+                    res = index;
+                    return true;
+                } else {
+                    return false;
+                }
+            }, this );
+        }
+
+        return res;
+    },
+
+
+    /**
+     * Overwrites Y.WidgetStdMod fuction in order to resolve Widget 3.1 issue:<br>
+     * If CONTENT_TEMPLATE is null, in renderUI the result of the following code:
+     * <code>this.getStdModNode( Y.WidgetStdMod.HEADER );</code> is null.
+     * The same is with <code>this.getStdModNode( Y.WidgetStdMod.BODY );</code>.
+     *
+     * @method _findStdModSection
+     * @protected
+     * @param {String} section The section for which the render Node is to be found. Either WidgetStdMod.HEADER, WidgetStdMod.BODY or WidgetStdMod.FOOTER.
+     * @return {Node} The rendered node for the given section, or null if not found.
+     */
+    _findStdModSection: function(section) {
+        return this.get(SRCNODE).one("> ." + Y.WidgetStdMod.SECTION_CLASS_NAMES[section]);
+    },
+
+    CONTENT_TEMPLATE : null
+}, {
+    /**
+     *  Static property provides a string to identify the class.
+     *
+     * @property Accordion.NAME
+     * @type String
+     * @static
+     */
+    NAME : AccName,
+
+    /**
+     * Static property used to define the default attribute
+     * configuration for the Accordion.
+     *
+     * @property Accordion.ATTRS
+     * @type Object
+     * @static
+     */
+    ATTRS : {
+        /**
+         * @description The event on which Accordion should listen for user interactions.
+         * The value can be also mousedown or mouseup. Mousedown event can be used if
+         * drag&drop is not enabled
+         *
+         * @attribute itemChosen
+         * @default click
+         * @type String
+         */
+        itemChosen: {
+            value: "click",
+            validator: Lang.isString
+        },
+
+        /**
+         * @description Contains the items, currently added to Accordion
+         *
+         * @attribute items
+         * @readOnly
+         * @default []
+         * @type Array
+         */
+        items: {
+            value: [],
+            readOnly: true,
+            validator: Lang.isArray
+        },
+
+        /**
+         * @attribute resizeEvent
+         *
+         * @description The event on which Accordion should listen for resizing.
+         * The value must be one of these:
+         * <ul>
+         *     <li> String "default" - the Accordion will subscribe to Y.windowresize event
+         *     </li>
+         *     <li> An object in the following form:
+         *         {
+         *             sourceObject: some_javascript_object,
+         *             resizeEvent: an_event_to_subscribe
+         *         }
+         *      </li>
+         * </ul>
+         * For example, if we are using LayoutManager's instance as sourceObject, we will have to use its "resize" event as resizeEvent
+         *
+         * @default "default"
+         * @type String or Object
+         */
+
+        resizeEvent: {
+            value: DEFAULT,
+            validator: function( value ){
+                if( value === DEFAULT ){
+                    return true;
+                } else if( Lang.isObject(value) ){
+                    if( Lang.isValue( value.sourceObject ) && Lang.isValue( value.resizeEvent ) ){
+                        return true;
+                    }
+                }
+
+                return false;
+            }
+        },
+
+        /**
+         * @attribute useAnimation
+         * @description Boolean indicating that Accordion should use animation when expanding or collapsing items.
+         *
+         * @default true
+         * @type Boolean
+         */
+        useAnimation: {
+            value: true,
+            validator: Lang.isBoolean
+        },
+
+        /**
+         * @attribute animation
+         * @description Animation config values, see Y.Animation
+         *
+         * @default <code> {
+         *    duration: 1,
+         *    easing: Easing.easeOutStrong
+         *  }
+         *  </code>
+         *
+         * @type Object
+         */
+        animation: {
+            value: {
+                duration: 1,
+                easing: Easing.easeOutStrong
+            },
+            validator: function( value ){
+                return Lang.isObject( value ) && Lang.isNumber( value.duration ) &&
+                    Lang.isFunction( value.easing );
+            }
+        },
+
+        /**
+         * @attribute reorderItems
+         * @description Boolean indicating that items can be reordered via drag and drop.<br>
+         *
+         * Enabling items reordering requires also including the optional drag and drop modules in YUI instance:<br>
+         * 'dd-constrain', 'dd-proxy', 'dd-drop', or just 'dd'
+         *
+         * @default false
+         * @type Boolean
+         */
+        reorderItems: {
+            value: false,
+            validator: function(value){
+                return Lang.isBoolean(value) && !Lang.isUndefined( Y.DD );
+            }
+        },
+
+        /**
+         * @attribute collapseOthersOnExpand
+         * @description If true, on item expanding, all other expanded and not set as always visible items, will be collapsed
+         * Otherwise, they will stay open
+         *
+         * @default true
+         * @type Boolean
+         */
+        collapseOthersOnExpand: {
+            value: true,
+            validator: Lang.isBoolean
+        }
+    }
+});
+
+}());
+
+/**
+ * Provides AccordionItem class
+ *
+ * @module gallery-accordion
+ */
+
+(function(){
+
+// Local constants
+var Lang = Y.Lang,
+    Node = Y.Node,
+    JSON = Y.JSON,
+    WidgetStdMod = Y.WidgetStdMod,
+    AccItemName = "accordion-item",
+    getCN = Y.ClassNameManager.getClassName,
+    
+    C_ICONEXPANDED_EXPANDING = getCN( AccItemName, "iconexpanded", "expanding" ),
+    C_ICONEXPANDED_COLLAPSING = getCN( AccItemName, "iconexpanded", "collapsing" ),
+
+    C_ICON = getCN( AccItemName, "icon" ),
+    C_LABEL = getCN( AccItemName, "label" ),
+    C_ICONALWAYSVISIBLE = getCN( AccItemName, "iconalwaysvisible" ),
+    C_ICONSCONTAINER = getCN( AccItemName, "icons" ),
+    C_ICONEXPANDED = getCN( AccItemName, "iconexpanded" ),
+    C_ICONCLOSE = getCN( AccItemName, "iconclose" ),
+    C_ICONCLOSE_HIDDEN = getCN( AccItemName, "iconclose", "hidden" ),
+
+    C_ICONEXPANDED_ON = getCN( AccItemName, "iconexpanded", "on" ),
+    C_ICONEXPANDED_OFF = getCN( AccItemName, "iconexpanded", "off" ),
+
+    C_ICONALWAYSVISIBLE_ON = getCN( AccItemName, "iconalwaysvisible", "on" ),
+    C_ICONALWAYSVISIBLE_OFF = getCN( AccItemName, "iconalwaysvisible", "off" ),
+
+    C_EXPANDED =  getCN( AccItemName, "expanded" ),
+    C_CLOSABLE =  getCN( AccItemName, "closable" ),
+    C_ALWAYSVISIBLE =  getCN( AccItemName, "alwaysvisible" ),
+    C_CONTENTHEIGHT =  getCN( AccItemName, "contentheight" ),
+
+    TITLE = "title",
+    STRINGS = "strings",
+    RENDERED = "rendered",
+    CLASS_NAME = "className",
+    AUTO = "auto",
+    STRETCH = "stretch",
+    FIXED = "fixed",
+    HEADER_SELECTOR = ".yui3-widget-hd",
+    DOT = ".",
+    HEADER_SELECTOR_SUB = ".yui3-widget-hd " + DOT,
+    INNER_HTML = "innerHTML",
+    ICONS_CONTAINER = "iconsContainer",
+    ICON = "icon",
+    NODE_LABEL = "nodeLabel",
+    ICON_ALWAYSVISIBLE = "iconAlwaysVisible",
+    ICON_EXPANDED = "iconExpanded",
+    ICON_CLOSE = "iconClose",
+    HREF = "href",
+    HREF_VALUE = "#",
+    YUICONFIG = "yuiConfig",
+
+    REGEX_TRUE = /^(?:true|yes|1)$/,
+    REGEX_AUTO = /^auto\s*/,
+    REGEX_STRETCH = /^stretch\s*/,
+    REGEX_FIXED = /^fixed-\d+/;
+
+/**
+ * Create an AccordionItem widget.
+ *
+ * @class AccordionItem
+ * @extends Widget
+ */
+
+Y.AccordionItem = Y.Base.create( AccItemName, Y.Widget, [Y.WidgetStdMod], {
+    /**
+     * Creates the header content
+     *
+     * @method _createHeader
+     * @protected
+     */
+    _createHeader: function(){
+        var closable, templates, strings,  iconsContainer,
+            icon, nodeLabel, iconExpanded, iconAlwaysVisible, iconClose;
+
+        icon = this.get( ICON );
+        nodeLabel = this.get( NODE_LABEL );
+        iconExpanded = this.get( ICON_EXPANDED );
+        iconAlwaysVisible = this.get( ICON_ALWAYSVISIBLE );
+        iconClose = this.get( ICON_CLOSE );
+        iconsContainer = this.get( ICONS_CONTAINER );
+
+        strings = this.get( STRINGS );
+        closable = this.get( "closable" );
+        templates = Y.AccordionItem.TEMPLATES;
+
+        if( !icon ){
+            icon = Node.create( templates.icon );
+            this.set( ICON, icon );
+        }
+
+        if( !nodeLabel ){
+            nodeLabel = Node.create( templates.label );
+            this.set( NODE_LABEL, nodeLabel );
+        } else if( !nodeLabel.hasAttribute( HREF ) ){
+            nodeLabel.setAttribute( HREF, HREF_VALUE );
+        }
+
+        nodeLabel.setContent( this.get( "label" ) );
+
+
+        if( !iconsContainer ){
+            iconsContainer = Node.create( templates.iconsContainer );
+            this.set( ICONS_CONTAINER, iconsContainer );
+        }
+
+        if( !iconAlwaysVisible ){
+            iconAlwaysVisible = Node.create( templates.iconAlwaysVisible );
+            iconAlwaysVisible.setAttribute( TITLE, strings.title_always_visible_off );
+            this.set( ICON_ALWAYSVISIBLE, iconAlwaysVisible );
+        } else if( !iconAlwaysVisible.hasAttribute( HREF ) ){
+            iconAlwaysVisible.setAttribute( HREF, HREF_VALUE );
+        }
+
+
+        if( !iconExpanded ){
+            iconExpanded = Node.create( templates.iconExpanded );
+            iconExpanded.setAttribute( TITLE, strings.title_iconexpanded_off );
+            this.set( ICON_EXPANDED, iconExpanded );
+        } else if( !iconExpanded.hasAttribute( HREF ) ){
+            iconExpanded.setAttribute( HREF, HREF_VALUE );
+        }
+
+
+        if( !iconClose ){
+            iconClose = Node.create( templates.iconClose );
+            iconClose.setAttribute( TITLE, strings.title_iconclose );
+            this.set( ICON_CLOSE, iconClose );
+        } else if( !iconClose.hasAttribute( HREF ) ){
+            iconClose.setAttribute( HREF, HREF_VALUE );
+        }
+
+        if( closable ){
+            iconClose.removeClass( C_ICONCLOSE_HIDDEN );
+        } else {
+            iconClose.addClass( C_ICONCLOSE_HIDDEN );
+        }
+
+        this._addHeaderComponents();
+    },
+
+    /**
+     * Add label and icons in the header. Also, it creates header in if not set from markup
+     *
+     * @method _addHeaderComponents
+     * @protected
+     */
+    _addHeaderComponents: function(){
+        var header, icon, nodeLabel, iconsContainer, iconExpanded,
+            iconAlwaysVisible, iconClose;
+
+        icon = this.get( ICON );
+        nodeLabel = this.get( NODE_LABEL );
+        iconExpanded = this.get( ICON_EXPANDED );
+        iconAlwaysVisible = this.get( ICON_ALWAYSVISIBLE );
+        iconClose = this.get( ICON_CLOSE );
+        iconsContainer = this.get( ICONS_CONTAINER );
+
+        header = this.getStdModNode( WidgetStdMod.HEADER );
+
+        if( !header ){
+            header = new Node( document.createDocumentFragment() );
+            header.appendChild( icon );
+            header.appendChild( nodeLabel );
+            header.appendChild( iconsContainer );
+            iconsContainer.appendChild( iconAlwaysVisible );
+            iconsContainer.appendChild( iconExpanded );
+            iconsContainer.appendChild( iconClose );
+
+            this.setStdModContent( WidgetStdMod.HEADER, header, WidgetStdMod.REPLACE );
+        } else {
+            if( !header.contains( icon ) ){
+                if( header.contains( nodeLabel ) ){
+                    header.insertBefore( icon, nodeLabel );
+                } else {
+                    header.appendChild( icon );
+                }
+            }
+
+            if( !header.contains( nodeLabel ) ){
+                header.appendChild( nodeLabel );
+            }
+
+            if( !header.contains( iconsContainer ) ){
+                header.appendChild( iconsContainer );
+            }
+
+            if( !iconsContainer.contains( iconAlwaysVisible ) ){
+                iconsContainer.appendChild( iconAlwaysVisible );
+            }
+
+            if( !iconsContainer.contains( iconExpanded ) ){
+                iconsContainer.appendChild( iconExpanded );
+            }
+
+            if( !iconsContainer.contains( iconClose ) ){
+                iconsContainer.appendChild( iconClose );
+            }
+        }
+    },
+
+
+    /**
+     * Handles the change of "labelChanged" property. Updates item's UI with the label provided
+     *
+     * @method _labelChanged
+     * @protected
+     * @param params {EventFacade} The event facade for the attribute change
+     */
+    _labelChanged: function( params ){
+        var label;
+
+        if( this.get( RENDERED ) ){
+            label = this.get( NODE_LABEL );
+            label.set( INNER_HTML, params.newVal );
+        }
+    },
+
+
+    /**
+     * Handles the change of "closableChanged" property. Hides or shows close icon
+     *
+     * @method _closableChanged
+     * @protected
+     * @param params {EventFacade} The event facade for the attribute change
+     */
+    _closableChanged: function( params ){
+        var iconClose;
+
+        if( this.get( RENDERED ) ){
+            iconClose = this.get( ICON_CLOSE );
+
+            if( params.newVal ){
+                iconClose.removeClass( C_ICONCLOSE_HIDDEN );
+            } else {
+                iconClose.addClass( C_ICONCLOSE_HIDDEN );
+            }
+        }
+    },
+
+
+    /**
+     * Initializer lifecycle implementation for the AccordionItem class.
+     *
+     * @method initializer
+     * @protected
+     * @param  config {Object} Configuration object literal for the AccordionItem
+     */
+    initializer: function( config ) {
+        this.after( "labelChange",  Y.bind( this._labelChanged, this ) );
+        this.after( "closableChange", Y.bind( this._closableChanged, this ) );
+    },
+
+
+    /**
+     * Destructor lifecycle implementation for the AccordionItem class.
+     *
+     * @method destructor
+     * @protected
+     */
+    destructor : function() {
+        // EMPTY
+    },
+
+
+    /**
+     * Creates AccordionItem's header.
+     *
+     * @method renderUI
+     * @protected
+     */
+    renderUI: function(){
+        this._createHeader();
+    },
+
+    /**
+     * Configures/Sets up listeners to bind Widget State to UI/DOM
+     *
+     * @method bindUI
+     * @protected
+     */
+    bindUI: function(){
+        var contentBox = this.get( "contentBox" );
+
+        contentBox.delegate( "click", Y.bind( this._onLinkClick, this ), HEADER_SELECTOR + ' a' );
+    },
+
+
+
+    /**
+     * Prevent default action on clicking the link in the label
+     *
+     * @method _onLinkClick
+     * @protected
+     *
+     * @param e {Event} The click event
+     */
+    _onLinkClick: function( e ){
+        e.preventDefault();
+    },
+
+   /**
+    * Marks the item as always visible by adding class to always visible icon.
+    * The icon will be updated only if needed.
+    *
+    * @method markAsAlwaysVisible
+    * @param alwaysVisible {Boolean} If true, the item should be marked as always visible.
+    * @return {Boolean} Return true if the icon has been updated, false if there was no need to update
+    */
+    markAsAlwaysVisible: function( alwaysVisible ){
+        var iconAlwaysVisisble, strings;
+
+        iconAlwaysVisisble = this.get( ICON_ALWAYSVISIBLE );
+        strings = this.get( STRINGS );
+
+        if( alwaysVisible ){
+            if( !iconAlwaysVisisble.hasClass( C_ICONALWAYSVISIBLE_ON ) ){
+                iconAlwaysVisisble.replaceClass( C_ICONALWAYSVISIBLE_OFF, C_ICONALWAYSVISIBLE_ON );
+                iconAlwaysVisisble.set( TITLE, strings.title_always_visible_on );
+                return true;
+            }
+        } else {
+            if( iconAlwaysVisisble.hasClass( C_ICONALWAYSVISIBLE_ON ) ){
+                iconAlwaysVisisble.replaceClass( C_ICONALWAYSVISIBLE_ON, C_ICONALWAYSVISIBLE_OFF );
+                iconAlwaysVisisble.set( TITLE, strings.title_always_visible_off );
+                return true;
+            }
+        }
+
+        return false;
+    },
+
+
+    /**
+    * Marks the item as expanded by adding class to expand icon.
+    * The icon will be updated only if needed.
+    *
+    * @method markAsExpanded
+    * @param expanded {Boolean} Boolean indicating that item should be marked as expanded.
+    * @return {Boolean} Return true if the icon has been updated, false if there was no need to update
+    */
+    markAsExpanded: function( expanded ){
+        var strings, iconExpanded;
+
+        iconExpanded = this.get( ICON_EXPANDED );
+        strings = this.get( STRINGS );
+
+        if( expanded ){
+            if( !iconExpanded.hasClass( C_ICONEXPANDED_ON ) ){
+                iconExpanded.replaceClass( C_ICONEXPANDED_OFF, C_ICONEXPANDED_ON );
+                iconExpanded.set( TITLE , strings.title_iconexpanded_on );
+                return true;
+            }
+        } else {
+            if( iconExpanded.hasClass( C_ICONEXPANDED_ON ) ){
+                iconExpanded.replaceClass( C_ICONEXPANDED_ON, C_ICONEXPANDED_OFF );
+                iconExpanded.set( TITLE , strings.title_iconexpanded_off );
+                return true;
+            }
+        }
+
+        return false;
+    },
+
+
+   /**
+    * Marks the item as expanding by adding class to expand icon.
+    * The method will update icon only if needed.
+    *
+    * @method markAsExpanding
+    * @param expanding {Boolean} Boolean indicating that the item should be marked as expanding.
+    * @return {Boolean} Return true if the icon has been updated, false if there was no need to update
+    */
+    markAsExpanding: function( expanding ){
+        var iconExpanded = this.get( ICON_EXPANDED );
+
+        if( expanding ){
+            if( !iconExpanded.hasClass( C_ICONEXPANDED_EXPANDING ) ){
+                iconExpanded.addClass( C_ICONEXPANDED_EXPANDING );
+                return true;
+            }
+        } else {
+            if( iconExpanded.hasClass( C_ICONEXPANDED_EXPANDING ) ){
+                iconExpanded.removeClass( C_ICONEXPANDED_EXPANDING );
+                return true;
+            }
+        }
+
+        return false;
+    },
+
+
+   /**
+    * Marks the item as collapsing by adding class to expand icon.
+    * The method will update icon only if needed.
+    *
+    * @method markAsCollapsing
+    * @param collapsing {Boolean} Boolean indicating that the item should be marked as collapsing.
+    * @return {Boolean} Return true if the icon has been updated, false if there was no need to update
+    */
+    markAsCollapsing: function( collapsing ){
+        var iconExpanded = this.get( ICON_EXPANDED );
+
+        if( collapsing ){
+            if( !iconExpanded.hasClass( C_ICONEXPANDED_COLLAPSING ) ){
+                iconExpanded.addClass( C_ICONEXPANDED_COLLAPSING );
+                return true;
+            }
+        } else {
+            if( iconExpanded.hasClass( C_ICONEXPANDED_COLLAPSING ) ){
+                iconExpanded.removeClass( C_ICONEXPANDED_COLLAPSING );
+                return true;
+            }
+        }
+
+        return false;
+    },
+
+
+    /**
+     * Forces the item to resize as result of direct content manipulation (via 'innerHTML').
+     * This method should be invoked if 'contentHeight' property has been set to 'auto'.
+     *
+     * @method resize
+     */
+    resize : function(){
+        this.fire( "contentUpdate" );
+    },
+
+
+    /**
+     * Parses and returns the value of contentHeight property, if set method "fixed".
+     * The value must be in this format: fixed-X, where X is integer
+     *
+     * @method _extractFixedMethodValue
+     * @param value {String} The value to be parsed
+     * @return {Number} The parsed value or null
+     * @protected
+     */
+    _extractFixedMethodValue: function( value ){
+        var i, length, chr, height = null;
+
+        for( i = 6, length = value.length; i < length; i++ ){ // 6 = "fixed-".length
+            chr = value.charAt(i);
+            chr = parseInt( chr, 10 );
+
+            if( Lang.isNumber( chr ) ){
+                height = (height * 10) + chr;
+            } else {
+                break;
+            }
+        }
+
+        return height;
+    },
+
+
+    /**
+     * Validator applied to the icon attribute. Setting new value is not allowed if Accordion has been rendered.
+     *
+     * @method _validateIcon
+     * @param value {MIXED} the value for the icon attribute
+     * @return {Boolean}
+     * @protected
+     */
+    _validateIcon: function( value ) {
+        return !this.get(RENDERED) || value;
+    },
+
+
+    /**
+     * Validator applied to the nodeLabel attribute. Setting new value is not allowed if Accordion has been rendered.
+     *
+     * @method _validateNodeLabel
+     * @param value {MIXED} the value for the nodeLabel attribute
+     * @return {Boolean}
+     * @protected
+     */
+    _validateNodeLabel: function( value ) {
+        return !this.get(RENDERED) || value;
+    },
+
+
+    /**
+     * Validator applied to the iconsContainer attribute. Setting new value is not allowed if Accordion has been rendered.
+     *
+     * @method _validateIconsContainer
+     * @param value {MIXED} the value for the iconsContainer attribute
+     * @return {Boolean}
+     * @protected
+     */
+    _validateIconsContainer: function( value ) {
+        return !this.get(RENDERED) || value;
+    },
+
+
+    /**
+     * Validator applied to the iconExpanded attribute. Setting new value is not allowed if Accordion has been rendered.
+     *
+     * @method _validateIconExpanded
+     * @param value {MIXED} the value for the iconExpanded attribute
+     * @return {Boolean}
+     * @protected
+     */
+    _validateIconExpanded: function( value ) {
+        return !this.get(RENDERED) || value;
+    },
+
+
+    /**
+     * Validator applied to the iconAlwaysVisible attribute. Setting new value is not allowed if Accordion has been rendered.
+     *
+     * @method _validateIconAlwaysVisible
+     * @param value {MIXED} the value for the iconAlwaysVisible attribute
+     * @return {Boolean}
+     * @protected
+     */
+    _validateIconAlwaysVisible: function( value ) {
+        return !this.get(RENDERED) || value;
+    },
+
+
+    /**
+     * Validator applied to the iconClose attribute. Setting new value is not allowed if Accordion has been rendered.
+     *
+     * @method _validateIconClose
+     * @param value {MIXED} the value for the iconClose attribute
+     * @return {Boolean}
+     * @protected
+     */
+    _validateIconClose: function( value ) {
+        return !this.get(RENDERED) || value;
+    },
+
+
+    /**
+     * Setter applied to the input when updating the icon attribute.  Input can
+     * be a Node, raw HTMLElement, or a selector string to locate it.
+     *
+     * @method _setIcon
+     * @param value {Node|HTMLElement|String} The icon element Node or selector
+     * @return {Node} The Node if found, null otherwise.
+     * @protected
+     */
+    _setIcon: function( value ){
+        return Y.one( value ) || null;
+    },
+
+
+    /**
+     * Setter applied to the input when updating the nodeLabel attribute.  Input can
+     * be a Node, raw HTMLElement, or a selector string to locate it.
+     *
+     * @method _setNodeLabel
+     * @param value {Node|HTMLElement|String} The nodeLabel element Node or selector
+     * @return {Node} The Node if found, null otherwise.
+     * @protected
+     */
+    _setNodeLabel: function( value ){
+        return Y.one( value ) || null;
+    },
+
+
+    /**
+     * Setter applied to the input when updating the iconsContainer attribute.  Input can
+     * be a Node, raw HTMLElement, or a selector string to locate it.
+     *
+     * @method _setIconsContainer
+     * @param value {Node|HTMLElement|String} The iconsContainer element Node or selector
+     * @return {Node} The Node if found, null otherwise.
+     * @protected
+     */
+    _setIconsContainer: function( value ){
+        return Y.one( value ) || null;
+    },
+
+
+    /**
+     * Setter applied to the input when updating the iconExpanded attribute.  Input can
+     * be a Node, raw HTMLElement, or a selector string to locate it.
+     *
+     * @method _setIconExpanded
+     * @param value {Node|HTMLElement|String} The iconExpanded element Node or selector
+     * @return {Node} The Node if found, null otherwise.
+     * @protected
+     */
+    _setIconExpanded: function( value ){
+        return Y.one( value ) || null;
+    },
+
+
+    /**
+     * Setter applied to the input when updating the iconAlwaysVisible attribute.  Input can
+     * be a Node, raw HTMLElement, or a selector string to locate it.
+     *
+     * @method _setIconAlwaysVisible
+     * @param value {Node|HTMLElement|String} The iconAlwaysVisible element Node or selector
+     * @return {Node} The Node if found, null otherwise.
+     * @protected
+     */
+    _setIconAlwaysVisible: function( value ){
+        return Y.one( value ) || null;
+    },
+
+
+    /**
+     * Setter applied to the input when updating the iconClose attribute.  Input can
+     * be a Node, raw HTMLElement, or a selector string to locate it.
+     *
+     * @method _setIconClose
+     * @param value {Node|HTMLElement|String} The iconClose element Node or selector
+     * @return {Node} The Node if found, null otherwise.
+     * @protected
+     */
+    _setIconClose: function( value ){
+        return Y.one( value ) || null;
+    },
+
+
+    /**
+     * Overwrites Widget's _applyParser method in order to parse yuiConfig attribute before entering in HTML_PARSER attributes
+     *
+     * @method _applyParser
+     * @protected
+     * @param config {Object} User configuration object (will be populated with values from Node)
+    */
+    _applyParser : function(config) {
+        var srcNode;
+
+        srcNode = this.get( "srcNode" );
+
+        if( srcNode ){
+            this._parsedYUIConfig = srcNode.getAttribute( YUICONFIG );
+
+            if( this._parsedYUIConfig ){
+                this._parsedYUIConfig = JSON.parse( this._parsedYUIConfig );
+            }
+        }
+
+        Y.AccordionItem.superclass._applyParser.apply( this, arguments );
+
+        delete this._parsedYUIConfig;
+    },
+
+
+    /**
+     * Overwrites Y.WidgetStdMod fuction in order to resolve Widget 3.1 issue:<br>
+     * If CONTENT_TEMPLATE is null, in renderUI the result of the following code:
+     * <code>this.getStdModNode( Y.WidgetStdMod.HEADER );</code> is null.
+     * The same is with <code>this.getStdModNode( Y.WidgetStdMod.BODY );</code>.
+     *
+     * @method _findStdModSection
+     * @protected
+     * @param {String} section The section for which the render Node is to be found. Either WidgetStdMod.HEADER, WidgetStdMod.BODY or WidgetStdMod.FOOTER.
+     * @return {Node} The rendered node for the given section, or null if not found.
+     */
+    _findStdModSection: function(section) {
+        return this.get("srcNode").one("> ." + Y.WidgetStdMod.SECTION_CLASS_NAMES[section]);
+    },
+
+    CONTENT_TEMPLATE : null
+}, {
+    /**
+     *  Static property provides a string to identify the class.
+     *
+     * @property NAME
+     * @type String
+     * @static
+     */
+    NAME : AccItemName,
+
+    /**
+     * Static property used to define the default attribute
+     * configuration for the Accordion.
+     *
+     * @property Accordion.ATTRS
+     * @type Object
+     * @static
+     */
+    ATTRS : {
+
+        /**
+         * @description The Node, representing item's icon
+         *
+         * @attribute icon
+         * @default null
+         * @type Node
+         */
+        icon: {
+            value: null,
+            validator: function( value ){
+                return this._validateIcon( value );
+            },
+            setter : function( value ) {
+                return this._setIcon( value );
+            }
+        },
+
+        /**
+         * @description The label of item
+         *
+         * @attribute label
+         * @default "&#160;"
+         * @type String
+         */
+        label: {
+            value: "&#160;",
+            validator: Lang.isString
+        },
+
+        /**
+         * @description The node, which contains item's label
+         *
+         * @attribute nodeLabel
+         * @default null
+         * @type Node
+         */
+        nodeLabel: {
+            value: null,
+            validator: function( value ){
+                return this._validateNodeLabel( value );
+            },
+            setter : function( value ) {
+                return this._setNodeLabel( value );
+            }
+        },
+
+
+        /**
+         * @description The container of iconAlwaysVisible, iconExpanded and iconClose
+         *
+         * @attribute iconsContainer
+         * @default null
+         * @type Node
+         */
+        iconsContainer: {
+            value: null,
+            validator: function( value ){
+                return this._validateIconsContainer( value );
+            },
+            setter : function( value ) {
+                return this._setIconsContainer( value );
+            }
+        },
+
+        /**
+         * @description The Node, representing icon expanded
+         *
+         * @attribute iconExpanded
+         * @default null
+         * @type Node
+         */
+        iconExpanded: {
+            value: null,
+            validator: function( value ){
+                return this._validateIconExpanded( value );
+            },
+            setter : function( value ) {
+                return this._setIconExpanded( value );
+            }
+        },
+
+
+        /**
+         * @description The Node, representing icon always visible
+         *
+         * @attribute iconAlwaysVisible
+         * @default null
+         * @type Node
+         */
+        iconAlwaysVisible: {
+            value: null,
+            validator: function( value ){
+                return this._validateIconAlwaysVisible( value );
+            },
+            setter : function( value ) {
+                return this._setIconAlwaysVisible( value );
+            }
+        },
+
+
+        /**
+         * @description The Node, representing icon close, or null if the item is not closable
+         *
+         * @attribute iconClose
+         * @default null
+         * @type Node
+         */
+        iconClose: {
+            value: null,
+            validator: function( value ){
+                return this._validateIconClose( value );
+            },
+            setter : function( value ) {
+                return this._setIconClose( value );
+            }
+        },
+
+        /**
+         * @description Get/Set expanded status of the item
+         *
+         * @attribute expanded
+         * @default false
+         * @type Boolean
+         */
+        expanded: {
+            value: false,
+            validator: Lang.isBoolean
+        },
+
+        /**
+         * @description Describe the method, which will be used when expanding/collapsing
+         * the item. The value should be an object with at least one property ("method"):
+         *  <dl>
+         *      <dt>method</dt>
+         *          <dd>The method can be one of these: "auto", "fixed" and "stretch"</dd>
+         *      <dt>height</dt>
+         *          <dd>Must be set only if method's value is "fixed"</dd>
+         *  </dl>
+         *
+         * @attribute contentHeight
+         * @default auto
+         * @type Object
+         */
+        contentHeight: {
+            value: {
+                method: AUTO
+            },
+            validator: function( value ){
+                if( Lang.isObject( value ) ){
+                    if( value.method === AUTO ){
+                        return true;
+                    } else if( value.method === STRETCH ){
+                        return true;
+                    } else if( value.method === FIXED && Lang.isNumber( value.height ) &&
+                        value.height >= 0 ){
+                        return true;
+                    }
+                }
+
+                return false;
+            }
+        },
+
+        /**
+         * @description Get/Set always visible status of the item
+         *
+         * @attribute alwaysVisible
+         * @default false
+         * @type Boolean
+         */
+        alwaysVisible: {
+            value: false,
+            validator: Lang.isBoolean
+        },
+
+
+        /**
+         * @description Get/Set the animaton specific settings. By default there are no any settings.
+         * If set, they will overwrite Accordion's animation settings
+         *
+         * @attribute animation
+         * @default {}
+         * @type Object
+         */
+        animation: {
+            value: {},
+            validator: Lang.isObject
+        },
+
+        /**
+         * @description Provides client side string localization support.
+         *
+         * @attribute strings
+         * @default Object English messages
+         * @type Object
+         */
+        strings: {
+            value: {
+                title_always_visible_off: "Click to set always visible on",
+                title_always_visible_on: "Click to set always visible off",
+                title_iconexpanded_off: "Click to expand",
+                title_iconexpanded_on: "Click to collapse",
+                title_iconclose: "Click to close"
+            }
+        },
+
+        /**
+         * @description Boolean indicating that the item can be closed by user.
+         * If true, there will be placed close icon, otherwise not
+         *
+         * @attribute closable
+         * @default false
+         * @type Boolean
+         */
+        closable: {
+            value: false,
+            validator: Lang.isBoolean
+        }
+    },
+
+
+    /**
+     * Static Object hash used to capture existing markup for progressive
+     * enhancement.  Keys correspond to config attribute names and values
+     * are selectors used to inspect the srcNode for an existing node
+     * structure.
+     *
+     * @property HTML_PARSER
+     * @type Object
+     * @protected
+     * @static
+     */
+    HTML_PARSER : {
+
+        icon: HEADER_SELECTOR_SUB + C_ICON,
+
+        label: function( srcNode ){
+            var node, labelSelector, yuiConfig, label;
+
+            yuiConfig = this._parsedYUIConfig;
+
+            if( yuiConfig && Lang.isValue( yuiConfig.label ) ){
+                return yuiConfig.label;
+            }
+
+            label = srcNode.getAttribute( "data-label" );
+
+            if( label ){
+                return label;
+            }
+
+            labelSelector = HEADER_SELECTOR_SUB + C_LABEL;
+            node = srcNode.one( labelSelector );
+
+            return (node) ? node.get( INNER_HTML ) : null;
+        },
+
+        nodeLabel: HEADER_SELECTOR_SUB + C_LABEL,
+
+        iconsContainer: HEADER_SELECTOR_SUB + C_ICONSCONTAINER,
+
+        iconAlwaysVisible: HEADER_SELECTOR_SUB + C_ICONALWAYSVISIBLE,
+
+        iconExpanded: HEADER_SELECTOR_SUB + C_ICONEXPANDED,
+
+        iconClose: HEADER_SELECTOR_SUB + C_ICONCLOSE,
+
+        expanded: function( srcNode ){
+            var yuiConfig, expanded;
+
+            yuiConfig = this._parsedYUIConfig;
+
+            if( yuiConfig && Lang.isBoolean( yuiConfig.expanded ) ){
+                return yuiConfig.expanded;
+            }
+
+            expanded = srcNode.getAttribute( "data-expanded" );
+
+            if( expanded ) {
+                return REGEX_TRUE.test( expanded );
+            }
+
+            return srcNode.hasClass( C_EXPANDED );
+        },
+
+        alwaysVisible: function( srcNode ){
+            var yuiConfig, alwaysVisible;
+
+            yuiConfig = this._parsedYUIConfig;
+
+            if( yuiConfig && Lang.isBoolean( yuiConfig.alwaysVisible ) ){
+                alwaysVisible = yuiConfig.alwaysVisible;
+            } else {
+                alwaysVisible = srcNode.getAttribute( "data-alwaysvisible" );
+
+                if( alwaysVisible ) {
+                    alwaysVisible = REGEX_TRUE.test( alwaysVisible );
+                } else {
+                    alwaysVisible = srcNode.hasClass( C_ALWAYSVISIBLE );
+                }
+            }
+
+            if( alwaysVisible ){
+                this.set( "expanded", true, {
+                    internalCall: true
+                } );
+            }
+
+            return alwaysVisible;
+        },
+
+        closable: function( srcNode ){
+            var yuiConfig, closable;
+
+            yuiConfig = this._parsedYUIConfig;
+
+            if( yuiConfig && Lang.isBoolean( yuiConfig.closable ) ){
+                return yuiConfig.closable;
+            }
+
+            closable = srcNode.getAttribute( "data-closable" );
+
+            if( closable ) {
+                return REGEX_TRUE.test( closable );
+            }
+
+            return srcNode.hasClass( C_CLOSABLE );
+        },
+
+        contentHeight: function( srcNode ){
+            var contentHeightClass, classValue, height = 0, index, yuiConfig,
+                contentHeight;
+
+            yuiConfig = this._parsedYUIConfig;
+
+            if( yuiConfig && yuiConfig.contentHeight ){
+                return yuiConfig.contentHeight;
+            }
+
+            contentHeight = srcNode.getAttribute( "data-contentheight" );
+
+            if( REGEX_AUTO.test( contentHeight ) ){
+                return {
+                    method: AUTO
+                };
+            } else if( REGEX_STRETCH.test( contentHeight ) ){
+                return {
+                    method: STRETCH
+                };
+            } else if( REGEX_FIXED.test( contentHeight ) ){
+                height = this._extractFixedMethodValue( contentHeight );
+
+                return {
+                    method: FIXED,
+                    height: height
+                };
+            }
+
+
+            classValue = srcNode.get( CLASS_NAME );
+
+            contentHeightClass = C_CONTENTHEIGHT + '-';
+
+            index = classValue.indexOf( contentHeightClass, 0);
+
+            if( index >= 0 ){
+                index += contentHeightClass.length;
+
+                classValue = classValue.substring( index );
+
+                if( REGEX_AUTO.test( classValue ) ){
+                    return {
+                        method: AUTO
+                    };
+                } else if( REGEX_STRETCH.test( classValue ) ){
+                    return {
+                        method: STRETCH
+                    };
+                } else if( REGEX_FIXED.test( classValue )  ){
+                    height = this._extractFixedMethodValue( classValue );
+
+                    return {
+                        method: FIXED,
+                        height: height
+                    };
+                }
+            }
+
+            return null;
+        }
+    },
+
+
+     /**
+      * The template HTML strings for each of header components.
+      * e.g.
+      * <pre>
+      *    {
+      *       icon : '&lt;a class="yui3-accordion-item-icon"&gt;&lt;/a&gt;',
+      *       label: '&lt;a href="#" class="yui3-accordion-item-label"&gt;&lt;/a&gt;',
+      *       iconsContainer: '&lt;div class="yui3-accordion-item-icons"&gt;&lt;/div&gt;',
+      *       iconAlwaysVisible: '&lt;a href="#" class="yui3-accordion-item-iconalwaysvisible"&gt;&lt;/a&gt;',
+      *       iconExpanded: '&lt;a href="#" class="yui3-accordion-item-iconexpanded"&gt;&lt;/a&gt;',
+      *       iconClose: '&lt;a href="#" class="yui3-accordion-item-iconclose yui3-accordion-item-iconclose-hidden"&gt;&lt;/a&gt;'
+      *    }
+      * </pre>
+      * @property WidgetStdMod.TEMPLATES
+      * @type Object
+      */
+    TEMPLATES : {
+         icon : '<a class="' + C_ICON + '"></a>',
+         label: '<a href="#" class="' + C_LABEL + '"></a>',
+         iconsContainer: '<div class="' + C_ICONSCONTAINER + '"></div>',
+         iconExpanded: ['<a href="#" class="', C_ICONEXPANDED, ' ', C_ICONEXPANDED_OFF, '"></a>'].join(''),
+         iconAlwaysVisible: ['<a href="#" class="', C_ICONALWAYSVISIBLE, ' ',  C_ICONALWAYSVISIBLE_OFF, '"></a>'].join(''),
+         iconClose: ['<a href="#" class="', C_ICONCLOSE, ' ', C_ICONCLOSE_HIDDEN, '"></a>'].join('')
+    }
+
+});
+
+}());
+
+
+
+}, '@VERSION@' ,{optional:['dd-constrain', 'dd-proxy', 'dd-drop'], requires:['event', 'anim-easing', 'widget', 'widget-stdmod', 'json-parse']});

=== added file 'lib/lp/contrib/javascript/yui3-gallery/gallery-accordion/gallery-accordion-min.js'
--- lib/lp/contrib/javascript/yui3-gallery/gallery-accordion/gallery-accordion-min.js	1970-01-01 00:00:00 +0000
+++ lib/lp/contrib/javascript/yui3-gallery/gallery-accordion/gallery-accordion-min.js	2011-02-15 11:27:17 +0000
@@ -0,0 +1,4 @@
+YUI.add("gallery-accordion",function(A){(function(){var u=A.Lang,V=A.Node,Z=A.Anim,H=A.Easing,N="accordion",X=A.WidgetStdMod,s=document.compatMode=="BackCompat",T=s&&A.UA.ie>0,U=T?1:0,J=A.ClassNameManager.getClassName,W="yui3-accordion-item",f=J(N,"proxyel","visible"),h=J(N,"graggroup"),b="beforeItemAdd",e="itemAdded",D="beforeItemRemove",i="itemRemoved",C="beforeItemResized",p="itemResized",d="beforeItemExpand",g="beforeItemCollapse",K="itemExpanded",m="itemCollapsed",j="beforeItemReorder",R="beforeEndItemReorder",S="itemReordered",k="default",O="animation",P="alwaysVisible",E="expanded",c="collapseOthersOnExpand",Y="items",t="contentHeight",B="iconClose",F="iconAlwaysVisible",G="stretch",r="px",a="contentBox",n="boundingBox",I="srcNode",l="rendered",o="bodyContent",Q="children",L="parentNode",q="node",M="data";A.Accordion=A.Base.create(N,A.Widget,[],{initializer:function(v){this.after("render",A.bind(this._afterRender,this));},destructor:function(){var v,y,w,x;v=this.get(Y);x=v.length;for(w=x-1;w>=0;w--){y=v[w];v.splice(w,1);this._removeItemHandles(y);y.destroy();}},_forCollapsing:{},_forExpanding:{},_animations:{},_itemsHandles:{},_removeItemHandles:function(x){var w,v;w=this._itemsHandles[x];for(v in w){if(w.hasOwnProperty(v)){v=w[v];v.detach();}}delete this._itemsHandles[x];},_getNodeOffsetHeight:function(x){var v,w;if(x instanceof V){if(x.hasMethod("getBoundingClientRect")){w=x.invoke("getBoundingClientRect");if(w){v=w.bottom-w.top;return v;}}else{v=x.get("offsetHeight");return A.Lang.isValue(v)?v:0;}}else{if(x){v=x.offsetHeight;return A.Lang.isValue(v)?v:0;}}return 0;},_setItemProperties:function(x,z,w){var v,y;v=x.get(P);y=x.get(E);if(z!=y){x.set(E,z,{internalCall:true});}if(w!==v){x.set(P,w,{internalCall:true});}},_setItemUI:function(w,x,v){w.markAsExpanded(x);w.markAsAlwaysVisible(v);},_afterRender:function(w){var v;v=this.get("resizeEvent");this._setUpResizing(v);this.after("resizeEventChange",A.bind(this._afterResizeEventChange,this));},_afterResizeEventChange:function(v){this._setUpResizing(v.newVal);},_onItemChosen:function(AA,AB,v){var z,x,y,w;z={};w=this.get(c);x=AA.get(P);y=AA.get(E);if(v){this.removeItem(AA);return;}else{if(AB){if(y){x=!x;y=x?true:y;this._setItemProperties(AA,y,x);this._setItemUI(AA,y,x);return;}else{this._forExpanding[AA]={"item":AA,alwaysVisible:true};if(w){z[AA]={"item":AA};this._storeItemsForCollapsing(z);}}}else{if(y){this._forCollapsing[AA]={"item":AA};}else{this._forExpanding[AA]={"item":AA,"alwaysVisible":x};if(w){z[AA]={"item":AA};this._storeItemsForCollapsing(z);}}}}this._processItems();},_adjustStretchItems:function(){var w=this.get(Y),x,v;x=this._getHeightPerStretchItem();v=this._forExpanding;A.Array.each(w,function(AC,AB,AA){var y,AE,AD,AF,z;AF=AC.get(t);z=AC.get(E);if(!v[AC]&&AF.method===G&&z){AD=this._animations[AC];if(AD){AD.stop();}y=AC.getStdModNode(X.BODY);AE=this._getNodeOffsetHeight(y);if(x<AE){this._processCollapsing(AC,x);}else{if(x>AE){this._processExpanding(AC,x);}}}},this);return x;},_getHeightPerStretchItem:function(){var v,x,w=0;x=this.get(Y);v=this.get(n).get("clientHeight");A.Array.each(x,function(AC,AB,AA){var AD,z,AF,AE,y;AF=AC.getStdModNode(X.HEADER);AE=AC.get(t);y=this._getNodeOffsetHeight(AF);v-=y;AD=!AC.get(E);if(AD){v-=U;return;}if(AE.method===G){w++;}else{z=this._getItemContentHeight(AC);v-=z;}},this);if(w>0){v/=w;}if(v<0){v=0;}return v;},_getItemContentHeight:function(x){var z,w=0,v,y;z=x.get(t);if(z.method==="auto"){v=x.getStdModNode(X.BODY);y=v.get(Q).item(0);w=y?this._getNodeOffsetHeight(y):0;}else{if(z.method==="fixed"){w=z.height;}else{w=this._getHeightPerStretchItem();}}return w;},_storeItemsForCollapsing:function(w){var v;w=w||{};v=this.get(Y);A.Array.each(v,function(AB,AA,z){var y,x;y=AB.get(E);x=AB.get(P);if(y&&!x&&!w[AB]){this._forCollapsing[AB]={"item":AB};}},this);},_expandItem:function(x,v){var w=x.get(P);this._processExpanding(x,v);this._setItemUI(x,true,w);},_processExpanding:function(AC,AB,v){var w,x,z,AD=false,AA,y;y=AC.getStdModNode(X.BODY);this.fire(C,{"item":AC});if(y.get("clientHeight")<=U){AD=true;this.fire(d,{"item":AC});}if(!v&&this.get("useAnimation")){z=AC.get(O)||{};w=new Z({node:y,to:{"height":AB}});w.on("end",A.bind(this._onExpandComplete,this,AC,AD));AA=this.get(O);w.set("duration",z.duration||AA.duration);w.set("easing",z.easing||AA.easing);x=this._animations[AC];if(x){x.stop();}AC.markAsExpanding(true);this._animations[AC]=w;w.run();}else{y.setStyle("height",AB+r);this.fire(p,{"item":AC});if(AD){this.fire(K,{"item":AC});}}},_onExpandComplete:function(v,w){delete this._animations[v];v.markAsExpanding(false);this.fire(p,{"item":v});if(w){this.fire(K,{"item":v});}},_collapseItem:function(v){this._processCollapsing(v,U);this._setItemUI(v,false,false);},_processCollapsing:function(AC,AB,v){var w,x,z,AA,y,AD=(AB===U);y=AC.getStdModNode(X.BODY);this.fire(C,{"item":AC});if(AD){this.fire(g,{"item":AC});}if(!v&&this.get("useAnimation")){z=AC.get(O)||{};w=new Z({node:y,to:{"height":AB}});w.on("end",A.bind(this._onCollapseComplete,this,AC,AD));AA=this.get(O);w.set("duration",z.duration||AA.duration);w.set("easing",z.easing||AA.easing);x=this._animations[AC];if(x){x.stop();}AC.markAsCollapsing(true);this._animations[AC]=w;w.run();}else{y.setStyle("height",AB+r);this.fire(p,{"item":AC});if(AD){this.fire(m,{"item":AC});}}},_onCollapseComplete:function(v,w){delete this._animations[v];v.markAsCollapsing(false);this.fire(p,{item:v});if(w){this.fire(m,{"item":v});}},_initItemDragDrop:function(w){var AA,v,z,x,y;AA=w.getStdModNode(X.HEADER);if(AA.dd){return;}z=this.get(n);x=w.get(n);v=new A.DD.Drag({node:AA,groups:[h]}).plug(A.Plugin.DDProxy,{moveOnEnd:false}).plug(A.Plugin.DDConstrained,{constrain2node:z});y=new A.DD.Drop({node:x,groups:[h]});v.on("drag:start",A.bind(this._onDragStart,this,v));v.on("drag:end",A.bind(this._onDragEnd,this,v));v.after("drag:end",A.bind(this._afterDragEnd,this,v));v.on("drag:drophit",A.bind(this._onDropHit,this,v));},_onDragStart:function(v,y){var x,w;w=this.getItem(v.get(q).get(L));
+x=v.get("dragNode");x.addClass(f);x.set("innerHTML",w.get("label"));return this.fire(j,{"item":w});},_onDragEnd:function(v,y){var x,w;x=v.get("dragNode");x.removeClass(f);x.set("innerHTML","");w=this.getItem(v.get(q).get(L));return this.fire(R,{"item":w});},_afterDragEnd:function(v,y){var w,x;x=v.get(M);if(x.drophit){w=this.getItem(v.get(q).get(L));v.set(M,{drophit:false});return this.fire(S,{"item":w});}return true;},_onDropHit:function(AE,AA){var z,AD,w,AC,y,v,AB,x,AF;AF=this.getItem(AE.get(q).get(L));x=this.getItem(AA.drop.get(q));if(x===AF){return false;}z=this.getItemIndex(AF);AD=this.getItemIndex(x);w=x.get(n);AC=AF.get(n);y=this.get(a);v=false;AB=this.get(Y);if(AD<z){v=true;}y.removeChild(AC);if(v){y.insertBefore(AC,w);AB.splice(z,1);AB.splice(AD,0,AF);}else{y.insertBefore(AC,w.next(W));AB.splice(AD+1,0,AF);AB.splice(z,1);}AE.set(M,{drophit:true});return true;},_processItems:function(){var x,w,y,AA,v,AB,z;x=this._forCollapsing;w=this._forExpanding;this._setItemsProperties();for(z in x){if(x.hasOwnProperty(z)){y=x[z];this._collapseItem(y.item);}}AA=this._adjustStretchItems();for(z in w){if(w.hasOwnProperty(z)){y=w[z];z=y.item;v=AA;AB=z.get(t);if(AB.method!==G){v=this._getItemContentHeight(z);}this._expandItem(z,v);}}this._forCollapsing={};this._forExpanding={};},_setItemsProperties:function(){var x,w,v;x=this._forCollapsing;w=this._forExpanding;for(v in x){if(x.hasOwnProperty(v)){v=x[v];this._setItemProperties(v.item,false,false);}}for(v in w){if(w.hasOwnProperty(v)){v=w[v];this._setItemProperties(v.item,true,v.alwaysVisible);}}},_afterItemExpand:function(z){var x,y,w,v;if(z.internalCall){return;}x=z.newVal;y=z.currentTarget;w=y.get(P);v=this.get(c);if(x){this._forExpanding[y]={"item":y,"alwaysVisible":w};if(v){this._storeItemsForCollapsing();}}else{this._forCollapsing[y]={"item":y};}this._processItems();},_afterItemAlwaysVisible:function(y){var x,v,w;if(y.internalCall){return;}v=y.newVal;x=y.currentTarget;w=x.get(E);if(v){if(w){this._setItemProperties(x,true,true);this._setItemUI(x,true,true);return;}else{this._forExpanding[x]={"item":x,"alwaysVisible":true};this._storeItemsForCollapsing();}}else{if(w){this._setItemUI(x,true,false);return;}else{return;}}this._processItems();},_afterContentHeight:function(AA){var y,w,v,z,x;y=AA.currentTarget;this._adjustStretchItems();if(AA.newVal.method!==G){x=y.get(E);w=this._getItemContentHeight(y);v=y.getStdModNode(X.BODY);z=this._getNodeOffsetHeight(v);if(w<z){this._processCollapsing(y,w,!x);}else{if(w>z){this._processExpanding(y,w,!x);}}}},_afterContentUpdate:function(AA){var x,v,z,w,AB,y;x=AA.currentTarget;AB=x.get("contentHeight").method==="auto";w=x.get(E);v=x.getStdModNode(X.BODY);z=this._getNodeOffsetHeight(v);if(AB&&w&&AA.src!==A.Widget.UI_SRC){A.later(0,this,function(){var AC=this._getItemContentHeight(x);if(AC!==z){y=this._animations[x];if(y){y.stop();}this._adjustStretchItems();if(AC<z){this._processCollapsing(x,AC,!w);}else{if(AC>z){this._processExpanding(x,AC,!w);}}}});}},_setUpResizing:function(v){if(this._resizeEventHandle){this._resizeEventHandle.detach();}if(v===k){this._resizeEventHandle=A.on("windowresize",A.bind(this._adjustStretchItems,this));}else{this._resizeEventHandle=v.sourceObject.on(v.resizeEvent,A.bind(this._adjustStretchItems,this));}},renderUI:function(){var y,x,w,v;y=this.get(I);w=this.get(a);v=y.get("id");w.set("id",v);x=y.all("> ."+W);x.each(function(AC,z,AB){var AA;if(!this.getItem(AC)){AA=new A.AccordionItem({srcNode:AC,id:AC.get("id")});this.addItem(AA);}},this);},bindUI:function(){var v,w;v=this.get(a);w=this.get("itemChosen");v.delegate(w,A.bind(this._onItemChosenEvent,this),".yui3-widget-hd");},_onItemChosenEvent:function(AA){var AC,AB,x,y,w,z,v;AC=AA.currentTarget;AB=AC.get(L);x=this.getItem(AB);y=x.get(F);w=x.get(B);z=(y===AA.target);v=(w===AA.target);this._onItemChosen(x,z,v);},addItem:function(AH,x){var AB,AF,z,AA,v,AE,AD,AG,y,AC,w;AC=this.fire(b,{"item":AH});if(!AC){return false;}AE=this.get(Y);AD=this.get(a);y=AH.get(a);if(!y.inDoc()){if(x){v=this.getItemIndex(x);if(v<0){return false;}AE.splice(v,0,AH);AD.insertBefore(y,x.get(n));}else{AE.push(AH);AD.insertBefore(y,null);}}else{w=AD.get(Q);AC=w.some(function(AK,AJ,AI){if(AK===y){AE.splice(AJ,0,AH);return true;}else{return false;}},this);if(!AC){return false;}}z=AH.getStdModNode(X.BODY);AA=AH.get(o);if(!z&&!AA){AH.set(o,"");}if(!AH.get(l)){AH.render();}AB=AH.get(E);AF=AH.get(P);AB=AB||AF;if(AB){this._forExpanding[AH]={"item":AH,"alwaysVisible":AF};}else{this._forCollapsing[AH]={"item":AH};}this._processItems();if(this.get("reorderItems")){this._initItemDragDrop(AH);}AG=this._itemsHandles[AH];if(!AG){AG={};}AG={"expandedChange":AH.after("expandedChange",A.bind(this._afterItemExpand,this)),"alwaysVisibleChange":AH.after("alwaysVisibleChange",A.bind(this._afterItemAlwaysVisible,this)),"contentHeightChange":AH.after("contentHeightChange",A.bind(this._afterContentHeight,this)),"contentUpdate":AH.after("contentUpdate",A.bind(this._afterContentUpdate,this))};this._itemsHandles[AH]=AG;this.fire(e,{"item":AH});return true;},removeItem:function(w){var v,z,y=null,x;v=this.get(Y);if(u.isNumber(w)){x=w;}else{if(w instanceof A.AccordionItem){x=this.getItemIndex(w);}else{return null;}}if(x>=0){this.fire(D,{item:w});y=v.splice(x,1)[0];this._removeItemHandles(y);z=y.get(n);z.remove();this._adjustStretchItems();this.fire(i,{item:w});}return y;},getItem:function(x){var v=this.get(Y),w=null;if(u.isNumber(x)){w=v[x];return(w instanceof A.AccordionItem)?w:null;}else{if(x instanceof V){A.Array.some(v,function(AB,AA,z){var y=AB.get(a);if(y===x){w=AB;return true;}else{return false;}},this);}}return w;},getItemIndex:function(x){var w=-1,v;if(x instanceof A.AccordionItem){v=this.get(Y);A.Array.some(v,function(AA,z,y){if(AA===x){w=z;return true;}else{return false;}},this);}return w;},_findStdModSection:function(v){return this.get(I).one("> ."+A.WidgetStdMod.SECTION_CLASS_NAMES[v]);},CONTENT_TEMPLATE:null},{NAME:N,ATTRS:{itemChosen:{value:"click",validator:u.isString},items:{value:[],readOnly:true,validator:u.isArray},resizeEvent:{value:k,validator:function(v){if(v===k){return true;
+}else{if(u.isObject(v)){if(u.isValue(v.sourceObject)&&u.isValue(v.resizeEvent)){return true;}}}return false;}},useAnimation:{value:true,validator:u.isBoolean},animation:{value:{duration:1,easing:H.easeOutStrong},validator:function(v){return u.isObject(v)&&u.isNumber(v.duration)&&u.isFunction(v.easing);}},reorderItems:{value:false,validator:function(v){return u.isBoolean(v)&&!u.isUndefined(A.DD);}},collapseOthersOnExpand:{value:true,validator:u.isBoolean}}});}());(function(){var u=A.Lang,b=A.Node,P=A.JSON,c=A.WidgetStdMod,d="accordion-item",N=A.ClassNameManager.getClassName,D=N(d,"iconexpanded","expanding"),s=N(d,"iconexpanded","collapsing"),O=N(d,"icon"),K=N(d,"label"),o=N(d,"iconalwaysvisible"),f=N(d,"icons"),m=N(d,"iconexpanded"),j=N(d,"iconclose"),Q=N(d,"iconclose","hidden"),S=N(d,"iconexpanded","on"),L=N(d,"iconexpanded","off"),E=N(d,"iconalwaysvisible","on"),k=N(d,"iconalwaysvisible","off"),Y=N(d,"expanded"),V=N(d,"closable"),h=N(d,"alwaysvisible"),i=N(d,"contentheight"),l="title",C="strings",q="rendered",H="className",e="auto",J="stretch",W="fixed",T=".yui3-widget-hd",Z=".",n=".yui3-widget-hd "+Z,r="innerHTML",t="iconsContainer",g="icon",R="nodeLabel",G="iconAlwaysVisible",a="iconExpanded",B="iconClose",p="href",U="#",F="yuiConfig",I=/^(?:true|yes|1)$/,M=/^auto\s*/,v=/^stretch\s*/,X=/^fixed-\d+/;A.AccordionItem=A.Base.create(d,A.Widget,[A.WidgetStdMod],{_createHeader:function(){var AE,AC,AD,AA,AB,z,x,w,y;AB=this.get(g);z=this.get(R);x=this.get(a);w=this.get(G);y=this.get(B);AA=this.get(t);AD=this.get(C);AE=this.get("closable");AC=A.AccordionItem.TEMPLATES;if(!AB){AB=b.create(AC.icon);this.set(g,AB);}if(!z){z=b.create(AC.label);this.set(R,z);}else{if(!z.hasAttribute(p)){z.setAttribute(p,U);}}z.setContent(this.get("label"));if(!AA){AA=b.create(AC.iconsContainer);this.set(t,AA);}if(!w){w=b.create(AC.iconAlwaysVisible);w.setAttribute(l,AD.title_always_visible_off);this.set(G,w);}else{if(!w.hasAttribute(p)){w.setAttribute(p,U);}}if(!x){x=b.create(AC.iconExpanded);x.setAttribute(l,AD.title_iconexpanded_off);this.set(a,x);}else{if(!x.hasAttribute(p)){x.setAttribute(p,U);}}if(!y){y=b.create(AC.iconClose);y.setAttribute(l,AD.title_iconclose);this.set(B,y);}else{if(!y.hasAttribute(p)){y.setAttribute(p,U);}}if(AE){y.removeClass(Q);}else{y.addClass(Q);}this._addHeaderComponents();},_addHeaderComponents:function(){var AC,x,AB,y,AA,z,w;x=this.get(g);AB=this.get(R);AA=this.get(a);z=this.get(G);w=this.get(B);y=this.get(t);AC=this.getStdModNode(c.HEADER);if(!AC){AC=new b(document.createDocumentFragment());AC.appendChild(x);AC.appendChild(AB);AC.appendChild(y);y.appendChild(z);y.appendChild(AA);y.appendChild(w);this.setStdModContent(c.HEADER,AC,c.REPLACE);}else{if(!AC.contains(x)){if(AC.contains(AB)){AC.insertBefore(x,AB);}else{AC.appendChild(x);}}if(!AC.contains(AB)){AC.appendChild(AB);}if(!AC.contains(y)){AC.appendChild(y);}if(!y.contains(z)){y.appendChild(z);}if(!y.contains(AA)){y.appendChild(AA);}if(!y.contains(w)){y.appendChild(w);}}},_labelChanged:function(x){var w;if(this.get(q)){w=this.get(R);w.set(r,x.newVal);}},_closableChanged:function(x){var w;if(this.get(q)){w=this.get(B);if(x.newVal){w.removeClass(Q);}else{w.addClass(Q);}}},initializer:function(w){this.after("labelChange",A.bind(this._labelChanged,this));this.after("closableChange",A.bind(this._closableChanged,this));},destructor:function(){},renderUI:function(){this._createHeader();},bindUI:function(){var w=this.get("contentBox");w.delegate("click",A.bind(this._onLinkClick,this),T+" a");},_onLinkClick:function(w){w.preventDefault();},markAsAlwaysVisible:function(x){var y,w;y=this.get(G);w=this.get(C);if(x){if(!y.hasClass(E)){y.replaceClass(k,E);y.set(l,w.title_always_visible_on);return true;}}else{if(y.hasClass(E)){y.replaceClass(E,k);y.set(l,w.title_always_visible_off);return true;}}return false;},markAsExpanded:function(x){var w,y;y=this.get(a);w=this.get(C);if(x){if(!y.hasClass(S)){y.replaceClass(L,S);y.set(l,w.title_iconexpanded_on);return true;}}else{if(y.hasClass(S)){y.replaceClass(S,L);y.set(l,w.title_iconexpanded_off);return true;}}return false;},markAsExpanding:function(x){var w=this.get(a);if(x){if(!w.hasClass(D)){w.addClass(D);return true;}}else{if(w.hasClass(D)){w.removeClass(D);return true;}}return false;},markAsCollapsing:function(w){var x=this.get(a);if(w){if(!x.hasClass(s)){x.addClass(s);return true;}}else{if(x.hasClass(s)){x.removeClass(s);return true;}}return false;},resize:function(){this.fire("contentUpdate");},_extractFixedMethodValue:function(AA){var x,z,y,w=null;for(x=6,z=AA.length;x<z;x++){y=AA.charAt(x);y=parseInt(y,10);if(u.isNumber(y)){w=(w*10)+y;}else{break;}}return w;},_validateIcon:function(w){return !this.get(q)||w;},_validateNodeLabel:function(w){return !this.get(q)||w;},_validateIconsContainer:function(w){return !this.get(q)||w;},_validateIconExpanded:function(w){return !this.get(q)||w;},_validateIconAlwaysVisible:function(w){return !this.get(q)||w;},_validateIconClose:function(w){return !this.get(q)||w;},_setIcon:function(w){return A.one(w)||null;},_setNodeLabel:function(w){return A.one(w)||null;},_setIconsContainer:function(w){return A.one(w)||null;},_setIconExpanded:function(w){return A.one(w)||null;},_setIconAlwaysVisible:function(w){return A.one(w)||null;},_setIconClose:function(w){return A.one(w)||null;},_applyParser:function(w){var x;x=this.get("srcNode");if(x){this._parsedYUIConfig=x.getAttribute(F);if(this._parsedYUIConfig){this._parsedYUIConfig=P.parse(this._parsedYUIConfig);}}A.AccordionItem.superclass._applyParser.apply(this,arguments);delete this._parsedYUIConfig;},_findStdModSection:function(w){return this.get("srcNode").one("> ."+A.WidgetStdMod.SECTION_CLASS_NAMES[w]);},CONTENT_TEMPLATE:null},{NAME:d,ATTRS:{icon:{value:null,validator:function(w){return this._validateIcon(w);},setter:function(w){return this._setIcon(w);}},label:{value:"&#160;",validator:u.isString},nodeLabel:{value:null,validator:function(w){return this._validateNodeLabel(w);},setter:function(w){return this._setNodeLabel(w);
+}},iconsContainer:{value:null,validator:function(w){return this._validateIconsContainer(w);},setter:function(w){return this._setIconsContainer(w);}},iconExpanded:{value:null,validator:function(w){return this._validateIconExpanded(w);},setter:function(w){return this._setIconExpanded(w);}},iconAlwaysVisible:{value:null,validator:function(w){return this._validateIconAlwaysVisible(w);},setter:function(w){return this._setIconAlwaysVisible(w);}},iconClose:{value:null,validator:function(w){return this._validateIconClose(w);},setter:function(w){return this._setIconClose(w);}},expanded:{value:false,validator:u.isBoolean},contentHeight:{value:{method:e},validator:function(w){if(u.isObject(w)){if(w.method===e){return true;}else{if(w.method===J){return true;}else{if(w.method===W&&u.isNumber(w.height)&&w.height>=0){return true;}}}}return false;}},alwaysVisible:{value:false,validator:u.isBoolean},animation:{value:{},validator:u.isObject},strings:{value:{title_always_visible_off:"Click to set always visible on",title_always_visible_on:"Click to set always visible off",title_iconexpanded_off:"Click to expand",title_iconexpanded_on:"Click to collapse",title_iconclose:"Click to close"}},closable:{value:false,validator:u.isBoolean}},HTML_PARSER:{icon:n+O,label:function(z){var y,AA,x,w;x=this._parsedYUIConfig;if(x&&u.isValue(x.label)){return x.label;}w=z.getAttribute("data-label");if(w){return w;}AA=n+K;y=z.one(AA);return(y)?y.get(r):null;},nodeLabel:n+K,iconsContainer:n+f,iconAlwaysVisible:n+o,iconExpanded:n+m,iconClose:n+j,expanded:function(y){var x,w;x=this._parsedYUIConfig;if(x&&u.isBoolean(x.expanded)){return x.expanded;}w=y.getAttribute("data-expanded");if(w){return I.test(w);}return y.hasClass(Y);},alwaysVisible:function(y){var x,w;x=this._parsedYUIConfig;if(x&&u.isBoolean(x.alwaysVisible)){w=x.alwaysVisible;}else{w=y.getAttribute("data-alwaysvisible");if(w){w=I.test(w);}else{w=y.hasClass(h);}}if(w){this.set("expanded",true,{internalCall:true});}return w;},closable:function(y){var x,w;x=this._parsedYUIConfig;if(x&&u.isBoolean(x.closable)){return x.closable;}w=y.getAttribute("data-closable");if(w){return I.test(w);}return y.hasClass(V);},contentHeight:function(AC){var AA,AB,w=0,x,z,y;z=this._parsedYUIConfig;if(z&&z.contentHeight){return z.contentHeight;}y=AC.getAttribute("data-contentheight");if(M.test(y)){return{method:e};}else{if(v.test(y)){return{method:J};}else{if(X.test(y)){w=this._extractFixedMethodValue(y);return{method:W,height:w};}}}AB=AC.get(H);AA=i+"-";x=AB.indexOf(AA,0);if(x>=0){x+=AA.length;AB=AB.substring(x);if(M.test(AB)){return{method:e};}else{if(v.test(AB)){return{method:J};}else{if(X.test(AB)){w=this._extractFixedMethodValue(AB);return{method:W,height:w};}}}}return null;}},TEMPLATES:{icon:'<a class="'+O+'"></a>',label:'<a href="#" class="'+K+'"></a>',iconsContainer:'<div class="'+f+'"></div>',iconExpanded:['<a href="#" class="',m," ",L,'"></a>'].join(""),iconAlwaysVisible:['<a href="#" class="',o," ",k,'"></a>'].join(""),iconClose:['<a href="#" class="',j," ",Q,'"></a>'].join("")}});}());},"@VERSION@",{optional:["dd-constrain","dd-proxy","dd-drop"],requires:["event","anim-easing","widget","widget-stdmod","json-parse"]});
\ No newline at end of file

=== added file 'lib/lp/contrib/javascript/yui3-gallery/gallery-accordion/gallery-accordion.js'
--- lib/lp/contrib/javascript/yui3-gallery/gallery-accordion/gallery-accordion.js	1970-01-01 00:00:00 +0000
+++ lib/lp/contrib/javascript/yui3-gallery/gallery-accordion/gallery-accordion.js	2011-02-15 11:27:17 +0000
@@ -0,0 +1,2890 @@
+YUI.add('gallery-accordion', function(Y) {
+
+/**
+ * Provides Accordion widget
+ *
+ * @module gallery-accordion
+ */
+
+(function(){
+
+// Local constants
+var Lang = Y.Lang,
+    Node = Y.Node,
+    Anim = Y.Anim,
+    Easing = Y.Easing,
+    AccName = "accordion",
+    WidgetStdMod = Y.WidgetStdMod,
+    QuirksMode = document.compatMode == "BackCompat",
+    IEQuirksMode = QuirksMode && Y.UA.ie > 0,
+    COLLAPSE_HEIGHT = IEQuirksMode ? 1 : 0,
+    getCN = Y.ClassNameManager.getClassName,
+    
+    C_ITEM = "yui3-accordion-item",
+    C_PROXY_VISIBLE = getCN( AccName, "proxyel", "visible" ),
+    DRAGGROUP = getCN( AccName, "graggroup" ),
+
+    BEFOREITEMADD = "beforeItemAdd",
+    ITEMADDED = "itemAdded",
+    BEFOREITEMREMOVE = "beforeItemRemove",
+    ITEMREMOVED = "itemRemoved",
+    BEFOREITEMERESIZED = "beforeItemResized",
+    ITEMERESIZED = "itemResized",
+
+    BEFOREITEMEXPAND  = "beforeItemExpand",
+    BEFOREITEMCOLLAPSE = "beforeItemCollapse",
+    ITEMEXPANDED = "itemExpanded",
+    ITEMCOLLAPSED = "itemCollapsed",
+
+    BEFOREITEMREORDER = "beforeItemReorder",
+    BEFOREENDITEMREORDER = "beforeEndItemReorder",
+    ITEMREORDERED = "itemReordered",
+    
+    DEFAULT = "default",
+    ANIMATION = "animation",
+    ALWAYSVISIBLE = "alwaysVisible",
+    EXPANDED = "expanded",
+    COLLAPSEOTHERSONEXPAND = "collapseOthersOnExpand",
+    ITEMS = "items",
+    CONTENT_HEIGHT = "contentHeight",
+    ICON_CLOSE = "iconClose",
+    ICON_ALWAYSVISIBLE = "iconAlwaysVisible",
+    STRETCH = "stretch",
+    PX = "px",
+    CONTENT_BOX = "contentBox",
+    BOUNDING_BOX = "boundingBox",
+    SRCNODE = "srcNode",
+    RENDERED = "rendered",
+    BODYCONTENT = "bodyContent",
+    CHILDREN = "children",
+    PARENT_NODE = "parentNode",
+    NODE = "node",
+    DATA = "data";
+
+
+/**
+ * Accordion creates an widget, consists of one or more items, which can be collapsed, expanded,
+ * set as always visible and reordered by using Drag&Drop. Collapsing/expanding might be animated.
+ *
+ * @class Accordion
+ * @extends Widget
+ */
+
+Y.Accordion = Y.Base.create( AccName, Y.Widget, [], {
+
+    /**
+     * Signals the beginning of adding an item to the Accordion.
+     *
+     * @event beforeItemAdd
+     * @param event {Event.Facade} An Event Facade object with the following attribute specific properties added:
+     *  <dl>
+     *      <dt>item</dt>
+     *          <dd>An <code>AccordionItem</code> instance of the item being added</dd>
+     *  </dl>
+     */
+
+
+    /**
+     * Signals an item has been added to the Accordion.
+     *
+     * @event itemAdded
+     * @param event {Event.Facade} An Event Facade object with the following attribute specific properties added:
+     *  <dl>
+     *      <dt>item</dt>
+     *          <dd>An <code>AccordionItem</code> instance of the item that has been added</dd>
+     *  </dl>
+     */
+
+
+    /**
+     * Signals the beginning of removing an item.
+     *
+     * @event beforeItemRemove
+     * @param event {Event.Facade} An Event Facade object with the following attribute specific properties added:
+     *  <dl>
+     *      <dt>item</dt>
+     *          <dd>An <code>AccordionItem</code> instance of the item being removed</dd>
+     *  </dl>
+     */
+
+
+    /**
+     * Signals an item has been removed from Accordion.
+     *
+     * @event itemRemoved
+     * @param event {Event.Facade} An Event Facade object with the following attribute specific properties added:
+     *  <dl>
+     *      <dt>item</dt>
+     *          <dd>An <code>AccordionItem</code> instance of the item that has been removed</dd>
+     *  </dl>
+     */
+
+
+    /**
+     * Signals the beginning of resizing an item.
+     *
+     * @event beforeItemResized
+     * @param event {Event.Facade} An Event Facade object with the following attribute specific properties added:
+     *  <dl>
+     *      <dt>item</dt>
+     *          <dd>An <code>AccordionItem</code> instance of the item being resized</dd>
+     *  </dl>
+     */
+
+
+    /**
+     * Signals an item has been resized.
+     *
+     * @event itemResized
+     * @param event {Event.Facade} An Event Facade object with the following attribute specific properties added:
+     *  <dl>
+     *      <dt>item</dt>
+     *          <dd>An <code>AccordionItem</code> instance of the item that has been resized</dd>
+     *  </dl>
+     */
+
+
+    /**
+     * Signals the beginning of expanding an item
+     *
+     * @event beforeItemExpand
+     * @param event {Event.Facade} An Event Facade object with the following attribute specific properties added:
+     *  <dl>
+     *      <dt>item</dt>
+     *          <dd>An <code>AccordionItem</code> instance of the item being expanded</dd>
+     *  </dl>
+     */
+
+
+    /**
+     * Signals the beginning of collapsing an item
+     *
+     * @event beforeItemCollapse
+     * @param event {Event.Facade} An Event Facade object with the following attribute specific properties added:
+     *  <dl>
+     *      <dt>item</dt>
+     *          <dd>An <code>AccordionItem</code> instance of the item being collapsed</dd>
+     *  </dl>
+     */
+
+
+    /**
+     * Signals an item has been expanded
+     *
+     * @event itemExpanded
+     * @param event {Event.Facade} An Event Facade object with the following attribute specific properties added:
+     *  <dl>
+     *      <dt>item</dt>
+     *          <dd>An <code>AccordionItem</code> instance of the item that has been expanded</dd>
+     *  </dl>
+     */
+
+
+    /**
+     * Signals an item has been collapsed
+     *
+     * @event itemCollapsed
+     * @param event {Event.Facade} An Event Facade object with the following attribute specific properties added:
+     *  <dl>
+     *      <dt>item</dt>
+     *          <dd>An <code>AccordionItem</code> instance of the item that has been collapsed</dd>
+     *  </dl>
+     */
+
+
+    /**
+     * Signals the beginning of reordering an item
+     *
+     * @event beforeItemReorder
+     * @param event {Event.Facade} An Event Facade object with the following attribute specific properties added:
+     *  <dl>
+     *      <dt>item</dt>
+     *          <dd>An <code>AccordionItem</code> instance of the item being reordered</dd>
+     *  </dl>
+     */
+
+
+    /**
+     * Fires before the end of item reordering
+     *
+     * @event beforeEndItemReorder
+     * @param event {Event.Facade} An Event Facade object with the following attribute specific properties added:
+     *  <dl>
+     *      <dt>item</dt>
+     *          <dd>An <code>AccordionItem</code> instance of the item being reordered</dd>
+     *  </dl>
+     */
+
+
+    /**
+     * Signals an item has been reordered
+     *
+     * @event itemReordered
+     * @param event {Event.Facade} An Event Facade object with the following attribute specific properties added:
+     *  <dl>
+     *      <dt>item</dt>
+     *          <dd>An <code>AccordionItem</code> instance of the item that has been reordered</dd>
+     *  </dl>
+     */
+
+
+    /**
+     * Initializer lifecycle implementation for the Accordion class. Publishes events,
+     * initializes internal properties and subscribes for resize event.
+     *
+     * @method initializer
+     * @protected
+     * @param config {Object} Configuration object literal for the Accordion
+     */
+    initializer: function( config ) {
+        this.after( "render", Y.bind( this._afterRender, this ) );
+    },
+
+
+    /**
+     * Destructor lifecycle implementation for the Accordion class.
+     * Removes and destroys all registered items.
+     *
+     * @method destructor
+     * @protected
+     */
+    destructor: function() {
+        var items, item, i, length;
+
+        items = this.get( ITEMS );
+        length = items.length;
+
+        for( i = length - 1; i >= 0; i-- ){
+            item = items[ i ];
+
+            items.splice( i, 1 );
+
+            this._removeItemHandles( item );
+
+            item.destroy();
+        }
+    },
+
+
+    /**
+     * Contains items for collapsing
+     * @property _forCollapsing
+     * @protected
+     * @type Object
+     */
+    _forCollapsing : {},
+
+
+    /**
+     * Contains items for expanding
+     * @property _forExpanding
+     * @protected
+     * @type Object
+     */
+    _forExpanding : {},
+
+
+    /**
+    * Contains currently running animations
+    * @property _animations
+    * @protected
+    * @type Object
+    */
+    _animations   : {},
+
+
+    /**
+     * Collection of items handles.
+     * Keeps track of each items's event handle, as returned from <code>Y.on</code> or <code>Y.after</code>.
+     * @property _itemHandles
+     * @private
+     * @type Object
+     */
+    _itemsHandles: {},
+
+
+    /**
+     * Removes all handles, attched to given item
+     *
+     * @method _removeItemHandles
+     * @protected
+     * @param item {Y.AccordionItem} The item, which handles to remove
+     */
+    _removeItemHandles: function( item ){
+        var itemHandles, itemHandle;
+
+        itemHandles = this._itemsHandles[ item ];
+
+        for( itemHandle in itemHandles ){
+            if( itemHandles.hasOwnProperty( itemHandle ) ){
+                itemHandle = itemHandles[ itemHandle ];
+                itemHandle.detach();
+            }
+        }
+
+        delete this._itemsHandles[ item ];
+    },
+
+    /**
+     * Obtains the precise height of the node provided, including padding and border.
+     *
+     * @method _getNodeOffsetHeight
+     * @protected
+     * @param node {Node|HTMLElement} The node to gather the height from
+     * @return {Number} The calculated height or zero in case of failure
+     */
+    _getNodeOffsetHeight: function( node ){
+        var height, preciseRegion;
+
+        if( node instanceof Node ){
+            if( node.hasMethod( "getBoundingClientRect" ) ){
+                preciseRegion = node.invoke( "getBoundingClientRect" );
+
+                if( preciseRegion ){
+                    height = preciseRegion.bottom - preciseRegion.top;
+
+                    return height;
+                }
+            } else {
+                height = node.get( "offsetHeight" );
+                return Y.Lang.isValue( height ) ? height : 0;
+            }
+        } else if( node ){
+            height = node.offsetHeight;
+            return Y.Lang.isValue( height ) ? height : 0;
+        }
+
+        return 0;
+    },
+
+
+    /**
+     * Updates expand and alwaysVisible properties of given item with the values provided.
+     * The properties will be updated only if needed.
+     *
+     * @method _setItemProperties
+     * @protected
+     * @param item {Y.AccordionItem} The item, which properties should be updated
+     * @param expanding {Boolean} The new value of "expanded" property
+     * @param alwaysVisible {Boolean} The new value of "alwaysVisible" property
+     */
+    _setItemProperties: function( item, expanding, alwaysVisible ){
+        var curAlwaysVisible, curExpanded;
+
+        curAlwaysVisible = item.get( ALWAYSVISIBLE );
+        curExpanded = item.get( EXPANDED );
+
+        if( expanding != curExpanded ){
+            item.set( EXPANDED, expanding, {
+                internalCall: true
+            });
+        }
+
+        if( alwaysVisible !== curAlwaysVisible ){
+            item.set( ALWAYSVISIBLE, alwaysVisible, {
+                internalCall: true
+            });
+        }
+    },
+
+
+    /**
+     * Updates user interface of an item and marks it as expanded, alwaysVisible or both
+     *
+     * @method _setItemUI
+     * @protected
+     * @param item {Y.AccordionItem} The item, which user interface should be updated
+     * @param expanding {Boolean} If true, the item will be marked as expanded.
+     * If false, the item will be marked as collapsed
+     * @param alwaysVisible {Boolean} If true, the item will be marked as always visible.
+     * If false, the always visible mark will be removed
+     */
+    _setItemUI: function( item, expanding, alwaysVisible ){
+        item.markAsExpanded( expanding );
+        item.markAsAlwaysVisible( alwaysVisible );
+    },
+
+
+    /**
+     * Sets listener to resize event
+     *
+     * @method _afterRender
+     * @protected
+     * @param e {Event} after render custom event
+     */
+    _afterRender: function( e ){
+        var resizeEvent;
+
+        resizeEvent = this.get( "resizeEvent" );
+
+        this._setUpResizing( resizeEvent );
+
+        this.after( "resizeEventChange", Y.bind( this._afterResizeEventChange, this ) );
+    },
+
+
+    /**
+     * Set up resizing with the new value provided
+     *
+     * @method _afterResizeEventChange
+     * @protected
+     * @param params {Event} after resizeEventChange custom event
+     */
+    _afterResizeEventChange: function( params ){
+        this._setUpResizing( params.newVal );
+    },
+
+
+    /**
+     * Distributes the involved items as result of user interaction on item header.
+     * Some items might be stored in the list for collapsing, other in the list for expanding.
+     * Finally, invokes <code>_processItems</code> function, except if item has been expanded and
+     * user has clicked on always visible icon.
+     * If the user clicked on close icon, the item will be closed.
+     *
+     * @method _onItemChosen
+     * @protected
+     * @param item {Y.AccordionItem} The item on which user has clicked or pressed key
+     * @param srcIconAlwaysVisible {Boolean} True if the user has clicked on always visible icon
+     * @param srcIconClose {Boolean} True if the user has clicked on close icon
+     */
+    _onItemChosen: function( item, srcIconAlwaysVisible, srcIconClose ){
+        var toBeExcluded, alwaysVisible, expanded, collapseOthersOnExpand;
+
+        toBeExcluded = {};
+        collapseOthersOnExpand = this.get( COLLAPSEOTHERSONEXPAND );
+        alwaysVisible = item.get( ALWAYSVISIBLE );
+        expanded      = item.get( EXPANDED );
+
+        if( srcIconClose ){
+            this.removeItem( item );
+            return;
+        } else if( srcIconAlwaysVisible ){
+            if( expanded ){
+                alwaysVisible = !alwaysVisible;
+                expanded = alwaysVisible ? true : expanded;
+
+                this._setItemProperties( item, expanded, alwaysVisible );
+                this._setItemUI( item, expanded, alwaysVisible );
+
+                return;
+            } else {
+                this._forExpanding[ item ] = {
+                    'item': item,
+                    alwaysVisible: true
+                };
+
+                if( collapseOthersOnExpand ){
+                    toBeExcluded[ item ] = {
+                        'item': item
+                    };
+
+                    this._storeItemsForCollapsing( toBeExcluded );
+                }
+            }
+        } else {
+            /*
+             * Do the opposite
+             */
+            if( expanded ){
+                this._forCollapsing[ item ] = {
+                    'item': item
+                };
+            } else {
+                this._forExpanding[ item ] = {
+                    'item': item,
+                    'alwaysVisible': alwaysVisible
+                };
+
+                if( collapseOthersOnExpand ){
+                    toBeExcluded[ item ] = {
+                        'item': item
+                    };
+
+                    this._storeItemsForCollapsing( toBeExcluded );
+                }
+            }
+        }
+
+        this._processItems();
+    },
+
+
+    /**
+     * Helper method to adjust the height of all items, which <code>contentHeight</code> property is set as "stretch".
+     * If some item has animation running, it will be stopped before running another one.
+     *
+     * @method adjustStretchItems
+     * @protected
+     * @return {Number} The calculated height per strech item
+     */
+    _adjustStretchItems: function(){
+        var items = this.get( ITEMS ), heightPerStretchItem, forExpanding;
+
+        heightPerStretchItem = this._getHeightPerStretchItem();
+        forExpanding = this._forExpanding;
+
+        Y.Array.each( items, function( item, index, items ){
+            var body, bodyHeight, anim, heightSettings, expanded;
+
+            heightSettings = item.get( CONTENT_HEIGHT );
+            expanded      = item.get( EXPANDED );
+
+            if( !forExpanding[ item ] && heightSettings.method === STRETCH && expanded ){
+                anim = this._animations[ item ];
+
+                // stop waiting animation
+                if( anim ){
+                    anim.stop();
+                }
+
+                body = item.getStdModNode( WidgetStdMod.BODY );
+                bodyHeight = this._getNodeOffsetHeight( body );
+
+                if( heightPerStretchItem < bodyHeight ){
+                    this._processCollapsing( item, heightPerStretchItem );
+                } else if( heightPerStretchItem > bodyHeight ){
+                    this._processExpanding( item, heightPerStretchItem );
+                }
+            }
+        }, this );
+
+        return heightPerStretchItem;
+    },
+
+    /**
+     * Calculates the height per strech item.
+     *
+     * @method _getHeightPerStretchItem
+     * @protected
+     * @return {Number} The calculated height per strech item
+     */
+    _getHeightPerStretchItem: function(){
+        var height, items, stretchCounter = 0;
+
+        items = this.get( ITEMS );
+        height = this.get( BOUNDING_BOX ).get( "clientHeight" );
+
+        Y.Array.each( items, function( item, index, items ){
+            var collapsed, itemContentHeight, header, heightSettings, headerHeight;
+
+            header = item.getStdModNode( WidgetStdMod.HEADER );
+            heightSettings = item.get( CONTENT_HEIGHT );
+
+            headerHeight = this._getNodeOffsetHeight( header );
+
+            height -= headerHeight;
+            collapsed = !item.get( EXPANDED );
+
+            if( collapsed ){
+                height -= COLLAPSE_HEIGHT;
+                return;
+            }
+
+            if( heightSettings.method === STRETCH ){
+                stretchCounter++;
+            } else {
+                itemContentHeight = this._getItemContentHeight( item );
+                height -= itemContentHeight;
+            }
+        }, this );
+
+        if( stretchCounter > 0 ){
+            height /= stretchCounter;
+        }
+
+        if( height < 0 ){
+            height = 0;
+        }
+
+        return height;
+    },
+
+
+    /**
+     * Calculates the height of given item depending on its "contentHeight" property.
+     *
+     * @method _getItemContentHeight
+     * @protected
+     * @param item {Y.AccordionItem} The item, which height should be calculated
+     * @return {Number} The calculated item's height
+     */
+    _getItemContentHeight: function( item ){
+        var heightSettings, height = 0, body, bodyContent;
+
+        heightSettings = item.get( CONTENT_HEIGHT );
+
+        if( heightSettings.method === "auto" ){
+            body = item.getStdModNode( WidgetStdMod.BODY );
+            bodyContent = body.get( CHILDREN ).item(0);
+            height = bodyContent ? this._getNodeOffsetHeight( bodyContent ) : 0;
+        } else if( heightSettings.method === "fixed" ) {
+            height = heightSettings.height;
+        } else {
+            height = this._getHeightPerStretchItem();
+        }
+
+        return height;
+    },
+
+
+    /**
+     * Stores all items, which are expanded and not set as always visible in list
+     * in order to be collapsed later.
+     *
+     * @method _storeItemsForCollapsing
+     * @protected
+     * @param itemsToBeExcluded {Object} (optional) Contains one or more <code>Y.AccordionItem</code> instances,
+     * which should be not included in the list
+     */
+    _storeItemsForCollapsing: function( itemsToBeExcluded ){
+        var items;
+
+        itemsToBeExcluded = itemsToBeExcluded || {};
+        items = this.get( ITEMS );
+
+        Y.Array.each( items, function( item, index, items ){
+            var expanded, alwaysVisible;
+
+            expanded = item.get( EXPANDED );
+            alwaysVisible = item.get( ALWAYSVISIBLE );
+
+            if( expanded && !alwaysVisible && !itemsToBeExcluded[ item ] ){
+                this._forCollapsing[ item ] = {
+                    'item': item
+                };
+            }
+        }, this );
+    },
+
+
+    /**
+     * Expands an item to given height. This includes also an update to item's user interface
+     *
+     * @method _expandItem
+     * @protected
+     * @param item {Y.AccordionItem} The item, which should be expanded.
+     * @param height {Number} The height to which we should expand the item
+     */
+    _expandItem: function( item, height ){
+        var alwaysVisible = item.get( ALWAYSVISIBLE );
+
+        this._processExpanding( item, height );
+        this._setItemUI( item, true, alwaysVisible );
+    },
+
+
+    /**
+     * Expands an item to given height. Depending on the <code>useAnimation</code> setting,
+     * the process of expanding might be animated. This setting will be ignored, if <code>forceSkipAnimation</code> param
+     * is <code>true</code>.
+     *
+     * @method _processExpanding
+     * @protected
+     * @param item {Y.AccordionItem} An <code>Y.AccordionItem</code> instance to be expanded
+     * @param forceSkipAnimation {Boolean} If true, the animation will be skipped,
+     * without taking in consideration Accordion's <code>useAnimation</code> setting
+     * @param height {Number} The height to which item should be expanded
+     */
+    _processExpanding: function( item, height, forceSkipAnimation ){
+        var anim, curAnim, animSettings, notifyOthers = false,
+            accAnimationSettings, body;
+
+        body = item.getStdModNode( WidgetStdMod.BODY );
+
+        this.fire( BEFOREITEMERESIZED, {
+            'item': item
+        });
+
+        if( body.get( "clientHeight" ) <= COLLAPSE_HEIGHT ){
+            notifyOthers = true;
+            this.fire( BEFOREITEMEXPAND, {
+                'item': item
+            });
+        }
+
+        if( !forceSkipAnimation && this.get( "useAnimation" ) ){
+            animSettings = item.get( ANIMATION ) || {};
+
+            anim = new Anim( {
+                node: body,
+                to: {
+                    'height': height
+                }
+            });
+
+            anim.on( "end", Y.bind( this._onExpandComplete, this, item, notifyOthers ) );
+
+            accAnimationSettings = this.get( ANIMATION );
+
+            anim.set( "duration", animSettings.duration || accAnimationSettings.duration );
+            anim.set( "easing"  , animSettings.easing   || accAnimationSettings.easing   );
+
+            curAnim = this._animations[ item ];
+
+            if( curAnim ){
+                curAnim.stop();
+            }
+
+            item.markAsExpanding( true );
+
+            this._animations[ item ] = anim;
+
+            anim.run();
+        } else {
+            body.setStyle( "height", height + PX );
+
+            this.fire( ITEMERESIZED, {
+                'item': item
+            });
+
+            if( notifyOthers ){
+                this.fire( ITEMEXPANDED, {
+                    'item': item
+                });
+            }
+        }
+    },
+
+
+    /**
+     * Executes when animated expanding completes
+     *
+     * @method _onExpandComplete
+     * @protected
+     * @param item {Y.AccordionItem} An <code>Y.AccordionItem</code> instance which has been expanded
+     * @param notifyOthers {Boolean} If true, itemExpanded event will be fired
+     */
+    _onExpandComplete: function( item, notifyOthers ){
+        delete this._animations[ item ];
+
+        item.markAsExpanding( false );
+
+        this.fire( ITEMERESIZED, {
+            'item': item
+        });
+
+        if( notifyOthers ){
+            this.fire( ITEMEXPANDED, {
+                'item': item
+            });
+        }
+    },
+
+
+    /**
+     * Collapse an item and update its user interface
+     *
+     * @method _collapseItem
+     * @protected
+     * @param item {Y.AccordionItem} The item, which should be collapsed
+     */
+    _collapseItem: function( item ){
+        this._processCollapsing( item, COLLAPSE_HEIGHT );
+        this._setItemUI( item, false, false );
+    },
+
+
+    /**
+     * Collapse an item to given height. Depending on the <code>useAnimation</code> setting,
+     * the process of collapsing might be animated. This setting will be ignored, if <code>forceSkipAnimation</code> param
+     * is <code>true</code>.
+     *
+     * @method _processCollapsing
+     * @protected
+     * @param item {Y.AccordionItem} An <code>Y.AccordionItem</code> instance to be collapsed
+     * @param height {Number} The height to which item should be collapsed
+     * @param forceSkipAnimation {Boolean} If true, the animation will be skipped,
+     * without taking in consideration Accordion's <code>useAnimation</code> setting
+     */
+    _processCollapsing: function( item, height, forceSkipAnimation ){
+        var anim, curAnim, animSettings, accAnimationSettings, body,
+            notifyOthers = (height === COLLAPSE_HEIGHT);
+
+        body = item.getStdModNode( WidgetStdMod.BODY );
+
+
+        this.fire( BEFOREITEMERESIZED, {
+            'item': item
+        });
+
+        if( notifyOthers ){
+            this.fire( BEFOREITEMCOLLAPSE, {
+                'item': item
+            });
+        }
+
+        if( !forceSkipAnimation && this.get( "useAnimation" ) ){
+            animSettings = item.get( ANIMATION ) || {};
+
+            anim = new Anim( {
+                node: body,
+                to: {
+                    'height': height
+                }
+            });
+
+            anim.on( "end", Y.bind( this._onCollapseComplete, this, item, notifyOthers ) );
+
+            accAnimationSettings = this.get( ANIMATION );
+
+            anim.set( "duration", animSettings.duration || accAnimationSettings.duration );
+            anim.set( "easing"  , animSettings.easing   || accAnimationSettings.easing );
+
+            curAnim = this._animations[ item ];
+
+            if( curAnim ){
+                curAnim.stop();
+            }
+
+            item.markAsCollapsing( true );
+
+            this._animations[ item ] = anim;
+
+            anim.run();
+        } else {
+            body.setStyle( "height", height + PX );
+
+            this.fire( ITEMERESIZED, {
+                'item': item
+            });
+
+            if( notifyOthers ){
+                this.fire( ITEMCOLLAPSED, {
+                    'item': item
+                });
+            }
+        }
+    },
+
+
+    /**
+     * Executes when animated collapsing completes
+     *
+     * @method _onCollapseComplete
+     * @protected
+     * @param item {Y.AccordionItem} An <code>Y.AccordionItem</code> instance which has been collapsed
+     * @param notifyOthers {Boolean} If true, itemCollapsed event will be fired
+     */
+    _onCollapseComplete: function( item, notifyOthers ){
+        delete this._animations[ item ];
+
+        item.markAsCollapsing( false );
+
+        this.fire( ITEMERESIZED, {
+            item: item
+        });
+
+        if( notifyOthers ){
+            this.fire( ITEMCOLLAPSED, {
+                'item': item
+            });
+        }
+    },
+
+
+    /**
+     * Make an item draggable. The item can be reordered later.
+     *
+     * @method _initItemDragDrop
+     * @protected
+     * @param item {Y.AccordionItem} An <code>Y.AccordionItem</code> instance to be set as draggable
+     */
+    _initItemDragDrop: function( item ){
+        var itemHeader, dd, bb, itemBB, ddrop;
+
+        itemHeader = item.getStdModNode( WidgetStdMod.HEADER );
+
+        if( itemHeader.dd ){
+            return;
+        }
+
+        bb = this.get( BOUNDING_BOX );
+        itemBB = item.get( BOUNDING_BOX );
+
+        dd = new Y.DD.Drag({
+            node: itemHeader,
+            groups: [ DRAGGROUP ]
+        }).plug(Y.Plugin.DDProxy, {
+            moveOnEnd: false
+        }).plug(Y.Plugin.DDConstrained, {
+            constrain2node: bb
+        });
+
+        ddrop = new Y.DD.Drop({
+            node: itemBB,
+            groups: [ DRAGGROUP ]
+        });
+
+        dd.on   ( "drag:start",   Y.bind( this._onDragStart,  this, dd ) );
+        dd.on   ( "drag:end"  ,   Y.bind( this._onDragEnd,    this, dd ) );
+        dd.after( "drag:end"  ,   Y.bind( this._afterDragEnd, this, dd ) );
+        dd.on   ( "drag:drophit", Y.bind( this._onDropHit,    this, dd ) );
+    },
+
+
+    /**
+     * Sets the label of the item being dragged on the drag proxy.
+     * Fires beforeItemReorder event - returning false will cancel reordering
+     *
+     * @method _onDragStart
+     * @protected
+     * @param dd {Y.DD.Drag} The drag instance of the item
+     * @param e {Event} the DD instance's drag:start custom event
+     */
+    _onDragStart: function( dd, e ){
+        var dragNode, item;
+
+        item = this.getItem( dd.get( NODE ).get( PARENT_NODE ) );
+        dragNode = dd.get( "dragNode" );
+
+        dragNode.addClass( C_PROXY_VISIBLE );
+        dragNode.set( "innerHTML", item.get( "label" ) );
+
+        return this.fire( BEFOREITEMREORDER, { 'item': item } );
+    },
+
+
+    /**
+     * Restores HTML structure of the drag proxy.
+     * Fires beforeEndItemReorder event - returning false will cancel reordering
+     *
+     * @method _onDragEnd
+     * @protected
+     * @param dd {Y.DD.Drag} The drag instance of the item
+     * @param e {Event} the DD instance's drag:end custom event
+     */
+    _onDragEnd: function( dd, e ){
+        var dragNode, item;
+
+        dragNode = dd.get( "dragNode" );
+
+        dragNode.removeClass( C_PROXY_VISIBLE );
+        dragNode.set( "innerHTML", "" );
+
+        item = this.getItem( dd.get( NODE ).get( PARENT_NODE ) );
+        return this.fire( BEFOREENDITEMREORDER, { 'item': item } );
+    },
+
+
+    /**
+     * Set drophit to false in dragdrop instance's custom value (if there has been drophit) and fires itemReordered event
+     *
+     * @method _afterDragEnd
+     * @protected
+     * @param dd {Y.DD.Drag} The drag instance of the item
+     * @param e {Event} the DD instance's drag:end custom event
+     */
+    _afterDragEnd: function( dd, e ){
+        var item, data;
+
+        data = dd.get( DATA );
+
+        if( data.drophit ){
+            item = this.getItem( dd.get( NODE ).get( PARENT_NODE ) );
+
+            dd.set( DATA, {
+                drophit: false
+            } );
+
+            return this.fire( ITEMREORDERED, { 'item': item } );
+        }
+
+        return true;
+    },
+
+
+    /**
+     * Moves the source item before or after target item.
+     *
+     * @method _onDropHit
+     * @protected
+     * @param dd {Y.DD.Drag} The drag instance of the item
+     * @param e {Event} the DD instance's drag:drophit custom event
+     */
+    _onDropHit: function( dd, e) {
+        var mineIndex, targetItemIndex, targetItemBB, itemBB, cb,
+            goingUp, items, targetItem, item;
+
+        item = this.getItem( dd.get( NODE ).get( PARENT_NODE ) );
+        targetItem = this.getItem( e.drop.get( NODE ) );
+
+        if( targetItem === item ){
+            return false;
+        }
+
+        mineIndex = this.getItemIndex( item );
+        targetItemIndex = this.getItemIndex( targetItem );
+        targetItemBB = targetItem.get( BOUNDING_BOX );
+        itemBB = item.get( BOUNDING_BOX );
+        cb = this.get( CONTENT_BOX );
+        goingUp = false;
+        items = this.get( ITEMS );
+
+        if( targetItemIndex < mineIndex ){
+            goingUp = true;
+        }
+
+        cb.removeChild( itemBB );
+
+        if( goingUp ){
+            cb. insertBefore( itemBB, targetItemBB );
+            items.splice( mineIndex, 1 );
+            items.splice( targetItemIndex, 0, item );
+        } else {
+            cb. insertBefore( itemBB, targetItemBB.next( C_ITEM ) );
+            items.splice( targetItemIndex + 1, 0, item );
+            items.splice( mineIndex, 1 );
+        }
+
+        dd.set( DATA, {
+            drophit: true
+        });
+
+        return true;
+    },
+
+
+    /**
+     * Process items as result of user interaction or properties change.
+     * This includes four steps:
+     * 1. Update the properties of the items
+     * 2. Collapse all items stored in the list for collapsing
+     * 3. Adjust all stretch items
+     * 4. Expand items stored in the list for expanding
+     *
+     * @method _processItems
+     * @protected
+     */
+    _processItems: function(){
+        var forCollapsing, forExpanding, itemCont, heightPerStretchItem,
+            height, heightSettings, item;
+
+        forCollapsing = this._forCollapsing;
+        forExpanding = this._forExpanding;
+
+        this._setItemsProperties();
+
+        for( item in forCollapsing ){
+            if( forCollapsing.hasOwnProperty( item ) ){
+                itemCont = forCollapsing[ item ];
+
+                this._collapseItem( itemCont.item );
+            }
+        }
+
+        heightPerStretchItem = this._adjustStretchItems();
+
+        for( item in forExpanding ){
+            if( forExpanding.hasOwnProperty( item ) ){
+                itemCont = forExpanding[ item ];
+                item = itemCont.item;
+                height = heightPerStretchItem;
+                heightSettings = item.get( CONTENT_HEIGHT );
+
+                if( heightSettings.method !== STRETCH ){
+                    height = this._getItemContentHeight( item );
+                }
+
+                this._expandItem( item, height );
+            }
+        }
+
+        this._forCollapsing = {};
+        this._forExpanding = {};
+    },
+
+
+    /**
+     * Update properties of items, which were stored in the lists for collapsing or expanding
+     *
+     * @method _setItemsProperties
+     * @protected
+     */
+    _setItemsProperties: function (){
+        var forCollapsing, forExpanding, itemData;
+
+        forCollapsing = this._forCollapsing;
+        forExpanding = this._forExpanding;
+
+        for( itemData in forCollapsing ){
+            if( forCollapsing.hasOwnProperty( itemData ) ){
+                itemData = forCollapsing[ itemData ];
+                this._setItemProperties( itemData.item, false, false );
+            }
+        }
+
+        for( itemData in forExpanding ){
+            if( forExpanding.hasOwnProperty( itemData ) ){
+                itemData = forExpanding[ itemData ];
+                this._setItemProperties( itemData.item, true, itemData.alwaysVisible );
+            }
+        }
+    },
+
+
+    /**
+     * Handles the change of "expand" property of given item
+     *
+     * @method _afterItemExpand
+     * @protected
+     * @param params {EventFacade} The event facade for the attribute change
+     */
+    _afterItemExpand: function( params ){
+        var expanded, item, alwaysVisible, collapseOthersOnExpand;
+
+        if( params.internalCall ){
+            return;
+        }
+
+        expanded = params.newVal;
+        item    = params.currentTarget;
+        alwaysVisible = item.get( ALWAYSVISIBLE );
+        collapseOthersOnExpand = this.get( COLLAPSEOTHERSONEXPAND );
+
+        if( expanded ){
+            this._forExpanding[ item ] = {
+                'item': item,
+                'alwaysVisible': alwaysVisible
+            };
+
+            if( collapseOthersOnExpand ){
+                this._storeItemsForCollapsing();
+            }
+        } else {
+            this._forCollapsing[ item ] = {
+                'item': item
+            };
+        }
+
+        this._processItems();
+    },
+
+    /**
+     * Handles the change of "alwaysVisible" property of given item
+     *
+     * @method _afterItemAlwaysVisible
+     * @protected
+     * @param params {EventFacade} The event facade for the attribute change
+     */
+    _afterItemAlwaysVisible: function( params ){
+        var item, alwaysVisible, expanded;
+
+        if( params.internalCall ){
+            return;
+        }
+
+        alwaysVisible = params.newVal;
+        item         = params.currentTarget;
+        expanded     = item.get( EXPANDED );
+
+        if( alwaysVisible ){
+            if( expanded ){
+                this._setItemProperties( item, true, true );
+                this._setItemUI( item, true, true );
+                return;
+            } else {
+                this._forExpanding[ item ] = {
+                    'item': item,
+                    'alwaysVisible': true
+                };
+
+                this._storeItemsForCollapsing();
+            }
+        } else {
+            if( expanded ){
+                this._setItemUI( item, true, false );
+                return;
+            } else {
+                return;
+            }
+        }
+
+        this._processItems();
+    },
+
+
+    /**
+     * Handles the change of "contentHeight" property of given item
+     *
+     * @method _afterContentHeight
+     * @protected
+     * @param params {EventFacade} The event facade for the attribute change
+     */
+    _afterContentHeight: function( params ){
+        var item, itemContentHeight, body, bodyHeight, expanded;
+
+        item = params.currentTarget;
+
+        this._adjustStretchItems();
+
+        if( params.newVal.method !== STRETCH ){
+            expanded = item.get( EXPANDED );
+            itemContentHeight = this._getItemContentHeight( item );
+
+            body = item.getStdModNode( WidgetStdMod.BODY );
+            bodyHeight = this._getNodeOffsetHeight( body );
+
+            if( itemContentHeight < bodyHeight ){
+                this._processCollapsing( item, itemContentHeight, !expanded );
+            } else if( itemContentHeight > bodyHeight ){
+                this._processExpanding( item, itemContentHeight, !expanded );
+            }
+        }
+    },
+
+
+    /**
+     * Handles the change of "contentUpdate" property of given item
+     *
+     * @method _afterContentUpdate
+     * @protected
+     * @param params {EventFacade} The event facade for the attribute change
+     */
+    _afterContentUpdate : function( params ){
+        var item, body, bodyHeight, expanded, auto, anim;
+
+        item = params.currentTarget;
+        auto = item.get( "contentHeight" ).method === "auto";
+        expanded = item.get( EXPANDED );
+
+        body = item.getStdModNode( WidgetStdMod.BODY );
+        bodyHeight = this._getNodeOffsetHeight( body );
+
+        if( auto && expanded && params.src !== Y.Widget.UI_SRC ){
+            Y.later( 0, this, function(){
+                var itemContentHeight = this._getItemContentHeight( item );
+
+                if( itemContentHeight !== bodyHeight ){
+                    anim = this._animations[ item ];
+
+                    // stop waiting animation
+                    if( anim ){
+                        anim.stop();
+                    }
+
+                    this._adjustStretchItems();
+
+                    if( itemContentHeight < bodyHeight ){
+                        this._processCollapsing( item, itemContentHeight, !expanded );
+                    } else if( itemContentHeight > bodyHeight ){
+                        this._processExpanding( item, itemContentHeight, !expanded );
+                    }
+                }
+            } );
+        }
+    },
+
+
+    /**
+     * Subscribe for resize event, which could be provided from the browser or from an arbitrary object.
+     * For example, if there is LayoutManager in the page, it is preferable to subscribe to its resize event,
+     * instead to those, which browser provides.
+     *
+     * @method _setUpResizing
+     * @protected
+     * @param value {String|Object} String "default" or object with the following properties:
+     *  <dl>
+     *      <dt>sourceObject</dt>
+     *          <dd>An abbitrary object</dd>
+     *      <dt>resizeEvent</dt>
+     *          <dd>The name of its resize event</dd>
+     *  </dl>
+     */
+    _setUpResizing: function( value ){
+        if( this._resizeEventHandle ){
+            this._resizeEventHandle.detach();
+        }
+
+        if( value === DEFAULT ){
+            this._resizeEventHandle = Y.on( 'windowresize', Y.bind( this._adjustStretchItems, this ) );
+        } else {
+            this._resizeEventHandle = value.sourceObject.on( value.resizeEvent, Y.bind( this._adjustStretchItems, this ) );
+        }
+    },
+
+
+    /**
+     * Creates one or more items found in Accordion's <code>contentBox</code>
+     *
+     * @method renderUI
+     * @protected
+     */
+    renderUI: function(){
+        var srcNode, itemsDom, contentBox, srcNodeId;
+
+        srcNode = this.get( SRCNODE );
+        contentBox = this.get( CONTENT_BOX );
+        srcNodeId = srcNode.get( "id" );
+
+        /*
+         * Widget 3.1 workaround - the Id of contentBox is generated by YUI, instead to keep srcNode's Id, so we set it manually
+         */
+        contentBox.set( "id", srcNodeId );
+
+        itemsDom = srcNode.all( "> ." + C_ITEM );
+
+        itemsDom.each( function( itemNode, index, itemsDom ){
+            var newItem;
+
+            if( !this.getItem( itemNode ) ){
+                newItem = new Y.AccordionItem({
+                    srcNode: itemNode,
+                    id : itemNode.get( "id" )
+                });
+
+                this.addItem( newItem );
+            }
+        }, this );
+    },
+
+
+    /**
+     * Add listener to <code>itemChosen</code> event in Accordion's content box
+     *
+     * @method bindUI
+     * @protected
+     */
+    bindUI: function(){
+        var contentBox, itemChosenEvent;
+
+        contentBox = this.get( CONTENT_BOX );
+        itemChosenEvent = this.get( 'itemChosen' );
+
+        contentBox.delegate( itemChosenEvent, Y.bind( this._onItemChosenEvent, this ), '.yui3-widget-hd' );
+    },
+
+
+    /**
+     * Listening for itemChosen event, determines the source (is that iconClose, iconAlwaysVisisble, etc.) and
+     * invokes this._onItemChosen for further processing
+     *
+     * @method _onItemChosenEvent
+     * @protected
+     *
+     * @param e {Event} The itemChosen event
+     */
+    _onItemChosenEvent: function(e){
+        var header, itemNode, item, iconAlwaysVisible,
+            iconClose, srcIconAlwaysVisible, srcIconClose;
+
+        header = e.currentTarget;
+        itemNode = header.get( PARENT_NODE );
+        item = this.getItem( itemNode );
+        iconAlwaysVisible = item.get( ICON_ALWAYSVISIBLE );
+        iconClose = item.get( ICON_CLOSE );
+        srcIconAlwaysVisible = (iconAlwaysVisible === e.target);
+        srcIconClose = (iconClose === e.target);
+
+        this._onItemChosen( item, srcIconAlwaysVisible, srcIconClose );
+    },
+
+
+    /**
+     * Add an item to Accordion. Items could be added/removed multiple times and they
+     * will be rendered in the process of adding, if not.
+     * The item will be expanded, collapsed, or set as always visible depending on the
+     * settings. Item's properties will be also updated, if they are incomplete.
+     * For example, if <code>alwaysVisible</code> is true, but <code>expanded</code>
+     * property is false, it will be set to true also.
+     *
+     * If the second param, <code>parentItem</code> is an <code>Y.AccordionItem</code> instance,
+     * registered in Accordion, the item will be added as child of the <code>parentItem</code>
+     *
+     * @method addItem
+     * @param item {Y.AccordionItem} The item to be added in Accordion
+     * @param parentItem {Y.AccordionItem} (optional) This item will be the parent of the item being added
+     *
+     * @return {Boolean} True in case of successfully added item, false otherwise
+     */
+    addItem: function( item, parentItem ){
+        var expanded, alwaysVisible, itemBody, itemBodyContent, itemIndex, items, contentBox,
+            itemHandles, itemContentBox, res, children;
+
+        res = this.fire( BEFOREITEMADD, {
+            'item': item
+        });
+
+        if( !res ){
+            return false;
+        }
+
+        items = this.get( ITEMS );
+        contentBox = this.get( CONTENT_BOX );
+
+        itemContentBox = item.get( CONTENT_BOX );
+
+        if( !itemContentBox.inDoc() ){
+            if( parentItem ){
+                itemIndex = this.getItemIndex( parentItem );
+
+                if( itemIndex < 0 ){
+                    return false;
+                }
+
+                items.splice( itemIndex, 0, item );
+                contentBox.insertBefore( itemContentBox, parentItem.get( BOUNDING_BOX ) );
+            } else {
+                items.push( item );
+                contentBox.insertBefore( itemContentBox, null );
+            }
+        } else {
+            children = contentBox.get( CHILDREN );
+
+            res = children.some( function( node, index, nodeList ){
+                if( node === itemContentBox ){
+                    items.splice( index, 0, item );
+                    return true;
+                } else {
+                    return false;
+                }
+            }, this );
+
+            if( !res ){
+                return false;
+            }
+        }
+
+        itemBody = item.getStdModNode( WidgetStdMod.BODY );
+        itemBodyContent = item.get( BODYCONTENT );
+
+        if( !itemBody && !itemBodyContent  ){
+            item.set( BODYCONTENT, "" );
+        }
+
+        if( !item.get( RENDERED ) ){
+            item.render();
+        }
+
+        expanded = item.get( EXPANDED );
+        alwaysVisible = item.get( ALWAYSVISIBLE );
+
+        expanded = expanded || alwaysVisible;
+
+        if( expanded ){
+            this._forExpanding[ item ] = {
+                'item': item,
+                'alwaysVisible': alwaysVisible
+            };
+        } else {
+            this._forCollapsing[ item ] = {
+                'item': item
+            };
+        }
+
+        this._processItems();
+
+        if( this.get( "reorderItems" ) ){
+            this._initItemDragDrop( item );
+        }
+
+        itemHandles = this._itemsHandles[ item ];
+
+        if( !itemHandles ){
+            itemHandles = {};
+        }
+
+        itemHandles = {
+            "expandedChange" : item.after( "expandedChange", Y.bind( this._afterItemExpand, this ) ),
+            "alwaysVisibleChange" : item.after( "alwaysVisibleChange", Y.bind( this._afterItemAlwaysVisible, this ) ),
+            "contentHeightChange" : item.after( "contentHeightChange", Y.bind( this._afterContentHeight, this ) ),
+            "contentUpdate" : item.after( "contentUpdate", Y.bind( this._afterContentUpdate, this ) )
+        };
+
+        this._itemsHandles[ item ] = itemHandles;
+
+        this.fire( ITEMADDED, {
+            'item': item
+        });
+
+        return true;
+    },
+
+
+    /**
+     * Removes an previously registered item in Accordion
+     *
+     * @method removeItem
+     * @param p_item {Y.AccordionItem|Number} The item to be removed, or its index
+     * @return {Y.AccordionItem} The removed item or null if not found
+     */
+    removeItem: function( p_item ){
+        var items, bb, item = null, itemIndex;
+
+        items = this.get( ITEMS );
+
+        if( Lang.isNumber( p_item ) ){
+            itemIndex = p_item;
+        } else if( p_item instanceof Y.AccordionItem ){
+            itemIndex = this.getItemIndex( p_item );
+        } else {
+            return null;
+        }
+
+        if( itemIndex >= 0 ){
+
+            this.fire( BEFOREITEMREMOVE, {
+                item: p_item
+            });
+
+            item = items.splice( itemIndex, 1 )[0];
+
+            this._removeItemHandles( item );
+
+            bb = item.get( BOUNDING_BOX );
+            bb.remove();
+
+            this._adjustStretchItems();
+
+            this.fire( ITEMREMOVED, {
+                item: p_item
+            });
+        }
+
+        return item;
+    },
+
+
+    /**
+     * Searching for item, previously registered in Accordion
+     *
+     * @method getItem
+     * @param param {Number|Y.Node} If number, this must be item's index.
+     * If Node, it should be the value of item's <code>contentBox</code> or <code>boundingBox</code> properties
+     *
+     * @return {Y.AccordionItem} The found item or null
+     */
+    getItem: function( param ){
+        var items = this.get( ITEMS ), item = null;
+
+        if( Lang.isNumber( param ) ){
+            item = items[ param ];
+            return (item instanceof Y.AccordionItem) ? item : null;
+        } else if( param instanceof Node ){
+            Y.Array.some( items, function( tmpItem, index, items ){
+                var contentBox = tmpItem.get( CONTENT_BOX );
+
+                /*
+                 * Both contentBox and boundingBox point to same node, so it is safe to check only one of them
+                 */
+                if( contentBox === param ){
+                    item = tmpItem;
+                    return true;
+                } else {
+                    return false;
+                }
+            }, this );
+        }
+
+        return item;
+    },
+
+
+    /**
+     * Looking for the index of previously registered item
+     *
+     * @method getItemIndex
+     * @param item {Y.AccordionItem} The item which index should be returned
+     * @return {Number} Item index or <code>-1</code> if item has been not found
+     */
+    getItemIndex: function( item ){
+        var res = -1, items;
+
+        if( item instanceof Y.AccordionItem ){
+            items = this.get( ITEMS );
+
+            Y.Array.some( items, function( tmpItem, index, items ){
+                if( tmpItem === item ){
+                    res = index;
+                    return true;
+                } else {
+                    return false;
+                }
+            }, this );
+        }
+
+        return res;
+    },
+
+
+    /**
+     * Overwrites Y.WidgetStdMod fuction in order to resolve Widget 3.1 issue:<br>
+     * If CONTENT_TEMPLATE is null, in renderUI the result of the following code:
+     * <code>this.getStdModNode( Y.WidgetStdMod.HEADER );</code> is null.
+     * The same is with <code>this.getStdModNode( Y.WidgetStdMod.BODY );</code>.
+     *
+     * @method _findStdModSection
+     * @protected
+     * @param {String} section The section for which the render Node is to be found. Either WidgetStdMod.HEADER, WidgetStdMod.BODY or WidgetStdMod.FOOTER.
+     * @return {Node} The rendered node for the given section, or null if not found.
+     */
+    _findStdModSection: function(section) {
+        return this.get(SRCNODE).one("> ." + Y.WidgetStdMod.SECTION_CLASS_NAMES[section]);
+    },
+
+    CONTENT_TEMPLATE : null
+}, {
+    /**
+     *  Static property provides a string to identify the class.
+     *
+     * @property Accordion.NAME
+     * @type String
+     * @static
+     */
+    NAME : AccName,
+
+    /**
+     * Static property used to define the default attribute
+     * configuration for the Accordion.
+     *
+     * @property Accordion.ATTRS
+     * @type Object
+     * @static
+     */
+    ATTRS : {
+        /**
+         * @description The event on which Accordion should listen for user interactions.
+         * The value can be also mousedown or mouseup. Mousedown event can be used if
+         * drag&drop is not enabled
+         *
+         * @attribute itemChosen
+         * @default click
+         * @type String
+         */
+        itemChosen: {
+            value: "click",
+            validator: Lang.isString
+        },
+
+        /**
+         * @description Contains the items, currently added to Accordion
+         *
+         * @attribute items
+         * @readOnly
+         * @default []
+         * @type Array
+         */
+        items: {
+            value: [],
+            readOnly: true,
+            validator: Lang.isArray
+        },
+
+        /**
+         * @attribute resizeEvent
+         *
+         * @description The event on which Accordion should listen for resizing.
+         * The value must be one of these:
+         * <ul>
+         *     <li> String "default" - the Accordion will subscribe to Y.windowresize event
+         *     </li>
+         *     <li> An object in the following form:
+         *         {
+         *             sourceObject: some_javascript_object,
+         *             resizeEvent: an_event_to_subscribe
+         *         }
+         *      </li>
+         * </ul>
+         * For example, if we are using LayoutManager's instance as sourceObject, we will have to use its "resize" event as resizeEvent
+         *
+         * @default "default"
+         * @type String or Object
+         */
+
+        resizeEvent: {
+            value: DEFAULT,
+            validator: function( value ){
+                if( value === DEFAULT ){
+                    return true;
+                } else if( Lang.isObject(value) ){
+                    if( Lang.isValue( value.sourceObject ) && Lang.isValue( value.resizeEvent ) ){
+                        return true;
+                    }
+                }
+
+                return false;
+            }
+        },
+
+        /**
+         * @attribute useAnimation
+         * @description Boolean indicating that Accordion should use animation when expanding or collapsing items.
+         *
+         * @default true
+         * @type Boolean
+         */
+        useAnimation: {
+            value: true,
+            validator: Lang.isBoolean
+        },
+
+        /**
+         * @attribute animation
+         * @description Animation config values, see Y.Animation
+         *
+         * @default <code> {
+         *    duration: 1,
+         *    easing: Easing.easeOutStrong
+         *  }
+         *  </code>
+         *
+         * @type Object
+         */
+        animation: {
+            value: {
+                duration: 1,
+                easing: Easing.easeOutStrong
+            },
+            validator: function( value ){
+                return Lang.isObject( value ) && Lang.isNumber( value.duration ) &&
+                    Lang.isFunction( value.easing );
+            }
+        },
+
+        /**
+         * @attribute reorderItems
+         * @description Boolean indicating that items can be reordered via drag and drop.<br>
+         *
+         * Enabling items reordering requires also including the optional drag and drop modules in YUI instance:<br>
+         * 'dd-constrain', 'dd-proxy', 'dd-drop', or just 'dd'
+         *
+         * @default false
+         * @type Boolean
+         */
+        reorderItems: {
+            value: false,
+            validator: function(value){
+                return Lang.isBoolean(value) && !Lang.isUndefined( Y.DD );
+            }
+        },
+
+        /**
+         * @attribute collapseOthersOnExpand
+         * @description If true, on item expanding, all other expanded and not set as always visible items, will be collapsed
+         * Otherwise, they will stay open
+         *
+         * @default true
+         * @type Boolean
+         */
+        collapseOthersOnExpand: {
+            value: true,
+            validator: Lang.isBoolean
+        }
+    }
+});
+
+}());
+
+/**
+ * Provides AccordionItem class
+ *
+ * @module gallery-accordion
+ */
+
+(function(){
+
+// Local constants
+var Lang = Y.Lang,
+    Node = Y.Node,
+    JSON = Y.JSON,
+    WidgetStdMod = Y.WidgetStdMod,
+    AccItemName = "accordion-item",
+    getCN = Y.ClassNameManager.getClassName,
+    
+    C_ICONEXPANDED_EXPANDING = getCN( AccItemName, "iconexpanded", "expanding" ),
+    C_ICONEXPANDED_COLLAPSING = getCN( AccItemName, "iconexpanded", "collapsing" ),
+
+    C_ICON = getCN( AccItemName, "icon" ),
+    C_LABEL = getCN( AccItemName, "label" ),
+    C_ICONALWAYSVISIBLE = getCN( AccItemName, "iconalwaysvisible" ),
+    C_ICONSCONTAINER = getCN( AccItemName, "icons" ),
+    C_ICONEXPANDED = getCN( AccItemName, "iconexpanded" ),
+    C_ICONCLOSE = getCN( AccItemName, "iconclose" ),
+    C_ICONCLOSE_HIDDEN = getCN( AccItemName, "iconclose", "hidden" ),
+
+    C_ICONEXPANDED_ON = getCN( AccItemName, "iconexpanded", "on" ),
+    C_ICONEXPANDED_OFF = getCN( AccItemName, "iconexpanded", "off" ),
+
+    C_ICONALWAYSVISIBLE_ON = getCN( AccItemName, "iconalwaysvisible", "on" ),
+    C_ICONALWAYSVISIBLE_OFF = getCN( AccItemName, "iconalwaysvisible", "off" ),
+
+    C_EXPANDED =  getCN( AccItemName, "expanded" ),
+    C_CLOSABLE =  getCN( AccItemName, "closable" ),
+    C_ALWAYSVISIBLE =  getCN( AccItemName, "alwaysvisible" ),
+    C_CONTENTHEIGHT =  getCN( AccItemName, "contentheight" ),
+
+    TITLE = "title",
+    STRINGS = "strings",
+    RENDERED = "rendered",
+    CLASS_NAME = "className",
+    AUTO = "auto",
+    STRETCH = "stretch",
+    FIXED = "fixed",
+    HEADER_SELECTOR = ".yui3-widget-hd",
+    DOT = ".",
+    HEADER_SELECTOR_SUB = ".yui3-widget-hd " + DOT,
+    INNER_HTML = "innerHTML",
+    ICONS_CONTAINER = "iconsContainer",
+    ICON = "icon",
+    NODE_LABEL = "nodeLabel",
+    ICON_ALWAYSVISIBLE = "iconAlwaysVisible",
+    ICON_EXPANDED = "iconExpanded",
+    ICON_CLOSE = "iconClose",
+    HREF = "href",
+    HREF_VALUE = "#",
+    YUICONFIG = "yuiConfig",
+
+    REGEX_TRUE = /^(?:true|yes|1)$/,
+    REGEX_AUTO = /^auto\s*/,
+    REGEX_STRETCH = /^stretch\s*/,
+    REGEX_FIXED = /^fixed-\d+/;
+
+/**
+ * Create an AccordionItem widget.
+ *
+ * @class AccordionItem
+ * @extends Widget
+ */
+
+Y.AccordionItem = Y.Base.create( AccItemName, Y.Widget, [Y.WidgetStdMod], {
+    /**
+     * Creates the header content
+     *
+     * @method _createHeader
+     * @protected
+     */
+    _createHeader: function(){
+        var closable, templates, strings,  iconsContainer,
+            icon, nodeLabel, iconExpanded, iconAlwaysVisible, iconClose;
+
+        icon = this.get( ICON );
+        nodeLabel = this.get( NODE_LABEL );
+        iconExpanded = this.get( ICON_EXPANDED );
+        iconAlwaysVisible = this.get( ICON_ALWAYSVISIBLE );
+        iconClose = this.get( ICON_CLOSE );
+        iconsContainer = this.get( ICONS_CONTAINER );
+
+        strings = this.get( STRINGS );
+        closable = this.get( "closable" );
+        templates = Y.AccordionItem.TEMPLATES;
+
+        if( !icon ){
+            icon = Node.create( templates.icon );
+            this.set( ICON, icon );
+        }
+
+        if( !nodeLabel ){
+            nodeLabel = Node.create( templates.label );
+            this.set( NODE_LABEL, nodeLabel );
+        } else if( !nodeLabel.hasAttribute( HREF ) ){
+            nodeLabel.setAttribute( HREF, HREF_VALUE );
+        }
+
+        nodeLabel.setContent( this.get( "label" ) );
+
+
+        if( !iconsContainer ){
+            iconsContainer = Node.create( templates.iconsContainer );
+            this.set( ICONS_CONTAINER, iconsContainer );
+        }
+
+        if( !iconAlwaysVisible ){
+            iconAlwaysVisible = Node.create( templates.iconAlwaysVisible );
+            iconAlwaysVisible.setAttribute( TITLE, strings.title_always_visible_off );
+            this.set( ICON_ALWAYSVISIBLE, iconAlwaysVisible );
+        } else if( !iconAlwaysVisible.hasAttribute( HREF ) ){
+            iconAlwaysVisible.setAttribute( HREF, HREF_VALUE );
+        }
+
+
+        if( !iconExpanded ){
+            iconExpanded = Node.create( templates.iconExpanded );
+            iconExpanded.setAttribute( TITLE, strings.title_iconexpanded_off );
+            this.set( ICON_EXPANDED, iconExpanded );
+        } else if( !iconExpanded.hasAttribute( HREF ) ){
+            iconExpanded.setAttribute( HREF, HREF_VALUE );
+        }
+
+
+        if( !iconClose ){
+            iconClose = Node.create( templates.iconClose );
+            iconClose.setAttribute( TITLE, strings.title_iconclose );
+            this.set( ICON_CLOSE, iconClose );
+        } else if( !iconClose.hasAttribute( HREF ) ){
+            iconClose.setAttribute( HREF, HREF_VALUE );
+        }
+
+        if( closable ){
+            iconClose.removeClass( C_ICONCLOSE_HIDDEN );
+        } else {
+            iconClose.addClass( C_ICONCLOSE_HIDDEN );
+        }
+
+        this._addHeaderComponents();
+    },
+
+    /**
+     * Add label and icons in the header. Also, it creates header in if not set from markup
+     *
+     * @method _addHeaderComponents
+     * @protected
+     */
+    _addHeaderComponents: function(){
+        var header, icon, nodeLabel, iconsContainer, iconExpanded,
+            iconAlwaysVisible, iconClose;
+
+        icon = this.get( ICON );
+        nodeLabel = this.get( NODE_LABEL );
+        iconExpanded = this.get( ICON_EXPANDED );
+        iconAlwaysVisible = this.get( ICON_ALWAYSVISIBLE );
+        iconClose = this.get( ICON_CLOSE );
+        iconsContainer = this.get( ICONS_CONTAINER );
+
+        header = this.getStdModNode( WidgetStdMod.HEADER );
+
+        if( !header ){
+            header = new Node( document.createDocumentFragment() );
+            header.appendChild( icon );
+            header.appendChild( nodeLabel );
+            header.appendChild( iconsContainer );
+            iconsContainer.appendChild( iconAlwaysVisible );
+            iconsContainer.appendChild( iconExpanded );
+            iconsContainer.appendChild( iconClose );
+
+            this.setStdModContent( WidgetStdMod.HEADER, header, WidgetStdMod.REPLACE );
+        } else {
+            if( !header.contains( icon ) ){
+                if( header.contains( nodeLabel ) ){
+                    header.insertBefore( icon, nodeLabel );
+                } else {
+                    header.appendChild( icon );
+                }
+            }
+
+            if( !header.contains( nodeLabel ) ){
+                header.appendChild( nodeLabel );
+            }
+
+            if( !header.contains( iconsContainer ) ){
+                header.appendChild( iconsContainer );
+            }
+
+            if( !iconsContainer.contains( iconAlwaysVisible ) ){
+                iconsContainer.appendChild( iconAlwaysVisible );
+            }
+
+            if( !iconsContainer.contains( iconExpanded ) ){
+                iconsContainer.appendChild( iconExpanded );
+            }
+
+            if( !iconsContainer.contains( iconClose ) ){
+                iconsContainer.appendChild( iconClose );
+            }
+        }
+    },
+
+
+    /**
+     * Handles the change of "labelChanged" property. Updates item's UI with the label provided
+     *
+     * @method _labelChanged
+     * @protected
+     * @param params {EventFacade} The event facade for the attribute change
+     */
+    _labelChanged: function( params ){
+        var label;
+
+        if( this.get( RENDERED ) ){
+            label = this.get( NODE_LABEL );
+            label.set( INNER_HTML, params.newVal );
+        }
+    },
+
+
+    /**
+     * Handles the change of "closableChanged" property. Hides or shows close icon
+     *
+     * @method _closableChanged
+     * @protected
+     * @param params {EventFacade} The event facade for the attribute change
+     */
+    _closableChanged: function( params ){
+        var iconClose;
+
+        if( this.get( RENDERED ) ){
+            iconClose = this.get( ICON_CLOSE );
+
+            if( params.newVal ){
+                iconClose.removeClass( C_ICONCLOSE_HIDDEN );
+            } else {
+                iconClose.addClass( C_ICONCLOSE_HIDDEN );
+            }
+        }
+    },
+
+
+    /**
+     * Initializer lifecycle implementation for the AccordionItem class.
+     *
+     * @method initializer
+     * @protected
+     * @param  config {Object} Configuration object literal for the AccordionItem
+     */
+    initializer: function( config ) {
+        this.after( "labelChange",  Y.bind( this._labelChanged, this ) );
+        this.after( "closableChange", Y.bind( this._closableChanged, this ) );
+    },
+
+
+    /**
+     * Destructor lifecycle implementation for the AccordionItem class.
+     *
+     * @method destructor
+     * @protected
+     */
+    destructor : function() {
+        // EMPTY
+    },
+
+
+    /**
+     * Creates AccordionItem's header.
+     *
+     * @method renderUI
+     * @protected
+     */
+    renderUI: function(){
+        this._createHeader();
+    },
+
+    /**
+     * Configures/Sets up listeners to bind Widget State to UI/DOM
+     *
+     * @method bindUI
+     * @protected
+     */
+    bindUI: function(){
+        var contentBox = this.get( "contentBox" );
+
+        contentBox.delegate( "click", Y.bind( this._onLinkClick, this ), HEADER_SELECTOR + ' a' );
+    },
+
+
+
+    /**
+     * Prevent default action on clicking the link in the label
+     *
+     * @method _onLinkClick
+     * @protected
+     *
+     * @param e {Event} The click event
+     */
+    _onLinkClick: function( e ){
+        e.preventDefault();
+    },
+
+   /**
+    * Marks the item as always visible by adding class to always visible icon.
+    * The icon will be updated only if needed.
+    *
+    * @method markAsAlwaysVisible
+    * @param alwaysVisible {Boolean} If true, the item should be marked as always visible.
+    * @return {Boolean} Return true if the icon has been updated, false if there was no need to update
+    */
+    markAsAlwaysVisible: function( alwaysVisible ){
+        var iconAlwaysVisisble, strings;
+
+        iconAlwaysVisisble = this.get( ICON_ALWAYSVISIBLE );
+        strings = this.get( STRINGS );
+
+        if( alwaysVisible ){
+            if( !iconAlwaysVisisble.hasClass( C_ICONALWAYSVISIBLE_ON ) ){
+                iconAlwaysVisisble.replaceClass( C_ICONALWAYSVISIBLE_OFF, C_ICONALWAYSVISIBLE_ON );
+                iconAlwaysVisisble.set( TITLE, strings.title_always_visible_on );
+                return true;
+            }
+        } else {
+            if( iconAlwaysVisisble.hasClass( C_ICONALWAYSVISIBLE_ON ) ){
+                iconAlwaysVisisble.replaceClass( C_ICONALWAYSVISIBLE_ON, C_ICONALWAYSVISIBLE_OFF );
+                iconAlwaysVisisble.set( TITLE, strings.title_always_visible_off );
+                return true;
+            }
+        }
+
+        return false;
+    },
+
+
+    /**
+    * Marks the item as expanded by adding class to expand icon.
+    * The icon will be updated only if needed.
+    *
+    * @method markAsExpanded
+    * @param expanded {Boolean} Boolean indicating that item should be marked as expanded.
+    * @return {Boolean} Return true if the icon has been updated, false if there was no need to update
+    */
+    markAsExpanded: function( expanded ){
+        var strings, iconExpanded;
+
+        iconExpanded = this.get( ICON_EXPANDED );
+        strings = this.get( STRINGS );
+
+        if( expanded ){
+            if( !iconExpanded.hasClass( C_ICONEXPANDED_ON ) ){
+                iconExpanded.replaceClass( C_ICONEXPANDED_OFF, C_ICONEXPANDED_ON );
+                iconExpanded.set( TITLE , strings.title_iconexpanded_on );
+                return true;
+            }
+        } else {
+            if( iconExpanded.hasClass( C_ICONEXPANDED_ON ) ){
+                iconExpanded.replaceClass( C_ICONEXPANDED_ON, C_ICONEXPANDED_OFF );
+                iconExpanded.set( TITLE , strings.title_iconexpanded_off );
+                return true;
+            }
+        }
+
+        return false;
+    },
+
+
+   /**
+    * Marks the item as expanding by adding class to expand icon.
+    * The method will update icon only if needed.
+    *
+    * @method markAsExpanding
+    * @param expanding {Boolean} Boolean indicating that the item should be marked as expanding.
+    * @return {Boolean} Return true if the icon has been updated, false if there was no need to update
+    */
+    markAsExpanding: function( expanding ){
+        var iconExpanded = this.get( ICON_EXPANDED );
+
+        if( expanding ){
+            if( !iconExpanded.hasClass( C_ICONEXPANDED_EXPANDING ) ){
+                iconExpanded.addClass( C_ICONEXPANDED_EXPANDING );
+                return true;
+            }
+        } else {
+            if( iconExpanded.hasClass( C_ICONEXPANDED_EXPANDING ) ){
+                iconExpanded.removeClass( C_ICONEXPANDED_EXPANDING );
+                return true;
+            }
+        }
+
+        return false;
+    },
+
+
+   /**
+    * Marks the item as collapsing by adding class to expand icon.
+    * The method will update icon only if needed.
+    *
+    * @method markAsCollapsing
+    * @param collapsing {Boolean} Boolean indicating that the item should be marked as collapsing.
+    * @return {Boolean} Return true if the icon has been updated, false if there was no need to update
+    */
+    markAsCollapsing: function( collapsing ){
+        var iconExpanded = this.get( ICON_EXPANDED );
+
+        if( collapsing ){
+            if( !iconExpanded.hasClass( C_ICONEXPANDED_COLLAPSING ) ){
+                iconExpanded.addClass( C_ICONEXPANDED_COLLAPSING );
+                return true;
+            }
+        } else {
+            if( iconExpanded.hasClass( C_ICONEXPANDED_COLLAPSING ) ){
+                iconExpanded.removeClass( C_ICONEXPANDED_COLLAPSING );
+                return true;
+            }
+        }
+
+        return false;
+    },
+
+
+    /**
+     * Forces the item to resize as result of direct content manipulation (via 'innerHTML').
+     * This method should be invoked if 'contentHeight' property has been set to 'auto'.
+     *
+     * @method resize
+     */
+    resize : function(){
+        this.fire( "contentUpdate" );
+    },
+
+
+    /**
+     * Parses and returns the value of contentHeight property, if set method "fixed".
+     * The value must be in this format: fixed-X, where X is integer
+     *
+     * @method _extractFixedMethodValue
+     * @param value {String} The value to be parsed
+     * @return {Number} The parsed value or null
+     * @protected
+     */
+    _extractFixedMethodValue: function( value ){
+        var i, length, chr, height = null;
+
+        for( i = 6, length = value.length; i < length; i++ ){ // 6 = "fixed-".length
+            chr = value.charAt(i);
+            chr = parseInt( chr, 10 );
+
+            if( Lang.isNumber( chr ) ){
+                height = (height * 10) + chr;
+            } else {
+                break;
+            }
+        }
+
+        return height;
+    },
+
+
+    /**
+     * Validator applied to the icon attribute. Setting new value is not allowed if Accordion has been rendered.
+     *
+     * @method _validateIcon
+     * @param value {MIXED} the value for the icon attribute
+     * @return {Boolean}
+     * @protected
+     */
+    _validateIcon: function( value ) {
+        return !this.get(RENDERED) || value;
+    },
+
+
+    /**
+     * Validator applied to the nodeLabel attribute. Setting new value is not allowed if Accordion has been rendered.
+     *
+     * @method _validateNodeLabel
+     * @param value {MIXED} the value for the nodeLabel attribute
+     * @return {Boolean}
+     * @protected
+     */
+    _validateNodeLabel: function( value ) {
+        return !this.get(RENDERED) || value;
+    },
+
+
+    /**
+     * Validator applied to the iconsContainer attribute. Setting new value is not allowed if Accordion has been rendered.
+     *
+     * @method _validateIconsContainer
+     * @param value {MIXED} the value for the iconsContainer attribute
+     * @return {Boolean}
+     * @protected
+     */
+    _validateIconsContainer: function( value ) {
+        return !this.get(RENDERED) || value;
+    },
+
+
+    /**
+     * Validator applied to the iconExpanded attribute. Setting new value is not allowed if Accordion has been rendered.
+     *
+     * @method _validateIconExpanded
+     * @param value {MIXED} the value for the iconExpanded attribute
+     * @return {Boolean}
+     * @protected
+     */
+    _validateIconExpanded: function( value ) {
+        return !this.get(RENDERED) || value;
+    },
+
+
+    /**
+     * Validator applied to the iconAlwaysVisible attribute. Setting new value is not allowed if Accordion has been rendered.
+     *
+     * @method _validateIconAlwaysVisible
+     * @param value {MIXED} the value for the iconAlwaysVisible attribute
+     * @return {Boolean}
+     * @protected
+     */
+    _validateIconAlwaysVisible: function( value ) {
+        return !this.get(RENDERED) || value;
+    },
+
+
+    /**
+     * Validator applied to the iconClose attribute. Setting new value is not allowed if Accordion has been rendered.
+     *
+     * @method _validateIconClose
+     * @param value {MIXED} the value for the iconClose attribute
+     * @return {Boolean}
+     * @protected
+     */
+    _validateIconClose: function( value ) {
+        return !this.get(RENDERED) || value;
+    },
+
+
+    /**
+     * Setter applied to the input when updating the icon attribute.  Input can
+     * be a Node, raw HTMLElement, or a selector string to locate it.
+     *
+     * @method _setIcon
+     * @param value {Node|HTMLElement|String} The icon element Node or selector
+     * @return {Node} The Node if found, null otherwise.
+     * @protected
+     */
+    _setIcon: function( value ){
+        return Y.one( value ) || null;
+    },
+
+
+    /**
+     * Setter applied to the input when updating the nodeLabel attribute.  Input can
+     * be a Node, raw HTMLElement, or a selector string to locate it.
+     *
+     * @method _setNodeLabel
+     * @param value {Node|HTMLElement|String} The nodeLabel element Node or selector
+     * @return {Node} The Node if found, null otherwise.
+     * @protected
+     */
+    _setNodeLabel: function( value ){
+        return Y.one( value ) || null;
+    },
+
+
+    /**
+     * Setter applied to the input when updating the iconsContainer attribute.  Input can
+     * be a Node, raw HTMLElement, or a selector string to locate it.
+     *
+     * @method _setIconsContainer
+     * @param value {Node|HTMLElement|String} The iconsContainer element Node or selector
+     * @return {Node} The Node if found, null otherwise.
+     * @protected
+     */
+    _setIconsContainer: function( value ){
+        return Y.one( value ) || null;
+    },
+
+
+    /**
+     * Setter applied to the input when updating the iconExpanded attribute.  Input can
+     * be a Node, raw HTMLElement, or a selector string to locate it.
+     *
+     * @method _setIconExpanded
+     * @param value {Node|HTMLElement|String} The iconExpanded element Node or selector
+     * @return {Node} The Node if found, null otherwise.
+     * @protected
+     */
+    _setIconExpanded: function( value ){
+        return Y.one( value ) || null;
+    },
+
+
+    /**
+     * Setter applied to the input when updating the iconAlwaysVisible attribute.  Input can
+     * be a Node, raw HTMLElement, or a selector string to locate it.
+     *
+     * @method _setIconAlwaysVisible
+     * @param value {Node|HTMLElement|String} The iconAlwaysVisible element Node or selector
+     * @return {Node} The Node if found, null otherwise.
+     * @protected
+     */
+    _setIconAlwaysVisible: function( value ){
+        return Y.one( value ) || null;
+    },
+
+
+    /**
+     * Setter applied to the input when updating the iconClose attribute.  Input can
+     * be a Node, raw HTMLElement, or a selector string to locate it.
+     *
+     * @method _setIconClose
+     * @param value {Node|HTMLElement|String} The iconClose element Node or selector
+     * @return {Node} The Node if found, null otherwise.
+     * @protected
+     */
+    _setIconClose: function( value ){
+        return Y.one( value ) || null;
+    },
+
+
+    /**
+     * Overwrites Widget's _applyParser method in order to parse yuiConfig attribute before entering in HTML_PARSER attributes
+     *
+     * @method _applyParser
+     * @protected
+     * @param config {Object} User configuration object (will be populated with values from Node)
+    */
+    _applyParser : function(config) {
+        var srcNode;
+
+        srcNode = this.get( "srcNode" );
+
+        if( srcNode ){
+            this._parsedYUIConfig = srcNode.getAttribute( YUICONFIG );
+
+            if( this._parsedYUIConfig ){
+                this._parsedYUIConfig = JSON.parse( this._parsedYUIConfig );
+            }
+        }
+
+        Y.AccordionItem.superclass._applyParser.apply( this, arguments );
+
+        delete this._parsedYUIConfig;
+    },
+
+
+    /**
+     * Overwrites Y.WidgetStdMod fuction in order to resolve Widget 3.1 issue:<br>
+     * If CONTENT_TEMPLATE is null, in renderUI the result of the following code:
+     * <code>this.getStdModNode( Y.WidgetStdMod.HEADER );</code> is null.
+     * The same is with <code>this.getStdModNode( Y.WidgetStdMod.BODY );</code>.
+     *
+     * @method _findStdModSection
+     * @protected
+     * @param {String} section The section for which the render Node is to be found. Either WidgetStdMod.HEADER, WidgetStdMod.BODY or WidgetStdMod.FOOTER.
+     * @return {Node} The rendered node for the given section, or null if not found.
+     */
+    _findStdModSection: function(section) {
+        return this.get("srcNode").one("> ." + Y.WidgetStdMod.SECTION_CLASS_NAMES[section]);
+    },
+
+    CONTENT_TEMPLATE : null
+}, {
+    /**
+     *  Static property provides a string to identify the class.
+     *
+     * @property NAME
+     * @type String
+     * @static
+     */
+    NAME : AccItemName,
+
+    /**
+     * Static property used to define the default attribute
+     * configuration for the Accordion.
+     *
+     * @property Accordion.ATTRS
+     * @type Object
+     * @static
+     */
+    ATTRS : {
+
+        /**
+         * @description The Node, representing item's icon
+         *
+         * @attribute icon
+         * @default null
+         * @type Node
+         */
+        icon: {
+            value: null,
+            validator: function( value ){
+                return this._validateIcon( value );
+            },
+            setter : function( value ) {
+                return this._setIcon( value );
+            }
+        },
+
+        /**
+         * @description The label of item
+         *
+         * @attribute label
+         * @default "&#160;"
+         * @type String
+         */
+        label: {
+            value: "&#160;",
+            validator: Lang.isString
+        },
+
+        /**
+         * @description The node, which contains item's label
+         *
+         * @attribute nodeLabel
+         * @default null
+         * @type Node
+         */
+        nodeLabel: {
+            value: null,
+            validator: function( value ){
+                return this._validateNodeLabel( value );
+            },
+            setter : function( value ) {
+                return this._setNodeLabel( value );
+            }
+        },
+
+
+        /**
+         * @description The container of iconAlwaysVisible, iconExpanded and iconClose
+         *
+         * @attribute iconsContainer
+         * @default null
+         * @type Node
+         */
+        iconsContainer: {
+            value: null,
+            validator: function( value ){
+                return this._validateIconsContainer( value );
+            },
+            setter : function( value ) {
+                return this._setIconsContainer( value );
+            }
+        },
+
+        /**
+         * @description The Node, representing icon expanded
+         *
+         * @attribute iconExpanded
+         * @default null
+         * @type Node
+         */
+        iconExpanded: {
+            value: null,
+            validator: function( value ){
+                return this._validateIconExpanded( value );
+            },
+            setter : function( value ) {
+                return this._setIconExpanded( value );
+            }
+        },
+
+
+        /**
+         * @description The Node, representing icon always visible
+         *
+         * @attribute iconAlwaysVisible
+         * @default null
+         * @type Node
+         */
+        iconAlwaysVisible: {
+            value: null,
+            validator: function( value ){
+                return this._validateIconAlwaysVisible( value );
+            },
+            setter : function( value ) {
+                return this._setIconAlwaysVisible( value );
+            }
+        },
+
+
+        /**
+         * @description The Node, representing icon close, or null if the item is not closable
+         *
+         * @attribute iconClose
+         * @default null
+         * @type Node
+         */
+        iconClose: {
+            value: null,
+            validator: function( value ){
+                return this._validateIconClose( value );
+            },
+            setter : function( value ) {
+                return this._setIconClose( value );
+            }
+        },
+
+        /**
+         * @description Get/Set expanded status of the item
+         *
+         * @attribute expanded
+         * @default false
+         * @type Boolean
+         */
+        expanded: {
+            value: false,
+            validator: Lang.isBoolean
+        },
+
+        /**
+         * @description Describe the method, which will be used when expanding/collapsing
+         * the item. The value should be an object with at least one property ("method"):
+         *  <dl>
+         *      <dt>method</dt>
+         *          <dd>The method can be one of these: "auto", "fixed" and "stretch"</dd>
+         *      <dt>height</dt>
+         *          <dd>Must be set only if method's value is "fixed"</dd>
+         *  </dl>
+         *
+         * @attribute contentHeight
+         * @default auto
+         * @type Object
+         */
+        contentHeight: {
+            value: {
+                method: AUTO
+            },
+            validator: function( value ){
+                if( Lang.isObject( value ) ){
+                    if( value.method === AUTO ){
+                        return true;
+                    } else if( value.method === STRETCH ){
+                        return true;
+                    } else if( value.method === FIXED && Lang.isNumber( value.height ) &&
+                        value.height >= 0 ){
+                        return true;
+                    }
+                }
+
+                return false;
+            }
+        },
+
+        /**
+         * @description Get/Set always visible status of the item
+         *
+         * @attribute alwaysVisible
+         * @default false
+         * @type Boolean
+         */
+        alwaysVisible: {
+            value: false,
+            validator: Lang.isBoolean
+        },
+
+
+        /**
+         * @description Get/Set the animaton specific settings. By default there are no any settings.
+         * If set, they will overwrite Accordion's animation settings
+         *
+         * @attribute animation
+         * @default {}
+         * @type Object
+         */
+        animation: {
+            value: {},
+            validator: Lang.isObject
+        },
+
+        /**
+         * @description Provides client side string localization support.
+         *
+         * @attribute strings
+         * @default Object English messages
+         * @type Object
+         */
+        strings: {
+            value: {
+                title_always_visible_off: "Click to set always visible on",
+                title_always_visible_on: "Click to set always visible off",
+                title_iconexpanded_off: "Click to expand",
+                title_iconexpanded_on: "Click to collapse",
+                title_iconclose: "Click to close"
+            }
+        },
+
+        /**
+         * @description Boolean indicating that the item can be closed by user.
+         * If true, there will be placed close icon, otherwise not
+         *
+         * @attribute closable
+         * @default false
+         * @type Boolean
+         */
+        closable: {
+            value: false,
+            validator: Lang.isBoolean
+        }
+    },
+
+
+    /**
+     * Static Object hash used to capture existing markup for progressive
+     * enhancement.  Keys correspond to config attribute names and values
+     * are selectors used to inspect the srcNode for an existing node
+     * structure.
+     *
+     * @property HTML_PARSER
+     * @type Object
+     * @protected
+     * @static
+     */
+    HTML_PARSER : {
+
+        icon: HEADER_SELECTOR_SUB + C_ICON,
+
+        label: function( srcNode ){
+            var node, labelSelector, yuiConfig, label;
+
+            yuiConfig = this._parsedYUIConfig;
+
+            if( yuiConfig && Lang.isValue( yuiConfig.label ) ){
+                return yuiConfig.label;
+            }
+
+            label = srcNode.getAttribute( "data-label" );
+
+            if( label ){
+                return label;
+            }
+
+            labelSelector = HEADER_SELECTOR_SUB + C_LABEL;
+            node = srcNode.one( labelSelector );
+
+            return (node) ? node.get( INNER_HTML ) : null;
+        },
+
+        nodeLabel: HEADER_SELECTOR_SUB + C_LABEL,
+
+        iconsContainer: HEADER_SELECTOR_SUB + C_ICONSCONTAINER,
+
+        iconAlwaysVisible: HEADER_SELECTOR_SUB + C_ICONALWAYSVISIBLE,
+
+        iconExpanded: HEADER_SELECTOR_SUB + C_ICONEXPANDED,
+
+        iconClose: HEADER_SELECTOR_SUB + C_ICONCLOSE,
+
+        expanded: function( srcNode ){
+            var yuiConfig, expanded;
+
+            yuiConfig = this._parsedYUIConfig;
+
+            if( yuiConfig && Lang.isBoolean( yuiConfig.expanded ) ){
+                return yuiConfig.expanded;
+            }
+
+            expanded = srcNode.getAttribute( "data-expanded" );
+
+            if( expanded ) {
+                return REGEX_TRUE.test( expanded );
+            }
+
+            return srcNode.hasClass( C_EXPANDED );
+        },
+
+        alwaysVisible: function( srcNode ){
+            var yuiConfig, alwaysVisible;
+
+            yuiConfig = this._parsedYUIConfig;
+
+            if( yuiConfig && Lang.isBoolean( yuiConfig.alwaysVisible ) ){
+                alwaysVisible = yuiConfig.alwaysVisible;
+            } else {
+                alwaysVisible = srcNode.getAttribute( "data-alwaysvisible" );
+
+                if( alwaysVisible ) {
+                    alwaysVisible = REGEX_TRUE.test( alwaysVisible );
+                } else {
+                    alwaysVisible = srcNode.hasClass( C_ALWAYSVISIBLE );
+                }
+            }
+
+            if( alwaysVisible ){
+                this.set( "expanded", true, {
+                    internalCall: true
+                } );
+            }
+
+            return alwaysVisible;
+        },
+
+        closable: function( srcNode ){
+            var yuiConfig, closable;
+
+            yuiConfig = this._parsedYUIConfig;
+
+            if( yuiConfig && Lang.isBoolean( yuiConfig.closable ) ){
+                return yuiConfig.closable;
+            }
+
+            closable = srcNode.getAttribute( "data-closable" );
+
+            if( closable ) {
+                return REGEX_TRUE.test( closable );
+            }
+
+            return srcNode.hasClass( C_CLOSABLE );
+        },
+
+        contentHeight: function( srcNode ){
+            var contentHeightClass, classValue, height = 0, index, yuiConfig,
+                contentHeight;
+
+            yuiConfig = this._parsedYUIConfig;
+
+            if( yuiConfig && yuiConfig.contentHeight ){
+                return yuiConfig.contentHeight;
+            }
+
+            contentHeight = srcNode.getAttribute( "data-contentheight" );
+
+            if( REGEX_AUTO.test( contentHeight ) ){
+                return {
+                    method: AUTO
+                };
+            } else if( REGEX_STRETCH.test( contentHeight ) ){
+                return {
+                    method: STRETCH
+                };
+            } else if( REGEX_FIXED.test( contentHeight ) ){
+                height = this._extractFixedMethodValue( contentHeight );
+
+                return {
+                    method: FIXED,
+                    height: height
+                };
+            }
+
+
+            classValue = srcNode.get( CLASS_NAME );
+
+            contentHeightClass = C_CONTENTHEIGHT + '-';
+
+            index = classValue.indexOf( contentHeightClass, 0);
+
+            if( index >= 0 ){
+                index += contentHeightClass.length;
+
+                classValue = classValue.substring( index );
+
+                if( REGEX_AUTO.test( classValue ) ){
+                    return {
+                        method: AUTO
+                    };
+                } else if( REGEX_STRETCH.test( classValue ) ){
+                    return {
+                        method: STRETCH
+                    };
+                } else if( REGEX_FIXED.test( classValue )  ){
+                    height = this._extractFixedMethodValue( classValue );
+
+                    return {
+                        method: FIXED,
+                        height: height
+                    };
+                }
+            }
+
+            return null;
+        }
+    },
+
+
+     /**
+      * The template HTML strings for each of header components.
+      * e.g.
+      * <pre>
+      *    {
+      *       icon : '&lt;a class="yui3-accordion-item-icon"&gt;&lt;/a&gt;',
+      *       label: '&lt;a href="#" class="yui3-accordion-item-label"&gt;&lt;/a&gt;',
+      *       iconsContainer: '&lt;div class="yui3-accordion-item-icons"&gt;&lt;/div&gt;',
+      *       iconAlwaysVisible: '&lt;a href="#" class="yui3-accordion-item-iconalwaysvisible"&gt;&lt;/a&gt;',
+      *       iconExpanded: '&lt;a href="#" class="yui3-accordion-item-iconexpanded"&gt;&lt;/a&gt;',
+      *       iconClose: '&lt;a href="#" class="yui3-accordion-item-iconclose yui3-accordion-item-iconclose-hidden"&gt;&lt;/a&gt;'
+      *    }
+      * </pre>
+      * @property WidgetStdMod.TEMPLATES
+      * @type Object
+      */
+    TEMPLATES : {
+         icon : '<a class="' + C_ICON + '"></a>',
+         label: '<a href="#" class="' + C_LABEL + '"></a>',
+         iconsContainer: '<div class="' + C_ICONSCONTAINER + '"></div>',
+         iconExpanded: ['<a href="#" class="', C_ICONEXPANDED, ' ', C_ICONEXPANDED_OFF, '"></a>'].join(''),
+         iconAlwaysVisible: ['<a href="#" class="', C_ICONALWAYSVISIBLE, ' ',  C_ICONALWAYSVISIBLE_OFF, '"></a>'].join(''),
+         iconClose: ['<a href="#" class="', C_ICONCLOSE, ' ', C_ICONCLOSE_HIDDEN, '"></a>'].join('')
+    }
+
+});
+
+}());
+
+
+
+}, '@VERSION@' ,{optional:['dd-constrain', 'dd-proxy', 'dd-drop'], requires:['event', 'anim-easing', 'widget', 'widget-stdmod', 'json-parse']});

=== modified file 'utilities/lp-deps.py'
--- utilities/lp-deps.py	2010-08-10 09:32:38 +0000
+++ utilities/lp-deps.py	2011-02-15 11:27:17 +0000
@@ -26,6 +26,7 @@
     (os.path.join('lib', 'lp', 'registry', 'javascript'), 'registry'),
     (os.path.join('lib', 'lp', 'translations', 'javascript'), 'translations'),
     (os.path.join('lib', 'lp', 'soyuz', 'javascript'), 'soyuz'),
+    (os.path.join('lib', 'lp', 'contrib', 'javascript', 'yui3-gallery', 'gallery-accordion'), 'contrib'),
     ]
 ICING_ROOT = os.path.join(TOP, 'lib', 'canonical', 'launchpad', 'icing')
 ICING_BUILD = os.path.join(ICING_ROOT, 'build')
@@ -48,6 +49,10 @@
     # We don't want the tests to be included.  If we want to nest the files in
     # more folders though, this is where we change it.
     for filename in os.listdir(full_dir):
+        # Some third-party JavaScript libraries may include pre-built -min and
+        # -debug files.  Skip those.
+        if filename.endswith('-min.js') or filename.endswith('-debug.js'):
+            continue
         if filename.endswith('.js'):
             basename, nothing = filename.split('.js')
             min_filename = basename + '-min.js'