User:Thundercraft5/global.js/AjaxRedirect.js

/** * AjaxRedirect * * Allows for quick redirection of pages. * * @author			Thundercraft5 (https://dev.fandom.com/wiki/User:Thundercraft5) (UCP Re-write) * @author			Ozuzanna (https://dev.fandom.com/wiki/User:Ozuzanna) (Original Script) * @version			0.1 * @license			CC-BY-SA 3.0 */

/* jshint esversion: 5, forin: true, immed: true, indent: 4, latedef: true, newcap: true, noarg: true, undef: true, undef: true, unused: true, browser: true, jquery: true, onevar: true, eqeqeq: true, multistr: true, maxerr: 999999, -W082, -W084 /* global mw, importArticles, AjaxRedirect */

(function {	"use strict";	if (window.AjaxRedirect && window.AjaxRedirect.loaded) {		return window.AjaxRedirect.warn('Script double loaded, exiting...');	}

/**	 * Main Script Class * 	 * @class				AjaxRedirect * @init				hooks * @loadcondition		canRun */	window.AjaxRedirect = $.extend(window.AjaxRedirect, {		// Variable for double load protection		loaded: true,

/**#====================================================================#		 * Default configuration options * 		 * These fields contain any default configuration variables. **#=====================================================================#		 */		/**#====================================================================#		 * Global Variables * 		 * These fields contain all data used by this script. **#=====================================================================#		 */		wg: mw.config.get([	       'wgCanonicalNamespace',	        'wgCanonicalSpecialPageName',	        'wgPageName',	        'wgUserGroups',		]), csrfToken: mw.user.tokens.values.csrfToken, version: 1, hooksCount: 0, switched: false, frames: {},

/**		 * Data object for Hooks fired by this script * 		 * @data		Hooks for this script * @field		hook * @used */		hook: Object.freeze({			loaded: mw.hook('dev.AjaxRedirect.loaded'),		}), /**		 * Data object for All external dependencies/waitfor's data *		 * @field		imports * @data		All external dependencies/waitfor's data * @used		import */		imports: Object.freeze({			scripts: [				'u:dev:MediaWiki:UI-js/code.js',				'u:dev:MediaWiki:I18n-js/code.js',			],			style: Object.freeze([ 'u:dev:MediaWiki:AjaxRedirect.css', ]),			hooks: Object.freeze([ 'dev.i18n', 'dev.ui', 'dev.qdmodal', ]),			await: Object.freeze([ 'mediawiki.api', 'mediawiki.notify', 'mediawiki.util', 'mediawiki.widgets.TitlesMultiselectWidget', ]),			otherOnloadPromises: [				$.Deferred(function(def) { if (mw.libs.QDmodal) { def.resolve; } else { $.ajax({							cache: true,							dataType: "script",							url: "https://dev.fandom.com/load.php?mode=articles&only=scripts&articles=MediaWiki:QDmodal.js"						}).then(function {							def.resolve;						}); }				})			],		}),

/**		 * User rights level object. * Stores data about the necessary rights to preform an action. *		 * @field				groupLevels * @parent				AjaxRedirect * @used				getRights */		groupLevels: Object.freeze({			"global": Object.freeze([ 'staff', 'helper', 'global-discussions-moderator', 'wiki-manager', 'soap', ]),

"checkuser": Object.freeze([				'soap',				'helper',				'staff',				'wiki-manager',				'content-team-member',				'checkuser',				'util',			]),

"block": Object.freeze([				'sysop',				'staff',				'helper',				'bureaucrat',				'global-discussions-moderator',				'wiki-manager',				'soap',			]),

"delete": Object.freeze([				'content-moderator',				'threadmoderator',				'sysop',				'soap',				'staff',				'helper',				'global-discussions-moderator',				'wiki-manager',				'content-team-member',				'util',			]),

"move": Object.freeze([				"user",			]), }),

/**#====================================================================#		 * Loader functions * 		 * These functions initialize the script and add the event handlers * to the page. **#=====================================================================#		 */

/**		 * Main initializer script function. * Adds the hooks the imported scripts fire. * Then, it loads them. *		 * @method		hooks * @class		AjaxRedirect */		hooks: function { this.imports.hooks.forEach(function(v) {				mw.hook(v).add(this.onHook.bind(this, v));			}.bind(this)); this.import; },

/**		 * Function for when a hook is loaded. * This is function is called 3 times. When the hooks count reach 3, it adds the click event handlers. *		 * @method		onHook * @class		AjaxRedirect */		onHook: function(hook, value) { // Increment Hook count ++this.hooksCount;

// Switch hook value switch (hook) { case("dev.i18n"): this.i18n = value; break;

case('dev.ui'): this.ui = value; break; case('dev.qdmodal'): this.Modal = value; break; }			if (this.hooksCount === 3) { // Load all imports $.when.apply($, this.imports.otherOnloadPromises.concat(mw.loader.using(this.imports.await))).then(function(userRights) {					this.i18n.loadMessages('AjaxRedirect', { language: this.lang })						.then(this.init.bind(this, userRights))						.catch(this.warn);				}.bind(this)).catch(this.warn); }		},

/**		 * Dependency importer. * This method imports any external scripts used by this one. * 		 * @method		import * @class		AjaxRedirect */		import: function { this.log('importing...');

// Check for previous imports this.checkForPreviousImports({				'dev.ui': 'ui',				'dev.i18n': 'i18n',				'dev.qdmodal': 'mw.libs.QDmodal',			}); this.imports.otherOnloadPromises.push(mw.user.getRights); if (this.imports.scripts.length) importArticles({				type: "script",				articles: this.imports.scripts,			}); importArticles({				type: "style",				articles: this.imports.style,			}); },

/**		 * Function to check for previously loaded libraries to save time. *		 * @method		checkForPreviousImports * @param {Object} libs - The libraries to check for * @returns {Void} * @class		BlockLookup */		checkForPreviousImports: function(libs) { Object.entries(libs).forEach(function(data) {				var hookName = data[0];				var devLib = data[1];				if (devLib.match('.')) {					var split = devLib.split('.');					var val = window[split.shift];					while (split.length) val = val[split.shift];					this.onHook(hookName, val);				} else {					if (window.dev[devLib]) {						this.onHook(hookName, window.dev[devLib]);						this.imports.scripts.splice(1, 0);					}				}			}, this); },

/**		 * Actual script initializer. * This function sets up the event handlers on the page * and sets the variables that cannot be loaded beforehand. *		 * @method		init * @class		AjaxRedirect */		init: function(userRights, i18n) { this.userRights = userRights; this.api = new mw.Api; this.i18n = i18n; this.getParamValue = mw.util.getParamValue; this.modal = new this.Modal;

Object.freeze(this.wg); this.log('Ready');

// Fire any hooks attached to this script this.hook.loaded.fire; this.i18n.useUserLang; // Create UI frames this.createFrames; // Init interface this.initInterface; },

/**#====================================================================#		 * Utility functions * 		 * These functions preform utilities for the script. **#=====================================================================#		 */

/**		 * Rights data function. * Returns an array of user groups for the requested action. * 		 * @method					getGroupLevels * @class					AjaxRedirect * @returns	{Array}			An Array of user groups for the requested action * @param {String} action	The action to request */		getGroupLevels: function(action) { action = action.toLowerCase;

switch (action.toLowerCase) { case ("global"): return this.groupLevels[action]; case ("checkuser"): return this.groupLevels[action]; case ("block"): return this.groupLevels[action]; case ("protect"): case ("delete"): return this.groupLevels["delete"]; case ("move"): return this.groupLevels[action]; }		},

/**		 * User groups rights checker function. * Checks if the user has the groups for the requested level. *		 * @method					hasGroup * @class					AjaxRedirect * @returns {Boolean}		Whether the user has the requested rights * @param {String} level	The action to request */		hasGroup: function(level) { var rights = this.getGroupLevels(level), len = rights.length;

while (len--) if (this.wg.wgUserGroups.indexOf(rights[len]) !== -1) return true;

return false; },		/**		 * Checks if the user has a specified right. * 		 * @class					AjaxRedirect * @method					hasRight * @param {String} right - The right to search for * @returns {Boolean}		Whether the user has the requested right */		hasRight: function(right) { return !!~this.userRights.indexOf(right); },		/**		 * Function to check whether the script can run. * Used outside the class. * 		 * @method		canRun * @class		AjaxRedirect */		canRun: function { return this.hasGroup("move"); },

/**		 * Function to load an `i18-js` message. * 		 * @method				msg * @class				AjaxRedirect * @param {String} 1	the message code * @param {*} arguments arguments to the message * @return {String} 	The message's contents */		msg: function { return this.i18n.msg.apply(null, arguments).plain; },

/**		 * Function to check if a value is nullish as this software * does not support the `??` operator. *		 * @method				isNullish * @class				AjaxRedirect * @param {*} v 		The value to check * @returns {Boolean}	Whether not the value is nullish */		isNullish: function(v) { return v === null || v === undefined; },

/**		 * Function to set up a nullish default as this software * does not support the `??` operator. * 		 * @method				nullishDefault * @class				AjaxRedirect * @param {*} v			The value to check and return if it is not nullish * @param {*} _default	The value to return if `v` is nullish * @returns {*} 		`v` if it is not nullish and `` if it is		 */ nullishDefault: function(v, _default) { return this.isNullish(v) ? _default : v;		},

/**		 * Function to create a logging method in the class * 		 * @method		 logBuilder * @class		  AjaxRedirect * @param {String} level - The level to log at. * @param {Arguments} args - The function arguments to call the logging function with. * @return {String} - The message that was passed to the logging function. */		logBuilder: function(level, args) { args = Array.from(args); console[level.toLowerCase].apply(null, ['[AjaxRedirect v' + this.version + ']:', '[' + level.toUpperCase + ']'].concat(args)); return args.join(' '); }.bind(this),

/**		 * Function to log a error message with the script's name. * 		 * @method		 error * @class		  AjaxRedirect * @param {*} arguments - The arguments to pass to the logging function. * @return {String} - The message that was passed to the logging function. */		error: function { return this.logBuilder('warn', arguments); }.bind(this),

/**		 * Function to log a warning message with the script's name. * 		 * @method		 warn * @class		  AjaxRedirect * @param {*} arguments - The arguments to pass to the logging function. * @return {String} - The message that was passed to the logging function. */		warn: function { return this.logBuilder('warn', arguments); }.bind(this),

/**		 * Function to log a debug message with the script's name. * 		 * @method			log * @class		  AjaxRedirect * @param {*} arguments - The arguments to pass to the logging function. * @return {String} - The message that was passed to the logging function. */		log: function { return this.logBuilder('log', arguments); }.bind(this),

/**		 * Function to convert a value into a string. * 		 * @param {*} value	- The value to convert. * @returns {String} - The converted value * @method			log * @class		  AjaxRedirect */		string: function(value) { if (Array.isArray(value)) { return value.join(''); } else { return String(value); }		},

/**		 * Function to create a link. * 		 * @method			makeLink * @class			AjaxRedirect * @param {page}	The page to link to. * @param {alt}		The alternate text for the link * @param {attrs}	The attributes for the link element. * @return {HTMLAnchorElement} - The link that was passed to the arguments. */		makeLink: function(page, alt, attrs) { var page = page || this.wg.wgPageName; var origPage = page; var attrs = attrs || {}; var wiki, specials = { '^(m|meta):': 'meta.wikimedia.org', '^(mw):': 'mediawiki.org', '^(ucp):': 'ucp.fandom.com', '^(wp|wikipedia):': 'en.wikipedia.org', '^(w|wikia):(?!c|community)': 'community.fandom.com', '^(dev):': 'dev.fandom.com', '^(?:w|wikia):(?:c|community):([a-z]+)?\.([a-z_\-0-9A-Z]+):': function(match) { var community = match[2], lang = match[1]; return "https://" + community + ".fandom.com" + lang ? '/' + lang : ''; }			};			if ((/^(.+?):/).test(page)) { for (var k in specials) { if (specials.hasOwnProperty(k)) { var v = specials[k]; if (new RegExp(k, 'i').test(page)) { if (typeof(v) === "string") { wiki = v;							} else if (typeof(v) === "function") { wiki = v(page.match(k)); }							page = page.replace(new RegExp(k), ''); break; }					}				}			}		},		/**#=====================================================================#		 * Main functions * 		 * These functions do the main work when running this script. **#=====================================================================#		 */		initInterface: function { $('.page-header__contribution-buttons > .wds-button-group .wds-list').append(this.ui({ type: "li", children: [{ type: "a", text: "Redirect", attr: { id: "AjaxRedirect-button", },					events: { click: this.openModal.bind(this), }				}],			}));		},		createFrames: function { this.frames = this.ui({			}); },		createMainUI: function { return this.ui({				type: "div",				attr: {					id: "AjaxRedirect-modalContent",					},				children: [{					type: "div",					children: [{						type: "div",						text: "Use the form below to preform redirections on this page. The redirected page will make the reader's browser redirect to the target page."					}, {						type: "h4",						class: "AjaxRedirect-header",						text: "Select Operation",					}, {						type: "select",						attr: {							id: "AjaxRedirect-switchOperation"							},						events: {							change: this.switchFrames.bind(this),							},						children: [{							type: "option",							value: "redirectTo",							text: "Redirect this page to another page",							attr: {								selected: "",								},						}, {							type: "option",							value: "redirectFrom",							text: "Redirect page(s) to this page",						}],					}],				}, {					type: "div",					attr: {						id: "AjaxRedirect-frameContent", },				}],			});		},		switchFrames: function {			this.frames.redirectTo = this.ui([{ type: "span", text: "Enter the page you want to redirect this page to:", }, {			}]);			this.frames.redirectFrom = this.ui({ });		},		openModal: function {			this.modal.show({ title: "Ajax Redirect", content: this.createMainUI, buttons: [{ text: "Redirect", click: this.onSubmit.bind(this), }]			});		},		onSubmit: function {			this.modal.hide;		},

});

if (!AjaxRedirect.canRun) return AjaxRedirect.log('User does not have necessary rights, exiting...');

AjaxRedirect.hooks; }.call(window.AjaxRedirect = window.AjaxRedirect || {}));