Expand collapsed elements when the browser tries to scroll to a child
Known issue: If you scroll to a fragment via hash, collapse a parent, and then click a link to the same fragment or press Enter in the address bar, the scrolling won't happen. This is because the hashchange event doesn't get fired, and I doubt there's a good solution. Bug: T276741 Change-Id: Ibd42d4a051b7bb07beeea4a36b0dc5977f315518
This commit is contained in:
parent
c4d687a162
commit
599c80d06e
2 changed files with 67 additions and 0 deletions
|
|
@ -156,6 +156,49 @@
|
|||
toggleElement( $collapsible, wasCollapsed ? 'expand' : 'collapse', $toggle, options );
|
||||
}
|
||||
|
||||
/**
|
||||
* If the URL contains a hash followed by the fragment identifier of an
|
||||
* element inside collapsed parents, expand them all and scroll to it.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
function hashHandler() {
|
||||
var fragmentId, fragment, $parents;
|
||||
|
||||
fragmentId = window.location.hash.slice( 1 );
|
||||
if ( !fragmentId ) {
|
||||
// The hash is empty
|
||||
return;
|
||||
}
|
||||
|
||||
fragment = document.getElementById( fragmentId );
|
||||
if ( !fragment ) {
|
||||
// The fragment doesn't exist
|
||||
return;
|
||||
}
|
||||
|
||||
$parents = $( fragment ).parents( '.mw-collapsed' );
|
||||
if ( !$parents.length ) {
|
||||
// The fragment is not in a collapsed element
|
||||
return;
|
||||
}
|
||||
|
||||
// Expand collapsed parents
|
||||
$parents.each( function () {
|
||||
var $collapsible = $( this );
|
||||
if ( $collapsible.data( 'mw-made-collapsible' ) ) {
|
||||
$collapsible.data( 'mw-collapsible' ).expand();
|
||||
} else {
|
||||
// The collapsible has not been initialized, so just prevent it
|
||||
// from being collapsed
|
||||
$collapsible.removeClass( 'mw-collapsed' );
|
||||
}
|
||||
} );
|
||||
|
||||
// Scroll to the fragment
|
||||
fragment.scrollIntoView();
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable collapsible-functionality on all elements in the collection.
|
||||
*
|
||||
|
|
@ -356,6 +399,9 @@
|
|||
|
||||
} );
|
||||
|
||||
// Attach hash handler
|
||||
window.addEventListener( 'hashchange', hashHandler );
|
||||
|
||||
/**
|
||||
* Fired after collapsible content has been initialized
|
||||
*
|
||||
|
|
@ -370,6 +416,9 @@
|
|||
return this;
|
||||
};
|
||||
|
||||
// Run hash handler right now in case the URL already has a hash
|
||||
hashHandler();
|
||||
|
||||
/**
|
||||
* @class jQuery
|
||||
* @mixins jQuery.plugin.makeCollapsible
|
||||
|
|
|
|||
|
|
@ -377,6 +377,24 @@
|
|||
$clone.find( '.mw-collapsible-toggle a' ).trigger( 'click' );
|
||||
} );
|
||||
|
||||
QUnit.test( 'reveal hash fragment', function ( assert ) {
|
||||
var $collapsible = prepareCollapsible(
|
||||
'<div class="mw-collapsible mw-collapsed">' + loremIpsum + '<div id="div,a:nth-child(even)">' + loremIpsum + '</div></div>'
|
||||
),
|
||||
fragment = document.getElementById( 'div,a:nth-child(even)' ),
|
||||
done = assert.async();
|
||||
|
||||
assert.assertTrue( fragment.offsetParent === null, 'initial: fragment is hidden' );
|
||||
|
||||
$collapsible.on( 'afterExpand.mw-collapsible', function () {
|
||||
assert.assertTrue( fragment.offsetParent !== null, 'after hash change: fragment is visible' );
|
||||
done();
|
||||
window.location.hash = '';
|
||||
} );
|
||||
|
||||
window.location.hash = 'div,a:nth-child(even)';
|
||||
} );
|
||||
|
||||
QUnit.test( 'T168689 - nested collapsible divs should keep independent state', function ( assert ) {
|
||||
var $collapsible1 = prepareCollapsible(
|
||||
'<div class="mw-collapsible">' + loremIpsum + '</div>'
|
||||
|
|
|
|||
Loading…
Reference in a new issue