corrade-http-templates – Rev 42

Subversion Repositories:
Rev:
/*!
 * jQuery UI Accordion 1.12.1
 * http://jqueryui.com
 *
 * Copyright jQuery Foundation and other contributors
 * Released under the MIT license.
 * http://jquery.org/license
 */

//>>label: Accordion
//>>group: Widgets
// jscs:disable maximumLineLength
//>>description: Displays collapsible content panels for presenting information in a limited amount of space.
// jscs:enable maximumLineLength
//>>docs: http://api.jqueryui.com/accordion/
//>>demos: http://jqueryui.com/accordion/
//>>css.structure: ../../themes/base/core.css
//>>css.structure: ../../themes/base/accordion.css
//>>css.theme: ../../themes/base/theme.css

( function( factory ) {
        if ( typeof define === "function" && define.amd ) {

                // AMD. Register as an anonymous module.
                define( [
                        "jquery",
                        "../version",
                        "../keycode",
                        "../unique-id",
                        "../widget"
                ], factory );
        } else {

                // Browser globals
                factory( jQuery );
        }
}( function( $ ) {

return $.widget( "ui.accordion", {
        version: "1.12.1",
        options: {
                active: 0,
                animate: {},
                classes: {
                        "ui-accordion-header": "ui-corner-top",
                        "ui-accordion-header-collapsed": "ui-corner-all",
                        "ui-accordion-content": "ui-corner-bottom"
                },
                collapsible: false,
                event: "click",
                header: "> li > :first-child, > :not(li):even",
                heightStyle: "auto",
                icons: {
                        activeHeader: "ui-icon-triangle-1-s",
                        header: "ui-icon-triangle-1-e"
                },

                // Callbacks
                activate: null,
                beforeActivate: null
        },

        hideProps: {
                borderTopWidth: "hide",
                borderBottomWidth: "hide",
                paddingTop: "hide",
                paddingBottom: "hide",
                height: "hide"
        },

        showProps: {
                borderTopWidth: "show",
                borderBottomWidth: "show",
                paddingTop: "show",
                paddingBottom: "show",
                height: "show"
        },

        _create: function() {
                var options = this.options;

                this.prevShow = this.prevHide = $();
                this._addClass( "ui-accordion", "ui-widget ui-helper-reset" );
                this.element.attr( "role", "tablist" );

                // Don't allow collapsible: false and active: false / null
                if ( !options.collapsible && ( options.active === false || options.active == null ) ) {
                        options.active = 0;
                }

                this._processPanels();

                // handle negative values
                if ( options.active < 0 ) {
                        options.active += this.headers.length;
                }
                this._refresh();
        },

        _getCreateEventData: function() {
                return {
                        header: this.active,
                        panel: !this.active.length ? $() : this.active.next()
                };
        },

        _createIcons: function() {
                var icon, children,
                        icons = this.options.icons;

                if ( icons ) {
                        icon = $( "<span>" );
                        this._addClass( icon, "ui-accordion-header-icon", "ui-icon " + icons.header );
                        icon.prependTo( this.headers );
                        children = this.active.children( ".ui-accordion-header-icon" );
                        this._removeClass( children, icons.header )
                                ._addClass( children, null, icons.activeHeader )
                                ._addClass( this.headers, "ui-accordion-icons" );
                }
        },

        _destroyIcons: function() {
                this._removeClass( this.headers, "ui-accordion-icons" );
                this.headers.children( ".ui-accordion-header-icon" ).remove();
        },

        _destroy: function() {
                var contents;

                // Clean up main element
                this.element.removeAttr( "role" );

                // Clean up headers
                this.headers
                        .removeAttr( "role aria-expanded aria-selected aria-controls tabIndex" )
                        .removeUniqueId();

                this._destroyIcons();

                // Clean up content panels
                contents = this.headers.next()
                        .css( "display", "" )
                        .removeAttr( "role aria-hidden aria-labelledby" )
                        .removeUniqueId();

                if ( this.options.heightStyle !== "content" ) {
                        contents.css( "height", "" );
                }
        },

        _setOption: function( key, value ) {
                if ( key === "active" ) {

                        // _activate() will handle invalid values and update this.options
                        this._activate( value );
                        return;
                }

                if ( key === "event" ) {
                        if ( this.options.event ) {
                                this._off( this.headers, this.options.event );
                        }
                        this._setupEvents( value );
                }

                this._super( key, value );

                // Setting collapsible: false while collapsed; open first panel
                if ( key === "collapsible" && !value && this.options.active === false ) {
                        this._activate( 0 );
                }

                if ( key === "icons" ) {
                        this._destroyIcons();
                        if ( value ) {
                                this._createIcons();
                        }
                }
        },

        _setOptionDisabled: function( value ) {
                this._super( value );

                this.element.attr( "aria-disabled", value );

                // Support: IE8 Only
                // #5332 / #6059 - opacity doesn't cascade to positioned elements in IE
                // so we need to add the disabled class to the headers and panels
                this._toggleClass( null, "ui-state-disabled", !!value );
                this._toggleClass( this.headers.add( this.headers.next() ), null, "ui-state-disabled",
                        !!value );
        },

        _keydown: function( event ) {
                if ( event.altKey || event.ctrlKey ) {
                        return;
                }

                var keyCode = $.ui.keyCode,
                        length = this.headers.length,
                        currentIndex = this.headers.index( event.target ),
                        toFocus = false;

                switch ( event.keyCode ) {
                case keyCode.RIGHT:
                case keyCode.DOWN:
                        toFocus = this.headers[ ( currentIndex + 1 ) % length ];
                        break;
                case keyCode.LEFT:
                case keyCode.UP:
                        toFocus = this.headers[ ( currentIndex - 1 + length ) % length ];
                        break;
                case keyCode.SPACE:
                case keyCode.ENTER:
                        this._eventHandler( event );
                        break;
                case keyCode.HOME:
                        toFocus = this.headers[ 0 ];
                        break;
                case keyCode.END:
                        toFocus = this.headers[ length - 1 ];
                        break;
                }

                if ( toFocus ) {
                        $( event.target ).attr( "tabIndex", -1 );
                        $( toFocus ).attr( "tabIndex", 0 );
                        $( toFocus ).trigger( "focus" );
                        event.preventDefault();
                }
        },

        _panelKeyDown: function( event ) {
                if ( event.keyCode === $.ui.keyCode.UP && event.ctrlKey ) {
                        $( event.currentTarget ).prev().trigger( "focus" );
                }
        },

        refresh: function() {
                var options = this.options;
                this._processPanels();

                // Was collapsed or no panel
                if ( ( options.active === false && options.collapsible === true ) ||
                                !this.headers.length ) {
                        options.active = false;
                        this.active = $();

                // active false only when collapsible is true
                } else if ( options.active === false ) {
                        this._activate( 0 );

                // was active, but active panel is gone
                } else if ( this.active.length && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {

                        // all remaining panel are disabled
                        if ( this.headers.length === this.headers.find( ".ui-state-disabled" ).length ) {
                                options.active = false;
                                this.active = $();

                        // activate previous panel
                        } else {
                                this._activate( Math.max( 0, options.active - 1 ) );
                        }

                // was active, active panel still exists
                } else {

                        // make sure active index is correct
                        options.active = this.headers.index( this.active );
                }

                this._destroyIcons();

                this._refresh();
        },

        _processPanels: function() {
                var prevHeaders = this.headers,
                        prevPanels = this.panels;

                this.headers = this.element.find( this.options.header );
                this._addClass( this.headers, "ui-accordion-header ui-accordion-header-collapsed",
                        "ui-state-default" );

                this.panels = this.headers.next().filter( ":not(.ui-accordion-content-active)" ).hide();
                this._addClass( this.panels, "ui-accordion-content", "ui-helper-reset ui-widget-content" );

                // Avoid memory leaks (#10056)
                if ( prevPanels ) {
                        this._off( prevHeaders.not( this.headers ) );
                        this._off( prevPanels.not( this.panels ) );
                }
        },

        _refresh: function() {
                var maxHeight,
                        options = this.options,
                        heightStyle = options.heightStyle,
                        parent = this.element.parent();

                this.active = this._findActive( options.active );
                this._addClass( this.active, "ui-accordion-header-active", "ui-state-active" )
                        ._removeClass( this.active, "ui-accordion-header-collapsed" );
                this._addClass( this.active.next(), "ui-accordion-content-active" );
                this.active.next().show();

                this.headers
                        .attr( "role", "tab" )
                        .each( function() {
                                var header = $( this ),
                                        headerId = header.uniqueId().attr( "id" ),
                                        panel = header.next(),
                                        panelId = panel.uniqueId().attr( "id" );
                                header.attr( "aria-controls", panelId );
                                panel.attr( "aria-labelledby", headerId );
                        } )
                        .next()
                                .attr( "role", "tabpanel" );

                this.headers
                        .not( this.active )
                                .attr( {
                                        "aria-selected": "false",
                                        "aria-expanded": "false",
                                        tabIndex: -1
                                } )
                                .next()
                                        .attr( {
                                                "aria-hidden": "true"
                                        } )
                                        .hide();

                // Make sure at least one header is in the tab order
                if ( !this.active.length ) {
                        this.headers.eq( 0 ).attr( "tabIndex", 0 );
                } else {
                        this.active.attr( {
                                "aria-selected": "true",
                                "aria-expanded": "true",
                                tabIndex: 0
                        } )
                                .next()
                                        .attr( {
                                                "aria-hidden": "false"
                                        } );
                }

                this._createIcons();

                this._setupEvents( options.event );

                if ( heightStyle === "fill" ) {
                        maxHeight = parent.height();
                        this.element.siblings( ":visible" ).each( function() {
                                var elem = $( this ),
                                        position = elem.css( "position" );

                                if ( position === "absolute" || position === "fixed" ) {
                                        return;
                                }
                                maxHeight -= elem.outerHeight( true );
                        } );

                        this.headers.each( function() {
                                maxHeight -= $( this ).outerHeight( true );
                        } );

                        this.headers.next()
                                .each( function() {
                                        $( this ).height( Math.max( 0, maxHeight -
                                                $( this ).innerHeight() + $( this ).height() ) );
                                } )
                                .css( "overflow", "auto" );
                } else if ( heightStyle === "auto" ) {
                        maxHeight = 0;
                        this.headers.next()
                                .each( function() {
                                        var isVisible = $( this ).is( ":visible" );
                                        if ( !isVisible ) {
                                                $( this ).show();
                                        }
                                        maxHeight = Math.max( maxHeight, $( this ).css( "height", "" ).height() );
                                        if ( !isVisible ) {
                                                $( this ).hide();
                                        }
                                } )
                                .height( maxHeight );
                }
        },

        _activate: function( index ) {
                var active = this._findActive( index )[ 0 ];

                // Trying to activate the already active panel
                if ( active === this.active[ 0 ] ) {
                        return;
                }

                // Trying to collapse, simulate a click on the currently active header
                active = active || this.active[ 0 ];

                this._eventHandler( {
                        target: active,
                        currentTarget: active,
                        preventDefault: $.noop
                } );
        },

        _findActive: function( selector ) {
                return typeof selector === "number" ? this.headers.eq( selector ) : $();
        },

        _setupEvents: function( event ) {
                var events = {
                        keydown: "_keydown"
                };
                if ( event ) {
                        $.each( event.split( " " ), function( index, eventName ) {
                                events[ eventName ] = "_eventHandler";
                        } );
                }

                this._off( this.headers.add( this.headers.next() ) );
                this._on( this.headers, events );
                this._on( this.headers.next(), { keydown: "_panelKeyDown" } );
                this._hoverable( this.headers );
                this._focusable( this.headers );
        },

        _eventHandler: function( event ) {
                var activeChildren, clickedChildren,
                        options = this.options,
                        active = this.active,
                        clicked = $( event.currentTarget ),
                        clickedIsActive = clicked[ 0 ] === active[ 0 ],
                        collapsing = clickedIsActive && options.collapsible,
                        toShow = collapsing ? $() : clicked.next(),
                        toHide = active.next(),
                        eventData = {
                                oldHeader: active,
                                oldPanel: toHide,
                                newHeader: collapsing ? $() : clicked,
                                newPanel: toShow
                        };

                event.preventDefault();

                if (

                                // click on active header, but not collapsible
                                ( clickedIsActive && !options.collapsible ) ||

                                // allow canceling activation
                                ( this._trigger( "beforeActivate", event, eventData ) === false ) ) {
                        return;
                }

                options.active = collapsing ? false : this.headers.index( clicked );

                // When the call to ._toggle() comes after the class changes
                // it causes a very odd bug in IE 8 (see #6720)
                this.active = clickedIsActive ? $() : clicked;
                this._toggle( eventData );

                // Switch classes
                // corner classes on the previously active header stay after the animation
                this._removeClass( active, "ui-accordion-header-active", "ui-state-active" );
                if ( options.icons ) {
                        activeChildren = active.children( ".ui-accordion-header-icon" );
                        this._removeClass( activeChildren, null, options.icons.activeHeader )
                                ._addClass( activeChildren, null, options.icons.header );
                }

                if ( !clickedIsActive ) {
                        this._removeClass( clicked, "ui-accordion-header-collapsed" )
                                ._addClass( clicked, "ui-accordion-header-active", "ui-state-active" );
                        if ( options.icons ) {
                                clickedChildren = clicked.children( ".ui-accordion-header-icon" );
                                this._removeClass( clickedChildren, null, options.icons.header )
                                        ._addClass( clickedChildren, null, options.icons.activeHeader );
                        }

                        this._addClass( clicked.next(), "ui-accordion-content-active" );
                }
        },

        _toggle: function( data ) {
                var toShow = data.newPanel,
                        toHide = this.prevShow.length ? this.prevShow : data.oldPanel;

                // 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 ( this.options.animate ) {
                        this._animate( toShow, toHide, data );
                } else {
                        toHide.hide();
                        toShow.show();
                        this._toggleComplete( data );
                }

                toHide.attr( {
                        "aria-hidden": "true"
                } );
                toHide.prev().attr( {
                        "aria-selected": "false",
                        "aria-expanded": "false"
                } );

                // if we're switching panels, remove the old header from the tab order
                // if we're opening from collapsed state, remove the previous header from the tab order
                // if we're collapsing, then keep the collapsing header in the tab order
                if ( toShow.length && toHide.length ) {
                        toHide.prev().attr( {
                                "tabIndex": -1,
                                "aria-expanded": "false"
                        } );
                } else if ( toShow.length ) {
                        this.headers.filter( function() {
                                return parseInt( $( this ).attr( "tabIndex" ), 10 ) === 0;
                        } )
                                .attr( "tabIndex", -1 );
                }

                toShow
                        .attr( "aria-hidden", "false" )
                        .prev()
                                .attr( {
                                        "aria-selected": "true",
                                        "aria-expanded": "true",
                                        tabIndex: 0
                                } );
        },

        _animate: function( toShow, toHide, data ) {
                var total, easing, duration,
                        that = this,
                        adjust = 0,
                        boxSizing = toShow.css( "box-sizing" ),
                        down = toShow.length &&
                                ( !toHide.length || ( toShow.index() < toHide.index() ) ),
                        animate = this.options.animate || {},
                        options = down && animate.down || animate,
                        complete = function() {
                                that._toggleComplete( 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.length ) {
                        return toShow.animate( this.showProps, duration, easing, complete );
                }
                if ( !toShow.length ) {
                        return toHide.animate( this.hideProps, duration, easing, complete );
                }

                total = toShow.show().outerHeight();
                toHide.animate( this.hideProps, {
                        duration: duration,
                        easing: easing,
                        step: function( now, fx ) {
                                fx.now = Math.round( now );
                        }
                } );
                toShow
                        .hide()
                        .animate( this.showProps, {
                                duration: duration,
                                easing: easing,
                                complete: complete,
                                step: function( now, fx ) {
                                        fx.now = Math.round( now );
                                        if ( fx.prop !== "height" ) {
                                                if ( boxSizing === "content-box" ) {
                                                        adjust += fx.now;
                                                }
                                        } else if ( that.options.heightStyle !== "content" ) {
                                                fx.now = Math.round( total - toHide.outerHeight() - adjust );
                                                adjust = 0;
                                        }
                                }
                        } );
        },

        _toggleComplete: function( data ) {
                var toHide = data.oldPanel,
                        prev = toHide.prev();

                this._removeClass( toHide, "ui-accordion-content-active" );
                this._removeClass( prev, "ui-accordion-header-active" )
                        ._addClass( prev, "ui-accordion-header-collapsed" );

                // Work around for rendering bug in IE (#5421)
                if ( toHide.length ) {
                        toHide.parent()[ 0 ].className = toHide.parent()[ 0 ].className;
                }
                this._trigger( "activate", null, data );
        }
} );

} ) );