253874 face icon

添加表情图标

  1. //@ts-check
  2. // ==UserScript==
  3. // @name 253874 face icon
  4. // @namespace {1863332F-7B8F-44F6-912E-6424CE3443F7}
  5. // @version 0.3
  6. // @description 添加表情图标
  7. // @author You
  8. // @match https://www.253874.net/*
  9. // @match https://253874.net/*
  10. // @icon https://www.253874.net/favicon.ico
  11. // @grant GM_addStyle
  12. // @require https://cdn.jsdelivr.net/gh/component/textarea-caret-position@b5845a4c39cf094b56925183c086f92c8f8fec68/index.js
  13. // @run-at document-end
  14. // @license GPL
  15. // ==/UserScript==
  16.  
  17. (function ()
  18. {
  19. 'use strict';
  20.  
  21. /** @type {HTMLTextAreaElement} */
  22. let input = document.querySelector('textarea[name=message]');
  23. if (!input) return;
  24. if (!input.form) return;
  25. GM_addStyle(`
  26. .faceblock {
  27. position: absolute;
  28. display: flex;
  29. width: 65px;
  30. height: 65px;
  31. background: rgba(255, 255, 255, 0.363);
  32. border: 1px solid #ccc;
  33.  
  34. justify-content: space-around;
  35. align-items: center;
  36.  
  37. pointer-events: none;
  38.  
  39. backdrop-filter: blur(5px);
  40.  
  41. z-index: 100;
  42. }
  43.  
  44. .faceblock img{
  45. max-width: 65px;
  46. max-height: 65px;
  47.  
  48. display: block;
  49. }
  50. `);
  51. //@ts-ignore
  52. hook_input(input);
  53.  
  54.  
  55. let ob = new MutationObserver(function (mutations)
  56. {
  57. for (const record of mutations)
  58. {
  59. if (record.type === 'childList' && record.addedNodes)
  60. {
  61. for (const n of record.addedNodes)
  62. {
  63. if (n instanceof HTMLElement &&
  64. typeof n.querySelector === 'function')
  65. {
  66. let input = n.querySelector('textarea[name=message]');
  67. //@ts-ignore
  68. if (input && input.form)
  69. {
  70. //@ts-ignore
  71. hook_input(input);
  72. }
  73. }
  74. }
  75. }
  76. }
  77. });
  78. ob.observe(document, {
  79. subtree: true,
  80. childList: true,
  81. attributes: false,
  82. });
  83.  
  84. /**
  85. *
  86. * @param {HTMLInputElement} input
  87. */
  88. function hook_input(input)
  89. {
  90. console.log('now hook the input,', input);
  91. let isfocus = input === document.activeElement;
  92. /** @type {HTMLDivElement} */
  93. let div;
  94. /** @type {HTMLFormElement} */
  95. let form = input.form;
  96. form.addEventListener('submit', function (e)
  97. {
  98. input.value = input.value.replace(/#([0-9]{3})([ \r\t\n]|$)/g, function (c, x)
  99. {
  100. return `<img src="/face/${x}.gif" alt="${x}" />`
  101. });
  102. }, { capture: true });
  103. input.addEventListener('focus', function ()
  104. {
  105. isfocus = true;
  106. update();
  107. });
  108. input.addEventListener('blur', function ()
  109. {
  110. isfocus = false;
  111. update();
  112. });
  113.  
  114. input.addEventListener('input', function () { update(); });
  115. input.addEventListener('scroll', function () { update(); });
  116. input.addEventListener('keyup', function (e) { update(); });
  117. input.addEventListener('click', function (e) { update(); });
  118. function update()
  119. {
  120. function removediv()
  121. {
  122. if (div)
  123. {
  124. div.remove();
  125. div = null;
  126. }
  127. }
  128. if (!isfocus)
  129. {
  130. removediv();
  131. }
  132. else
  133. {
  134. let face;
  135. if ((face = getAroundFace(input)) && face)
  136. {
  137. //@ts-ignore
  138. const position = getCaretCoordinates(input, input.selectionStart);
  139. if (!div)
  140. {
  141. div = document.createElement('div');
  142. div.classList.add('faceblock');
  143. form.appendChild(div);
  144. }
  145. div.innerHTML = `<img src="/face/${face}.gif" alt="${face}"/>`;
  146. div.style.top = (input.offsetTop - input.scrollTop + position.top) + 'px';
  147. div.style.left = (input.offsetLeft - input.scrollLeft + position.left + 2) + 'px';
  148. }
  149. else
  150. {
  151. removediv();
  152. }
  153. }
  154. }
  155.  
  156. function getAroundFace(input)
  157. {
  158.  
  159. let value = input.value;
  160. let s1 = input.selectionStart;
  161. let s2 = input.selectionEnd;
  162. if (s1 >= 0 && s1 <= value.length &&
  163. s2 >= 0 && s2 <= value.length &&
  164. s1 === s2)
  165. {
  166. //#123
  167. for (let i = 0; i < 4; ++i)
  168. {
  169. if (value[s1] === '#') break;
  170. if (s1 < 0) break;
  171. --s1;
  172. }
  173.  
  174. return getFaceAt(value, s1);
  175. }
  176. return null;
  177. }
  178.  
  179. function getFaceAt(value, s1)
  180. {
  181. function isempty(x)
  182. {
  183. return ' \r\n\t'.indexOf(x) >= 0;
  184. }
  185. if (value[s1] === '#'
  186. && (value.length === s1 + 4 || isempty(value[s1 + 4])))
  187. {
  188. let token = value.substring(s1 + 1, s1 + 1 + 3);
  189. if (/^[0-9]{3}$/.test(token))
  190. return token;
  191. }
  192. return null;
  193. }
  194.  
  195. }
  196. })();