mirror of
https://github.com/jquery/jquery-ui.git
synced 2024-11-21 11:04:24 +00:00
Accordion: Rewrote the animation code. Fixes #4178 - Accordion animation a bit jumpy in some browsers. Fixes #7371 - Accordion: Incorrect size when zoomed.
This commit is contained in:
parent
f262a531fa
commit
3d9f6b5bc7
@ -1,7 +1,7 @@
|
||||
commonWidgetTests( "accordion", {
|
||||
defaults: {
|
||||
active: 0,
|
||||
animated: "slide",
|
||||
animate: {},
|
||||
collapsible: false,
|
||||
disabled: false,
|
||||
event: "click",
|
||||
|
@ -1,6 +1,7 @@
|
||||
commonWidgetTests( "accordion", {
|
||||
defaults: {
|
||||
active: 0,
|
||||
animate: null,
|
||||
animated: "slide",
|
||||
autoHeight: true,
|
||||
clearStyle: false,
|
||||
|
@ -18,13 +18,13 @@ function accordion_equalHeights( accordion, min, max ) {
|
||||
}
|
||||
|
||||
function accordion_setupTeardown() {
|
||||
var animated = $.ui.accordion.prototype.options.animated;
|
||||
var animate = $.ui.accordion.prototype.options.animate;
|
||||
return {
|
||||
setup: function() {
|
||||
$.ui.accordion.prototype.options.animated = false;
|
||||
$.ui.accordion.prototype.options.animate = false;
|
||||
},
|
||||
teardown: function() {
|
||||
$.ui.accordion.prototype.options.animated = animated;
|
||||
$.ui.accordion.prototype.options.animate = animate;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
265
ui/jquery.ui.accordion.js
vendored
265
ui/jquery.ui.accordion.js
vendored
@ -17,7 +17,7 @@ $.widget( "ui.accordion", {
|
||||
version: "@VERSION",
|
||||
options: {
|
||||
active: 0,
|
||||
animated: "slide",
|
||||
animate: {},
|
||||
collapsible: false,
|
||||
event: "click",
|
||||
header: "> li > :first-child,> :not(li):even",
|
||||
@ -35,7 +35,7 @@ $.widget( "ui.accordion", {
|
||||
_create: function() {
|
||||
var options = this.options;
|
||||
|
||||
this.lastToggle = {};
|
||||
this.prevShow = this.prevHide = $();
|
||||
this.element.addClass( "ui-accordion ui-widget ui-helper-reset" );
|
||||
|
||||
this.headers = this.element.find( options.header )
|
||||
@ -62,6 +62,7 @@ $.widget( "ui.accordion", {
|
||||
this.active.next().addClass( "ui-accordion-content-active" );
|
||||
|
||||
this._createIcons();
|
||||
this.originalHeight = this.element[0].style.height;
|
||||
this.refresh();
|
||||
|
||||
// ARIA
|
||||
@ -156,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", "" );
|
||||
}
|
||||
},
|
||||
@ -229,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
|
||||
@ -267,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() {
|
||||
@ -276,7 +278,9 @@ $.widget( "ui.accordion", {
|
||||
.height( maxHeight );
|
||||
}
|
||||
|
||||
return this;
|
||||
if ( heightStyle !== "content" ) {
|
||||
this.element.height( this.element.height() );
|
||||
}
|
||||
},
|
||||
|
||||
_activate: function( index ) {
|
||||
@ -361,41 +365,20 @@ $.widget( "ui.accordion", {
|
||||
},
|
||||
|
||||
_toggle: function( data ) {
|
||||
var that = this,
|
||||
options = this.options,
|
||||
toShow = data.newContent,
|
||||
toHide = data.oldContent;
|
||||
var toShow = data.newContent,
|
||||
toHide = this.prevShow.length ? this.prevShow : data.oldContent;
|
||||
|
||||
function complete() {
|
||||
that._completed( data );
|
||||
}
|
||||
// handle activating a panel during the animation for another activation
|
||||
this.prevShow.add( this.prevHide ).stop( true, true );
|
||||
this.prevShow = toShow;
|
||||
this.prevHide = toHide;
|
||||
|
||||
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";
|
||||
}
|
||||
|
||||
animations[ animation ]({
|
||||
widget: this,
|
||||
toShow: toShow,
|
||||
toHide: toHide,
|
||||
prevShow: this.lastToggle.toShow,
|
||||
prevHide: this.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
|
||||
@ -415,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)
|
||||
@ -437,123 +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" ),
|
||||
showOverflowX = options.toHide.css( "overflowX" ),
|
||||
showOverflowY = options.toHide.css( "overflowY" ),
|
||||
hideOverflow = options.toHide.css( "overflow" ),
|
||||
hideOverflowX = options.toHide.css( "overflowX" ),
|
||||
hideOverflowY = options.toHide.css( "overflowY" ),
|
||||
percentDone = 0,
|
||||
$.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 = {},
|
||||
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,
|
||||
overflowX: showOverflowX,
|
||||
overflowY: showOverflowY
|
||||
});
|
||||
options.toHide.css({
|
||||
overflow: hideOverflow,
|
||||
overflowX: hideOverflowX,
|
||||
overflowY: hideOverflowY
|
||||
});
|
||||
options.complete();
|
||||
}
|
||||
});
|
||||
},
|
||||
bounceslide: function( options ) {
|
||||
this.slide( options, {
|
||||
easing: options.down ? "easeOutBounce" : "swing",
|
||||
duration: options.down ? 1000 : 200
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
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" } );
|
||||
|
||||
|
||||
|
||||
@ -697,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 );
|
||||
|
Loading…
Reference in New Issue
Block a user