User:Becasita/common.js

From Yugipedia
Jump to: navigation, search

Note: After saving, you have to bypass your browser's cache to see the changes. Internet Explorer: hold down Ctrl and click the Refresh or Reload button. Firefox: hold down ⇧ Shift while clicking Reload (or press Ctrl+⇧ Shift+R). Google Chrome and Safari users can just click the Reload button. For details and instructions about other browsers, see Wikipedia:Bypass your cache.

/**
 * Main JS function.
 */
(function(window, $, mw, console, delay) {
	"use strict";

	const LAST_LOG = '23:41, 5 February 2024 (UTC)'; //<pre>

	mw.loader.using( ['mediawiki.api', 'mediawiki.util'] ).done(function() {
		/**
		 * Global objects.
		 */

		const conf = mw.config.get([
			'wgNamespaceNumber',
			'wgPageName'
		]);

		
		$.extend(conf, {
			action: mw.util.getParamValue('action'),
			api: function(query, callbacks, method) {
				return new mw.Api()[method || 'get'](query)
					.done(callbacks.done)
					.fail(callbacks.fail)
					.always(callbacks.always);
			}
		});


		const page = {
			hasContent: $('#ca-history').length && conf.wgNamespaceNumber !== -1,
			$content: $('#content'),
			$mwHead: $('#mw-head'),
			$userBar: $('#p-personal').children('ul'),
			$leftNav: $('#left-navigation').find('#p-namespaces').children('ul'),
			$rightNav: $('#right-navigation').find('#p-views').children('ul'),
			$rightMenu: $('#right-navigation').find('#p-cactions').find('ul'),
			$star: $('#ca-watch').length ? $('#ca-watch') : $('#ca-unwatch')
		};

		/** End. */


		/**
		 * Constructors and prototypes.
		 */

		// ------
		// String:
		String.prototype.strip = function(c) {
			return String(this).replace(new RegExp(c || ' ', 'g'), '');
		};

		// ------
		// Query:
		function Query(endpoint, query) {
			// query | url | full | endpoint
			if($.isPlainObject(endpoint)) {
				query = endpoint;
				endpoint = undefined;
			}
			this.query = query || {};
			this.url = this.fetch();
			this.full = this.extend();
			this.endpoint = String(endpoint || '').trim().toLowerCase().strip('.php');
		}
		// Extend prototype:
		$.extend(Query.prototype, {
			// "Private" methods:
			extend: function() {
				return $.extend({}, this.url, this.query);
			},
			fetch: function(parameters) {
				const query = {};
				const getValue = function(parameter) {
					return query[parameter];
				};
				const getValues = function(parameters) {
					return (Array.isArray(parameters)
						? parameters.map(function(v) {
							return getValue(v);
						})
						: getValue(parameters)
					);
				};
				window.location.search.slice(1).split('&').forEach(function(component) {
					if(!component.trim()) return;
					const parts = component.split('=');
					query[window.decodeURIComponent(parts[0])] = window.decodeURIComponent(parts[1] || '');
				});
				return parameters ? getValues(parameters) : query;
			},

			// "Getters":
			getEndpoint: function() {
				return this.endpoint;
			},
			getQuery: function(type) {
				switch((type+'').trim().toLowerCase()) {
					case 'full': return this.full;
					case 'url': return this.url;
					default: return this.query;
				}
			},

			// Other:
			print: function(full) {
				const query = this.getQuery(full && 'full');
				return [
					mw.util.wikiScript(this.getEndpoint()),
					Object.keys(query).map(function(key) {
						return [
							window.encodeURIComponent(key),
							window.encodeURIComponent(query[key])
						].join('=');
					}).join('&')
				].join('?');
			},
		});

		// Static method:
		Query.fetch = Query.prototype.fetch;

		// ------
		// State:
		function State(message) {
			this.message = message || 'Pending...';
			this.status = 'pending';
		}
		$.extend(State.prototype, {
			getMessage: function() {
				return this.message;
			},
			setMessage: function(m) {
				this.message = m || '';
				return this;
			},
			getStatus: function() {
				return this.status;
			},
			setStatus: function(s) { // Private.
				this.status = s || '';
				return this;
			},
			pending: function() {
				return this.setStatus('pending');
			},
			done: function() {
				return this.setStatus('done');
			},
			failed: function() {
				return this.setStatus('failed');
			},
			show: function() {
				items.$specialMessages.removeClass('hide')
					.children()
						.removeClass().addClass(this.getStatus())
						.text(this.getMessage());
				return this;
			}
		});

		/** End. */


		/**
		 * Utility functions.
		 */


		/** End. */


		/**
		 * Buttons.
		 */

		const items = {
			$searchBar: $('<li>', {
				id: 'pt-search',
				html: $('#p-search')
			}),
			$specialMessages: $('<li>', {
				id: 'pt-special-messages',
				html: $('<span>', {
					id: 'special-messages',
					class: 'hide'
				})
			}),
			$userBarBottom: $('<div>', {
				id: 'p-bottom'
			}),
			$diff: $('<li>', {
				id: 'ca-diff',
				class: 'collapsible',
				html: $('<span>', {
					html: $('<a>', {
						title: 'Last diff for this page.',
						text: 'Diff'
					})
				})
			}),
			$raw: $('<li>', {
				id: 'ca-raw',
				html: $('<a>', {
					href: new Query({
						title: conf.wgPageName,
						action: 'raw'
					}).print(),
					title: 'View the raw content.',
					text: 'Raw'
				})
			}),
			$safe: $('<li>', {
				id: 'ca-safe',
				html: $('<a>', {
					href: new Query({
						title: conf.wgPageName,
						safemode: true
					}).print(true),
					title: 'View the page in safemode.',
					text: 'Safe'
				})
			}),
			$debug: $('<li>', {
				id: 'ca-debug',
				html: $('<a>', {
					href: new Query({
						title: conf.wgPageName,
						debug: true
					}).print(true),
					title: 'View page in debug mode.',
					text: 'Debug'
				})
			}),
			$contentLabels: $('<li>', {
				id: 'ca-labels-qqx',
				html: $('<a>', {
					href: new Query({
						title: conf.wgPageName,
						uselang: Query.fetch().uselang === 'qqx' ? '' : 'qqx'
					}).print(true),
					title: 'Toggle content labels.',
					text: 'qqx'
				})
			}),
			$toggle: $('<li>', {
				id: 'ca-toggle',
				html: $('<a>', {
					href: '#',
					title: 'Toggle hidden content.',
					text: 'Toggle'
				})
			})
		};

		// Change "View history" button label to simply "History".
		$('#ca-history').find('a').text('History');

		// Move the search bar and add container for special messages to the user bar:
		page.$userBar
			.prepend(items.$searchBar)
			.append(items.$specialMessages);

		// Place the buttons for the page inside a container in the user bar:
		page.$mwHead.append(
			items.$userBarBottom.append(
				$('#left-navigation')
			).append(
				$('#right-navigation')
			)
		);

		// Extract the buttons from the right "More" menu and place them next to the other ones:
		page.$rightMenu.children().each(function() {
			const $this = $(this);
			page.$rightNav.append(
				$this.addClass('collapsible').html(function() {
					return $('<span>', {
						html: $this.html()
					});
				})
			);
		});

		// Add button to display raw content and last diff (only if the page has content):
		if(page.hasContent) {
			page.$rightMenu.append(items.$raw);
			$('#ca-history').after(items.$diff);
		}

		// Add a safemode button and a toggle button to the right "More" menu:
		page.$rightMenu
			.append(items.$contentLabels)
			.append(items.$safe)
			.append(items.$debug)
			.append(items.$toggle);

		// Place the (un)watch star in the last spot.
		page.$rightNav.append(page.$star);

		/** End. */


		/**
		 * Procedures.
		 */

		// -----------------------------------------------------
		// Adapt the top buttons to the diff pages: ("prettyfy")
		$(function selectDiffButton() {
			if(Query.fetch('diff')) {
				$('#ca-diff').addClass('selected');
				$('#ca-view').removeClass('selected');
			}
		});

		// ----------------------
		// Get lastest diff link:
		$(function getLatestDiffLink() {
			const mainFunctionName = 'getLatestDiffLink'; //arguments.callee.name;
			const query = {
				action: 'query',
				prop: 'revisions',
				titles: conf.wgPageName,
				rvprop: 'ids|user|timestamp|size|parsedcomment|flags',
				rvlimit: 2,
				formatversion: 2,
				format: 'json'
			};
			const callbacks = {
				done: function(data) {
					try {
						const currentRevision = data.query.pages[0].revisions[0];
						items.$diff.off('click')
							.find('a')
								.attr('href', new Query({
									diff: currentRevision.revid
								}).print());
					} catch(e) {
						console.log('%c«' + mainFunctionName + '()» error!', 'color: red;');
						if(e instanceof TypeError) {
							console.log("%cCan't get diff!", 'color: red;', '(known)');
						} else {
							console.error(e);
						}
						console.log(new Query('api', query).print(), data);
						return;
					}
				},
				fail: console.log,
				always: function() {
					console.log('%cDiff getter loaded!', 'color: blue;');
				}
			};
			return conf.api(query, callbacks);
		});

		// -------------------------
		// Toggle stuff I've hidden:
		$(function toggleWhatIHaveHidden() {
			[	// Add toggle class to all selectors:
				'#siteNotice', '#editpage-copywarn',
				'.mw-editTools', '.smw-editpage-help',
				'#n-Twitter', '#n-Facebook', '#p-random'
			].forEach(function(selector) {
				$(selector).addClass('toggle');
			});
		});

		/**
		 * Events.
		 */

		// Diff:
		items.$diff.click(function(e) {
			// Prevent default event:
			e.preventDefault();
			// Display state as failed: (if successfull, the Api request done() will "off" this event.)
			new State('Failed to get diff!').failed().show();
		});

		// Toggle:
		items.$toggle.click(function(e) {
			e.preventDefault();
			$('.toggle').toggle();
		});

		/** End. */

		/*************************************************************************/
		/**
		 * Add a link to Special:PrefiIndex to the sidebar.
		 */ 
		$( '#p-tb' ).find( 'ul' ).append( $( '<li>', {
			id: 't-prefixindex',
			html: $( '<a>', {
				href: '/wiki/Special:PrefixIndex/' + conf.wgPageName,
				text: 'Prefix index',
			} ),
		} ) );

		/*************************************************************************/
		
	});


	/**
	 * Return.
	 */

	console.log(
		'%cUser Common.js loaded! Last version from ' + LAST_LOG + '.',
		'color: blue;'
	);

	return true;

	/** End. */

})(window, window.jQuery, window.mediaWiki, window.console, (function(window, $) {
	"use strict";
	return function(t, fn) {
		if(!fn && $.isFunction(t)) {
			fn = t;
			t = undefined;
		}
		return window.setTimeout(fn, t);
	};
})(window, window.jQuery));
/** End. */
//</pre>