User:Nw520/GadgetManager.js

From Meta, a Wikimedia project coordination wiki

Note: After publishing, you may have to bypass your browser's cache to see the changes.

  • Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
  • Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
  • Internet Explorer / Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5
  • Opera: Press Ctrl-F5.
( function () {
	if ( window.nw520 === undefined ) {
		window.nw520 = {};
	}

	const strings = {
		'nw520-gadgetManager-loadLazy': {
			de: 'Weitere Gadgets nachladen',
			en: 'Load more gadgets'
		}
	};

	const lazyGadgets = [];
	let lazyGadgetsLoaded = false;
	const urlParams = new URLSearchParams( window.location.search );
	let keyboardListener = null;
	let portlet = null;

	window.nw520.gadgetManager = {
		addKeyboardListener: function ( letter ) {
			if ( lazyGadgets.length === 0 ) {
				return false;
			}

			keyboardListener = function ( e ) {
				if ( !e.ctrlKey && e.key === letter && e.target.tagName === 'BODY' ) {
					e.preventDefault();
					window.nw520.gadgetManager.loadLazyGadgets();
				}
			};
			document.addEventListener( 'keyup', keyboardListener, false );
			return true;
		},
		addLazyPortlet: function () {
			if ( lazyGadgets.length === 0 ) {
				return false;
			}

			setupStrings();

			portlet = mw.util.addPortletLink( 'p-tb', '#', mw.msg( 'nw520-gadgetManager-loadLazy' ) );
			portlet.addEventListener( 'click', function ( e ) {
				e.preventDefault();
				portlet.style.pointerEvents = 'none';
				window.nw520.gadgetManager.loadLazyGadgets().then( function () {
					portlet.remove();
				} );
			} );
			return portlet;
		},
		gadgets: [],
		loadLazyGadgets: function () {
			if ( lazyGadgetsLoaded ) {
				return false;
			}
			if ( keyboardListener !== null ) {
				document.addEventListener( 'keyup', keyboardListener, false );
			}
			if ( portlet !== null ) {
				portlet.style.pointerEvents = 'none';
			}
			lazyGadgetsLoaded = true;

			return new Promise( function ( resolve, reject ) {
				Promise.allSettled( lazyGadgets.map( function ( gadget ) {
					return loadGadget( gadget[ 0 ], gadget[ 1 ], gadget[ 2 ] );
				} ) ).then( function () {
					if ( portlet !== null ) {
						portlet.remove();
					}
					resolve();
				}, reject );
			} );
		},
		registerGadget: function ( slug, url, lazy ) {
			window.nw520.gadgetManager.gadgets.push( [ slug, url ] );
			if ( urlParams.get( 'nogadget' ) === null || ( urlParams.get( 'nogadget' ) !== '' && !urlParams.get( 'nogadget' ).split( ',' ).map( function ( x ) {
				return x.toLowerCase();
			} ).includes( slug.toLowerCase() ) ) ) {
				if ( lazy === true ) {
					lazyGadgets.push( [ slug, url ] );
				} else {
					loadGadget( slug, url );
				}
			}
		}
	};

	function loadGadget( slug, url ) {
		if ( typeof url === 'function' ) {
			return Promise.resolve( url() );
		} else if ( url.match( /^(https?:)?\/\// ) ) {
			return mw.loader.getScript( url );
		} else {
			return mw.loader.using( url );
		}
	}

	function setupStrings() {
		const lang = mw.config.get( 'wgUserLanguage' );
		mw.messages.set( Object.fromEntries( Object.keys( strings ).map( function ( stringKey ) {
			return [ stringKey, strings[ stringKey ][ lang ] ?? strings[ stringKey ].en ];
		} ) ) );
	}
}() );