📄 accordionbehavior.js
字号:
/// </summary>
/// <param name="pane" type="Object" mayBeNull="false">
/// The pane is an object of the form {header, content, animation} corresponding to
/// that pane's header section, content section, and the animation used to open and
/// close its content section. The content element is a new div that has been created
/// to wrap the original div (so we can completely collapse it - even if it has
/// padding, margins, etc.) which is pointed to by a dynamic _original property. The
/// header element has a dynamic _index property indicating its position in the
/// Accordion's pane collection (used primarily by the headers' shared click
/// handler). Furthermore, the animation will either be an instance of
/// LengthAnimation or ParallelAnimation (in the latter case, it will have two
/// children which are a LengthAnimation and a FadeAnimation). There will be two
/// dynamic properties _length and _fade pointing to each of these children (to
/// easily set the length and fadeEffect properties). There is also a dynamic _ended
/// property which is an event handler to be fired when the animation is complete,
/// a dynamic _opening property to indicate whether the animation was opening or
/// closing the pane, and a dynamic _pane property to provide a reference to the pane
/// that was being animated.
/// </param>
/// <returns type="AjaxControlToolkit.Animation.Animation">
/// Animation for the desired section
/// </returns>
var animation = pane.animation;
if (!animation) {
// Determine whether or not to just use the length animation or build a
// composite effect with fading transitions (note that only the parent
// animation has the duration/fps specfied)
var length = null;
var fade = null;
if (!this._fadeTransitions) {
animation = length = new AjaxControlToolkit.Animation.LengthAnimation(pane.content, this._duration, this._framesPerSecond, "style", "height", 0, 0, "px");
} else {
length = new AjaxControlToolkit.Animation.LengthAnimation(null, null, null, "style", "height", 0, 0, "px");
fade = new AjaxControlToolkit.Animation.FadeAnimation(null, null, null, AjaxControlToolkit.Animation.FadeEffect.FadeOut, 0, 1, false);
animation = new AjaxControlToolkit.Animation.ParallelAnimation(pane.content, this._duration, this._framesPerSecond, [fade, length]);
}
// Create references to the length and fade animations so we can easily
// set the length and fadeEffect properties when animating without having
// to reach into the composite animation.
pane.animation = animation;
animation._length = length;
animation._fade = fade;
animation._pane = pane;
animation._opening = true;
animation._behavior = this;
animation._ended = Function.createDelegate(pane.animation, this._onAnimationFinished);
animation.add_ended(pane.animation._ended);
animation.initialize();
}
return animation;
},
_onAnimationFinished : function() {
/// <summary>
/// _onAnimationFinished is an event handler played after an animation (to open/
/// close an accordion pane) has completed. The delegate for this function should
/// have associated it with an animation (so the this references below are expecting
/// to reach expando fields declared on the animation). It invokes _endPaneChange
/// for the current pane.
/// </summary>
/// <returns />
this._behavior._endPaneChange(this._pane, this._opening);
},
_initializeLayout : function() {
/// <summary>
/// Setup the layout of the accordion (either when the behavior is created or when the
/// AutoSize mode is changed).
/// </summary>
/// <returns />
// Stop any animations that are still playing (i.e. that haven't finished opening
// or closing from changing previous panes) in case the user changed the AutoSize
// mode while an animation was playing.
for (var i = 0; i < this._panes.length; i++) {
var animation = this._panes[i].animation;
if (animation && animation.get_isPlaying()) {
animation.stop();
}
}
// Cache the initial size of the accordion
var accordion = this.get_element();
this._initialHeight = accordion.offsetHeight;
var style = accordion.style;
// Initialize the accordion itself
if (this._autoSize === AjaxControlToolkit.AutoSize.None) {
// Remove the window resizing handler
this._disposeResizeHandler();
// IE7 appears to have a rendering quirk where it will hide the
// accordion if we change height or overflow from the empty string
// to auto when it's contained in a fixed size div. We'll just not
// change the value if that's the case.
var isIE7 = (Sys.Browser.agent == Sys.Browser.InternetExplorer && Sys.Browser.version >= 7)
if (!isIE7 || (isIE7 && style.height && style.height.length > 0)) {
style.height = 'auto';
}
if (!isIE7 || (isIE7 && style.overflow && style.overflow.length > 0)) {
style.overflow = 'auto';
}
} else {
// Add the window's resizing handler
this._addResizeHandler();
style.height = accordion.offsetHeight + 'px';
style.overflow = 'hidden';
}
// Setup the layout attributes for the pane so that it will be in a proper opened
// or closed state
for (var i = 0; i < this._panes.length; i++) {
this._initializePane(i);
}
// Resize the selected pane so (depending on the AutoSize mode) it will fill the
// available remaining space after the headers have been laid out.
this._resizeSelectedPane();
},
_initializePane : function(index) {
/// <summary>
/// Setup the layout attributes for the pane so that it will be in a proper opened or
/// closed. This will be called when adding a new pane for the first time or when
/// changing the AutoSize mode.
/// </summary>
/// <param name="index" type="Number" integer="true">
/// Index of the pane to initialize
/// </param>
/// <returns />
var pane = this.get_Pane(index);
if (!pane) {
return;
}
var wrapper = pane.content;
var original = wrapper._original;
var opened = (index === this._selectedIndex);
wrapper.style.height = (opened || (this._autoSize === AjaxControlToolkit.AutoSize.Fill)) ? 'auto' : '0px';
wrapper.style.overflow = opened ? 'auto' : 'hidden';
wrapper.style.display = opened ? 'block' : 'none';
original.style.height = 'auto';
original.style.maxHeight = '';
original.style.overflow = opened ? 'auto' : 'hidden';
var opacity = (opened || !this._fadeTransitions) ? 1 : 0;
if (this._autoSize === AjaxControlToolkit.AutoSize.Fill) {
if ($common.getElementOpacity(original) != opacity) {
$common.setElementOpacity(original, opacity);
}
if ($common.getElementOpacity(wrapper) != 1) {
$common.setElementOpacity(wrapper, 1);
}
} else {
if ($common.getElementOpacity(wrapper) != opacity) {
$common.setElementOpacity(wrapper, opacity);
}
if ($common.getElementOpacity(original) != 1) {
$common.setElementOpacity(original, 1);
}
}
},
_addResizeHandler : function() {
/// <summary>
/// Attach the resize handler
/// </summary>
/// <returns />
/// <remarks>
/// This has been pulled out into its own method since we need to selectively wire
/// up the resize handler depending on the AutoSize mode.
/// </remarks>
if (!this._resizeHandler) {
this._resizeHandler = Function.createDelegate(this, this._resizeSelectedPane);
$addHandler(window, "resize", this._resizeHandler);
}
},
dispose : function() {
/// <summary>
/// Dispose of the AccordionBehavior
/// </summary>
/// <returns />
// Remove the window resizing handler
this._disposeResizeHandler();
// Wipe all the animations
this._disposeAnimations();
// Wipe the _panes collection. We're careful to wipe any expando properties
// which could cause memory leaks in IE6.
for (var i = this._panes.length - 1; i >= 0; i--) {
var pane = this._panes[i];
if (pane) {
if (pane.header) {
pane.header._index = null;
$removeHandler(pane.header, "click", this._headerClickHandler);
pane.header = null;
}
if (pane.content) {
pane.content._original = null;
pane.content = null;
}
this._panes[i] = null;
delete this._panes[i];
}
}
this._panes = null;
this._headerClickHandler = null;
AjaxControlToolkit.AccordionBehavior.callBaseMethod(this, 'dispose');
},
_disposeResizeHandler : function() {
/// <summary>
/// Remove the resize handler
/// </summary>
/// <returns />
/// <remarks>
/// This has been pulled out into its own method since we need to selectively wire
/// up the resize handler depending on the AutoSize mode.
/// </remarks>
if (this._resizeHandler) {
$removeHandler(window, "resize", this._resizeHandler);
this._resizeHandler = null;
}
},
_disposeAnimations : function() {
/// <summary>
/// Dispose all the animations. This method was pulled out of dispose so we could
/// allow the user to change the FadeTransitions property after the behavior was
/// already initialized. We can merge it back into dispose once we support generic
/// animations on the Accordion.
/// </summary>
/// <returns />
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -