﻿// (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.

// 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 height.  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 height.
    /// 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.AccordionBehavior = function(element) {
    /// <summary>
    /// The AccordionBehavior is used to turn properly structured HTML into an Accordion.
    /// </summary>
    /// <param name="element" type="Sys.UI.DomElement" domElement="true">
    /// The DOM element the behavior is associated with
    /// </param>
    AjaxControlToolkit.AccordionBehavior.initializeBase(this, [element]);
    
     // The this._selectedIndex variable is used to track the currently visible content
    // pane.  It is persisted via ClientState so that it can be restored on PostBack.
    this._selectedIndex = 0;  
    
    // The following variables are associative arrays - for each AccordionPane they
    // track its header element, its content pane element, and the animations
    // used to open and close its content pane when the header element is clicked.
    // We actually have three arrays for the animations - the main is a CompositeAnimation
    // which is composed of a LengthAnimation and FadeAnimation, which the other arrays
    // are used to manage.  Keeping seperate arrays makes the other animations easier to
    // retrieve when changining their values to either open or close.  It's worth noting
    // that if this._fadeTransitions is false, then the this._animations array contains the length
    // animations and the other animation arrays are unused.
    this._headers =  [];
    this._panes =  [];
    this._animations =  [];
    this._lengthAnimations =  [];
    this._fadeAnimations =  [];
    
    // The this._fadeTransitions flag determines whether or not we enable the fancy fade
    // animation effect on top of the opening and closing effect
    this._fadeTransitions = false;
    
    /// Determine how growth of the Accordion will be controlled.  If it is set to
    /// None, then the Accordion can grow as large or as small as necessary.  If it is
    /// set to Limit, then the Accordion will always be less than or equal to its
    /// Height.  If it is set to Fill then it will always be equal to its Height.
    this._autoSize =  AjaxControlToolkit.AutoSize.None;
    
    // The available height represents the amount of space an expanded pane can fill
    // after all of the headers have been taken into account.  We use this.for auto
    // sizing.
    this._availableHeight =  Number.MAX_VALUE;
    
    // The amount of vertical space required by all of the headers (including their
    // margins).  this.is used to determine how much of the total space is available
    // for expanding one of the content panes.
    this._headerHeight =  0;
    
    // Minimum height allowed to a pane before we change from scrolling the contents
    // of a pane and change to scrolling the contents of the entire accordion
    this._minimimPaneHeight =  20;
    
    // Hack: We use this.flag to prevent the resize handler from firing once when we
    // know that our animations will cause the page to grow in size
    this._skipNextResize =  false;
    
    // The this._duration represents the transition duration of the animations in seconds
    this._duration =  0.25;
    
    // The this._framesPerSecond is used to tune the animation to perform well depending on
    // the the type of effect being used an the number of accordion panes, etc.
    this._framesPerSecond =  30;

    // The this._clickHandler is a reference to the event handler that all the header
    // elements of our panes will be wired up to
    this._clickHandler =  null;
    
    // The this._resizeHandler is a reference to the global event handler used to patch
    // up the accordion when the window is resized
    this._resizeHandler =  null;   
    
}
AjaxControlToolkit.AccordionBehavior.prototype = {
    initialize : function() {
        /// <summary>
        /// The initialize function is responsible for getting the selected index from
        /// the ClientState mechanism and walking the children of the behavior's target
        /// to find all of the accordion's child panes.  It builds up collections of the
        /// headers and the content panes as well as wires up the headers to an event
        /// handler.  Finally, all the content panes except the selected one are hidden.
        /// </summary>
        /// <returns />
        AjaxControlToolkit.AccordionBehavior.callBaseMethod(this, 'initialize');
        
        // Create the OnClick handler
        this._clickHandler = Function.createDelegate(this, this._onHeaderClick);
        
        // Get the selected index from ClientState
        var state = this.get_ClientState();
        if (state !== null && state !== '') {
            var index = parseInt(state);
            if (index != this._selectedIndex) {
                this._selectedIndex = index;
                this.raisePropertyChanged('SelectedIndex');
            }
        }
        
        // Walk the children of the target control to obtain the accordion's
        // child panes.  We are expecting a hierarchy of container elements,
        // such as divs and spans, that looks like this.
        //   <div id="accordion">           this.control.element
        //     <span id="pane1">            this.control.element.childNodes[i]
        //       <div id="header1">         this.control.element.childNodes[i].childNodes[0]
        //         <div> ... </div>         this.control.element.childNodes[i].childNodes[0].childNodes[0]
        //       </div>
        //       <div id="content1">        this.control.element.childNodes[i].childNodes[1]
        //         <div> ... </div>         this.control.element.childNodes[i].childNodes[1].childNodes[0]
        //       </div>
        //     </span>
        //     .
        //     .
        //     .
        //   </div>
        // We'll collect the headers and content panes into their respective arrays
        // and wire up event handlers to the header.  We also add a paneIndex value
        // to the header which functions as an event argument to determine which pane
        // should be selected when any of the headers was clicked.
        var e = this.get_element();
        var children = e.childNodes;
        for (var i = 0, p = 0; i < children.length; i++) {
            var child = children[i];
            if (child.nodeType == 1) {
                // Get the accordion pane
                var grandChildren = child.childNodes;
                if (grandChildren.length == 2) {
                    // Get the pane's header
                    var header = this._getElement(grandChildren, 0);
                    Array.add(this._headers, header);
                    header.paneIndex = p++;
                    $addHandler(header, "click", this._clickHandler);
                    
                    // Get the pane's content
                    Array.add(this._panes, this._getElement(grandChildren, 1));
                }
            }
        }
        
        // Create the resize handler
        this._resizeHandler = Function.createDelegate(this, this._onResize);
        $addHandler(window, "resize", this._resizeHandler);
                
        // Hide all of the content panes except for the selected pane
        for (var i = this._panes.length - 1; i >= 0; i--) {
            var pane = this._panes[i];
            pane.style.overflow = 'hidden';
            if (i != this._selectedIndex) {
                pane.style.height = '0px';
            }
        }
        
        // Call _onResize to setup the selected panel for initial display (by
        // adjusting its height, etc., so the page doesn't flicker)
        this._onResize();
        
        // Register for partial update events so we are notified when an UpdatePanel has finished
        // posting back (because if something in the UpdatePanel changed size during the Postback
        // we may have to grow/shrink to accomodate it)
        this.registerPartialUpdateEvents();
    },
    
    dispose : function() {
        /// <summary>
        /// Dispose of the AccordionBehavior
        /// </summary>
        /// <returns />

        // Clear all the animations
        this._disposeAnimations();
        this._animations = null;
        this._lengthAnimations = null;
        this._fadeAnimations = null;
        
        // Remove all the event handlers
        if (this._resizeHandler) {
            $removeHandler(window, "resize", this._resizeHandler);            
            this._resizeHandler = null;
        }
        if (this._clickHandler) {
            for (var i = this._headers.length - 1; i >= 0; i--) {
                var header = this._headers[i];
                if (header) {
                    $removeHandler(header, "click", this._clickHandler);                    
                }
            }

            this._clickHandler = null;
            this._headers = null;
            this._panes = null;
        }
        
        AjaxControlToolkit.AccordionBehavior.callBaseMethod(this, 'dispose');
    },
    
    _getElement : function(childNodes, i) {
        /// <summary>
        /// Get the ith element in the childNodes (this.is used to ignore whitespace, etc.)
        /// </summary>
        /// <param name="childNodes" domElement="true" parameterArray="true" elementType="Sys.UI.DomElement">
        /// Array of child nodes
        /// </param>
        /// <param name="i" integer="true">
        /// Index of the desired element
        /// </param>
        /// <returns type="Sys.UI.DomElement" domElement="true">
        /// Desired element
        /// </returns>

        if (childNodes && childNodes.length) {
            var index = -1;
            for (var j = 0; j < childNodes.length; j++) {
                var child = childNodes[j];
                if (child && child.nodeType == 1) {
                    if (++index == i) {
                        return child;
                    }
                }
            }
        }
        return 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.
        /// </summary>
        /// <returns />

        for (var i = this._animations.length - 1; i >= 0; i--) {
            if (this._animations[i]) {
                // Stop the animation if it was still playing
                if (this._animations[i].get_isPlaying()) {
                    this._animations[i].stop();
                }
                // Clear the animation
                this._animations[i].dispose();
                delete this._animations[i];
                // Disposing the CompositeAnimation will take care of its children
                // but we do need to clear the array elements
                if (this._fadeTransitions) {
                    delete this._lengthAnimations[i];
                    delete this._fadeAnimations[i];
                }
            }
        }
    },
    
    _onHeaderClick : function(evt) {
        /// <summary>
        /// OnClick handler to open the desired pane
        /// </summary>
        /// <param name="evt" type="Sys.UI.DomEvent">
        /// Event info
        /// </param>
        /// <returns />
        
        // TODO: Clean this up to use the new event features

        // Get the appropriate event object depending on the browser
        // (note: this.may go away when we remove the Safari compat fix in Common)
        if (!evt) {
            evt = window.event;
        }
        
        // Get the control that raised the event
        var header = evt.target;
        // Walk up its control hierarchy until we find the accordion
        // pane's header which we marked with the paneIndex field
        while (header && (typeof(header.paneIndex) === 'undefined')) {
            header = header.parentNode;
        }
             
        // Select this.pane (which saves it to ClientState and initiates
        // an animation to show the content pane)
        this.set_SelectedIndex(header.paneIndex);        
        return false;
    },
    
    _partialUpdateEndRequest : function(sender, endRequestEventArgs) {
        /// <summary>
        /// Resize the Accordion when a partial update (via an UpdatePanel) finishes
        /// in case the size of the content changes
        /// </summary>
        /// <param name="sender" type="Object">
        /// Sender
        /// </param>
        /// <param name="endRequestEventArgs" type="Sys.WebForms.EndRequestEventArgs">
        /// Event arguments
        /// </param>
        AjaxControlToolkit.AccordionBehavior.callBaseMethod(this, '_partialUpdateEndRequest', [sender, endRequestEventArgs]);
        
        // Use _changePanes to handle the resize because it will animate nicely  
        this._changePanes(-1);
    },
    
    _onResize : function(evt) {
        /// <summary>
        /// Patch up the Accordion after the window is resized.  this.is necessary
        /// to call: 1) whenver the window.onresize event is raised, 2) the behavior
        /// is initialized, 3) the AutoSize property is changed.  Given that more or
        /// less horizontal space will affect the amount of vertical space available,
        /// we need to recompute how to layout the headers and currently selected
        /// content pane.
        /// </summary>
        /// <param name="evt" type="Sys.UI.DomEvent">
        /// Event info
        /// </param>
        /// <returns />
        
        // TODO: Clean this up to use the new event features

        if (!this._panes)
            return;
        var pane = this._panes[this._selectedIndex];
        if (!pane)
            return;
        if (this._autoSize == AjaxControlToolkit.AutoSize.None && this._skipNextResize) {
            // Since the animations will change the page size and fire this.event,
            // we need to not resize when we're animating
            this._skipNextResize = false;
            return;
        }

        // Determine the maximum available height
        this._computeAvailableHeight();
        
        // Adjust the pane depending on how we autosize
        pane.style.height = this._computeSelectedPaneHeight() + 'px';
    },
    
    _getTotalHeight : function(element) {
        /// <summary>
        /// Get the total height for an element
        /// </summary>
        /// <param name="element" type="Sys.UI.DomElement" domElement="true">
        /// Element
        /// </param>
        /// <returns type="Number" integer="true">
        /// Height of the element (including its margins)
        /// </returns>
        return element.offsetHeight + this._getMarginHeight(element);
    },
    
    _getMarginHeight : function(element) {
        /// <summary>
        /// Get the total margin height for an element
        /// </summary>
        /// <param name="element" type="Sys.UI.DomElement" domElement="true">
        /// Element
        /// </param>
        /// <returns type="Number" integer="true">
        /// Margin height of the element
        /// </returns>

        var marginTop = parseInt(CommonToolkitScripts.getCurrentStyle(element, 'marginTop'));
        if (isNaN(marginTop)) {
            marginTop = 0;
        }
        
        var marginBottom = parseInt(CommonToolkitScripts.getCurrentStyle(element, 'marginBottom'));
        if (isNaN(marginBottom)) {
            marginBottom = 0;
        }
        
        return marginTop + marginBottom;
    },
    
    _getPaddingHeight : function(element) {
        /// <summary>
        /// Get the total padding height for an element
        /// </summary>
        /// <param name="element" type="Sys.UI.DomElement" domElement="true">
        /// Element
        /// </param>
        /// <returns type="Number" integer="true">
        /// Padding height of the element
        /// </returns>

        var paddingTop = parseInt(CommonToolkitScripts.getCurrentStyle(element, 'paddingTop'));
        if (isNaN(paddingTop)) {
            paddingTop = 0;
        }
        
        var paddingBottom = parseInt(CommonToolkitScripts.getCurrentStyle(element, 'paddingBottom'));
        if (isNaN(paddingBottom)) {
            paddingBottom = 0;
        }
        
        return paddingTop + paddingBottom;
    },
    
    _computeAvailableHeight : function() {
        /// <summary>
        /// Determine how much available height we have to fill with the expanded
        /// content panes after all the spaces required for the headers has been used
        /// </summary>
        /// <returns type="Number" integer="true">
        /// Available height
        /// </returns>

        var element = this.get_element();
        if (!this.get_isInitialized() || !element)
            return;
        
        // Compute the amount of space used by all the headers
        this._headerHeight = 0;
        for (var i = 0; i < this._headers.length; i++) {
            this._headerHeight += this._getTotalHeight(this._getElement(this._headers[i].childNodes, 0));
        }
        
        if (this._autoSize == AjaxControlToolkit.AutoSize.None) {
            this._availableHeight = Number.MAX_VALUE;
            element.style.overflow = 'hidden';
        } else {
            // Get the height of the element
            var elementHeight = parseInt(CommonToolkitScripts.getCurrentStyle(element, 'height'));
            if (isNaN(elementHeight)) {
                elementHeight = element.offsetHeight;
            }
            // Determine the height we have to work with
            this._availableHeight = elementHeight - this._headerHeight;
            // If we don't have enough height to display a reasonable
            // amount of information, let's make the whole thing scroll
            if (this._availableHeight <= this._minimimPaneHeight) {
                this._availableHeight = Number.MAX_VALUE;
                element.style.overflow = 'scroll';
                element.style.overflowX = 'auto';
            } else {
                element.style.overflow = 'hidden';
            }
        }
    },
    
    _computeSelectedPaneHeight : function() {
        /// <summary>
        /// Compute the height for the selected pane and properly setup its child
        /// and overflow.  this.is used when animating and resizing to automatically
        /// provide the correct size depending on the current AutoSize option.
        /// </summary>
        /// <returns type="Number" integer="true">
        /// Height for the selected pane
        /// </returns>

        var height;
        var pane = this._panes[this._selectedIndex];
        var child = this._getElement(pane.childNodes, 0);
        child.style.height = 'auto';
        switch (this._autoSize) {
            case AjaxControlToolkit.AutoSize.None :
                pane.style.overflow = "hidden";
                height = pane.scrollHeight;
                break;
            case AjaxControlToolkit.AutoSize.Fill :
                if (this._availableHeight != Number.MAX_VALUE) {
                    height = this._availableHeight;
                    if (pane.scrollHeight > this._availableHeight) {
                        pane.style.overflow = "scroll";
                        pane.style.overflowX = "auto";
                    } else if (pane.scrollHeight <= this._availableHeight) {
                        pane.style.overflow = "hidden";
                        var extraSpace = this._getMarginHeight(child) + this._getPaddingHeight(child);
                        child.style.height = (this._availableHeight - extraSpace - 1) + 'px';
                    }
                } else {
                    height = pane.scrollHeight;
                    pane.style.overflow = "hidden";
                }
                break;
            case AjaxControlToolkit.AutoSize.Limit :
                height = Math.min(pane.scrollHeight, this._availableHeight);
                if (pane.scrollHeight > this._availableHeight) {
                    pane.style.overflow = "scroll";
                    pane.style.overflowX = "auto";
                } else {
                    pane.style.overflow = "hidden";
                }
                break;
        }
        return height;
    },
    
    _getAnimation : function(index) {
        /// <summary>
        /// Get the animation for the specified accordion section or
        /// demand create the animation if it doesn't already exist.
        /// </summary>
        /// <param name="index" type="Number" integer="true">
        /// Index of the Accordion section
        /// </param>
        /// <returns type="AjaxControlToolkit.Animation.Animation">
        /// Animation for the desired section
        /// </returns>

        var animation = this._animations[index];
        if (!animation) {
            // Get the pane for this.animation
            var pane = this._panes[index];
            pane.style.overflow = 'hidden';
            
            // Create the length animation to open/close the pane
            var length = new AjaxControlToolkit.Animation.LengthAnimation(pane, this._duration, this._framesPerSecond, "style", "height", 0, 0, "px");
            // Determine whether or not to just use the length animation
            // or build a composite effect with fading transitions
            if (!this._fadeTransitions) { 
                animation = length;
            } else {
                // Store the length animation
                this._lengthAnimations[index] = length;
                // Create the fade animation to fade it in/out
                var fade = this._fadeAnimations[index] = new AjaxControlToolkit.Animation.FadeAnimation(pane, this._duration, this._framesPerSecond, AjaxControlToolkit.Animation.FadeEffect.FadeOut, 0, 1, true);
                // Create the composite animation to play the two at once
                animation = this._animations[index] = new AjaxControlToolkit.Animation.ParallelAnimation(pane, this._duration, this._framesPerSecond, [fade, length]);
            }
            animation.initialize();
        }
        return animation;
    },
    
    _changePanes : function(lastIndex) {
        /// <summary>
        /// Change to the selected pane while animating the transition.
        /// We will loop through each pane and get its animation (or demand
        /// create it if it doesn't have one yet), stop playing it if it's
        /// currently playing, change its parameters to either open or close
        /// and then animate it.  Because we have an animation for each content
        /// pane and we stop them if they were already playing, the accordion
        /// has the ability to nicely change panes again before the animation
        /// is finished.
        /// </summary>
        /// <param name="lastIndex" type="Number" integer="true">
        /// Index of the last selected Accordion pane
        /// </param>
        /// <returns />

        var e = this.get_element();
        
        if (!this.get_isInitialized() || !e)
            return;
            
        if (this._autoSize == AjaxControlToolkit.AutoSize.None) {
            // Adjust the height before we even start
            var selectedHeight = this._getTotalHeight(this._getElement(this._panes[this._selectedIndex].childNodes, 0));
            e.style.height = (this._headerHeight + selectedHeight) + 'px';
            this._skipNextResize = true;
        }
        
        // Loop through each pane
        for (var i = 0; i < this._panes.length; i++) {            
            // Get the composite animation for the pane.  If the animation
            // is still playing (i.e. it hasn't finished a hide/show from a
            // previous change) or if it is the selected or last selected pane
            // then we will animate it for this.change.  If it does not
            // satisfy the above criteria, then we move on to the next pane
            var animation = this._getAnimation(i);
            if (animation.get_isPlaying()) {
                animation.stop();
            } else if ((i != this._selectedIndex) && (i != lastIndex)) {
                continue;
            }
            
            // Get the pane and the length animation
            var length = null;
            var pane = this._panes[i];
      
            // Setup the fade effect if we are using it
            if (this._fadeTransitions) {
                this._fadeAnimations[i].set_effect((i != this._selectedIndex)
                    ? AjaxControlToolkit.Animation.FadeEffect.FadeOut : AjaxControlToolkit.Animation.FadeEffect.FadeIn);
                length = this._lengthAnimations[i];
            } else {
                // If we're not using the fade effect, then the only animation
                // is the length animation
                length = animation;
            }
            
            // Configure the length animation to either open or close
            // depending on whether or not this.is the selected pane
            length.set_startValue(pane.offsetHeight);
            if (i != this._selectedIndex) {
                length.set_endValue(0);
            } else {
                length.set_endValue(this._computeSelectedPaneHeight());
            }
            
            // Play the animation to open the selected pane or close any
            // other panes
            animation.play();
        }
    },
    
    get_Count : function() {
        /// <value type="Number" integer="true">
        /// Number of Accordion sections
        /// </summary>
        return this._panes ? this._panes.length : 0;
    },
    
    get_Header : function(i) { 
        /// <summary>
        /// Get a specific header given its index
        /// </summary>
        /// <param name="i" type="Number" integer="true">
        /// Index of the desired Accordion section
        /// </param>
        /// <returns type="Sys.UI.DomElement" domElement="true">
        /// Desired header
        /// </returns>
        return (this._headers && i >= 0 && i < this._headers.length) ? this._headers[i] : null;
    },
    
    get_Pane : function(i) {
        /// <summary>
        /// Get a specific pane given its index
        /// </summary>
        /// <param name="i" type="Number" integer="true">
        /// Index of the desired Accordion section
        /// </param>
        /// <returns type="Sys.UI.DomElement" domElement="true">
        /// Desired pane
        /// </returns>
        return (this._panes && i >= 0 && i < this._panes.length) ? this._panes[i] : null;
    },
    
    get_TransitionDuration : function() {
        /// <value type="Number">
        /// Length of time to transition between Accordion sections in milleseconds.  The default value is 250ms.
        /// </value>
        return this._duration * 1000;
    },
    set_TransitionDuration : function(value) {
        if (this._duration != (value / 1000)) {
            this._duration = value / 1000;
        
            // Update the animations with the new duration
            for (var i = this._panes.length - 1; i >= 0; i--) {
                var pane = this._panes[i];
                var animation = this._animations[i];
                if (animation) {
                    animation.set_duration(this._duration);
                    // Only set the duration on the other animations if we are
                    // using the fade transitions
                    if (this._fadeTransitions) {
                        this._lengthAnimations[i].set_duration(this._duration);
                        this._fadeAnimations[i].set_duration(this._duration);
                    }
                }
            }
            
            this.raisePropertyChanged('TransitionDuration');
        }
    },
    
    get_FramesPerSecond : function() {
        /// <value type="Number" integer="true">
        /// Number of steps per second in the transition animations.  The default is 25.
        /// </value>
        return this._framesPerSecond;
    },
    set_FramesPerSecond : function(value) {
        if (this._framesPerSecond != value) {
            this._framesPerSecond = value;
            
            // Update the animations with the new fps
            for (var i = this._panes.length - 1; i >= 0; i--) {
                var pane = this._panes[i];
                var animation = this._animations[i];
                if (animation) {
                    animation.set_fps(this._framesPerSecond);
                    // Only set the fps on the other animations if we are
                    // using the fade transitions
                    if (this._fadeTransitions) {
                        this._lengthAnimations[i].set_fps(this._framesPerSecond);
                        this._fadeAnimations[i].set_fps(this._framesPerSecond);
                    }
                }
            }
            this.raisePropertyChanged('FramesPerSecond');
        }
    },
    
    get_AutoSize : function() {
        /// <value type="AjaxControlToolkit.AutoSize">
        /// AutoSize mode
        /// </value>
        return this._autoSize;
    },
    set_AutoSize : function(value) {        
        if (this._autoSize != value) {
            this._autoSize = value;
            this.raisePropertyChanged('AutoSize');
            this._onResize();
        }
    },
    
    get_FadeTransitions : function() {
        /// <value type="Boolean">
        /// Whether or not to fade the accordion panes when transitioning
        /// </value>
        return this._fadeTransitions;
    },
    set_FadeTransitions : function(value) {
        if (this._fadeTransitions != value) {
            this._fadeTransitions = value;
            this._disposeAnimations();
            this._animations = [];
            this._fadeAnimations = [];
            this._lengthAnimations = [];
            if (!this._fadeTransitions) {
                for (var i = this._panes.length - 1; i >= 0; i--) {
                    CommonToolkitScripts.setElementOpacity(this._panes[i], 1);
                }
            }
            this.raisePropertyChanged('FadeTransitions');
        }
    },

    get_SelectedIndex : function() {
        /// <value type="Number" integer="true">
        /// Index of the currently selected Accordion section
        /// </value>
        return this._selectedIndex;
    },
    set_SelectedIndex : function(value) {
        // Only make the change if they clicked a different pane
        if (this._selectedIndex != value) {
            var lastIndex = this._selectedIndex;
            this._selectedIndex = value;
            // Save the selected pane to preserve on postbacks
            this.set_ClientState(this._selectedIndex);
            // Animate the pane changes
            this._changePanes(lastIndex);
            this.raisePropertyChanged('SelectedIndex');
        }
    }   
}
AjaxControlToolkit.AccordionBehavior.registerClass('AjaxControlToolkit.AccordionBehavior', AjaxControlToolkit.BehaviorBase);
//    // Get a type descriptor
//    getDescriptor : function() {
//        var td = AjaxControlToolkit.AccordionBehavior.callBaseMethod(this. 'getDescriptor');
//        td.addProperty('AutoSize', String);
//        td.addProperty('FadeTransitions', Boolean);
//        td.addProperty('FramesPerSecond', Number);
//        td.addProperty('SelectedIndex', Number);
//        td.addProperty('TransitionDuration', Number);
//        return td;
//    }
if(typeof(Sys)!=='undefined')Sys.Application.notifyScriptLoaded();