📌 Current mission: start filling the wiki — create pages, upload images, and join the Discord!

MediaWiki:Common.js

From Asylum Wiki
Revision as of 16:25, 12 July 2026 by Felix (talk | contribs) (Emote autocomplete for the source editor)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigationJump to search

Note: After publishing, you may have to bypass your browser's cache to see the changes.

  • Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
  • Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
  • Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5.
/* Asylum Wiki — emote autocomplete for the source editor.
   In any edit box, type ":" followed by 2+ characters (e.g. :kon) and pick
   a suggestion with the arrow keys + Enter, or click it. Inserts {{e|name|ext}}.
   Regenerate the EMOTES map when new emotes are uploaded (see Project:Emotes). */
(function () {
    'use strict';

    var EMOTES = {"00":"gif","00_1":"gif","00_2":"gif","00_3":"gif","00_4":"gif","00_5":"gif","00_6":"gif","4Concern":"png","4Smile":"png","4chan":"png","4clover":"png","770133186713485333":"png","A_touhoucirnodance":"gif","AndyDrunk":"gif","AshGiggle":"gif","B_rikadeadstare":"gif","C_blacklaugh":"png","Cirnoblush":"png","Clover":"png","Coal":"png","Coal_(1)":"png","D_dancespin":"gif","D_vibe":"gif","Dancing":"gif","G_areyou":"png","Geass":"png","Haych":"png","Hesrightyouknow":"png","Incel":"png","JuliaGiggle":"gif","KonataAww":"gif","KonataCornet":"png","KonataCornet1":"png","KonataDark":"png","KonataHappy":"gif","KonataHeart":"png","KonataIDK":"png","KonataPeace":"png","KonataProud":"gif","KonataSad":"png","KonataSleepy":"png","KonataSmug":"png","KonataTea":"gif","KonataWoah":"png","KonataYawn1":"gif","LohenOh":"png","Mymystare":"png","N_pussyalert":"gif","P_KEKKKKKK":"png","P_blush":"png","P_cheers":"png","P_clown":"png","P_coffee":"png","P_dumb":"png","P_feelingbad":"png","P_feels":"png","P_heart":"png","P_hmm":"png","P_kek":"png","P_kekkers":"gif","P_kekkkk":"png","P_nobodycares":"png","P_notimpressed":"png","P_ok":"png","P_pointnlaugh":"png","P_suicide":"png","P_sweat":"png","P_think":"gif","P_tos":"gif","Pepesmirk":"png","Pepobusiness":"png","Press_f":"png","Q_bearpout":"gif","Q_bearsclingy":"png","Q_bearshrug":"png","Q_bearshug":"gif","Q_bearskiss":"gif","Q_bearsmwah":"png","R_rikablush":"png","R_rikaglasses":"png","R_rikaheart":"png","R_tenshicry":"png","Rainbowdashq":"png","RemiANGRYE":"png","RemiYOUCANNOTSAYTHAT":"png","Remiblush":"png","Remiugh":"gif","Reversecard":"png","Rikacoal":"png","Rikadoctos":"png","Rikahappy":"png","Rip":"gif","S_angryjak":"png","S_christmasfloyd":"png","S_chud":"png","S_chudjak":"png","S_chudsmug":"png","S_corrupt":"png","S_doomer":"png","S_egirl":"png","S_itsover":"png","S_laughjak":"gif","S_pajeet":"png","S_shhh":"png","S_soy":"png","S_soyrage":"png","S_troonsob":"png","Sealbro":"png","Smoke_mymelody":"gif","Society":"png","Soyhang":"png","Soyhang_(1)":"png","Spade":"png","SpinAndrew":"gif","SpinAndy":"gif","SpinAshley":"gif","SpinLey":"gif","Tenshicry":"png","Teto_tired":"png","Think":"png","Tinyblackpecker":"png","Tinyface":"png","Transheart":"png","Transheart_1":"png","Tt2_awkward":"png","Tt2_cute":"png","Tt2_excited":"png","Tt2_proud":"png","Tt2_tears":"png","Tt2_wink":"png","Tt_angry":"png","Tt_annoyed":"png","Tt_cool":"png","Tt_cry":"png","Tt_embarrassed":"png","Tt_happy":"png","Tt_kiss":"png","Tt_rollingeyes":"png","Tt_shy":"png","Tt_thinking":"png","Tt_thumbsup":"png","Tumblr_2970f9c20a30bc965a62897a1":"png","V_downvote":"png","V_upvote":"png","W_grin":"png","Wanwan":"png","Wanwan2":"png","Wanwanautism":"png","Wanwandance":"gif","Wanwanerm":"gif","Wanwangrumpy":"gif","Wanwanheadpat":"gif","Wanwanlick":"gif","Wanwanlove":"gif","Wanwanwaow":"gif","Wanwanwave":"gif","Wanwanwave_1":"gif","Y_correction":"png","Y_nerdplead":"png","Y_pacdance":"gif","Y_samsungcry":"png","Y_skype4l":"gif","Y_skypegiggle":"gif","Y_skypenotlistening":"gif","Y_skyperofl":"gif","Y_skypetired":"gif","Y_skypetongue":"gif","Yotsubablackface":"png","Yotsubacamera":"png","Yotsubaconfused":"png","Yotsubacool":"png","Yotsubahappy":"png","Yotsubahearteyes":"png","Yotsubahide":"png","Yotsubahuh":"png","Yotsubasalute":"png","Yotsubasing":"png","Yotsubastare":"png","Yotsubawhatever":"png","Yotsubaxp":"png","Z_black":"png","Z_blue":"png","Z_buryebil":"gif","Z_darkblue":"png","Z_green":"png","Z_lgbtq":"png","Z_noose":"png","Z_orange":"png","Z_pink":"png","Z_purple":"png","Z_red":"png","Z_white":"png","Z_wumpyangry":"gif","Z_wumpylove":"gif","Z_wumpysleep":"gif","Z_wumpythink":"gif","Z_yellow":"png"};
    var NAMES = Object.keys(EMOTES);

    function init() {
        var ta = document.getElementById('wpTextbox1');
        if (!ta) return;

        var box = document.createElement('div');
        box.className = 'emote-ac';
        box.style.display = 'none';
        document.body.appendChild(box);

        var items = [];
        var active = -1;
        var matchStart = -1;

        function hide() {
            box.style.display = 'none';
            items = [];
            active = -1;
            matchStart = -1;
        }

        function fileUrl(name) {
            return '/index.php?title=Special:Redirect/file/' +
                encodeURIComponent(name + '.' + EMOTES[name]) + '&width=24';
        }

        function caretXY(pos) {
            var style = window.getComputedStyle(ta);
            var div = document.createElement('div');
            var props = ['fontFamily', 'fontSize', 'fontWeight', 'lineHeight',
                'letterSpacing', 'paddingTop', 'paddingRight', 'paddingBottom',
                'paddingLeft', 'borderTopWidth', 'borderRightWidth',
                'borderBottomWidth', 'borderLeftWidth', 'boxSizing', 'width'];
            for (var i = 0; i < props.length; i++) {
                div.style[props[i]] = style[props[i]];
            }
            div.style.position = 'absolute';
            div.style.visibility = 'hidden';
            div.style.whiteSpace = 'pre-wrap';
            div.style.wordWrap = 'break-word';
            div.textContent = ta.value.substring(0, pos);
            var marker = document.createElement('span');
            marker.textContent = '​';
            div.appendChild(marker);
            document.body.appendChild(div);
            var rect = ta.getBoundingClientRect();
            var out = {
                top: rect.top + window.scrollY + marker.offsetTop - ta.scrollTop + 22,
                left: rect.left + window.scrollX + marker.offsetLeft - ta.scrollLeft
            };
            document.body.removeChild(div);
            return out;
        }

        function insert(idx) {
            var name = items[idx];
            if (!name || matchStart < 0) return;
            var text = '{{e|' + name + '|' + EMOTES[name] + '}}';
            ta.setRangeText(text, matchStart, ta.selectionStart, 'end');
            hide();
            ta.focus();
        }

        function render(pos) {
            box.innerHTML = '';
            items.forEach(function (name, i) {
                var d = document.createElement('div');
                d.className = 'emote-ac-item' + (i === active ? ' emote-ac-active' : '');
                var img = document.createElement('img');
                img.src = fileUrl(name);
                img.loading = 'lazy';
                var span = document.createElement('span');
                span.textContent = name;
                d.appendChild(img);
                d.appendChild(span);
                d.addEventListener('mousedown', function (e) {
                    e.preventDefault();
                    insert(i);
                });
                box.appendChild(d);
            });
            var xy = caretXY(pos);
            box.style.top = xy.top + 'px';
            box.style.left = xy.left + 'px';
            box.style.display = 'block';
        }

        ta.addEventListener('input', function () {
            var pos = ta.selectionStart;
            var before = ta.value.substring(Math.max(0, pos - 40), pos);
            var m = before.match(/:([A-Za-z0-9_]{2,})$/);
            if (!m) { hide(); return; }
            var q = m[1].toLowerCase();
            var starts = [], contains = [];
            for (var i = 0; i < NAMES.length; i++) {
                var lower = NAMES[i].toLowerCase();
                if (lower.indexOf(q) === 0) starts.push(NAMES[i]);
                else if (lower.indexOf(q) !== -1) contains.push(NAMES[i]);
            }
            items = starts.concat(contains).slice(0, 8);
            if (!items.length) { hide(); return; }
            matchStart = pos - m[1].length - 1;
            active = 0;
            render(pos);
        });

        ta.addEventListener('keydown', function (e) {
            if (box.style.display === 'none') return;
            if (e.key === 'ArrowDown') {
                e.preventDefault();
                active = (active + 1) % items.length;
                render(ta.selectionStart);
            } else if (e.key === 'ArrowUp') {
                e.preventDefault();
                active = (active - 1 + items.length) % items.length;
                render(ta.selectionStart);
            } else if (e.key === 'Enter' || e.key === 'Tab') {
                e.preventDefault();
                insert(active);
            } else if (e.key === 'Escape') {
                hide();
            }
        });

        ta.addEventListener('blur', function () {
            setTimeout(hide, 200);
        });
    }

    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', init);
    } else {
        init();
    }
})();