* @param {Object|undefined} options
*/
function toggleElement( $collapsible, action, $defaultToggle, options ) {
- var $collapsibleContent, $containers;
+ var $collapsibleContent, $containers, hookCallback;
options = options || {};
// Validate parameters
return;
}
+ // Trigger a custom event to allow callers to hook to the collapsing/expanding,
+ // allowing the module to be testable, and making it possible to
+ // e.g. implement persistence via cookies
+ $collapsible.trigger( action === 'expand' ? 'beforeExpand.mw-collapsible' : 'beforeCollapse.mw-collapsible' );
+ hookCallback = function () {
+ $collapsible.trigger( action === 'expand' ? 'afterExpand.mw-collapsible' : 'afterCollapse.mw-collapsible' );
+ };
+
// Handle different kinds of elements
if ( !options.plainMode && $collapsible.is( 'table' ) ) {
// http://stackoverflow.com/questions/467336#920480
if ( options.instantHide ) {
$containers.hide();
+ hookCallback();
} else {
- $containers.stop( true, true ).fadeOut();
+ $containers.stop( true, true ).fadeOut( hookCallback );
}
} else {
- $containers.stop( true, true ).fadeIn();
+ $containers.stop( true, true ).fadeIn( hookCallback );
}
} else if ( !options.plainMode && ( $collapsible.is( 'ul' ) || $collapsible.is( 'ol' ) ) ) {
if ( action === 'collapse' ) {
if ( options.instantHide ) {
$containers.hide();
+ hookCallback();
} else {
- $containers.stop( true, true ).slideUp();
+ $containers.stop( true, true ).slideUp( hookCallback );
}
} else {
- $containers.stop( true, true ).slideDown();
+ $containers.stop( true, true ).slideDown( hookCallback );
}
} else {
if ( action === 'collapse' ) {
if ( options.instantHide ) {
$collapsibleContent.hide();
+ hookCallback();
} else {
- $collapsibleContent.slideUp();
+ $collapsibleContent.slideUp( hookCallback );
}
} else {
- $collapsibleContent.slideDown();
+ $collapsibleContent.slideDown( hookCallback );
}
// Otherwise assume this is a customcollapse with a remote toggle
if ( action === 'collapse' ) {
if ( options.instantHide ) {
$collapsible.hide();
+ hookCallback();
} else {
if ( $collapsible.is( 'tr' ) || $collapsible.is( 'td' ) || $collapsible.is( 'th' ) ) {
- $collapsible.fadeOut();
+ $collapsible.fadeOut( hookCallback );
} else {
- $collapsible.slideUp();
+ $collapsible.slideUp( hookCallback );
}
}
} else {
if ( $collapsible.is( 'tr' ) || $collapsible.is( 'td' ) || $collapsible.is( 'th' ) ) {
- $collapsible.fadeIn();
+ $collapsible.fadeIn( hookCallback );
} else {
- $collapsible.slideDown();
+ $collapsible.slideDown( hookCallback );
}
}
}
* @param {jQuery.Event|null} e either the event or null if unavailable
* @param {Object|undefined} options
*/
- function togglingHandler( $toggle, $collapsible, event, options ) {
+ function togglingHandler( $toggle, $collapsible, e, options ) {
var wasCollapsed, $textContainer, collapseText, expandText;
- if ( event ) {
+ if ( options === undefined ) {
+ options = {};
+ }
+
+ if ( e ) {
// Don't fire if a link was clicked, if requested (for premade togglers by default)
- if ( options.linksPassthru && $.nodeName( event.target, 'a' ) ) {
- return true;
+ if ( options.linksPassthru && $.nodeName( e.target, 'a' ) ) {
+ return;
} else {
- event.preventDefault();
- event.stopPropagation();
+ e.preventDefault();
+ e.stopPropagation();
}
}
*/
function toggleLinkPremade( $that, e, options ) {
var $collapsible = $that.eq( 0 ).closest( '.mw-collapsible' );
- options = $.extend( { toggleClasses: true }, options );
+ options = $.extend( { toggleClasses: true, linksPassthru: true }, options );
togglingHandler( $that, $collapsible, e, options );
}
* @param {jQuery} $collapsible
*/
function toggleLinkCustom( $that, e, options, $collapsible ) {
- options = $.extend( { linksPassthru: true }, options );
togglingHandler( $that, $collapsible, e, options );
}
.parent()
.prepend( ' [' )
.append( '] ' )
- .on( 'click.mw-collapse', function ( e, opts ) {
+ .on( 'click.mw-collapsible', function ( e, opts ) {
opts = $.extend( { toggleText: { collapseText: collapsetext, expandText: expandtext } }, options, opts );
toggleLinkDefault( $(this), e, opts );
} );
// Bind the custom togglers
if ( $customTogglers && $customTogglers.length ) {
- $customTogglers.on( 'click.mw-collapse', function ( e, opts ) {
+ $customTogglers.on( 'click.mw-collapsible', function ( e, opts ) {
opts = $.extend( {}, options, opts );
toggleLinkCustom( $(this), e, opts, $collapsible );
} );
if ( !$toggle.length ) {
$firstItem.eq(-1).prepend( $toggleLink );
} else {
- $toggleLink = $toggle.off( 'click.mw-collapse' ).on( 'click.mw-collapse', function ( e, opts ) {
+ $toggleLink = $toggle.off( 'click.mw-collapsible' ).on( 'click.mw-collapsible', function ( e, opts ) {
opts = $.extend( {}, options, opts );
toggleLinkPremade( $toggle, e, opts );
} );
}
$collapsible.prepend( $toggleLink.wrap( '<li class="mw-collapsible-toggle-li"></li>' ).parent() );
} else {
- $toggleLink = $toggle.off( 'click.mw-collapse' ).on( 'click.mw-collapse', function ( e, opts ) {
+ $toggleLink = $toggle.off( 'click.mw-collapsible' ).on( 'click.mw-collapsible', function ( e, opts ) {
opts = $.extend( {}, options, opts );
toggleLinkPremade( $toggle, e, opts );
} );
if ( !$toggle.length ) {
$collapsible.prepend( $toggleLink );
} else {
- $toggleLink = $toggle.off( 'click.mw-collapse' ).on( 'click.mw-collapse', function ( e, opts ) {
+ $toggleLink = $toggle.off( 'click.mw-collapsible' ).on( 'click.mw-collapsible', function ( e, opts ) {
opts = $.extend( {}, options, opts );
toggleLinkPremade( $toggle, e, opts );
} );