User:MonkeysHK/common.js

/* 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, ace */

$.when(   $.Deferred(function(def) { $(function {            def.resolve;        }); }),    mw.loader.using(['mediawiki.util', 'mediawiki.api', 'ext.codeEditor.ace']),    $.Deferred(function(def) { if (mw.libs.QDmodal) { def.resolve(mw.libs.QDmodal); } else { $.ajax({               cache: true,                dataType: "script",                url: "https://dev.fandom.com/load.php?mode=articles&only=scripts&articles=MediaWiki:QDmodal.js"            }).done(function {                 def.resolve(mw.libs.QDmodal);            }); }   }) ).then(function {    // Pages    var allowedPages = [        // "Module:Inventory_slot/Tooltips",        "Module:Inventory_slot/Test", // used only when testing with user script    ];    if (!allowedPages.includes(mw.config.get('wgPageName')) || (window.TooltipsEditor && window.TooltipsEditor.loaded)) return;

var api = new mw.Api;

console.log("Loading TooltipsEditor...");

window.TooltipsEditor = Object.assign(this, {       // variables; undefined variables are just for easier variable tracking        modal: new mw.libs.QDmodal("TooltipsEditor"),        closing: undefined,        actions: [],        loaded: true,        isInMain: false,        data: undefined,        json: undefined,        oldjson: undefined,        oldjsonkeys: undefined,        colorRules: undefined,        editor: undefined,        lastFocusedEditor: undefined,        lastFocusedElement: undefined,

colorConversions: { 0: "black", 1: "dark_blue", 2: "dark_green", 3: "dark_aqua", 4: "dark_red", 5: "dark_purple", 6: "gold", 7: "gray", 8: "dark_gray", 9: "blue", a: "green", b: "aqua", c: "red", d: "light_purple", e: "yellow", f: "white", l: "bold", n: "underline", m: "strikethrough", o: "italic", r: "reset", },       colorConvList: "0123456789abcdef", conversions: { "l": "bold", "m": "strikethrough", "n": "underline", "o": "italic", },       rarityConversions: { "Common": "f", "Uncommon": "a", "Rare": "9", "Epic": "5", "Legendary": "6", "Mythic": "d", "Supreme": "4", "Special": "c", "Very Special": "c", },       shortForm: { "Common": "C", "Uncommon": "U", "Rare": "R", "Epic": "E", "Legendary": "L", "Mythic": "M", "Supreme": "SE", "Special": "SL", "Very Special": "VSL", },       specialchars: ("❤ ❈ ❁ ✦ ☣ ☠ ✎ ∞ ✯ ♣ ❂ ⚔ ⫽ α ✹ ⸕ ☘ 🗲 ❣ ⚚ ⸎ ʬ") .replaceAll(" ", "  ") .split(" ") .map(function(v) {               if (!v.match(" ")) {                    return $("", { "class": "TooltipsEditor-insertChar", text: v,                       title: "Insert \"" + v + "\"", });               } else {                    return v;                }            }), escapes: { regex: /\\(ench?a?n?t?m?e?n?t?|ra?r?i?t?y?|poti?o?n|sta?t?)\{(?: .+?)\}|\\(?:[rntvb]|x[0-9a-fA-F]{2}|u[0-9a-fA-F]{1,4}|u\{[0-9a-fA-F]{1,6}\}|[0-2][0-7]{0,2}|3[0-7][0-7]?|[4-7][0-7].)/, token: "backescape.code", },

// helper functions for this.updateActions inOldjson: function (k) { return this.oldjsonkeys.indexOf(k) !== -1; },       throwOldjson: function(k) { if (this.inOldjson(k) && !(k in this.oldjson)) { this.oldjson[k] = {}; Object.assign(this.oldjson[k], this.json[k]); }       },        updateOne: function(k) { if (k) { if (this.inOldjson(k) && !(k in this.json)) this.actions[k] = "remove"; else if (!this.inOldjson(k) && (k in this.json)) this.actions[k] = "add"; else if (!this.inOldjson(k) && !(k in this.json)) { if (k in this.actions) delete this.actions[k]; }               else if (this.oldjson[k].name === this.json[k].name && this.oldjson[k].title === this.json[k].title && this.oldjson[k].text === this.json[k].text) { if (k in this.actions) delete this.actions[k]; if (k in this.oldjson) delete this.oldjson[k]; }               else this.actions[k] = "modify"; }       },        revertAction: function { var key = $(this).attr("data-value"); if (key in this.oldjson) { this.json[key] = {}; Object.assign(this.json[key], this.oldjson[key]); delete this.oldjson[key]; }           else if (key in this.json) delete this.json[key]; if (key in this.actions) delete this.actions[key]; mw.notify("for "+key, {title: "Undo Successful", type:"success"}); this.updateActions; if ($("#TooltipsEditor-searchInput").val.trim !== "") $("#TooltipsEditor-searchInput").keyup; },

// main function this.updateActions updateActions: function(keys) { // calling updateActions without keys will refresh the table without additional change // keys can be an array of strings or one string if (keys) { if (typeof(keys) === "string") { this.updateOne(keys); }               else { for (var i = 0; i < keys.length; i++) { var k = keys[i]; this.updateOne(k); }               }            }

var $log = $("#TooltipsEditor-actionLog"); var len = Object.keys(this.actions).length; var ls = ],[],[],[;

$log.empty.append($("", {text: len ? "Unsaved changes: " : "No changes were made", "class": "actions-none"}));

if (len) { Object.keys(this.actions).sort.forEach(function(k) {                   switch(this.actions[k]) {                        case("add"): {                            ls[0].push($("", {                                html: [                                    "Added "+k,                                    $("", { text: "undo", "class": "actions-undo-button", "data-value": k }).on("click", this.revertAction),                                    $("", { "class": "actions-edit-button", text: "edit", "data-tooltipTitle": this.json[k] && this.json[k].title && this.json[k].title.replaceAll("&amp;", "&"), "data-tooltipText": this.json[k] && this.json[k].text && this.json[k].text.replaceAll("&amp;", "&"), "data-tooltipLink": this.json[k] && this.json[k].name && this.json[k].name.replaceAll("&amp;", "&"), "data-tooltipKey": k.replaceAll("&amp;", "&") }),                                   $(" ", {                                        "class": "actions-preview-button minetip", text: "preview (current)", "data-minetip-text": this.json[k] && this.json[k].text && this.json[k].text.replaceAll("&amp;", "&"), "data-minetip-title": this.json[k] && this.json[k].title && this.json[k].title.replaceAll("&amp;", "&"), })                               ],                                "class": "actions-add"                            }));                            break;                        }                        case("modify"): {                            ls[1].push($("", {                                html: [                                    "Modified "+k,                                    $("", { text: "undo", "class": "actions-undo-button", "data-value": k }).on("click", this.revertAction),                                    $("", { "class": "actions-edit-button", text: "edit", "data-tooltipTitle": this.json[k] && this.json[k].title && this.json[k].title.replaceAll("&amp;", "&"), "data-tooltipText": this.json[k] && this.json[k].text && this.json[k].text.replaceAll("&amp;", "&"), "data-tooltipLink": this.json[k] && this.json[k].name && this.json[k].name.replaceAll("&amp;", "&"), "data-tooltipKey": k.replaceAll("&amp;", "&") }),                                   $(" ", {                                        "class": "actions-preview-button minetip", text: "preview (undo)", "data-minetip-text": this.oldjson[k] && this.oldjson[k].text && this.oldjson[k].text.replaceAll("&amp;", "&"), "data-minetip-title": this.oldjson[k] && this.oldjson[k].title && this.oldjson[k].title.replaceAll("&amp;", "&"), }),                                   $(" ", {                                        "class": "actions-preview-button minetip", text: "preview (current)", "data-minetip-text": this.json[k] && this.json[k].text && this.json[k].text.replaceAll("&amp;", "&"), "data-minetip-title": this.json[k] && this.json[k].title && this.json[k].title.replaceAll("&amp;", "&"), })                               ],                                "class": "actions-modify"                            }));                            break;                        }                        case("remove"): {                            ls[2].push($("", {                                html: [                                    "Removed "+k,                                    $("", { text: "undo", "class": "actions-undo-button", "data-value": k }).on("click", this.revertAction),                                    $(" ", { "class": "actions-preview-button minetip", text: "preview (undo)", "data-minetip-text": this.oldjson[k] && this.oldjson[k].text && this.oldjson[k].text.replaceAll("&amp;", "&"), "data-minetip-title": this.oldjson[k] && this.oldjson[k].title && this.oldjson[k].title.replaceAll("&amp;", "&"), })                               ],                                "class": "actions-remove"                            }));                            break;                        }                    }                }.bind(this)); }

ls.forEach(function(v) { $log.append(v) }); $log.append($("", {text: "Saving changes will also sort all Tooltips in alphabetical order.", "class": "actions-none"})); $("#TooltipsEditor-undoLog").append(ls[3]); //.prepend(ls[3]) $("#TooltipsEditor-totalTooltips").html($(" ", { html: [ "Tooltips Count: "+Object.keys(this.json).length, $(" ", (function { var diff = Object.keys(this.json).length - this.oldjsonkeys.length; if (diff < 0) { return { text: "("+diff+")", css: {color: "red"} }; } else if (diff > 0) { return { text: "(+"+diff+")", css: {color: "lime"} }; } else { return { text: "(0)", css: {color: "gray"} }; }                   }.bind(this))), ],               css: {float: "right"}, }));       },

// helper functions for this.generateSearch searchArray: function(arr, search) { var splitSearch = function(str) { var pattern = str.split("").map(function(v) {                   return "(?=.*" + mw.RegExp.escape(v) + ")";                }).join(""); var regex = new RegExp(pattern, "i"); var match = str.match(regex);

return match && match[0]; };

return arr.filter(function(v) {               return v.toLowerCase.includes(search.toLowerCase) || splitSearch(v.toLowerCase, search.toLowerCase);            }); },

// main function this.generateSearch generateSearch: function { $("#searchResultsMessage").css({ display: "" });

var $this = $("#TooltipsEditor-searchInput"); var $results = $("#TooltipsEditor-searchResults"); var val = $this.val; var abort = false;

if (val.trim === "") return $results.html(" Enter a search term to start searching. ");

var names = Object.keys(this.json).sort; var results = this.searchArray(names, val);

if (results.length > 100) { results.length = 100; abort = true; }

$results.empty;

results.forEach(function(v) {               $results[0].appendChild($("", {                    html: [                        $("", { href: mw.util.getUrl(v), title: v,                           text: v,                            target: "_blank" }),                       " (",                         $("", {                            "class": "TooltipsEditor-editTooltip",                            text: "edit",                            "data-tooltipTitle": this.json[v] && this.json[v].title && this.json[v].title.replaceAll("&amp;", "&"),                            "data-tooltipText": this.json[v] && this.json[v].text && this.json[v].text.replaceAll("&amp;", "&"),                            "data-tooltipLink": this.json[v] && this.json[v].name && this.json[v].name.replaceAll("&amp;", "&"),                            "data-tooltipKey": v.replaceAll("&amp;", "&")                        }), " &bull; ", $(" ", {                           "class": "TooltipsEditor-previewTooltip minetip",                             text: "preview",                            "data-minetip-text": this.json[v] && this.json[v].text && this.json[v].text.replaceAll("&amp;", "&"),                            "data-minetip-title": this.json[v] && this.json[v].title && this.json[v].title.replaceAll("&amp;", "&"),                         }), " &bull; ", $("", {                           "class": "TooltipsEditor-removeTooltip",                             text: "remove",                            "data-key": v.replaceAll("&amp;", "&"),                         }), ")",                   ],                })[0]);            }.bind(this));

if (!results.length) return $results.html(" No tooltip matched your search. "); else if (abort) $results.append(" Showing the first 100 results. "); else $results.append(" Total: "+results.length+(results.length > 1 && " results" || " result" )+". "); },

// helper functions for this.openEditor convertSlashes: function(s) { return s.replaceAll(/(?<!\\)\//g, "\n"); },

// main function this.openEditor openEditor: function(text, title, link, key) { this.isInMain = false; var oldKey = key;

$("#TooltipsEditor-search").css({ display: "none" }); $("#TooltipsEditor-editor").css({ display: "" });

ace.tooltipsTextEditor.resize; ace.tooltipsTitleEditor.resize;

ace.tooltipsTextEditor.setValue(this.convertSlashes(text || "")); ace.tooltipsTitleEditor.setValue(title || ""); $("#TooltipsEditor-link").val(link || ""); $("#TooltipsEditor-key").val(key || "");

$(".qdmodal-button").css({ display: "none" }); $("#TooltipsEditor-save, #TooltipsEditor-preview, #TooltipsEditor-cancel").remove; var $button1 = $(" ", {                   "class": "oo-ui-buttonElement",                }).append(                    $(" ", { id: "TooltipsEditor-save", text: "Save", "class": "oo-ui-buttonElement-button", click: function { var text = ace.tooltipsTextEditor.getValue, title = ace.tooltipsTitleEditor.getValue, key = $("#TooltipsEditor-key").val, link = $("#TooltipsEditor-link").val;

this.throwOldjson(oldKey); this.throwOldjson(key);

if (!key) return alert("You need to enter a tooltip ID!"); if (!link) return alert("You need to enter the tooltip's link!");

if (oldKey) delete this.json[oldKey]; this.editor.addClass("mw-ajax-loader"); $(".qdmodal-button").css({ display: "" }); $("#TooltipsEditor-editor, #searchResultsMessage").css({ display: "none" });

api.post({                                action: "parse",                                 contentmodel: "wikitext",                                text: "",                            }).then(function(data) {                                this.json[key] = {                                    text: text ? $(data.parse.text["*"])                                        .find("p")                                        .html                                        .trim                                        .replace(/&amp;/g, "&")                                        .replace(/(?<!\\)\\/g, "\\\\")                                        .replace(/ /g, " "): undefined,                                    title: title.trim,                                    name: link.trim,                                };                                this.isInMain = true; this.data = this.json; // TODO: DATA? THIS.DATA?

this.updateActions([oldKey, key]); this.reset(true); }.bind(this));                       }.bind(this),                    }) );           var $button2 = $(" ", { "class": "oo-ui-buttonElement", }).append( $(" ", {                       id: "TooltipsEditor-cancel",                        text: "Cancel",                        "class": "oo-ui-buttonElement-button",                        click: function {                            this.reset(confirm("Go back to main page without saving?"));                        }.bind(this),                    }) );           var $button3 = $(" ", { "class": "oo-ui-buttonElement", css: {"float": "right"}, }).append( $(" ", {                       id: "TooltipsEditor-preview",                        "class": "minetip oo-ui-buttonElement-button",                        text: "Preview",                    }) );           $("#TooltipsEditor-editor").append( $button1, $button2, $button3 );           this.updatePreview;        },

// helper functions for this.MainProcess processResult: function(d) { return JSON.parse(d.replaceAll(/\\(?![\'\"\/])/g, '\\\\'));       },        onMatch: function(str) {            var match = this.splitRegex.exec(str);            var values = match.slice(1);            values.push(match[0]);

var types = this.token.apply(this, values);

if (typeof types === "string") return [{ type: types, value: str }];           var tokens = []; for (var i = 0, l = types.length; i < l; i++) { if (values[i]) tokens[tokens.length] = { type: types[i], value: values[i] };           }            return tokens; },       replaceLines: function(s) { return s.replaceAll(/(?<!\\)\//g, "\\/").replaceAll(/\n/g, "/"); },       reset: function(confirm) { if (confirm) { $("#TooltipsEditor-search").css({ display: "" }); $("#TooltipsEditor-searchResults").empty; $("#searchResultsMessage, #TooltipsEditor-editor").css({ display: "none" }); $("#TooltipsEditor > section").removeClass("mw-ajax-loader"); ace.tooltipsTextEditor.setValue(""); ace.tooltipsTitleEditor.setValue(""); $("#TooltipsEditor-key, #TooltipsEditor-link").val(""); $(".qdmodal-button").css({ display: "" }); if ($("#TooltipsEditor-searchInput").val.trim !== "") $("#TooltipsEditor-searchInput").keyup; }       },        getHighlightRules: function { var formats = [];

this.$rules = { start: [{ regex: /&([0-9a-f])/, token: function(code) { this.nextCode = code; this.colorRules["color-" + code].formats = []; return "escape.format.code.color"; }.bind(this), next: function { return "color-" + this.nextCode; }.bind(this), onMatch: this.onMatch, }, {                   regex: /&r/, token: function { formats = []; return "escape.format.code.color"; }.bind(this), }, this.escapes, { regex: /&([l-o])/, token: function(code) { formats.push(this.conversions[code]); return "escape.format.code.color"; }.bind(this), }, {                   regex: /[^\0]/, token: function { var ret = "text.formatted"; formats.forEach(function(code) {                           ret += ".format_" + code;                        }); return ret; },               }],            };

for (var prefix in this.colorRules) { if (this.colorRules.hasOwnProperty(prefix)) { var data = this.colorRules[prefix]; this.$rules[prefix] = data.rules; }           }

this.normalizeRules; },       processColors: function { return Object.keys(this.colorConversions) .map(function(v, i, a) {                   return $("", { "class": "TooltipsEditor-insertFormat" + ((i === a.length-1) && " TooltipsEditor-last" || ""), text: this.colorConversions[v].replaceAll("_", " ").replaceAll(/(\w)(\w*)/g, function(_, $1, $2) {                            return $1.toUpperCase + $2;                        }), "data-insert": "&" + v,                   });                }.bind(this)); },       processRarityTexts: function { return Object.keys(this.rarityConversions) .map(function(v, i, a) {                   return $(" ", { html: [ $("<a>", {                               "class": "TooltipsEditor-insertFormat",                                text: v,                                "data-insert": "&l&" + this.rarityConversions[v] + v.toUpperCase,                                style: "font-style: italic;",                            }), $("<a>", {                               "class": "TooltipsEditor-insertFormat" + ((i === a.length-1) && " TooltipsEditor-last" || ""),                                text: this.shortForm[v],                                "data-insert": "&" + this.rarityConversions[v],                                style: "font-style: italic;",                            }), ]                   });                }.bind(this)); },       updatePreview: function { $("#TooltipsEditor-preview").attr({               "data-minetip-text": this.replaceLines(ace.tooltipsTextEditor.getValue),                "data-minetip-title": ace.tooltipsTitleEditor.getValue,            }); },       insertText: function(text) { var editor = this.lastFocusedEditor; if (!editor && this.lastFocusedElement) { return this.lastFocusedElement.textSelection("encapsulateSelection", {                   pre: text,                    peri: "",                }), true; }

editor.insert(text, 1);

return true; },       setupEditor: function(id) { console.log("Point 1"); var aceEditor = ace.edit(id); console.log("Point 1.1"); var mode = new (ace.require("ace/mode/javascript").Mode); console.log("Point 1.2"); mode.HighlightRules = ace.require("ace/mode/minecraft-tooltips").MinecraftHighlightRules; console.log("Point 1.3"); aceEditor.session.setMode(mode);

console.log("Point 2"); if (id === "TooltipsEditor-text-AceEditor") { aceEditor.setOptions({                   wrapBehavioursEnabled: true,                    wrap: true,                });

console.log("Point 3"); aceEditor.session.on("change", function {                   var height = aceEditor.session.getScreenLength                        * aceEditor.renderer.lineHeight                        + aceEditor.renderer.scrollBar.getWidth + "px";

$(id).css({ height: height }); aceEditor.resize;

if (aceEditor.session.getScreenWidth > 1000) { $(id).css({ width: "1000px" }); }               });            }

console.log("Point 4"); aceEditor.session.on("change", this.updatePreview.bind(this)); aceEditor.on("focus", function {               this.lastFocusedEditor = aceEditor;            }.bind(this));

console.log("Point 5"); return aceEditor; },

// main function this.MainProcess MainProcess: function { this.oldJson = {}; this.json = {}; if (arguments.length > 1) { var jsonStr = [];

// Merge result into a single string to limit JSON.parse calls if (Array.isArray(arguments[0])) { Array.from(arguments).forEach(function(v) {                       jsonStr.push(v[0]["return"].replace(/^\{|\}$/g, ""));                    }); }               else jsonStr.push(arguments[0]["return"].replace(/^\{|\}$/g, "")); // Parse String this.json = this.processResult("{" + jsonStr.join(",") + "}"); } else { this.json = this.processResult(arguments[0]); }

this.editor = $("#TooltipsEditor > section"); this.data = this.json; this.oldjsonkeys = Object.keys(this.json);

ace.define("ace/mode/minecraft-tooltips", [], function(require, exports) {               var oop = require("../lib/oop");                var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;

this.colorRules = {};

this.colorConvList.split("").forEach(function(code) {                   this["color-" + code] = {                        formats: [],                        rules: [{                            token: function(code) {                                this.nextCode = code;                                return "escape.format.code.color";                            },                            regex: /&([0-9a-f])/,                            next: function {                                return "color-" + this.nextCode;                            },                            onMatch: this.onMatch,                        }, {                            regex: /&([l-o])/,                            token: function(code) {                                this.formats.push(this.conversions[code]);                                return "escape.format.code.text";                            }, }, {                           token: "language.escape.format.code", regex: /&r/, next: "start", }, this.escapes, { regex: /[^\0]/, token: function { var ret = "format.color.format-" + code + ".code"; this.formats.forEach(function(code) {                                   ret += ".format_" + code;                                }); return ret; },                       }],                    };

var data = this["color-" + code]; data.rules[0].token = data.rules[0].token.bind(data); data.rules[0].next = data.rules[0].next.bind(data); data.rules[1].token = data.rules[1].token.bind(data); data.rules[4].token = data.rules[4].token.bind(data); }, this.colorRules);

var MinecraftHighlightRules = this.getHighlightRules;

oop.inherits(MinecraftHighlightRules, TextHighlightRules);

exports.MinecraftHighlightRules = MinecraftHighlightRules; }.bind(this));

this.editor.append(               $(" ", { id: "TooltipsEditor-search", html: [ $(" ", { id: "TooltipsEditor-totalTooltips" }), " Tooltips Editor Main Page ", "Search Existing Tooltip: ", $(" ", {                           id: "TooltipsEditor-searchInput",                            keyup: this.generateSearch.bind(this),                        }), " or ", $(" ", {                           "class": "oo-ui-buttonElement",                            html: [                                $(" ", { id: "TooltipsEditor-addNew", "class": "oo-ui-buttonElement-button", text: "Add New Tooltip", click: this.openEditor.bind(this), })                           ]                        }),                        " ",                        $("<ul>", {                            id: "TooltipsEditor-actionLog",                            css: {                                "list-style-type": "none",                                "margin-left": "0.8em",                            },                        }), $(" ", {                           id: "TooltipsEditor-undoLog"                        }), " ",                       $("<b>", { text: "Search Results: ", id: "searchResultsMessage", style: "display: none;" }), $("<ul>", {                           id: "TooltipsEditor-searchResults",                            css: {                                "list-style-type": "square",                                "margin-left": "0.8em",                            },                        }), $(" ", {                           css: {"font-style": "italic", float: "right", "margin-bottom": "1em"},                            html: [                                $(" ", { css: {"margin-left": "0.5em"}, html: ["(", $("<a>", { href: mw.util.getUrl("MediaWiki:Gadget-TooltipsEditor.js"), text: "View JavaScript", target: "_blank" }), ")" ]                               }),                                $(" ", {                                    css: {"margin-left": "0.5em"}, html: ["(", $("<a>", { text: "Debug" }).on("click", function { var it = prompt("Please enter an item to see its JSON"); if (it !== null && it !== "") { if (it in this.json) { console.log({                                                   "JSON": this.json[it].text,                                                    "OUTPUT-WOULD-BE": this.json[it].text.replace(/(['"])/g, "\\$1").replaceAll(/&amp;/g, "&"),                                                });                                                mw.notify("See results in console", {title: "Debug", type:"warning"});                                            }                                            else mw.notify("Debug failed: Item not found.", {title: "Debug", type:"warning"});                                        }                                    }), ")" ]                                }),                            ]                        })                    ]                }),                $(" ", {                    id: "TooltipsEditor-editor", style: "display: none;", html: [ "This editor uses minecraft formatting codes (",                       $("<a>", { href: "https://minecraft.gamepedia.com/Formatting codes", text: "more info", title: "https://minecraft.gamepedia.com/Formatting codes", }),                       ") and the template ", $(" ", {                           html: [                                "",                             ],                        }), "for extra formatting. See the template\'s documentation for more info.", " ",                       $(" ", {                            html: [                                $(" ", { text: "Toolbox (Click to Insert)", css: {"font-weight": "bold", "font-size": "16px"}}),                                $(" ", { html: [ "Formatting", $(" ", { id: "TooltipsEditor-insertFormat", html: this.processColors, "class": "noselect" }), " ",                                       "Special Character", $(" ", { id: "TooltipsEditor-insertChar", html: this.specialchars, "class": "noselect" }), " ",                                       "Rarity Text/Color", $(" ", { id: "TooltipsEditor-insertFormat", html: this.processRarityTexts, "class": "noselect" }), ],                               }),                            ],                        })," ",                        $(" ", { text: "Tooltip ID: ", css: { "font-weight": "bold", "width": "8.7em", display: "inline-block" } }), $(" ", { css: { width: "400px", position: "relative" }, id: "TooltipsEditor-key" }), " ",                       $(" ", { text: "Tooltip Link: ", css: { "font-weight": "bold", "width": "8.7em", display: "inline-block" } }), $(" ", { css: { width: "400px", position: "relative" }, id: "TooltipsEditor-link" }), " "," ",                       $(" ", { text: "Tooltip Title: ", css: { "font-weight": "bold" } }), $(" ", {                           id: "TooltipsEditor-title-AceEditor",                            css: {                                height: "20px",                                "min-width": "600px",                                "max-width": "1000px",                                "font-size": "14px",                                "line-height": "18px",                                "border": "1px solid #474747",                            }                        }), $(" ", { text: "Tooltip Text: ", css: { "font-weight": "bold" } }), $(" ", {                           id: "TooltipsEditor-text-AceEditor",                            css: {                                "font-size": "14px",                                "line-height": "18px",                                "min-height": "200px",                                "max-height": "400px",                                "min-width": "600px",                                "max-width": "1000px",                                "border": "1px solid #474747",                            }                        }), ]               })            );

$(".TooltipsEditor-insertFormat:not('.TooltipsEditor-last')").after($(" ", { text: " • ", }));           this.editor.removeClass("mw-ajax-loader"); this.updateActions;

$("#TooltipsEditor-key, #TooltipsEditor-link").focus(function {               this.lastFocusedElement = $(this);                this.lastFocusedEditor = null;            }.bind(this));

$(".TooltipsEditor-insertFormat").click(function {               var $this = $(this);                var insert = $this.attr("data-insert");

if (this.lastFocusedEditor) { var editor = this.lastFocusedEditor;

var selection = editor.selection; if (!selection.ranges.length) { editor.insert(insert); } else { selection.ranges.forEach(function(range) {                           editor.session.insert({ row: range.start.row, column: range.start.column }, insert);                       }); }                   this.lastFocusedEditor.focus; }               else this.lastFocusedElement.focus; }.bind(this));

console.log('Setting up TooltipsTextEditor: '); window.ace.tooltipsTextEditor = this.setupEditor("TooltipsEditor-text-AceEditor"); console.log(window.ace.tooltipsTextEditor); console.log('Setting up TooltipsTitleEditor: '); window.ace.tooltipsTitleEditor = this.setupEditor("TooltipsEditor-title-AceEditor"); console.log(window.ace.tooltipsTitleEditor);

$(document.body).on("click", ".TooltipsEditor-insertChar", function(e) {               e.preventDefault;                e.stopImmediatePropagation;

if (this.lastFocusedEditor) { this.insertText($(this).attr("data-insert") || $(this).text); this.lastFocusedEditor.focus; }               else this.lastFocusedElement.focus; }.bind(this));

$(document.body).on("click", ".TooltipsEditor-removeTooltip", function {               var $this = $(this);                var key = $this.attr("data-key");

this.throwOldjson(key); delete this.json[key]; this.updateActions(key); $("#TooltipsEditor-searchInput").keyup; }.bind(this));

$(document.body).on("click", ".TooltipsEditor-editTooltip, .actions-edit-button", function {               var $this = $(this);

this.openEditor(                   $this.attr("data-tooltipText"),                     $this.attr("data-tooltipTitle"),                     $this.attr("data-tooltipLink"),                    $this.attr("data-tooltipKey")                ); }.bind(this));       },

// helper functions for this.onClick luaTableToJson: function(s) { return api.post({               action: "scribunto-console",                title: mw.config.get("wgPageName"),                question: "=mw.text.jsonEncode(p)",                content: s,            }); },       editorCloseHandler: function { this.closing = true;

if (confirm("Are you sure you want to save and close the editor?")) this.modal.hide; else return;

var ret = [];

Object.keys(this.data).sort.forEach(function(k) {               var v = this.data[k];

ret.push([                   "\t['" + k.replace(/(['"])/g, "\\$1") + "'] = {",                    v.name ? "name = '" + v.name.replace(/(['"])/g, "\\$1") + "', " : "",                    v.title ? "title = '" + v.title.replace(/(['"])/g, "\\$1") + "', " : "",                    v.text ? "text = '" + v.text.replace(/(['"])/g, "\\$1") + "', " : "",                    "},",                ].join("")); }.bind(this));

ret = "return {\n" + ret.join("\n") + "\n}\n".replaceAll(/&amp;/g, "&"); console.log(ret);

api.postWithEditToken({               action: "edit",                text: ret,                title: mw.config.get("wgPageName"),                summary: "Updating tooltips (TooltipsEditor)",                minor: true,            }).always(console.log);

mw.notify("", {title: "Tooltips Saved!", type:"success"}); },

// main function this.onClick onClick: function(tooltips) { this.closing = false;

$(window).on("beforeunload", function {               if (!this.closing)                    return "Are you sure you want to exit the page and discard your changes?";            }.bind(this));

this.modal.show({               title: "Tooltips Editor",                onHide: function {                    if (!this.closing && confirm("Are you sure you want to exit the editor and discard your changes?")) {                        this.closing = true;                        return true;                    }                    else if (this.closing) return true;                    else return false;                }.bind(this),                buttons: [{                    text: "Save and Close",                    handler: this.editorCloseHandler.bind(this),                }],            }); $("#TooltipsEditor > section").attr("class", "mw-ajax-loader");

var promises = []; var split = tooltips.split("\n");

// Split lua table into multiple tables due to size limitation of 500k bytes if (split.length > 1350) { var lines = split; lines.pop; lines.shift;

for (var i = 0; i < lines.length; i += 900) { var ret = "return {\n" + lines.slice(i, i + 900).join("\n") + "\n}"; promises.push(this.luaTableToJson(ret)); }           } else { promises = [this.luaTableToJson(tooltips)]; }

$.when.apply($, promises).then(this.MainProcess.bind(this), function(code, e) {               return alert("Failed to parse Tooltips: ", e), console.warn("Failed to parse Tooltips: ", e);            }).catch(console.warn); },

// entry point init: function { $(' ', {               rel: "stylesheet",                 href: "https://hypixel-skyblock.fandom.com/wiki/MediaWiki:Gadget-TooltipsEditor.css?action=raw&ctype=text/css"             }).appendTo('head');

$(".editTooltips").click(function {               api.get({ action: "query", format: "json", prop: "revisions", titles: mw.config.get("wgPageName"), formatversion: 2, rvprop: "content", rvslots: "*" }).then(function(d) { var content = d.query.pages[0].revisions[0].slots.main.content;

this.actions = []; this.onClick(content); }.bind(this));           }.bind(this)); },   });

this.init; }.bind((window.TooltipsEditor = window.TooltipsEditor || Object.create(null)))).catch(console.warn);