mczwlt_fast_emoji_plugin

love

  1. // ==UserScript==
  2. // @name mczwlt_fast_emoji_plugin
  3. // @namespace https://forum.mczwlt.net/
  4. // @version 2025-02-01
  5. // @description love
  6. // @author Aurora_creeper
  7. // @match https://forum.mczwlt.net/*
  8. // @grant GM_addStyle
  9. // @license MIT
  10. // ==/UserScript==
  11.  
  12. const DATA = {
  13. default: {
  14. icon: '',
  15. urls: [
  16. 'https://attachment.mczwlt.net/mczwlt/public/user/2025/01/31/_NhmDq_mGPM2UycACZ447.png',
  17. ],
  18. },
  19. };
  20.  
  21. function css(arg) {
  22. GM_addStyle(arg);
  23. }
  24.  
  25. function html(arg) {
  26. return arg;
  27. }
  28.  
  29. (function () {
  30. 'use strict';
  31.  
  32. css`
  33. .fast_emoji {
  34. z-index: 6000;
  35. user-select: none;
  36. position: fixed;
  37. left: 0.9rem;
  38. bottom: 5rem;
  39. display: flex;
  40. align-items: flex-end;
  41. }
  42.  
  43. .fast_emoji_button {
  44. z-index: 5200;
  45. height: 3.25rem;
  46. width: 3.25rem;
  47. border-radius: 100rem;
  48. background: royalblue;
  49. display: inline-block;
  50. position: relative;
  51. }
  52.  
  53. .fast_emoji_button > p {
  54. line-height: 2.5rem;
  55. font-size: 3.25rem;
  56. color: white;
  57. text-align: center;
  58. cursor: pointer;
  59. }
  60.  
  61. .fast_emoji .fast_emoji_box {
  62. display: none;
  63. }
  64.  
  65. .fast_emoji.active .fast_emoji_box {
  66. display: inline-block;
  67. }
  68.  
  69. .fast_emoji_box {
  70. z-index: 5100;
  71. width: 32.5rem;
  72. height: 18.5rem;
  73. background-color: white;
  74. border-radius: 0.25rem;
  75. box-shadow: 0.1rem 0.1rem 0.25rem #eee, -0.1rem -0.1rem 0.25rem #eee;
  76. position: relative;
  77. }
  78. `;
  79.  
  80. const fastEmoji = document.createElement('div');
  81. fastEmoji.classList.add('fast_emoji');
  82.  
  83. // solve button icon
  84. const button_icon = document.createElement('p');
  85. button_icon.classList.add('fast_emoji_button_icon');
  86. button_icon.innerHTML = '+';
  87.  
  88. // solve button
  89. const button = document.createElement('div');
  90. button.classList.add(`fast_emoji_button`);
  91.  
  92. button.appendChild(button_icon);
  93.  
  94. function activeToggle() {
  95. fastEmoji.classList.toggle('active');
  96.  
  97. const inter = fastEmoji.classList.contains('active') ? '-' : '+';
  98. button_icon.innerHTML = inter;
  99. }
  100.  
  101. button_icon.addEventListener('click', activeToggle);
  102.  
  103. fastEmoji.appendChild(button);
  104.  
  105. // solve box
  106. const box = document.createElement('p');
  107. box.classList.add('fast_emoji_box');
  108. fastEmoji.appendChild(box);
  109.  
  110. // solve inner items
  111. // sorry for suck class name
  112. css`
  113. .fast_emoji_subBox {
  114. margin-left: 22px;
  115. }
  116.  
  117. .fast_emoji_title {
  118. line-height: 40px;
  119. font-size: 1rem;
  120. margin: 0;
  121. }
  122.  
  123. .fast_emoji_emojiBox {
  124. width: 500px;
  125. height: 265px;
  126. height: 200px;
  127. overflow: auto;
  128. }
  129.  
  130. .fast_emoji_aEmoji {
  131. cursor: default;
  132. display: inline-block;
  133. width: 65px;
  134. height: 65px;
  135. padding: 5px;
  136. margin-right: -2px;
  137. margin-bottom: -2px;
  138. border: 2px solid #ededee;
  139. transition: color 0.1s cubic-bezier(0.2, 0.8, 0.1, 0.8);
  140. background-size: contain;
  141. background-repeat: no-repeat;
  142. background-origin: content-box;
  143. background-position: center;
  144. }
  145.  
  146. .fast_emoji_aEmoji[style]:hover {
  147. width: 65px;
  148. height: 65px;
  149. padding: 2.5px;
  150. background-color: #f3f3f4;
  151. }
  152. `;
  153.  
  154. let activeTextarea = null;
  155. document.addEventListener(
  156. 'focus',
  157. (event) => {
  158. if (event.target.tagName === 'TEXTAREA') {
  159. activeTextarea = event.target;
  160. }
  161. },
  162. true
  163. );
  164.  
  165. const subBox = document.createElement('div');
  166. subBox.classList.add('fast_emoji_subBox');
  167. box.appendChild(subBox);
  168.  
  169. const title = document.createElement('p');
  170. title.classList.add('fast_emoji_title');
  171. title.innerText = 'Emoji';
  172. subBox.appendChild(title);
  173.  
  174. const emojiBox = document.createElement('div');
  175. emojiBox.classList.add('fast_emoji_emojiBox');
  176. subBox.appendChild(emojiBox);
  177.  
  178. function leftClickCallback(event) {
  179. event.preventDefault();
  180. if (!activeTextarea) return;
  181.  
  182. const target = event.target;
  183. const cursorPosition = activeTextarea.selectionStart;
  184. const currentValue = activeTextarea.value;
  185.  
  186. console.log(target.style.backgroundImage);
  187.  
  188. const match = target.style.backgroundImage.match(
  189. /url\(["']?(.*?)["']?\)/
  190. );
  191. if (!match) return;
  192.  
  193. const textToInsert = `![](${match[1]})`;
  194. const newValue =
  195. currentValue.slice(0, cursorPosition) +
  196. textToInsert +
  197. currentValue.slice(cursorPosition);
  198.  
  199. activeTextarea.value = newValue;
  200. activeTextarea.selectionStart = activeTextarea.selectionEnd =
  201. cursorPosition + textToInsert.length;
  202.  
  203. activeTextarea.focus();
  204. activeToggle();
  205. }
  206.  
  207. let mxEmoji = 60;
  208. for (const name in DATA) {
  209. const slot = DATA[name];
  210. if (slot?.urls?.length instanceof Number)
  211. mxEmoji = Math.max(mxEmoji, slot.urls.length);
  212. }
  213.  
  214. for (let index = 0; index < mxEmoji; index++) {
  215. // const itemWarpper = document.createElement('div');
  216. const item = document.createElement('div');
  217. item.classList.add('fast_emoji_aEmoji');
  218. item.style.backgroundImage = `url(${DATA.default.urls[index]})`;
  219. item.addEventListener('click', leftClickCallback);
  220. // itemWarpper.appendChild(item);
  221. emojiBox.appendChild(item);
  222. }
  223.  
  224. // APPEND
  225. document.body.appendChild(fastEmoji);
  226.  
  227. // post effect
  228. })();