User:Krinkle/global.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.
mw.loader.using('mediawiki.util', function () {
	mw.hook('krinkle.perf-menu').add(function () {
		$('#p-perf ul').append('<hr>');
		mw.util.addPortletLink('p-perf', mw.util.getUrl('Special:Prefixindex/MediaWiki:'), 'Special:PrefixIndex/MediaWiki:');
		mw.util.addPortletLink('p-perf', mw.util.getUrl('Special:RecentChanges', { namespace: 8, days: 30, limit: 100 }), 'RecentChanges/MediaWiki:');
		mw.util.addPortletLink('p-perf', mw.util.getUrl('Special:Gadgets'), 'Special:Gadgets');
		mw.util.addPortletLink('p-perf', mw.util.getUrl('Special:GadgetUsage'), 'Special:GadgetUsage');
		$('#p-perf ul').append('<hr>');
		mw.util.addPortletLink('p-perf', 'https://commons.wikimedia.org/wiki/User:Krinkle/', 'commons: Userpages');
		mw.util.addPortletLink('p-perf', 'https://meta.wikimedia.org/wiki/User:Krinkle/Le_Tour_de_Wik%C3%AD', 'meta: Tour');
		mw.util.addPortletLink('p-perf', 'https://meta.wikimedia.org/wiki/User:Krinkle/global.js', 'meta: global.js');
	});
});


// [[File:Krinkle_Perf.js]]
mw.loader.load('https://meta.wikimedia.org/w/index.php?title=User:Krinkle/Scripts/Perf.js&action=raw&ctype=text/javascript');

// [[File:Krinkle_Countervandalism.js]]
mw.loader.load('https://meta.wikimedia.org/w/index.php?title=User:Krinkle/Scripts/Countervandalism.js&action=raw&ctype=text/javascript');

/**
 * Use canonical namespace name in the browser's address bar.
 *
 * This makes it easier to change the domain name when manually changing
 * the URL, without having to fix the localised namespace name which depends
 * on the wiki's content language.
 *
 * @source https://meta.wikimedia.org/wiki/User:Krinkle/global.js
 * @version 2016-11-14
 * @author Timo Tijhof, 2016
 */
mw.loader.using('mediawiki.util', function () {
	var url,
		conf = mw.config.get([
			'wgCanonicalNamespace',
			'wgCanonicalSpecialPageName',
			'wgFormattedNamespaces',
			'wgNamespaceNumber',
			'wgTitle'
		]);
	// Only run this on plain page views, not in the main namespace, and only if
	// the browser supports the History API. Note: pathname check is WMF-specific.
	if (conf.wgNamespaceNumber !== 0 && !location.search && location.pathname.indexOf(mw.util.getUrl('')) === 0 && history.replaceState) {
		// Special-namespace
		if (conf.wgNamespaceNumber === -1 && conf.wgCanonicalSpecialPageName) {
			url = mw.util.getUrl(
				conf.wgCanonicalNamespace + ':' + conf.wgCanonicalSpecialPageName
				// Preserve subpage (if any)
				+ conf.wgTitle.replace(/^[^/]+/, '')
			);
		// Leave ASCII namespace names untouched, like "Wikipedia" or "Commons_talk"
		} else if (/^[a-zA-Z ]+$/.test(conf.wgFormattedNamespaces[conf.wgNamespaceNumber])) {
			return;
		} else {
			url = mw.util.getUrl(conf.wgCanonicalNamespace + ':' + conf.wgTitle);
		}
		history.replaceState(history.state, document.title, url + location.hash);
	}
});

/**
 * Unwatch from watchlist
 *
 * Add an "unwatch" link near each entry on the watchlist view ([[bugzilla:424]]).
 *
 * @source https://www.mediawiki.org/wiki/Snippets/Unwatch_from_watchlist
 * @author Krinkle
 * @revision 2016-09-01
 */
mw.hook( 'wikipage.content' ).add( function ( $content ) {
	// Only on Watchlist and not in the /edit or /raw mode
	if ( mw.config.get( 'wgCanonicalSpecialPageName' ) !== 'Watchlist' || location.href.indexOf( '/edit' ) > 0 || location.href.indexOf( '/raw' ) > 0 ) {
		return;
	}
	mw.loader.using( ['mediawiki.util', 'mediawiki.api.watch'] ).then( function () {
		// Get the links
		var $wlHistLinks = $content.find( 'ul.special .mw-changeslist-line .mw-changeslist-history');
		$wlHistLinks.each( function () {
			var $unwatch,
				$el = $( this ),
				title = mw.util.getParamValue( 'title', this.href );
			$unwatch = $el.clone()
				.text( 'unwatch' )
				.attr( 'href', function ( i, val ) {
					return val.replace( 'action=history', 'action=unwatch' );
				} )
				.on( 'click', function ( e ) {
					new mw.Api().unwatch( title )
						.done( function () {
							$unwatch.css( { pointerEvents: 'none', opacity: 0.5 } );
						} )
						.fail( function () {
							$unwatch.off( 'click' ).append( ' (try again?)' );
						} );
					e.preventDefault();
				} );
			$el.after( $unwatch ).after( ' | ' );
		} );
	} );
} );

/**
 * Extra buttons in toolbar
 * @stats [[File:Krinkle_InsertWikiEditorButton.js]]
 */
// <nowiki>
if (mw.config.get('wgCanonicalNamespace') === 'MediaWiki') {
  if (!mw.libs.getInsertWikiEditorButton) {
    mw.libs.getInsertWikiEditorButton = $.ajax({ dataType: 'script', cache: true,
      url: 'https://meta.wikimedia.org/w/index.php?title=User:Krinkle/Scripts/InsertWikiEditorButton.js&action=raw&ctype=text/javascript'
    });
  }
  mw.libs.getInsertWikiEditorButton.then(function () {
	// Default value
	krInsertWikiEditorButton({
			id: 'mwint-reset',
			icon: 'https://upload.wikimedia.org/wikipedia/commons/thumb/5/51/Gartoon_actions_editcopy.svg/22px-Gartoon_actions_editcopy.svg.png',
			label: 'Reset interface message to default value',
			insertBefore: '{{subst:{{subst:FULLPAGENAME}}/{{subst:CONTENTLANGUAGE}}}}',
			insertAfter: '',
			sampleText: '',
			autoSummary: { summary: 'Update message', position: 'replace' }
	});
  });
}
// </nowiki>


/**
 * advancedtemplatesandbox
 *
 * Based on <https://en.wikipedia.org/wiki/User:Jackmcbarn/advancedtemplatesandbox.js>
 * Version: Krinkle-2010-07-10
 */
var $tplTemplate = $('#wpTemplateSandboxTemplate');
var $tplPage = $('#wpTemplateSandboxPage');
if ($tplTemplate.prop('type') == 'hidden') {
	$('#templatesandbox-editform').prepend(
		'<legend>Preview page with this template</legend>'
	);
	$tplTemplate
		.attr({
			type: 'text',
			size: '60',
			spellcheck: 'true'
		})
		.wrap(
			'<label>Template name: </label>'
		)
		.after('<br>');
	$tplPage
		.attr({
			type: 'text',
			size: '60',
			'data-mw-searchsuggest': '{"wrapAsLink":false}',
			class: 'mw-searchInput'
		})
		.wrap(
			'<label>Page title: </label>'
		)
		.after(
			' <input name="wpTemplateSandboxPreview" value="Show preview" type="submit">'
		);
}

/**
 * Find where and how a certain module is used.
 *
 * This finds which modules depend or load a given module.
 *
 * The first array are modules that directly depend on the given module.
 *
 * The second and third array represent higher-level features that are probably
 * more recognisable and well-known, which use the module indirectly through
 * a dependency on a module in the previous array.
 *
 * Usage:
 *
 *   mw.loader.findAll('mediawiki.util')
 *   //> 0: [ modules that load mediawiki.util ]
 *   //> 1: [ modules that load one of the modules in 0 ]
 *   //> 2: [ modules that load one of the modules in 1 ]
 *
 * @source https://wikitech.wikimedia.org/wiki/MediaWiki_Engineering/Runbook/Module_source
 *
 * @param {string} needle Module name, part of a module name, or a part of the module's script content.
 * @param {Object} [options]
 * @param {string|undefined} [options.state] Only consider modules having this state on the current page.
 * @param {boolean} [options.strict=false] If true, needle is only used to find exact module names.
 * @return {Array} An array of arrays. The first array contains the modules that directly contain or depend on `needle`, the second array contains modules containing or depending on modules from the first array, and so on.
 */
mw.loader.findAll = function findAll(needle, options) {
	var depth = 0;
	var seen = [];
	var ret = [];
	var prev;
	var results;
	function find(needle) {
		return mw.loader.getModuleNames().filter(function (moduleName) {
			var obj = mw.loader.moduleRegistry[moduleName];
			if (moduleName === needle) {
				return false;
			}
			if (options && options.state && obj.state !== options.state) {
				return false;
			}
			if (!options || !options.strict) {
				// Loose matching in the scripts' contents.
				if (obj.script && obj.script.toString().indexOf(needle) !== -1) {
					return true;
				}
			}
			// Direct dependencies
			return obj.dependencies.indexOf(needle) !== -1;
		});
	}
	while (depth < 3) {
		depth++;
		if (!prev) {
			results = find(needle);
			ret.push(results);
			seen.push.apply(seen, results);
		} else {
			results = [];
			prev.slice().forEach(function (result) {
				var subResults = find(result).filter(function (item) {
					return seen.indexOf(item) === -1;
				});
				results.push.apply(results, subResults);
				seen.push.apply(seen, subResults);
			});
			ret.push(results);
		}
		prev = results;
	}
	return ret;
};

/**
 * Like findAll(), but only considering dependencies of modules loaded on the current page.
 *
 * Useful for tracing warnings, such as "This page is using the deprecated module <name>."
 *
 * @source https://wikitech.wikimedia.org/wiki/MediaWiki_Engineering/Runbook/Module_source
 * @param {string} needle Module name
 * @param {Object} [options]
 * @return {Array}
 */
mw.loader.findReady = function findReady(needle, options) {
	var allOptions = Object.create(options || null);
	allOptions.state = 'ready';
	allOptions.strict = true;
	return mw.loader.findAll(needle, allOptions);
};