Jump to content

MediaWiki:Gadget-tabbedwindow.js

From wikiNonStop

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)
  • Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5.
/**
 *
 * tabbedWindow.js
 *
 * It embeds an OOUI tabbed window on all pages in the API namespace on MediaWiki.org.
 * Each tab of the window contains sample code in a programming language (PHP, Javascript, Python, etc.)
 * demonstrating the use of the MediaWiki Action API.
 *
 * @license magnet:?xt=urn:btih:1f739d935676111cfff4b4693e3816e664797050&dn=gpl-3.0.txt GPL-v3-or-Later
 * @licstart  The following is the entire license notice for the JavaScript code in this gadget.
 *
 * Copyright (C) 2019 Jay Prakash <https://meta.wikimedia.org/wiki/User:Jayprakash12345> and contributors
 *
 * The JavaScript/Gadget code in this page is free software: you can
 * redistribute it and/or modify it under the terms of the GNU
 * General Public License (GNU GPL) as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option)
 * any later version.  The code is distributed WITHOUT ANY WARRANTY;
 * without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE.  See the GNU GPL for more details.
 *
 * As additional permission under GNU GPL version 3 section 7, you
 * may distribute non-source (e.g., minimized or compacted) forms of
 * that code without the copy of the GNU GPL normally required by
 * section 4, provided you include this license notice and a URL
 * through which recipients can access the Corresponding Source.
 *
 * @licend  The above is the entire license notice for the JavaScript/Gadget code in this gadget.
 */

( function () {
	'use strict';

	function trySettingTab( indexLayout, hash ) {
		const possiblePanelName = hash.slice( 1 );
		const possiblePanel = possiblePanelName && indexLayout.getTabPanel( possiblePanelName );
		if ( possiblePanel ) {
			indexLayout.setTabPanel( possiblePanelName );
			indexLayout.scrollElementIntoView();
		}
	}

	/**
	 * This function fetches sample code in different programming languages
	 * from the sub-sections of the section "Sample Code" and places
	 * them into an OOUI tabbed window.
	 *
	 * @param {jQuery} $tabbedWindows
	 */
	function makeTabWindow( $tabbedWindows ) {

		$tabbedWindows.each( ( i, tabbedWindow ) => {

			const indexLayout = new OO.ui.IndexLayout( {
				expanded: false
			} );

			const tabs = [];
			$( tabbedWindow ).find( 'h3, h4, h5, h6' ).each( ( j, heading ) => {
				const $heading = $( heading );
				let $headingWrapper, $headingText;
				if ( $heading.closest( '.mw-heading' ).length ) {
					$headingWrapper = $heading.closest( '.mw-heading' );
					$headingText = $heading;
				} else if ( $heading.find( '.mw-headline' ).length ) {
					$headingWrapper = $heading;
					$headingText = $heading.find( '.mw-headline' );
				} else {
					return;
				}
				const id = $headingText.attr( 'id' );

				const $content = $headingWrapper.nextUntil( 'h3, h4, h5, h6, .mw-heading3, .mw-heading4, .mw-heading5, .mw-heading6' );

				// Add the heading the content panel to preserve the original IDs as may be required by other tools (T350840)
				$content.prepend( $headingWrapper.hide() );

				const tabPanel = new OO.ui.TabPanelLayout( id, {
					expanded: false,
					label: $headingText.text(),
					// Attach the original DOM elements directly by reference.
					// This means they move directly in memory instead of getting copied/serialized/parsed as HTML.
					// If we didn't move them, but instead copied and re-parsed HTML, then it would disconnect events
					// and other live references from gadgets and extensions, which breaks sorting features, responsive gallery, etc.
					$content: $content
				} );

				tabPanel.$element.css( 'padding', '0.5em' );

				tabs.push( tabPanel );
			} );

			indexLayout.addTabPanels( tabs );

			const panelLayout = new OO.ui.PanelLayout( {
				expanded: false,
				framed: true,
				content: [ indexLayout ]
			} );

			$( tabbedWindow ).empty().append( panelLayout.$element );

			// Workaround for T348680
			mw.hook( 've.deactivationComplete' ).fire();

			// Select and scroll to any initially linked item in the address
			trySettingTab( indexLayout, location.hash );
			// Keep address bar updated with sharable link (also makes forward/backward browser navigation work)
			if ( history.replaceState ) {
				indexLayout.on( 'set', ( tabPanel ) => {
					history.replaceState( null, document.title, '#' + tabPanel.getName() );
				} );
			}
			// Support anchor links on the same page (from table of Contents, or [[#Section]] links)
			window.addEventListener( 'hashchange', () => {
				trySettingTab( indexLayout, location.hash );
			} );

		} );
	}

	mw.hook( 'wikipage.content' ).add( ( $content ) => {
		const $tabbedWindows = $content.find( '.mw-gadget-tabbedwindow' );
		if ( $tabbedWindows.length > 0 ) {
			// Viewing an API subject page with tabs on it, let's make them nice!
			mw.loader.using( [ 'oojs-ui-widgets' ] ).then( () => {
				makeTabWindow( $tabbedWindows );
			} );
		}
	} );
}() );