您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Adds ability to input emoji and symbol characters via picker popup which is accessible using ALT+` (ALT and backquote) keyboard shortcut (configurable in the script). Character will be generated at the (blinking) cursor. If there's text selected, the character will replace the selection. Note: this script will not work on inputboxes whose keyboard inputs is script driven. e.g. WYSIWYG text boxes.
// ==UserScript== // @name Emoji & Symbol Picker // @namespace https://gf.qytechs.cn/en/users/85671-jcunews // @version 1.1.7 // @author jcunews // @license GNU AGPLv3 // @description Adds ability to input emoji and symbol characters via picker popup which is accessible using ALT+` (ALT and backquote) keyboard shortcut (configurable in the script). Character will be generated at the (blinking) cursor. If there's text selected, the character will replace the selection. Note: this script will not work on inputboxes whose keyboard inputs is script driven. e.g. WYSIWYG text boxes. // @match *://*/* // @include *:* // @grant none // ==/UserScript== ((eleHdr, eleFontSize, eleAll, prevEleDown, eleDown, dragBaseX, dragBaseY, dragStartX, dragStartY, eleFocus, a, b) => { //=== CONFIGURATION BEGIN === //hotkey setting to show/hide picker panel var hotkeyCtrl = false; var hotkeyShift = false; var hotkeyAlt = true; var hotkeyKey = "`"; //=== CONFIGURATION END === var blocks = [ "Emoticons (1F600-1F64F)", "Supplemental Symbols and Pictographs (1F900-1F9FF)\u{1f985}", "Miscellaneous Symbols and Pictographs (1F300-1F5FF)", "Transport and Map Symbols (1F680-1F6FF)", "Miscellaneous Symbols (2600-26FF)", "Dingbats (2700-27BF)", "Arrows (2190-21FF)", "Miscellaneous Symbols and Arrows (2B00-2BFF)", "Supplemental Arrows-C (1F800-1F8FF)", "Miscellaneous Technical (2300-23FF)", "Geometric Shapes (25A0-25FF)\u25a4", "Geometric Shapes Extended (1F780-1F7FF)\u{1f78a}", "Block Elements (2580-259F)\u258a", "Box Drawing (2500-257F)\u2554" ]; var fontSizes = [8, 9, 10, 11, 12, 14, 16, 18, 20, 22, 24, 26, 28, 36, 48, 72, 96, 120, 144, 176, 208, 240]; function isEditable(e) { while (e) { if (e.contentEditable === "true") return true; e = e.parentNode; } return false; } function panelMove(e) { panel.style.left = dragBaseX + (e.screenX - dragStartX) + "px"; panel.style.top = dragBaseY + (e.screenY - dragStartY) + "px"; }; function panelResize(e) { panel.style.width = dragBaseX + (e.screenX - dragStartX) + "px"; panel.style.height = dragBaseY + (e.screenY - dragStartY) + "px"; }; function selectBlock() { panel.querySelector(".ekResize~.ekButton.selected").classList.remove("selected"); this.classList.add("selected"); panel.querySelector(".ekBlock.selected").classList.remove("selected"); panel.querySelector(`.ekBlock[index="${this.getAttribute("index")}"]`).classList.add("selected"); panel.querySelector(".ekBody").scrollTo(0, 0); } if (document.contentType === "application/xml") return; var to = {createHTML: s => s}, tp = window.trustedTypes?.createPolicy ? trustedTypes.createPolicy("", to) : to, html = s => tp.createHTML(s); var panel = document.createElement("DIV"); panel.id = "ekPanel"; panel.innerHTML = html(`<style> #ekPanel{display:block;position:fixed;z-index:999999999;left:33vw;top:33vh;box-shadow:0 0 10px 0;border:2px solid #000;border-radius:6px;box-sizing:border-box;min-width:58ex;width:58ex;max-width:99vw;min-height:6.8em;max-height:99vh;height:12em;background:#fff;font:normal normal normal 12pt/normal sans-serif} #ekPanel *{font:inherit} .ekContent{display:flex;flex-direction:column;position:relative;width:100%;height:100%} .ekHeader{flex-shrink:1;margin:0;padding:0 0 .15em .5ex;background:#000;color:#fff;cursor:move} .ekButton{display:inline-block;vertical-align:top;width:1.5em;height:1.5em;text-align:center;cursor:pointer} #ekPanel .ekClose{float:right;border-radius:4px;background:#f00;font-size:84%} .ekBody{display:block;flex-shrink:1;height:100%;overflow-y:scroll} .ekBlock{display:none} .ekBlock.selected{display:block} .ekBlock .ekButton{margin:0 .3ex .3ex 0} .ekBlock .ekButton:hover{background:#ddf} .ekFooter{display:block;flex-shrink:1;border-top:1px solid #000} .ekResize{position:absolute;right:0;bottom:0;border-top:1em solid #fff;border-right:1em solid #bbb;width:auto;height:auto;cursor:se-resize} .ekResize~.ekButton{margin-right:.3ex;border-radius:4px} .ekResize~.ekButton.selected{background:#bdb} .ekResize~.ekButton:hover{background:#ddf} .ekResize~.ekButton:last-child{margin-right:1.5em} #ekPanel .ekFontSize{margin-left:2ex;font-size:84%} </style> <div class="ekContent"> <h4 class="ekHeader"><div class="ekClose ekButton">✖</div>Emoji & Symbol Picker</h4> <div class="ekBody"></div> <div class="ekFooter"> <div class="ekResize ekButton"></div> <select class="ekFontSize"></select> </div> </div>`); panel.addEventListener("mousedown", e => { if (document.activeElement && (document.activeElement !== eleFontSize)) eleFocus = document.activeElement; prevEleDown = eleDown; eleDown = e.target; if (((prevEleDown === eleFontSize) && (eleDown === eleFontSize)) || !eleDown || !["SELECT", "OPTION"].includes(eleDown.tagName)) { eleDown = null; e.preventDefault(); eleFocus && eleFocus.focus(); } }); (eleHdr = panel.querySelector(".ekHeader")).onmousedown = e => { if ((e.buttons !== 1) || (e.target !== eleHdr)) return; e.preventDefault(); dragBaseX = panel.offsetLeft; dragBaseY = panel.offsetTop; dragStartX = e.screenX; dragStartY = e.screenY; addEventListener("mousemove", panelMove); panel.onmouseup = function(e) { removeEventListener("mousemove", panelMove); panel.onmouseup = null; }; }; panel.querySelector(".ekClose").onclick = () => { panel.remove(); eleFocus && eleFocus.focus(); eleFocus = null; }; (a = panel.querySelector(".ekBody")).addEventListener("click", (e,c,s,d,f) => { if (((e = e.target).className !== "ekButton") || !eleFocus) return; if ((eleFocus.tagName === "TEXTAREA") || ((eleFocus.tagName === "INPUT") && (eleFocus.type === "text"))) { a = eleFocus.selectionStart; b = eleFocus.selectionEnd; if (a > b) { c = a; a = b; b = c; } eleFocus.value = eleFocus.value.slice(0, a) + e.textContent + eleFocus.value.slice(b); eleFocus.selectionStart = eleFocus.selectionEnd = a + e.textContent.length; } else if (isEditable(eleFocus) && (s = getSelection())) { eleFocus && eleFocus.focus(); if (("InstallTrigger" in window) && (s.rangeCount > 1)) { //Firefox can't mix text and element nodes in a selection. So if there's multiple seletion ranges, merge them into one range. a = s.getRangeAt(s.rangeCount - 1); b = a.endContainer; c = a.endOffset; s.collapseToStart(); a = s.getRangeAt(0); a.setEnd(b, c); } s.deleteFromDocument(); a = s.getRangeAt(0); b = a.startContainer; c = a.startOffset; if (b.nodeType === Node.ELEMENT_NODE) { b.insertBefore(document.createTextNode(e.textContent), b.childNodes[c]); } else b.data = b.data.slice(0, c) + e.textContent + b.data.slice(c); a.setStart(b, c + e.textContent.length); a.setEnd(b, c + e.textContent.length); } }); b = panel.querySelector(".ekFooter"); blocks.forEach((n,i,e,d,s,j,h) => { b.insertBefore(e = document.createElement("DIV"), b.lastElementChild); j = n.lastIndexOf(")"); if (j < (n.length - 1)) { s = n.codePointAt(j + 1); n = n.slice(0, j + 1); } e.title = n; d = n.match(/\((.*)-(.*)\)/); d.shift(); d = d.map(v => parseInt(v, 16)); e.textContent = String.fromCodePoint(s || d[0]); e.className = "ekButton" + (i ? "" : " selected"); e.setAttribute("index", i); e.onclick = selectBlock; e = document.createElement("DIV"); e.className = "ekBlock" + (i ? "" : " selected"); e.setAttribute("index", i); s = ""; for (j = d[0]; j <= d[1]; j++) { h = j.toString(16).toUpperCase(); s += `<div class="ekButton" title="Character code ${j} (0x${("0000000" + h).slice(j > 0xffffff ? 0 : j > 0xffff ? -6 : -4)})">&#x${h};</div>`; } e.innerHTML = html(s); a.appendChild(e); }); (eleAll = Array.from(panel.querySelectorAll("*"))).unshift(panel); eleFontSize = panel.querySelector(".ekFontSize"); fontSizes.forEach(v => { eleFontSize.appendChild(b = document.createElement("OPTION")); b.textContent = v + "pt"; (v === 12) && (b.selected = true); }); eleFontSize.onchange = () => { panel.querySelector(".ekBody").style.fontSize = eleFontSize.value; eleFocus && eleFocus.focus(); }; panel.querySelector(".ekResize").onmousedown = e => { if (e.buttons !== 1) return; e.preventDefault(); dragBaseX = panel.offsetWidth; dragBaseY = panel.offsetHeight; dragStartX = e.screenX; dragStartY = e.screenY; addEventListener("mousemove", panelResize); panel.onmouseup = function(e) { removeEventListener("mousemove", panelResize); panel.onmouseup = null; }; }; addEventListener("keydown", e => { if ((e.ctrlKey !== hotkeyCtrl) || (e.shiftKey !== hotkeyShift) || (e.altKey !== hotkeyAlt) || (e.key.toUpperCase() !== hotkeyKey.toUpperCase())) return; e.preventDefault(); e.stopPropagation(); e.stopImmediatePropagation(); if (panel.parentNode) { panel.remove(); eleFocus && eleFocus.focus(); } else { eleFocus = document.activeElement; eleDown = null; document.body.appendChild(panel); } }, true); })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址