diff options
author | Jörn Zaefferer <joern.zaefferer@gmail.com> | 2012-02-21 17:48:55 +0100 |
---|---|---|
committer | Jörn Zaefferer <joern.zaefferer@gmail.com> | 2012-02-21 17:48:55 +0100 |
commit | 6528b48b4762b0ddf3697580444fdf9f34e7eca9 (patch) | |
tree | 46e0e17d0b8356d0e9d142e9a00bdf242d5bbf2c /ui/jquery.ui.accordion.js | |
parent | 98d72c7f6d0f1c535774d4db85556626e016603c (diff) | |
parent | d32a9e81ecb8a201c1737c3226a99c33ced451af (diff) | |
download | jquery-ui-6528b48b4762b0ddf3697580444fdf9f34e7eca9.tar.gz jquery-ui-6528b48b4762b0ddf3697580444fdf9f34e7eca9.zip |
Merge branch 'master' into selectmenu
Diffstat (limited to 'ui/jquery.ui.accordion.js')
-rw-r--r-- | ui/jquery.ui.accordion.js | 330 |
1 files changed, 147 insertions, 183 deletions
diff --git a/ui/jquery.ui.accordion.js b/ui/jquery.ui.accordion.js index 127099d59..8731c17ca 100644 --- a/ui/jquery.ui.accordion.js +++ b/ui/jquery.ui.accordion.js @@ -13,12 +13,11 @@ */ (function( $, undefined ) { -// TODO: use ui-accordion-header-active class and fix styling $.widget( "ui.accordion", { version: "@VERSION", options: { active: 0, - animated: "slide", + animate: {}, collapsible: false, event: "click", header: "> li > :first-child,> :not(li):even", @@ -34,19 +33,18 @@ $.widget( "ui.accordion", { }, _create: function() { - var self = this, - options = self.options; + var options = this.options; - self.lastToggle = {}; - self.element.addClass( "ui-accordion ui-widget ui-helper-reset" ); + this.prevShow = this.prevHide = $(); + this.element.addClass( "ui-accordion ui-widget ui-helper-reset" ); - self.headers = self.element.find( options.header ) + this.headers = this.element.find( options.header ) .addClass( "ui-accordion-header ui-helper-reset ui-state-default ui-corner-all" ); - self._hoverable( self.headers ); - self._focusable( self.headers ); - self.headers.find( ":first-child" ).addClass( "ui-accordion-heading" ); + this._hoverable( this.headers ); + this._focusable( this.headers ); + this.headers.find( ":first-child" ).addClass( "ui-accordion-heading" ); - self.headers.next() + this.headers.next() .addClass( "ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom" ); // don't allow collapsible: false and active: false @@ -57,26 +55,27 @@ $.widget( "ui.accordion", { if ( options.active < 0 ) { options.active += this.headers.length; } - self.active = self._findActive( options.active ) - .addClass( "ui-state-default ui-state-active" ) + this.active = this._findActive( options.active ) + .addClass( "ui-accordion-header-active ui-state-active" ) .toggleClass( "ui-corner-all" ) .toggleClass( "ui-corner-top" ); - self.active.next().addClass( "ui-accordion-content-active" ); + this.active.next().addClass( "ui-accordion-content-active" ); - self._createIcons(); - self.refresh(); + this._createIcons(); + this.originalHeight = this.element[0].style.height; + this.refresh(); // ARIA - self.element.attr( "role", "tablist" ); + this.element.attr( "role", "tablist" ); - self.headers + this.headers .attr( "role", "tab" ) - .bind( "keydown.accordion", $.proxy( self, "_keydown" ) ) + .bind( "keydown.accordion", $.proxy( this, "_keydown" ) ) .next() .attr( "role", "tabpanel" ); - self.headers - .not( self.active ) + this.headers + .not( this.active ) .attr({ "aria-expanded": "false", "aria-selected": "false", @@ -86,10 +85,10 @@ $.widget( "ui.accordion", { .hide(); // make sure at least one header is in the tab order - if ( !self.active.length ) { - self.headers.eq( 0 ).attr( "tabIndex", 0 ); + if ( !this.active.length ) { + this.headers.eq( 0 ).attr( "tabIndex", 0 ); } else { - self.active.attr({ + this.active.attr({ "aria-expanded": "true", "aria-selected": "true", tabIndex: 0 @@ -98,12 +97,19 @@ $.widget( "ui.accordion", { // only need links in tab order for Safari if ( !$.browser.safari ) { - self.headers.find( "a" ).attr( "tabIndex", -1 ); + this.headers.find( "a" ).attr( "tabIndex", -1 ); } this._setupEvents( options.event ); }, + _getCreateEventData: function() { + return { + header: this.active, + content: !this.active.length ? $() : this.active.next() + }; + }, + _createIcons: function() { var icons = this.options.icons; if ( icons ) { @@ -113,13 +119,15 @@ $.widget( "ui.accordion", { this.active.children( ".ui-accordion-header-icon" ) .removeClass( icons.header ) .addClass( icons.activeHeader ); - this.element.addClass( "ui-accordion-icons" ); + this.headers.addClass( "ui-accordion-icons" ); } }, _destroyIcons: function() { - this.headers.children( ".ui-accordion-header-icon" ).remove(); - this.element.removeClass( "ui-accordion-icons" ); + this.headers + .removeClass( "ui-accordion-icons" ) + .children( ".ui-accordion-header-icon" ) + .remove(); }, _destroy: function() { @@ -131,7 +139,7 @@ $.widget( "ui.accordion", { // clean up headers this.headers .unbind( ".accordion" ) - .removeClass( "ui-accordion-header ui-accordion-disabled ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top" ) + .removeClass( "ui-accordion-header ui-accordion-header-active ui-accordion-disabled ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top" ) .removeAttr( "role" ) .removeAttr( "aria-expanded" ) .removeAttr( "aria-selected" ) @@ -149,6 +157,7 @@ $.widget( "ui.accordion", { .removeAttr( "role" ) .removeClass( "ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-accordion-disabled ui-state-disabled" ); if ( this.options.heightStyle !== "content" ) { + this.element.css( "height", this.originalHeight ); contents.css( "height", "" ); } }, @@ -222,12 +231,12 @@ $.widget( "ui.accordion", { }, refresh: function() { - var options = this.options, + var heightStyle = this.options.heightStyle, parent = this.element.parent(), maxHeight, overflow; - if ( options.heightStyle === "fill" ) { + if ( heightStyle === "fill" ) { // IE 6 treats height like minHeight, so we need to turn off overflow // in order to get a reliable height // we use the minHeight support test because we assume that only @@ -260,7 +269,7 @@ $.widget( "ui.accordion", { $( this ).innerHeight() + $( this ).height() ) ); }) .css( "overflow", "auto" ); - } else if ( options.heightStyle === "auto" ) { + } else if ( heightStyle === "auto" ) { maxHeight = 0; this.headers.next() .each(function() { @@ -269,7 +278,9 @@ $.widget( "ui.accordion", { .height( maxHeight ); } - return this; + if ( heightStyle !== "content" ) { + this.element.height( this.element.height() ); + } }, _activate: function( index ) { @@ -335,15 +346,15 @@ $.widget( "ui.accordion", { // switch classes active - .removeClass( "ui-state-active ui-corner-top" ) - .addClass( "ui-state-default ui-corner-all" ) + .removeClass( "ui-accordion-header-active ui-state-active ui-corner-top" ) + .addClass( "ui-corner-all" ) .children( ".ui-accordion-header-icon" ) .removeClass( options.icons.activeHeader ) .addClass( options.icons.header ); if ( !clickedIsActive ) { clicked - .removeClass( "ui-state-default ui-corner-all" ) - .addClass( "ui-state-active ui-corner-top" ) + .removeClass( "ui-corner-all" ) + .addClass( "ui-accordion-header-active ui-state-active ui-corner-top" ) .children( ".ui-accordion-header-icon" ) .removeClass( options.icons.header ) .addClass( options.icons.activeHeader ); @@ -354,41 +365,20 @@ $.widget( "ui.accordion", { }, _toggle: function( data ) { - var self = this, - options = self.options, - toShow = data.newContent, - toHide = data.oldContent; - - function complete() { - self._completed( data ); - } + var toShow = data.newContent, + toHide = this.prevShow.length ? this.prevShow : data.oldContent; - if ( options.animated ) { - var animations = $.ui.accordion.animations, - animation = options.animated, - additional; - - if ( !animations[ animation ] ) { - additional = { - easing: $.easing[ animation ] ? animation : "slide", - duration: 700 - }; - animation = "slide"; - } + // handle activating a panel during the animation for another activation + this.prevShow.add( this.prevHide ).stop( true, true ); + this.prevShow = toShow; + this.prevHide = toHide; - animations[ animation ]({ - widget: self, - toShow: toShow, - toHide: toHide, - prevShow: self.lastToggle.toShow, - prevHide: self.lastToggle.toHide, - complete: complete, - down: toShow.length && ( !toHide.length || ( toShow.index() < toHide.index() ) ) - }, additional ); + if ( this.options.animate ) { + this._animate( toShow, toHide, data ); } else { toHide.hide(); toShow.show(); - complete(); + this._completed( data ); } // TODO assert that the blur and focus triggers are really necessary, remove otherwise @@ -408,17 +398,51 @@ $.widget( "ui.accordion", { .focus(); }, + _animate: function( toShow, toHide, data ) { + var total, easing, duration, + that = this, + down = toShow.length && + ( !toHide.length || ( toShow.index() < toHide.index() ) ), + animate = this.options.animate || {}, + options = down && animate.down || animate, + complete = function() { + toShow.removeData( "accordionHeight" ); + that._completed( data ); + }; + + if ( typeof options === "number" ) { + duration = options; + } + if ( typeof options === "string" ) { + easing = options; + } + // fall back from options to animation in case of partial down settings + easing = easing || options.easing || animate.easing; + duration = duration || options.duration || animate.duration; + + if ( !toHide.size() ) { + return toShow.animate( showProps, duration, easing, complete ); + } + if ( !toShow.size() ) { + return toHide.animate( hideProps, duration, easing, complete ); + } + + total = toShow.show().outerHeight(); + toHide.animate( hideProps, duration, easing ); + toShow + .hide() + .data( "accordionHeight", { + total: total, + toHide: toHide + }) + .animate( this.options.heightStyle === "content" ? showProps : showPropsAdjust, + duration, easing, complete ); + }, + _completed: function( data ) { var toShow = data.newContent, toHide = data.oldContent; - if ( this.options.heightStyle === "content" ) { - toShow.add( toHide ).css({ - height: "", - overflow: "" - }); - } - // other classes are removed before the animation; this one needs to stay until completed toHide.removeClass( "ui-accordion-content-active" ); // Work around for rendering bug in IE (#5421) @@ -430,113 +454,19 @@ $.widget( "ui.accordion", { } }); -$.extend( $.ui.accordion, { - animations: { - slide: function( options, additions ) { - if ( options.prevShow || options.prevHide ) { - options.prevHide.stop( true, true ); - options.toHide = options.prevShow; - } - - var showOverflow = options.toShow.css( "overflow" ), - hideOverflow = options.toHide.css( "overflow" ), - percentDone = 0, - showProps = {}, - hideProps = {}, - fxAttrs = [ "height", "paddingTop", "paddingBottom" ], - originalWidth; - options = $.extend({ - easing: "swing", - duration: 300 - }, options, additions ); - - options.widget.lastToggle = options; - - if ( !options.toHide.size() ) { - originalWidth = options.toShow[0].style.width; - options.toShow - .show() - .width( options.toShow.width() ) - .hide() - .animate({ - height: "show", - paddingTop: "show", - paddingBottom: "show" - }, { - duration: options.duration, - easing: options.easing, - complete: function() { - options.toShow.width( originalWidth ); - options.complete(); - } - }); - return; - } - if ( !options.toShow.size() ) { - options.toHide.animate({ - height: "hide", - paddingTop: "hide", - paddingBottom: "hide" - }, options ); - return; - } - // fix width before calculating height of hidden element - var s = options.toShow; - originalWidth = s[0].style.width; - s.width( s.parent().width() - - parseFloat( s.css( "paddingLeft" ) ) - - parseFloat( s.css( "paddingRight" ) ) - - ( parseFloat( s.css( "borderLeftWidth" ) ) || 0 ) - - ( parseFloat( s.css( "borderRightWidth" ) ) || 0 ) ); - - $.each( fxAttrs, function( i, prop ) { - hideProps[ prop ] = "hide"; - - var parts = ( "" + $.css( options.toShow[0], prop ) ).match( /^([\d+-.]+)(.*)$/ ), - // work around bug when a panel has no height - #7335 - propVal = prop === "height" && parts[ 1 ] === "0" ? 1 : parts[ 1 ]; - showProps[ prop ] = { - value: propVal, - unit: parts[ 2 ] || "px" - }; - }); - options.toShow.css({ height: 0, overflow: "hidden" }).show(); - options.toHide - .filter( ":hidden" ) - .each( options.complete ) - .end() - .filter( ":visible" ) - .animate( hideProps, { - step: function( now, settings ) { - if ( settings.prop == "height" || settings.prop == "paddingTop" || settings.prop == "paddingBottom" ) { - percentDone = ( settings.end - settings.start === 0 ) ? 0 : - ( settings.now - settings.start ) / ( settings.end - settings.start ); - } - - options.toShow[ 0 ].style[ settings.prop ] = - ( percentDone * showProps[ settings.prop ].value ) - + showProps[ settings.prop ].unit; - }, - duration: options.duration, - easing: options.easing, - complete: function() { - options.toShow.css({ - width: originalWidth, - overflow: showOverflow - }); - options.toHide.css( "overflow", hideOverflow ); - options.complete(); - } - }); - }, - bounceslide: function( options ) { - this.slide( options, { - easing: options.down ? "easeOutBounce" : "swing", - duration: options.down ? 1000 : 200 - }); - } - } -}); +$.fx.step.accordionHeight = function( fx ) { + var elem = $( fx.elem ), + data = elem.data( "accordionHeight" ); + elem.height( data.total - elem.outerHeight() - data.toHide.outerHeight() + elem.height() ); +}; +var hideProps = {}, + showProps = {}, + showPropsAdjust = {}; +hideProps.height = hideProps.paddingTop = hideProps.paddingBottom = + hideProps.borderTopWidth = hideProps.borderBottomWidth = "hide"; +showProps.height = showProps.paddingTop = showProps.paddingBottom = + showProps.borderTopWidth = showProps.borderBottomWidth = "show"; +$.extend( showPropsAdjust, showProps, { accordionHeight: "show" } ); @@ -554,7 +484,7 @@ if ( $.uiBackCompat !== false ) { var _create = prototype._create; prototype._create = function() { if ( this.options.navigation ) { - var self = this, + var that = this, headers = this.element.find( this.options.header ), content = headers.next(), current = headers.add( content ) @@ -564,7 +494,7 @@ if ( $.uiBackCompat !== false ) { if ( current ) { headers.add( content ).each( function( index ) { if ( $.contains( this, current ) ) { - self.options.active = Math.floor( index / 2 ); + that.options.active = Math.floor( index / 2 ); return false; } }); @@ -680,6 +610,40 @@ if ( $.uiBackCompat !== false ) { return ret; }; }( jQuery, jQuery.ui.accordion.prototype ) ); + + // animated option + // NOTE: this only provides support for "slide", "bounceslide", and easings + // not the full $.ui.accordion.animations API + (function( $, prototype ) { + $.extend( prototype.options, { + animate: null, + animated: "slide" + }); + + var _create = prototype._create; + prototype._create = function() { + var options = this.options; + if ( options.animate === null ) { + if ( !options.animated ) { + options.animate = false; + } else if ( options.animated === "slide" ) { + options.animate = 300; + } else if ( options.animated === "bounceslide" ) { + options.animate = { + duration: 200, + down: { + easing: "easeOutBounce", + duration: 1000 + } + } + } else { + options.animate = options.animated; + } + } + + _create.call( this ); + }; + }( jQuery, jQuery.ui.accordion.prototype ) ); } })( jQuery ); |