mediawiki-skins-Vector/vector.js
Thiemo Mättig d46cb97aeb Fix dysfunctional collapseCondition when right-most tab is the star
The issue I'm fixing here is described at
https://www.wikidata.org/wiki/Wikidata:Contact_the_development_team#Hard_to_read_titles

The code I'm touching here is from 2014. I believe the issue is not new, but
pops up extremely rarely. Multiple conditions must met:
1. The user must use an extreme zoom (or an extreme font size), or a
   super-narrow browser window. This is also how you should reproduce
   this: make your browser window very narrow, and then start zooming in
   extremely.
2. The issue only appears in namespaces where you can not move pages! This
   is the case for the vast majority of pages on Wikidata and the reason why
   it appears to be a Wikidata-only issue (which it is not). If you can move
   a page, the right-most button is "Move", which is wide enough to be worth
   collapsing, or is already collapsed.

If the right-most (":last") button is the watch star, the code believes it is
not worth collapsing it because the "More" button would consume more space.
This is true, but does not consider the other buttons that can also be
collapsed.

My code considers all collapsible buttons.

Change-Id: I6e94750b3b80940005f4d655e5e9b426d44b2ffb
2017-11-30 18:53:02 +00:00

110 lines
3.4 KiB
JavaScript

/**
* Vector-specific scripts
*/
jQuery( function ( $ ) {
/**
* Collapsible tabs
*/
var $cactions = $( '#p-cactions' ),
$tabContainer = $( '#p-views ul' ),
rAF = window.requestAnimationFrame || setTimeout,
// Avoid forced style calculation during page load
initialCactionsWidth = function () {
var width = $cactions.width();
initialCactionsWidth = function () {
return width;
};
return width;
};
rAF( initialCactionsWidth );
/**
* Focus search input at the very end
*/
$( '#searchInput' ).attr( 'tabindex', $( document ).lastTabIndex() + 1 );
/**
* Dropdown menu accessibility
*/
$( 'div.vectorMenu' ).each( function () {
var $el = $( this );
$el.find( '> h3 > span' ).parent()
.attr( 'tabindex', '0' )
// For accessibility, show the menu when the h3 is clicked (bug 24298/46486)
.on( 'click keypress', function ( e ) {
if ( e.type === 'click' || e.which === 13 ) {
$el.toggleClass( 'menuForceShow' );
e.preventDefault();
}
} );
} );
// Bind callback functions to animate our drop down menu in and out
// and then call the collapsibleTabs function on the menu
$tabContainer
.on( 'beforeTabCollapse', function () {
// If the dropdown was hidden, show it
if ( $cactions.hasClass( 'emptyPortlet' ) ) {
$cactions.removeClass( 'emptyPortlet' );
$cactions.find( 'h3' )
.css( 'width', '1px' )
.animate( { width: initialCactionsWidth() }, 'normal' );
}
} )
.on( 'beforeTabExpand', function () {
// If we're removing the last child node right now, hide the dropdown
if ( $cactions.find( 'li' ).length === 1 ) {
$cactions.find( 'h3' ).animate( { width: '1px' }, 'normal', function () {
$( this ).attr( 'style', '' )
.parent().addClass( 'emptyPortlet' );
} );
}
} )
.collapsibleTabs( {
expandCondition: function ( eleWidth ) {
// (This looks a bit awkward because we're doing expensive queries as late as possible.)
var distance = $.collapsibleTabs.calculateTabDistance();
// If there are at least eleWidth + 1 pixels of free space, expand.
// We add 1 because .width() will truncate fractional values but .offset() will not.
if ( distance >= eleWidth + 1 ) {
return true;
} else {
// Maybe we can still expand? Account for the width of the "Actions" dropdown if the
// expansion would hide it.
if ( $cactions.find( 'li' ).length === 1 ) {
return distance >= eleWidth + 1 - initialCactionsWidth();
} else {
return false;
}
}
},
collapseCondition: function () {
var collapsibleWidth = 0;
// (This looks a bit awkward because we're doing expensive queries as late as possible.)
// TODO The dropdown itself should probably "fold" to just the down-arrow (hiding the text)
// if it can't fit on the line?
// Never collapse if there is no overlap.
if ( $.collapsibleTabs.calculateTabDistance() >= 0 ) {
return false;
}
// Always collapse if the "More" button is already shown.
if ( !$cactions.hasClass( 'emptyPortlet' ) ) {
return true;
}
$tabContainer.children( 'li.collapsible' ).each( function ( index, element ) {
collapsibleWidth += $( element ).width();
// Stop this possibly expensive loop the moment the condition is met.
return !( collapsibleWidth > initialCactionsWidth() );
} );
return collapsibleWidth > initialCactionsWidth();
}
} );
} );