📄 accordionbehavior.js
字号:
// (c) Copyright Microsoft Corporation.
// this source is subject to the Microsoft Permissive License.
// See http://www.microsoft.com/resources/sharedsource/licensingbasics/sharedsourcelicenses.mspx.
// All other rights reserved.
/// <reference name="MicrosoftAjax.debug.js" />
/// <reference name="MicrosoftAjaxTimer.debug.js" />
/// <reference name="MicrosoftAjaxWebForms.debug.js" />
/// <reference path="../ExtenderBase/BaseScripts.js" />
/// <reference path="../Common/Common.js" />
/// <reference path="../Compat/Timer/Timer.js" />
/// <reference path="../Animation/Animations.js" />
// Some of the techniques used in this.script were adapted with permission from Bertrand
// LeRoy's MIX06 Demo (http://weblogs.asp.net/bleroy/archive/2006/03/28/441343.aspx)
Type.registerNamespace('AjaxControlToolkit');
AjaxControlToolkit.AutoSize = function() {
/// <summary>
/// The AutoSize enumeration is used to specify how the AccordionBehavior limits
/// the growth of the accordion when panes are expanded and collapsed. It must
/// correspond to the AutoSize CLR enumeration in AutoSize.cs.
/// </summary>
/// <field name="None" type="Number" integer="true">
/// Allow the accordion to expand/collapse without restriction.
/// </field>
/// <field name="Fill" type="Number" integer="true">
/// Keep the accordion the same size as its specified size. If any
/// panes are larger or smaller than the available space, grow or shrink
/// them to the available space.
/// </field>
/// <field name="Limit" type="Number" integer="true">
/// Prevent the accordion from growing any larger than its specified size.
/// If the content of a pane is too large to fit, grow it to fill the
/// remaining space.
/// </field>
throw Error.invalidOperation();
}
AjaxControlToolkit.AutoSize.prototype = {
None : 0,
Fill : 1,
Limit : 2
}
AjaxControlToolkit.AutoSize.registerEnum("AjaxControlToolkit.AutoSize", false);
AjaxControlToolkit.AccordionSelectedIndexChangeEventArgs = function(oldIndex, selectedIndex) {
/// <summary>
/// Event arguments used to provide notification when an accordion's selected
/// index is changed. The same event argument type is used for both the
/// selectedIndexChanging event and the selectedIndexChanged events. If you set
/// the cancel property to true during the selectedIndexChanging event, the
/// accordion will not change panes. The cancel property has no effect during
/// the selectedIndexChanged event.
/// </summary>
/// <param name="oldIndex" type="Number" integer="true" mayBeNull="false">
/// Last selected index
/// </param>
/// <param name="selectedIndex" type="Number" integer="true" mayBeNull="false">
/// New selected index
/// </param>
AjaxControlToolkit.AccordionSelectedIndexChangeEventArgs.initializeBase(this);
this._oldIndex = oldIndex;
this._selectedIndex = selectedIndex;
}
AjaxControlToolkit.AccordionSelectedIndexChangeEventArgs.prototype = {
get_oldIndex : function() {
/// <value type="Number" integer="true" mayBeNull="false">
/// Last selected index
/// </value>
return this._oldIndex;
},
set_oldIndex : function(value) {
this._oldIndex = value;
},
get_selectedIndex : function() {
/// <value type="Number" integer="true" mayBeNull="false">
/// New selected index
/// </value>
return this._selectedIndex;
},
set_selectedIndex : function(value) {
this._selectedIndex = value;
}
}
AjaxControlToolkit.AccordionSelectedIndexChangeEventArgs.registerClass('AjaxControlToolkit.AccordionSelectedIndexChangeEventArgs', Sys.CancelEventArgs);
// The Accordion layout is slightly complex because we support several AutoSize modes
// that are applied to an element collection across multiple events and animations.
// To make the code a little easier to understand, we'll provide a brief description
// of the element format, the control flow for laying out the elements, and an informal
// "correctness proof" of our algorithm.
//
// The Accordion server control will create a collection of panes which it will dump
// out as a sequence of <div>s where the (2i)th <div> is the ith header and the
// (2i+1)th <div> is the ith content section:
//
// <div id="Accordion" ... >
// ...
// <div id="2i" ... >Ith Header</div>
// <div id="2i+1" ... >Ith Content</div>
// ...
// </div>
//
// Because the <div>s may have padding, borders, or margins (we'll refer to these
// additional pixels as the "gutter"), we cannot collapse them all the way during
// animation (i.e. myDiv.style.height = '0px' will still show myDiv's padding,
// borders, and margins). To work around this, we wrap all of the content section
// <div>s in wrappers that have no "gutter" style to end up with a tree of DOM
// elements that looks like:
//
// <div id="Accordion" ... >
// ...
// <div id="2i" ... >Ith Header</div>
// <div id="2i+1 Wrapper">
// <div id="2i+1 Original" ... >Ith Content</div>
// </div>
// ...
// </div>
//
// We automatically wrap the content section when it is passed to the addPane
// function. From here on out, we'll refer to the behavior's target element (the
// root <div>) as the accordion, the dynamically created <div> as a wrapper, and
// the content section <div> as the original <div>.
//
// The primary purpose of the accordion is to expand and collapse its panes so that
// at most only one pane is open at a time. We want to do this using animations for
// a polished effect, but we must also respect the AutoSize modes (where None allows
// the accordion to grow unrestrained, Limit provides a maximum height for the
// accordion, and Fill forces the accordion to always be the specified size). Given
// the structure of an accordion, original <div>s, and wrapper <div>s, we accomplish
// the layout requirements using the following CSS properties:
// Accordion root <div>:
// height
// overflow
// Wrapper <div>:
// height
// opacity
// overflow
// display
// Original content section <div>:
// height
// maxHeight
// overflow
//
// The large table below precisely defines the expected value of the properties at
// any given point in time. Each of the columns 1 through 8 represents a possible
// state of the accordion. Most of the time the accordion will be in states 1 and 5
// until the user clicks a header section and triggers a series of changes. The rows
// of the table represent the properties of elements in a particular AutoSize mode.
// For example, a closed wrapper <div> with the Limit AutoSize mode should have a value
// of '0px' for its height. Most of the properties in the the table are literal values
// like 'auto', 'hidden', '0px', etc. The value Current for a property is used to
// indicate that a height set to 'auto' should be assigned its explicit value (i.e.
// element.offsetHeight) so that it will not be able to grow/shrink during an animation.
// The value Remaining for a height property refers specifically to the available space
// remaining after all the header sections of the accordion have been taken into
// consideration (this is used specifically for setting the size of the open content
// section when working in Limit or Fill AutoSize modes). It's important to note that
// the Remaining value, retrieved by calling _getRemainingHeight, is slightly different
// for a wrapper <div> compared to a an original <div> because it must also consider the
// "gutter" offsets for an original <div>. Finally, the animations (columns 3 and 7)
// are represented as transformations that take one property value to another when played.
//
// ------------------------+---------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------+
// | +--- Closing an open pane | Opening a closed pane <--+ |
// AutoSize Mode | | 1. 2. 3. 4. | 5. 6. 7. 8. | |
// Element | +--> Opened -> Before Closing -> Closing -> After Closing --+-> Closed -> Before Opening -> Opening -> After Opening ---+ |
// Property | Pane Animation Animation Animation | Pane Animation Animation Animation |
// ------------------------+---------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------+
// None: | | |
// Accordion: | | |
// height: | 'auto' . . . | 'auto' . . . |
// overflow: | 'auto' . . 'auto' | 'auto' . . 'auto' |
// Wrapper: | | |
// height: | 'auto' . Current -> '0px' . | '0px' . '0px' -> Current 'auto' |
// opacity: | 1.0 . 1.0 -> 0.0 . | 0.0 . 0.0 -> 1.0 . |
// overflow: | 'auto' 'hidden' . . | 'hidden' . . 'auto' |
// display: | 'block' . . 'none' | 'none' 'block' . . |
// Original: | | |
// height: | 'auto' . . . | 'auto' . . . |
// maxHeight: | '' . . . | '' . . . |
// overflow: | 'auto' 'hidden' . . | 'hidden' . . 'auto' |
// ------------------------+---------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------+
// Limit: | | |
// Accordion: | | |
// height: | Current . . . | Current . . . |
// overflow: | 'hidden' . . . | 'hidden' . . . |
// Wrapper: | | |
// height: | 'auto' Remaining Remaining -> '0px' . | '0px' . '0px' -> Remaining 'auto' |
// opacity: | 1.0 . 1.0 -> 0.0 . | 0.0 . 0.0 -> 1.0 . |
// overflow: | 'auto' 'hidden' . . | 'hidden' . . 'auto' |
// display: | 'block' . . 'none' | 'none' 'block' . . |
// Original: | | |
// height: | 'auto' . . . | 'auto' . . . |
// maxHeight: | Remaining 'auto' . . | 'auto' . . Remaining |
// overflow: | 'auto' 'hidden' . . | 'hidden' . . 'auto' |
// ------------------------+---------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------+
// Fill: | | |
// Accordion: | | |
// height: | Current . . . | Current . . . |
// overflow: | 'hidden' . . . | 'hidden' . . . |
// Wrapper: | | |
// height: | 'auto' . . . | 'auto' . . . |
// opacity: | 1.0 . 1.0 -> 0.0 . | 0.0 . 0.0 -> 1.0 . |
// overflow: | 'auto' 'hidden' . . | 'hidden' . . 'auto' |
// display: | 'block' . . 'none' | 'none' 'block' . . |
// Original: | | |
// height: | Remaining . Remaining -> '0px' . | '0px' . '0px' -> Remaining . |
// maxHeight: | '' . . . | '' . . . |
// overflow: | 'auto' 'hidden' . . | 'hidden' . . 'auto' |
// ------------------------+---------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------+
//
// Although this table is rather large, it's extremely useful because it allows
// us to present an informal argument for the correctness of our layout algorithm.
// It's easy to verify that if an accordion starts in state 1 and proceeds through
// steps 2, 3, and 4 when closing, it will arrive properly in state 5. Similarly
// an accordion starting in state 5 that is opened will progress through steps 6, 7,
// and 8 to arrive back at step 1. Clearly then any accordion starting in a valid
// state of 1 or 5 can be opened or closed repeatedly and return to a proper state.
// It's also worth pointing out that this layout algorithm can operate on one or two
// panes at a time (i.e. if all panes were closed and one were clicked, it would
// open a single pane... but if one pane were already open and another were clicked,
// it would have to close one while opening the other).
//
// States 1 and 5 from the above table are implemented in the _intiailizeLayout and
// _initializePane functions. States 2 and 6 are handled by the _startPaneChange
// function while states 4 and 8 are handled by the _endPaneChange function. Finally,
// states 3 and 7 are intialized and played in the _changePanes function.
AjaxControlToolkit.AccordionBehavior = function(element) {
/// <summary>
/// The AccordionBehavior is used to turn properly structured XHTML into an
/// Accordion with panes that can expand one at a time.
/// </summary>
/// <param name="element" type="Sys.UI.DomElement" domElement="true">
/// The DOM element the behavior is associated with. It should contain an
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -