mediawiki-skins-Vector/resources/skins.vector.js/skin.js
Nicholas Ray 87959c8a59 Move limitedWidthToggle.js and features.js to skins.vector.es6 module
In preparation for 856718 where pinnableElement.js makes use of features.js,
move features.js and limitedWidthToggle.js out of the skins.vector.js module and
into the skins.vector.es6 module. This will make it easier to use by
pinnableElement.js without needing the es6 module to depend on the es5 module.

This does have the negative side-effect of causing the limited width feature to
not be supported by IE11 (and other non-ES6 browsers), however this tradeoff was
discussed with our product manager to be acceptable. Additionally, this
maintains the status quo as the toggle button does not currently show in IE11
(which may be a bug).

Bug: T322051
Change-Id: If0e8cb98deabe847c2cc71fddb90ca36d15e5f8f
2022-12-07 16:45:52 -07:00

149 lines
5.3 KiB
JavaScript

var languageButton = require( './languageButton.js' ),
echo = require( './echo.js' ),
initSearchLoader = require( './searchLoader.js' ).initSearchLoader,
dropdownMenus = require( './dropdownMenus.js' ).dropdownMenus,
sidebarPersistence = require( './sidebarPersistence.js' ),
watchstar = require( './watchstar.js' ),
// @ts-ignore
menuTabs = require( './menuTabs.js' ),
checkbox = require( './checkbox.js' );
/**
* Wait for first paint before calling this function. That's its whole purpose.
*
* Some CSS animations and transitions are "disabled" by default as a workaround to this old Chrome
* bug, https://bugs.chromium.org/p/chromium/issues/detail?id=332189, which otherwise causes them to
* render in their terminal state on page load. By adding the `vector-animations-ready` class to the
* `html` root element **after** first paint, the animation selectors suddenly match causing the
* animations to become "enabled" when they will work properly. A similar pattern is used in Minerva
* (see T234570#5779890, T246419).
*
* Example usage in Less:
*
* ```less
* .foo {
* color: #f00;
* transform: translateX( -100% );
* }
*
* // This transition will be disabled initially for JavaScript users. It will never be enabled for
* // non-JavaScript users.
* .vector-animations-ready .foo {
* transition: transform 100ms ease-out;
* }
* ```
*
* @param {Document} document
* @return {void}
*/
function enableCssAnimations( document ) {
document.documentElement.classList.add( 'vector-animations-ready' );
}
/**
* In https://phabricator.wikimedia.org/T313409 #p-namespaces was renamed to #p-associatedPages
* This code maps items added by gadgets to the new menu.
* This code can be removed in MediaWiki 1.40.
*/
function addNamespacesGadgetSupport() {
// Set up hidden dummy portlet.
var dummyPortlet = document.createElement( 'div' );
dummyPortlet.setAttribute( 'id', 'p-namespaces' );
dummyPortlet.setAttribute( 'style', 'display: none;' );
dummyPortlet.appendChild( document.createElement( 'ul' ) );
document.body.appendChild( dummyPortlet );
mw.hook( 'util.addPortletLink' ).add( function ( /** @type {Element} */ node ) {
// If it was added to p-namespaces, show warning and move.
// eslint-disable-next-line no-jquery/no-global-selector
if ( $( '#p-namespaces' ).find( node ).length ) {
// eslint-disable-next-line no-jquery/no-global-selector
$( '#p-associated-pages ul' ).append( node );
// @ts-ignore
mw.log.warn( 'Please update call to mw.util.addPortletLink with ID p-namespaces. Use p-associatedPages instead.' );
// in case it was empty before:
mw.util.showPortlet( 'p-associated-pages' );
}
} );
}
/**
* @param {Window} window
* @return {void}
*/
function main( window ) {
enableCssAnimations( window.document );
sidebarPersistence.init();
checkbox.init( window.document );
initSearchLoader( document );
languageButton();
echo();
dropdownMenus();
// menuTabs should follow `dropdownMenus` as that can move menu items from a
// tab menu to a dropdown.
menuTabs();
addNamespacesGadgetSupport();
watchstar();
}
/**
* @param {Window} window
* @return {void}
*/
function init( window ) {
var now = mw.now();
// This is the earliest time we can run JS for users (and bucket anonymous
// users for A/B tests).
// Where the browser supports it, for a 10% sample of users
// we record a value to give us a sense of the expected delay in running A/B tests or
// disabling JS features. This will inform us on various things including what to expect
// with regards to delay while running A/B tests to anonymous users.
// When EventLogging is not available this will reject.
// This code can be removed by the end of the Desktop improvements project.
// https://www.mediawiki.org/wiki/Desktop_improvements
mw.loader.using( 'ext.eventLogging' ).then( function () {
if (
mw.eventLog &&
mw.eventLog.eventInSample( 100 /* 1 in 100 */ ) &&
window.performance &&
window.performance.timing &&
window.performance.timing.navigationStart
) {
mw.track( 'timing.Vector.ready', now - window.performance.timing.navigationStart ); // milliseconds
}
} );
}
init( window );
/**
* Because stickyHeader.js clones the user menu, it must initialize before
* dropdownMenus.js initializes in order for the sticky header's user menu to
* bind the necessary checkboxHack event listeners. This is solved by using
* mw.loader.using to ensure that the skins.vector.es6 module initializes first
* followed by initializing this module. If the es6 module loading fails (which
* can happen in browsers that don't support es6), continue to initialize this
* module.
*/
function initAfterEs6Module() {
mw.loader.using( 'skins.vector.es6' ).then( function () {
// Loading of the 'skins.vector.es6' module has succeeded. Initialize the
// `skins.vector.es6` module first.
require( /** @type {string} */ ( 'skins.vector.es6' ) ).main();
// Initialize this module second.
main( window );
}, function () {
// Loading of the 'skins.vector.es6' has failed (e.g. this will fail in
// browsers that don't support ES6) so only initialize this module.
main( window );
} );
}
if ( document.readyState === 'interactive' || document.readyState === 'complete' ) {
initAfterEs6Module();
} else {
// This is needed when document.readyState === 'loading'.
document.addEventListener( 'DOMContentLoaded', function () {
initAfterEs6Module();
} );
}