User:Unready/common.js

From Wikipedia, the free encyclopedia
Note: After saving, you have to bypass your browser's cache to see the changes. Google Chrome, Firefox, Microsoft Edge and Safari: Hold down the ⇧ Shift key and click the Reload toolbar button. For details and instructions about other browsers, see Wikipedia:Bypass your cache.
// short-circuit running this file, Wikia-style, usually for debugging
if (/(?:\?|&)useuserjs=0(?:&|$)/.test(location.search)) {
	throw 'Exiting on useuserjs=0';
}
/**
 * For action=purge GET, change it to POST, then reload the page
 * Restores pre-1.28 behavior to MW 1.28+
 * Based on meta:User:Glaisher/autoPurge.js, 21 Aug 2016
 */
(function (mw, $) {
	if ((mw.config.get('wgAction') === 'purge') &&
		($.inArray('user', mw.config.get('wgUserGroups')) + 1)) {
		$.post(mw.config.get('wgScriptPath') + '/api.php', {
			format: 'none',
			action: 'purge',
			titles: mw.config.get('wgPageName').replace(/_/g, ' ')
		}, function () {
			// remove action=purge, but keep the rest
			location.replace(
				location.pathname +
				location.search
					.replace(/(?:\?|&)action=purge$/i, '')
					.replace(/(\?|&)action=purge&/i, '$1') +
				location.hash
			);
		});
	}
}(mediaWiki, jQuery));
/**
 * Description:
 * Load scripts/stylesheets from wiki articles
 *
 * Version 1.0: 15 May 2015
 *   Original version for Wikipedia use
 * Version 2.0: 6 July 2016
 *   Rewrite with jQuery.Deferred; Implement using
 *
 * License: CC BY-SA
 *   http://creativecommons.org/licenses/by-sa/3.0/
 */
(window.user = window.user || {}).loader = user.loader || (function (mw, $) {
	'use strict';

	var
		self = {
			version: '2.0: 6 Jul 2016'
		},
		urlBase = mw.config.get('wgScriptPath') +
				'/index.php?title=$1&action=raw&ctype=$2',
		wikiDomain = mw.config.get('wgServerName').split('.'),
		wikiSubdomain = [],
		registry = {};

	// get a single title, either JavaScript or CSS
	// return a promise, possibly used by $.when
	function getTitle(title, wiki) {
		var
			type, url, t;

		if (/css$/.test(title)) {
			type = 'text/css';
		} else if (/js$/.test(title)) {
			type = 'text/javascript';
		} else {
			self.message += '\nInvalid type for title: "' +
				title + '" must be css or js';
			return $.Deferred().reject().promise();
		}
		// "wiki" encode the article title, skips encoding some characters
		url = urlBase.replace('$2', type).replace('$1', title.replace(/\s/g, '_')
			.replace(/[^$,/:;@]/g, function (c) {
				return encodeURIComponent(c);
			})
		);
		if (wiki !== wikiSubdomain) {
			url = '//' + wiki + wikiDomain + url;
		}
		switch (type) {
		case 'text/css':
			t = document.createElement('link');
			t.rel = 'stylesheet';
			t.href = url;
			$('head').append(t);
			t = $.Deferred().resolve().promise();
			break;
		case 'text/javascript':
			t = $.ajax(url, {
				cache: true,
				crossDomain: true,
				dataType: 'script'
			}).promise();
			break;
		}
		return t;
	}

	// load wiki articles as scripts or styles
	// articles = string or array of strings
	//   which are titles of articles to load
	// JavaScript articles terminate with js
	// stylesheet articles terminate with css
	// titles can be prepended with the form "u:<host>:"
	//   to designate a different host in the same domain
	// return an array of promises
	function load(articles) {
		var
			d = [], // the array of promises, one element per title
			wiki, title, t, i;

		if (typeof articles === 'string') {
			articles = [articles];
		} else if (!$.isArray(articles)) {
			self.message +=
				'\nload :: articles is not an array: ' + typeof articles;
			return [$.Deferred().reject().promise()];
		}
		for ( i = 0 ; i < articles.length ; ++i ) {
			title = articles[i];
			if (typeof title === 'string' ) {
				t = title.split(':');
				if ((t.length > 2) && (t[0] === 'u')) {
					wiki = t[1];
					title = t.splice(2).join(':');
				} else {
					wiki = wikiSubdomain;
				}
				t = wiki + ':' + title;
				if (!registry[t]) {
					registry[t] = getTitle(title, wiki);
				}
				d[i] = registry[t];
			} else {
				self.message +=
					'\nload :: title ' + i + ' is not a string: ' + typeof title;
				d[i] = $.Deferred().reject().promise();
			}
		}
		return d;
	}

	// load wiki articles as scripts or styles
	//   on the condition that the prerequisites are loaded
	// prereqs = string or array of strings
	//   which are titles to load before articles
	// articles = string or array of strings
	//   which are titles of articles to load
	// return a promise
	function using(prereqs, articles) {
		if (typeof prereqs === 'string') {
			prereqs = [prereqs];
		} else if (!$.isArray(prereqs)) {
			self.message +=
				'\nusing :: prereqs is not an array: ' + typeof prereqs;
			return $.Deferred().reject().promise();
		}
		if (typeof articles === 'string') {
			articles = [articles];
		} else if (!$.isArray(articles)) {
			self.message +=
				'\nusing :: articles is not an array: ' + typeof articles;
			return $.Deferred().reject().promise();
		}
		// load the articles when the prereqs complete
		// when() wants a list of individual arguments, not an array, so apply it
		return $.when.apply(null, load(prereqs)).done(function () {
			// when() resolves when the prereqs are loaded, not when they've run
			//   so enqueue load(articles) to give prereqs a chance to run
			setTimeout(load, 0, articles);
		}).promise();
	}

	// break the current qualified name
	//   into subdomain and domain names
	while (wikiDomain.length > 2) {
		wikiSubdomain.push(wikiDomain.shift());
	}
	wikiSubdomain = wikiSubdomain.join('.');
	wikiDomain = '.' + wikiDomain.join('.');
	self.message = 'OK, subdomain = ' + wikiSubdomain +
		', domain = ' + wikiDomain;
	// two methods to return
	self.load = load;
	self.using = using;
	return self;
}(mediaWiki, jQuery));
// ----------------------------------------------------------------------
(function (mw, $) {
	'use strict';

	var
		wgPageName = mw.config.get('wgPageName'),
		wgAction = mw.config.get('wgAction'),
		articles = [];
/*
	if (wgPageName === 'Special:Watchlist') {
		articles.push('User:Unready/ui.refresh.css'); // [[User:Unready/ui.refresh.css]]
		articles.push('User:Unready/ui.refresh.js');  // [[User:Unready/ui.refresh.js]]
	}
*/
	if (wgPageName === 'Special:Watchlist') {
		// move #watchlist-message outside #mw-content-text
		$('#mw-content-text').before($('#watchlist-message'));
		// define a custom watchlist
		$('#mw-content-text').empty().append('<div id="app-wlist"></div>');
	}
	// Watchlist (on any page)
	if ($('#app-wlist').length === 1) {
		articles.push('User:Unready/app.wlist.css'); // [[User:Unready/app.wlist.css]]
		articles.push('User:Unready/app.wlist.js');  // [[User:Unready/app.wlist.js]]
	}
	articles.push('User:Unready/ui.wikimarks.css'); // [[User:Unready/ui.wikimarks.css]]
	articles.push('User:Unready/ui.wikimarks.js');  // [[User:Unready/ui.wikimarks.js]]
	articles.push('User:Unready/ui.clock.css');     // [[User:Unready/ui.clock.css]]
	articles.push('User:Unready/ui.clock.js');      // [[User:Unready/ui.clock.js]]
	if (articles.length > 0) {
		user.loader.load(articles);
	}

	// insert tab for tab key event in edit areas
	// however, because of Event.timeStamp,
	//   it's broken in IE 8 and earlier
	//   and might be broken in Chrome 49 and later
	(function () {
		var
			last = 0;

		// event handler
		function onKey(e) {
			var
				epoch = e.timeStamp,
				s = this.selectionStart,
				t = this.scrollTop,
				v = this.value;

			if (e.keyCode === 9) {
				e.preventDefault();
				if (epoch !== last) {
					// insert a tab
					this.value =
						v.substr(0, s) + '\t' + v.substr(this.selectionEnd);
					this.scrollTop = t;
					this.selectionStart = this.selectionEnd = s + 1;
					last = epoch;
				}
			}
		}

		// exit if events don't have timestamps
		if (!document.createEvent ||
			!document.createEvent('HTMLEvents').timeStamp) {
			return;
		}
		// attach keydown and keypress handler to edit textarea
		$('#wpTextbox1')
			.keydown(onKey)
			.keypress(onKey);
	}());
}(mediaWiki, jQuery));