User:Former User aDB0haVymg/Gadgets/mwEmojiUI.js
外观
注意:保存之后,你必须清除浏览器缓存才能看到做出的更改。Google Chrome、Firefox、Microsoft Edge及Safari:按住⇧ Shift键并单击工具栏的“刷新”按钮。参阅Help:绕过浏览器缓存以获取更多帮助。
/**
*
* MWEmojiUI.js
*
* ----
*
* Add tasteful emoji icons to MediaWiki's bland interface links
*
* ----
*
* @version 8
* @author User:Classy_Melissa at zh-two.iwiki.icu
* @license CC-0 (Public Domain)
*
*/
/* globals mw */
// wrap in meta function to prevent scope leak
"use strict";
function mwEmojiUIContainerFunction () {
// "global" config values
const MWEMOJIUI_NUM_PADDING_SPACES = 1; // how many spaces to add after the emoji
const MWEMOJIUI_MAX_CONSOLE_LOGS = 5; // maximum number of element-not-found msgs handed to the console
// "global" static variables
var numPrintedConsoleLog = 0;
/**
* Syntax of the "emoji map" object
* [
* 0: target: a CSS selector to a particular element,
* which will have its innerText amended with the emoji
* 1: string: the string to prepend to the link text (usually an emoji)
* ]
*/
// all emoji maps. An array of "emoji match" objects
const emojiMaps = [
// sidebar
["#n-Main-Page a", "🏡"],
["#n-Recent-changes a", "🆕"],
// navigation bar ("ca")
["#ca-view a", "📄"],
["#ca-talk a", "💬"],
["#ca-ve-edit a", "📝"],
["#ca-viewsource a", "👁🗨"],
["#ca-edit a", "👩💻"],
["#ca-history a", "🗄️"],
["#ca-delete a", "🗑️"],
["#ca-move a", "🔀"],
["#ca-protect a", "🔐"],
["#ca-unprotect a", "🔓"],
// toolbar ("pt")
["#pt-mytalk a", "💬"],
["#pt-preferences a", "⚙️"],
["#pt-watchlist a", "👁️"],
["#pt-betafeatures a", "💡"],
["#pt-mycontris a", "💖"],
["#pt-logout a", "❌"],
// category
["#mw-normal-catlinks", "📚"],
// tools ("t")
["#t-whatlinkshere", "🕵️♀️"],
["#t-recentchangeslinked", "🆕"],
["#t-upload", "📤"],
["#t-specialpages", "⚙️"],
["#t-print", "🖨️"],
["#t-permalink", "⚓"],
["#t-info", "🔖"],
["#t-cite", "📎"],
["#t-contributions", "💖"],
["#t-log", "🧾"],
["#t-blockip", "🛑"],
["#t-userrights", "✅"],
// zhwp specific styles
// navigation portals ("n")
["#n-mainpage-description", "🏡"],
["#n-indexpage", "🗃"],
["#n-Featured_content", "⭐"],
["#n-currentevents", "📰"],
["#n-recentchanges", "🗓️"],
["#n-randompage", "🔀"]
];
/**
* Generates a <span> tag to contain the new emoji and padding whitespaces
* @returns {HTMLElement} an empty span
*/
function makeContainerElement() {
const newSpan = document.createElement("span");
newSpan.style.display = "inline";
newSpan.style.backgroundImage = "none";
return newSpan;
}
/**
* Logs to console that some selector is not found.
* @param {String} targetSelector the selector that isn't found
*/
function complainSelectorNotFound(targetSelector) {
if (numPrintedConsoleLog <= MWEMOJIUI_MAX_CONSOLE_LOGS) {
++numPrintedConsoleLog;
console.log(
"MWEmojiUI.js Info: Element \"" + targetSelector + "\" doesn't seem to be present."
);
}
}
/**
* Appends an emoji to an element specified by the map.
* Raises an exception if something goes wrong
* @param {String[]} map
*/
function appendEmojiByMap(map) {
// extract variables from the map array
const targetSelector = map[0];
const emojiToInsert = map[1];
// try to find the element
const targetElement = document.querySelector(targetSelector);
// if the element is not found,
// then log a message in the console & quit
if (!targetElement) {
complainSelectorNotFound(targetSelector);
return;
}
//-- the element is found --
// calculate the new innerText string
var newInnerTextString = "";
newInnerTextString += emojiToInsert; // deep copy as a preventative measure
// append padding spaces
for (var i = 0; i < MWEMOJIUI_NUM_PADDING_SPACES; ++i) {
newInnerTextString += ' ';
}
// create a new container element, and apply the new innerText string
const newContainer = makeContainerElement();
newContainer.innerText = newInnerTextString;
// apply the change
targetElement.insertAdjacentElement("afterbegin", newContainer);
// done
}
/**
* Returns a promise to process one item of the emojiMaps
* @param {String[]} map the map to process
* @returns {Promise} promise to process the map
*/
function promiseToAppendEmojiByMap(map) {
return new Promise(
// it'll simply call processMap function. Reject iff there's a exception.
// rejection should go all the way up to the original caller of ignite()
function(resolve, reject) {
try {
appendEmojiByMap(map);
resolve();
} catch (exception) {
reject(exception);
}
}
);
}
function ignite(key) {
// promises to process each emojiMap
var mapProcessPromises = [];
// start the processes
emojiMaps.forEach( function(thisMap) {
mapProcessPromises.push( promiseToAppendEmojiByMap(thisMap) );
} );
// simply have whoever that called ignition handle the promises
return Promise.all(mapProcessPromises);
}
// kickstart the operation
ignite()/* Promise<> */.catch(
// if one fails, notify the user
function(rejectReason) {
mw.notify("MWEmojiUI.js Error: " + rejectReason.toString());
}
);
}
mwEmojiUIContainerFunction();