Merge "Sidebar: Collapses at lower resolutions, expands when resized"
This commit is contained in:
commit
e00603010b
|
@ -11,19 +11,36 @@ var /** @type {MwApi} */api,
|
||||||
SIDEBAR_CHECKBOX_ID = 'mw-sidebar-checkbox',
|
SIDEBAR_CHECKBOX_ID = 'mw-sidebar-checkbox',
|
||||||
SIDEBAR_PREFERENCE_NAME = 'VectorSidebarVisible';
|
SIDEBAR_PREFERENCE_NAME = 'VectorSidebarVisible';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if persistent is enabled at current time.
|
||||||
|
* When a user is using a browser with a screen resolution of < 1000 it is assumed
|
||||||
|
* that it is preferred that the sidebar remains closed across page views, as otherwise
|
||||||
|
* it gets in the way of reading. More context at T316191.
|
||||||
|
*
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
function isPersistentEnabled() {
|
||||||
|
return window.innerWidth >= 1000;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Execute a debounced API request to save the sidebar user preference.
|
* Execute a debounced API request to save the sidebar user preference.
|
||||||
* The request is meant to fire 1000 milliseconds after the last click on
|
* The request is meant to fire 1000 milliseconds after the last click on
|
||||||
* the sidebar button.
|
* the sidebar button.
|
||||||
*
|
*
|
||||||
* @param {HTMLInputElement} checkbox
|
* @param {HTMLInputElement} checkbox
|
||||||
|
* @param {number} timeout duration
|
||||||
|
* @param {boolean} shouldTriggerResize whether a resize event is needed.
|
||||||
* @return {any}
|
* @return {any}
|
||||||
*/
|
*/
|
||||||
function saveSidebarState( checkbox ) {
|
function saveSidebarState( checkbox, timeout, shouldTriggerResize ) {
|
||||||
return debounce( function () {
|
return debounce( function () {
|
||||||
api = api || new mw.Api();
|
api = api || new mw.Api();
|
||||||
api.saveOption( SIDEBAR_PREFERENCE_NAME, checkbox.checked ? 1 : 0 );
|
api.saveOption( SIDEBAR_PREFERENCE_NAME, checkbox.checked ? 1 : 0 );
|
||||||
|
|
||||||
|
if ( !shouldTriggerResize ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
// Trigger a resize event so other parts of the page can adapt:
|
// Trigger a resize event so other parts of the page can adapt:
|
||||||
var event;
|
var event;
|
||||||
if ( typeof Event === 'function' ) {
|
if ( typeof Event === 'function' ) {
|
||||||
|
@ -34,7 +51,7 @@ function saveSidebarState( checkbox ) {
|
||||||
event.initUIEvent( 'resize', true, false, window, 0 );
|
event.initUIEvent( 'resize', true, false, window, 0 );
|
||||||
}
|
}
|
||||||
window.dispatchEvent( event );
|
window.dispatchEvent( event );
|
||||||
}, 1000 );
|
}, timeout );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -46,17 +63,79 @@ function saveSidebarState( checkbox ) {
|
||||||
*/
|
*/
|
||||||
function bindSidebarClickEvent( checkbox, button ) {
|
function bindSidebarClickEvent( checkbox, button ) {
|
||||||
if ( checkbox instanceof HTMLInputElement && button ) {
|
if ( checkbox instanceof HTMLInputElement && button ) {
|
||||||
checkbox.addEventListener( 'input', saveSidebarState( checkbox ) );
|
var handler = saveSidebarState( checkbox, 1000, true );
|
||||||
|
checkbox.addEventListener( 'input', function () {
|
||||||
|
if ( isPersistentEnabled() ) {
|
||||||
|
handler();
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var /** @type {boolean} */ wasCollapsedDuringResize = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Collapses the sidebar if screen resolution too small.
|
||||||
|
*
|
||||||
|
* @param {HTMLInputElement} checkbox
|
||||||
|
*/
|
||||||
|
function collapseSidebar( checkbox ) {
|
||||||
|
if ( checkbox.checked ) {
|
||||||
|
wasCollapsedDuringResize = true;
|
||||||
|
checkbox.checked = false;
|
||||||
|
saveSidebarState( checkbox, 0, false )();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Expands the sidebar when the window is resized if it was previously collapsed.
|
||||||
|
*
|
||||||
|
* @param {HTMLInputElement} checkbox
|
||||||
|
*/
|
||||||
|
function expandSidebar( checkbox ) {
|
||||||
|
if ( wasCollapsedDuringResize && !checkbox.checked ) {
|
||||||
|
wasCollapsedDuringResize = false;
|
||||||
|
checkbox.checked = true;
|
||||||
|
saveSidebarState( checkbox, 0, false )();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function init() {
|
function init() {
|
||||||
var checkbox = window.document.getElementById( SIDEBAR_CHECKBOX_ID ),
|
var checkbox = /** @type {HTMLInputElement|null} */ (
|
||||||
|
window.document.getElementById( SIDEBAR_CHECKBOX_ID )
|
||||||
|
),
|
||||||
button = window.document.getElementById( SIDEBAR_BUTTON_ID );
|
button = window.document.getElementById( SIDEBAR_BUTTON_ID );
|
||||||
|
|
||||||
if ( mw.config.get( 'wgUserName' ) && !mw.config.get( 'wgVectorDisableSidebarPersistence' ) ) {
|
if ( mw.config.get( 'wgUserName' ) && !mw.config.get( 'wgVectorDisableSidebarPersistence' ) ) {
|
||||||
bindSidebarClickEvent( checkbox, button );
|
bindSidebarClickEvent( checkbox, button );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the user has resized their window, an open sidebar will be taking up lots of space
|
||||||
|
// so we should disable it.
|
||||||
|
// When this happens the user must expand it again manually, to avoid conflicts with multiple
|
||||||
|
// open windows (for example when an editor is viewing 2 articles side by side).
|
||||||
|
if ( checkbox ) {
|
||||||
|
var mediaQuery = window.matchMedia( '(max-width: 1000px)' );
|
||||||
|
var onMediaQueryChangeCollapse = function ( /** @type {MediaQueryListEvent} */ event ) {
|
||||||
|
if ( event.matches ) {
|
||||||
|
// @ts-ignore we checked it already.
|
||||||
|
collapseSidebar( checkbox );
|
||||||
|
} else {
|
||||||
|
// @ts-ignore we checked it already.
|
||||||
|
expandSidebar( checkbox );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if ( mediaQuery.matches ) {
|
||||||
|
collapseSidebar( checkbox );
|
||||||
|
}
|
||||||
|
if ( mediaQuery.addEventListener ) {
|
||||||
|
mediaQuery.addEventListener( 'change', onMediaQueryChangeCollapse );
|
||||||
|
} else {
|
||||||
|
// Before Safari 14, MediaQueryList is based on EventTarget,
|
||||||
|
// so you must use addListener() and removeListener() to observe media query lists.
|
||||||
|
mediaQuery.addListener( onMediaQueryChangeCollapse );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
|
Loading…
Reference in New Issue