// ==UserScript==
// @name Reddit Multi Emote Picker (WORKING)
// @namespace http://tampermonkey.net/
// @version 1.3
// @description Adds a popup emote picker with multiple emotes to Reddit comment box on right-click, inserts emote text like [emote:t5_33td5:59888](http://img)
// @author You
// @match https://www.reddit.com/r/*/comments/*
// @grant none
// ==/UserScript==
(function () {
'use strict';
const baseEmoteId = 59888; // starting emote number for Clueless
const emoteNames = [
'Clueless',
'Okayeg',
'cmonBruh',
'Copesen',
'forsenCD',
'forsenE',
'tf',
'FeelsOkayMan',
'gachiGASM',
'monkaOMEGA',
'LULE',
'OMEGALUL',
'PagMan',
'forsenBased',
'Sadeg',
'forsenAlright',
'forsenLevel',
'pepeLaugh',
'forsenDespair',
'sadE',
'forsenMaxLevel',
'maoE',
'Wutface',
'MegaLUL',
'Docsen',
'amongE',
'Batchest',
'forsenNugget',
'LongHairMaxLevel',
'Pewds',
'monkaLaugh'
];
const emoteBaseUrl = 'https://rarestemotes.github.io/emotes/images/';
// Build EMOTES array with name, image src, and emote code string
const EMOTES = emoteNames.map((name, index) => {
// Image URL: base + name + ".png"
const src = `${emoteBaseUrl}${name}.png`;
// Emote code: using the ID starting at 59888 and incrementing
const code = `[emote:t5_33td5:${baseEmoteId + index}](http://img)`;
return { name, src, code };
});
let currentTarget = null;
const picker = document.createElement('div');
picker.id = 'customEmotePicker';
picker.style.position = 'absolute';
picker.style.background = '#1a1a1b';
picker.style.border = '1px solid #555';
picker.style.padding = '10px';
picker.style.zIndex = 9999;
picker.style.borderRadius = '8px';
picker.style.boxShadow = '0 4px 12px rgba(0,0,0,0.6)';
picker.style.display = 'none';
picker.style.width = '220px';
picker.style.display = 'grid';
picker.style.gridTemplateColumns = 'repeat(5, 1fr)';
picker.style.gap = '8px';
picker.style.textAlign = 'center';
EMOTES.forEach(({ name, src, code }) => {
const emote = document.createElement('img');
emote.src = src;
emote.alt = name;
emote.title = name;
emote.style.width = '32px';
emote.style.height = '32px';
emote.style.cursor = 'pointer';
emote.style.userSelect = 'none';
emote.addEventListener('click', () => {
if (currentTarget) {
currentTarget.focus();
const selection = window.getSelection();
if (selection.rangeCount === 0) return;
const range = selection.getRangeAt(0);
range.deleteContents();
const textNode = document.createTextNode(code);
range.insertNode(textNode);
range.setStartAfter(textNode);
range.collapse(true);
selection.removeAllRanges();
selection.addRange(range);
currentTarget.dispatchEvent(new InputEvent('input', {
bubbles: true,
cancelable: true,
inputType: 'insertText',
data: code
}));
}
picker.style.display = 'none';
currentTarget = null;
});
picker.appendChild(emote);
});
document.body.appendChild(picker);
// Show picker on right-click inside comment box
document.addEventListener('contextmenu', (e) => {
const editable = e.target.closest('div[contenteditable="true"][role="textbox"]');
if (editable) {
e.preventDefault();
currentTarget = editable;
picker.style.left = `${e.pageX}px`;
picker.style.top = `${e.pageY}px`;
picker.style.display = 'grid';
} else {
picker.style.display = 'none';
currentTarget = null;
}
});
// Hide on click elsewhere
document.addEventListener('click', () => {
picker.style.display = 'none';
currentTarget = null;
});
})();