Twitter - 为用户添加备注

为用户添加备注功能,以帮助识别和搜索; 鼠标移网页右下角弹出搜索按钮

当前为 2020-06-03 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Twitter - Add notes to the user
  3. // @name:zh-CN Twitter - 为用户添加备注
  4. // @name:zh-TW Twitter - 為使用者新增備註
  5. // @namespace https://gf.qytechs.cn/zh-CN/users/193133-pana
  6. // @homepage https://www.sailboatweb.com
  7. // @version 1.1.4
  8. // @description Add a note for users to help identify and search; the search button pops up in the lower right corner
  9. // @description:zh-CN 为用户添加备注功能,以帮助识别和搜索; 鼠标移网页右下角弹出搜索按钮
  10. // @description:zh-TW 為使用者新增備註功能,以幫助識別和搜尋; 滑鼠移網頁右下角彈出搜尋按鈕
  11. // @author pana
  12. // @license GNU General Public License v3.0 or later
  13. // @include http*://*twitter.com/*
  14. // @require https://cdnjs.cloudflare.com/ajax/libs/arrive/2.4.1/arrive.min.js
  15. // @grant GM_getValue
  16. // @grant GM_setValue
  17. // ==/UserScript==
  18.  
  19. (function() {
  20. 'use strict';
  21. const LANG = {
  22. 'EN': {
  23. 'title': 'Note',
  24. 'add_button_text': 'Add note',
  25. 'add_button_title': 'Add notes to the user',
  26. 'modify_button_text': 'Modify note',
  27. 'modify_button_title': 'Modify notes for the user',
  28. 'input_placeholder': '(Enter a note, delete it when blanked; press Enter to save)',
  29. 'save_button_text': 'Save',
  30. 'clear_button_text': 'Clear',
  31. 'cancel_button_text': 'Cancel',
  32. 'search_placeholder': 'Search notes'
  33. },
  34. 'ZH_CN': {
  35. 'title': '备注',
  36. 'add_button_text': '添加备注',
  37. 'add_button_title': '为用户添加备注',
  38. 'modify_button_text': '修改备注',
  39. 'modify_button_title': '为用户修改备注',
  40. 'input_placeholder': '(请输入备注,置空时删除;按下Enter键保存)',
  41. 'save_button_text': '保存',
  42. 'clear_button_text': '清除',
  43. 'cancel_button_text': '取消',
  44. 'search_placeholder': '搜索备注'
  45. },
  46. 'ZH_TW': {
  47. 'title': '備註',
  48. 'add_button_text': '新增備註',
  49. 'add_button_title': '為使用者新增備註',
  50. 'modify_button_text': '修改備註',
  51. 'modify_button_title': '為使用者修改備註',
  52. 'input_placeholder': '(請輸入備註,置空時刪除;按下Enter鍵儲存)',
  53. 'save_button_text': '儲存',
  54. 'clear_button_text': '清除',
  55. 'cancel_button_text': '取消',
  56. 'search_placeholder': '搜尋備註'
  57. }
  58. };
  59. const ICON = {
  60. 'NOTE_GRAY': 'url(data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjI0cHgiIGhlaWdodD0iMjRweCIgdmlld0JveD0iMCAwIDI0IDI0IiBhcmlhLWxhYmVsbGVkYnk9Im5ld0ljb25UaXRsZSIgc3Ryb2tlPSJyZ2IoMTAxLCAxMTksIDEzNCkiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InNxdWFyZSIgc3Ryb2tlLWxpbmVqb2luPSJtaXRlciIgZmlsbD0ibm9uZSIgY29sb3I9InJnYigxMDEsIDExOSwgMTM0KSI+IDx0aXRsZSBpZD0ibmV3SWNvblRpdGxlIj5OZXc8L3RpdGxlPiA8cGF0aCBkPSJNMTkgMTRWMjJIMi45OTk5N1Y0SDEzIi8+IDxwYXRoIGQ9Ik0xNy40NjA4IDQuMDM5MjFDMTguMjQxOCAzLjI1ODE3IDE5LjUwODIgMy4yNTgxNiAyMC4yODkyIDQuMDM5MjFMMjAuOTYwOCA0LjcxMDc5QzIxLjc0MTggNS40OTE4NCAyMS43NDE4IDYuNzU4MTcgMjAuOTYwOCA3LjUzOTIxTDExLjU4NTggMTYuOTE0MkMxMS4yMTA3IDE3LjI4OTMgMTAuNzAyIDE3LjUgMTAuMTcxNiAxNy41TDcuNSAxNy41TDcuNSAxNC44Mjg0QzcuNSAxNC4yOTggNy43MTA3MSAxMy43ODkzIDguMDg1NzkgMTMuNDE0MkwxNy40NjA4IDQuMDM5MjFaIi8+IDxwYXRoIGQ9Ik0xNi4yNSA1LjI1TDE5Ljc1IDguNzUiLz4gPC9zdmc+)',
  61. 'NOTE_BLUE': 'url(data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjI0cHgiIGhlaWdodD0iMjRweCIgdmlld0JveD0iMCAwIDI0IDI0IiBhcmlhLWxhYmVsbGVkYnk9Im5ld0ljb25UaXRsZSIgc3Ryb2tlPSJyZ2JhKDI5LDE2MSwyNDIsMS4wMCkiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InNxdWFyZSIgc3Ryb2tlLWxpbmVqb2luPSJtaXRlciIgZmlsbD0ibm9uZSIgY29sb3I9InJnYmEoMjksMTYxLDI0MiwxLjAwKSI+IDx0aXRsZSBpZD0ibmV3SWNvblRpdGxlIj5OZXc8L3RpdGxlPiA8cGF0aCBkPSJNMTkgMTRWMjJIMi45OTk5N1Y0SDEzIi8+IDxwYXRoIGQ9Ik0xNy40NjA4IDQuMDM5MjFDMTguMjQxOCAzLjI1ODE3IDE5LjUwODIgMy4yNTgxNiAyMC4yODkyIDQuMDM5MjFMMjAuOTYwOCA0LjcxMDc5QzIxLjc0MTggNS40OTE4NCAyMS43NDE4IDYuNzU4MTcgMjAuOTYwOCA3LjUzOTIxTDExLjU4NTggMTYuOTE0MkMxMS4yMTA3IDE3LjI4OTMgMTAuNzAyIDE3LjUgMTAuMTcxNiAxNy41TDcuNSAxNy41TDcuNSAxNC44Mjg0QzcuNSAxNC4yOTggNy43MTA3MSAxMy43ODkzIDguMDg1NzkgMTMuNDE0MkwxNy40NjA4IDQuMDM5MjFaIi8+IDxwYXRoIGQ9Ik0xNi4yNSA1LjI1TDE5Ljc1IDguNzUiLz4gPC9zdmc+)',
  62. 'SEARCH': 'url(data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjI0cHgiIGhlaWdodD0iMjRweCIgdmlld0JveD0iMCAwIDI0IDI0IiBhcmlhLWxhYmVsbGVkYnk9InNlYXJjaEljb25UaXRsZSIgc3Ryb2tlPSJyZ2JhKDI5LDE2MSwyNDIsMS4wMCkiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InNxdWFyZSIgc3Ryb2tlLWxpbmVqb2luPSJtaXRlciIgZmlsbD0ibm9uZSIgY29sb3I9InJnYmEoMjksMTYxLDI0MiwxLjAwKSI+IDx0aXRsZSBpZD0ic2VhcmNoSWNvblRpdGxlIj5TZWFyY2g8L3RpdGxlPiA8cGF0aCBkPSJNMTQuNDEyMTEyMiwxNC40MTIxMTIyIEwyMCwyMCIvPiA8Y2lyY2xlIGN4PSIxMCIgY3k9IjEwIiByPSI2Ii8+IDwvc3ZnPg==)'
  63. };
  64. const STYLE_VALUE = `
  65. .my_twitter_note_btn {
  66. height: 36px;
  67. width: 36px;
  68. margin-top: -8px;
  69. margin-bottom: -8px;
  70. margin-right: -8px;
  71. margin-left: 30px;
  72. background-image: ${ICON.NOTE_GRAY};
  73. background-repeat: no-repeat;
  74. background-size: 18px auto;
  75. background-position: center;
  76. background-color: rgba(0, 0, 0, 0);
  77. border-bottom-left-radius: 9999px;
  78. border-bottom-right-radius: 9999px;
  79. border-top-left-radius: 9999px;
  80. border-top-right-radius: 9999px;
  81. transition-property: background-color, box-shadow;
  82. transition-duration: 0.2s;
  83. }
  84. .my_twitter_note_btn:hover {
  85. background-image: ${ICON.NOTE_BLUE};
  86. background-color: rgba(29, 161, 242, 0.1);
  87. }
  88. .my_before_follow_note_btn {
  89. height: 39px;
  90. width: 39px;
  91. background-image: ${ICON.NOTE_BLUE};
  92. background-repeat: no-repeat;
  93. background-size: 19px auto;
  94. background-position: center;
  95. margin-bottom: 10px;
  96. margin-right: 10px;
  97. cursor: pointer;
  98. border: 1px solid rgba(29,161,242,1.00);
  99. border-bottom-left-radius: 9999px;
  100. border-bottom-right-radius: 9999px;
  101. border-top-left-radius: 9999px;
  102. border-top-right-radius: 9999px;
  103. background-color: rgba(0, 0, 0, 0);
  104. transition-property: background-color, box-shadow;
  105. transition-duration: 0.2s;
  106. }
  107. .my_before_follow_note_btn:hover {
  108. background-color: rgba(29, 161, 242, 0.1);
  109. }
  110. .list_show, .show_separator {
  111. display: block !important;
  112. }
  113. #presentation_div_for_user {
  114. display: flex;
  115. position: fixed;
  116. background-color: rgba(0, 0, 0, .5);
  117. top: 0;
  118. bottom: 0;
  119. left: 0;
  120. right: 0;
  121. z-index: 101;
  122. align-items: center;
  123. justify-content: center;
  124. }
  125. .dialog_div_for_user {
  126. position: relative;
  127. width: 400px;
  128. background-color: rgb(21, 32, 43);
  129. border: 0 solid #000;
  130. border-radius: 12px;
  131. display: flex;
  132. flex-direction: column;
  133. }
  134. .user_title_span_for_user {
  135. min-height: 48px;
  136. text-align: center;
  137. border: 1px solid rgba(0, 0, 0, .5);
  138. color: #1da1f2;
  139. font-weight: bold;
  140. background-color: rgba(0, 0, 0, 0);
  141. border-top-left-radius: 12px;
  142. border-top-right-radius: 12px;
  143. }
  144. .tag_input_for_user {
  145. min-height: 32px;
  146. margin: 5px;
  147. border: 1px solid rgba(29, 161, 242, 0.1);
  148. padding-left: 5px;
  149. background-color: #253341;
  150. color: #fff;
  151. }
  152. .button_for_user {
  153. min-height: 48px;
  154. cursor: pointer;
  155. border: 1px solid rgba(0, 0, 0, .5);
  156. background-color: rgba(0, 0, 0, 0);
  157. color: #fff;
  158. }
  159. .cancel_button_for_user {
  160. border-bottom-left-radius: 12px;
  161. border-bottom-right-radius: 12px;
  162. }
  163. #searchFrame {
  164. position: relative;
  165. }
  166. #myInputSearch {
  167. width: 350px;
  168. height: 40px;
  169. border: 2px solid #000;
  170. border-radius: 40px;
  171. padding: 0 20px;
  172. position: relative;
  173. background-color: rgb(37, 51, 65);
  174. color: #fff;
  175. outline: none;
  176. }
  177. #tagsList {
  178. width: 350px;
  179. height: 250px;
  180. overflow-y: scroll;
  181. text-align: left;
  182. display: none;
  183. position: absolute;
  184. margin: 0 20px;
  185. z-index: 100;
  186. background-color: rgb(37, 51, 65);
  187. border: 1px solid rgba(29, 161, 242, 0.1);
  188. }
  189. .ins_list_item {
  190. cursor: pointer;
  191. color: #fff;
  192. padding-left: 5px;
  193. height: 25px;
  194. line-height: 25px;
  195. }
  196. .ins_highlight {
  197. background-color: #6699cc;
  198. }
  199. .ins_hide {
  200. display: none;
  201. }
  202. .ins_tag_span {
  203. color: #336699;
  204. }
  205. .my_note_btn_hide {
  206. display: none;
  207. }
  208. ol.script-list li:hover .my_twitter_note_btn {
  209. display: inline !important;
  210. }
  211. .expand_box {
  212. bottom: 0px;
  213. height: 50px;
  214. position: fixed;
  215. right: -50px;
  216. transition: 0.5s;
  217. width: 100px;
  218. z-index: 99;
  219. }
  220. .show_expand_box {
  221. right: 0;
  222. width: 50px;
  223. }
  224. #expandSpan {
  225. border-radius: 99px;
  226. border: 1px solid #00A1D6;
  227. bottom: 1vh;
  228. color: #FFF;
  229. cursor: pointer;
  230. display: block;
  231. font-size: 13px;
  232. height: 38px;
  233. line-height: 38px;
  234. position: absolute;
  235. right: 1vw;
  236. text-align: center;
  237. width: 38px;
  238. z-index: 98;
  239. background-image: ${ICON.SEARCH};
  240. background-repeat: no-repeat;
  241. background-size: 24px auto;
  242. background-position: center;
  243. }
  244. #my_search_bottom_layer_div {
  245. display: flex;
  246. position: fixed;
  247. background-color: rgba(0, 0, 0, .5);
  248. top: -50vh;
  249. bottom: 0;
  250. left: 0;
  251. right: 0;
  252. z-index: 100;
  253. align-items: center;
  254. justify-content: center;
  255. }
  256. `;
  257. var selector = {
  258. 'body': 'body',
  259. 'root': '#react-root div .r-13awgt0.r-12vffkv',
  260. 'homepage': {
  261. 'article': 'article',
  262. 'tool_bar': '.css-1dbjc4n.r-18u37iz.r-1wtj0ep.r-156q2ks.r-1mdbhws',
  263. 'show_name': '.css-901oao.css-bfa6kz.r-1qd0xha.r-a023e6.r-vw2c0b.r-ad9z0x.r-bcqeeo.r-3s2u2q.r-qvutc0 > span',
  264. 'id': '.css-901oao.css-bfa6kz.r-18u37iz.r-1qd0xha.r-a023e6.r-16dba41.r-ad9z0x.r-bcqeeo.r-qvutc0 > span',
  265. 'reprint_a': '.css-1dbjc4n.r-1iusvr4.r-16y2uox.r-5f2r5o.r-m611by a',
  266. 'reprint_name': '.css-1dbjc4n.r-1iusvr4.r-16y2uox.r-5f2r5o.r-m611by a > span > span',
  267. 'at': 'a.css-4rbku5.css-18t94o4.css-901oao.css-16my406.r-1loqt21.r-1qd0xha.r-ad9z0x.r-bcqeeo.r-qvutc0',
  268. 'user_frame': '.css-18t94o4.css-1dbjc4n.r-1ny4l3l.r-1j3t67a.r-1w50u8q.r-o7ynqc.r-6416eg',
  269. 'blockquote': 'div[role="blockquote"]'
  270. },
  271. 'userpage': {
  272. 'main_user_id': '.css-1dbjc4n.r-15d164r.r-1g94qm0 .css-1dbjc4n.r-18u37iz.r-1wbh5a2 > div > span',
  273. 'main': '.css-1dbjc4n.r-ku1wi2.r-1j3t67a.r-m611by',
  274. 'id': '.css-1dbjc4n.r-18u37iz.r-1wbh5a2 > div > span',
  275. 'follow': '.css-1dbjc4n.r-obd0qt.r-18u37iz.r-1w6e6rj.r-1h0z5md.r-dnmrzs',
  276. 'show_name': '.css-901oao.r-1qd0xha.r-1b6yd1w.r-1vr29t4.r-ad9z0x.r-bcqeeo.r-qvutc0 > span'
  277. }
  278. };
  279. var modify_style = selector.homepage.show_name + '{ white-space: normal; }\n';
  280. class Twitter_Note {
  281. constructor(config, lang, show_list = []) {
  282. this.config = config;
  283. this.lang = lang;
  284. this.showList = show_list;
  285. }
  286. createNoteBtn(user_id, callback, class_name = "my_twitter_note_btn") {
  287. let btn = document.createElement('div');
  288. btn.className = class_name;
  289. if (this.judgeUsers(user_id)) {
  290. btn.title = this.lang.modify_button_title;
  291. } else {
  292. btn.title = this.lang.add_button_title;
  293. }
  294. btn.addEventListener('click', (event) => {
  295. event.stopPropagation();
  296. document.body.appendChild(this.createNoteFrame(user_id, () => {
  297. if (this.judgeUsers(user_id)) {
  298. btn.title = this.lang.modify_button_title;
  299. } else {
  300. btn.title = this.lang.add_button_title;
  301. }
  302. if (typeof(callback) == 'function') {
  303. callback();
  304. }
  305. }));
  306. });
  307. return btn;
  308. }
  309. doneHandle(user_id, ele, path_name) {
  310. if (path_name) {
  311. if (ele.querySelector(path_name + ' .ins_tag_span')) {
  312. let tag_dom = ele.querySelector(path_name + ' .ins_tag_span');
  313. if (this.judgeUsers(user_id)) {
  314. tag_dom.textContent = this.getUserFormatTag(user_id);
  315. } else {
  316. ele.querySelector(path_name).removeChild(tag_dom);
  317. }
  318. } else {
  319. if (this.judgeUsers(user_id)) {
  320. ele.querySelector(path_name).appendChild(this.createNoteSpan(user_id));
  321. }
  322. }
  323. } else {
  324. if (ele.querySelector('.ins_tag_span')) {
  325. let an_tag_dom = ele.querySelector('.ins_tag_span');
  326. if (this.judgeUsers(user_id)) {
  327. an_tag_dom.textContent = this.getUserFormatTag(user_id);
  328. } else {
  329. ele.removeChild(an_tag_dom);
  330. }
  331. } else {
  332. if (this.judgeUsers(user_id)) {
  333. ele.appendChild(this.createNoteSpan(user_id));
  334. }
  335. }
  336. }
  337. }
  338. judgeUsers(user_id) {
  339. if (this.getUserIndex(user_id) == -1) {
  340. return false;
  341. }
  342. return true;
  343. }
  344. getUserIndex(user_id) {
  345. for (let i in this.config.users_array) {
  346. if (user_id == this.config.users_array[i].id) {
  347. return i;
  348. }
  349. }
  350. return -1;
  351. }
  352. getUserTag(user_id) {
  353. if (this.judgeUsers(user_id)) {
  354. return this.config.users_array[this.getUserIndex(user_id)].tag;
  355. }
  356. return '';
  357. }
  358. getUserFormatTag(user_id) {
  359. if (this.judgeUsers(user_id)) {
  360. return '[' + this.getUserTag(user_id) + ']';
  361. }
  362. return '';
  363. }
  364. writeUsers(user_id, tag_value) {
  365. if (this.judgeUsers(user_id)) {
  366. let index = this.getUserIndex(user_id);
  367. if (tag_value) {
  368. this.config.users_array[index].tag = tag_value;
  369. } else {
  370. this.config.users_array.splice(index, 1);
  371. }
  372. } else {
  373. if (tag_value) {
  374. let temp_scripts_obj = {
  375. 'id': user_id,
  376. 'tag': tag_value
  377. };
  378. this.config.users_array.push(temp_scripts_obj);
  379. }
  380. }
  381. GM_setValue('twitter_config', this.config);
  382. }
  383. removeNoteFrame(frame_id = 'presentation_div_for_user') {
  384. let temp_ele = document.getElementById(frame_id);
  385. if (temp_ele) {
  386. temp_ele.parentNode.removeChild(temp_ele);
  387. }
  388. }
  389. createNoteFrame(user_id, callback) {
  390. let that = this;
  391. let presentation_div = document.createElement('div');
  392. presentation_div.id = 'presentation_div_for_user';
  393. presentation_div.addEventListener('click', function (event) {
  394. if (event.target === this) {
  395. that.removeNoteFrame();
  396. }
  397. });
  398. let dialog_div = document.createElement('div');
  399. dialog_div.className = 'dialog_div_for_user';
  400. let user_title_p = document.createElement('button');
  401. user_title_p.className = 'user_title_span_for_user';
  402. user_title_p.textContent = "ID: " + user_id;
  403. let tag_input = document.createElement('input');
  404. tag_input.className = 'tag_input_for_user';
  405. tag_input.type = 'text';
  406. tag_input.placeholder = this.lang.input_placeholder;
  407. if (this.judgeUsers(user_id)) {
  408. tag_input.value = this.config.users_array[this.getUserIndex(user_id)].tag;
  409. } else {
  410. tag_input.value = '';
  411. }
  412. tag_input.addEventListener('keyup', (e) => {
  413. if (e.keyCode === 13) {
  414. this.writeUsers(user_id, tag_input.value);
  415. this.resetSearchFrame();
  416. if (typeof(callback) == 'function') {
  417. callback();
  418. }
  419. this.removeNoteFrame();
  420. }
  421. });
  422. setTimeout(function() {
  423. try {
  424. tag_input.focus();
  425. tag_input.select();
  426. } catch(e) {
  427. console.error(e);
  428. }
  429. }, 200);
  430. let save_button = document.createElement('button');
  431. save_button.className = 'button_for_user';
  432. save_button.type = 'button';
  433. save_button.innerText = this.lang.save_button_text;
  434. save_button.addEventListener('click', () => {
  435. this.writeUsers(user_id, tag_input.value);
  436. this.resetSearchFrame();
  437. if (typeof(callback) == 'function') {
  438. callback();
  439. }
  440. this.removeNoteFrame();
  441. });
  442. let clear_button = document.createElement('button');
  443. clear_button.className = 'button_for_user';
  444. clear_button.type = 'button';
  445. clear_button.innerText = this.lang.clear_button_text;
  446. clear_button.addEventListener('click', () => {
  447. this.writeUsers(user_id, '');
  448. this.resetSearchFrame();
  449. if (typeof(callback) == 'function') {
  450. callback();
  451. }
  452. this.removeNoteFrame();
  453. });
  454. let cancel_button = document.createElement('button');
  455. cancel_button.className = 'button_for_user cancel_button_for_user';
  456. cancel_button.type = 'button';
  457. cancel_button.innerText = this.lang.cancel_button_text;
  458. cancel_button.addEventListener('click', () => {
  459. this.removeNoteFrame();
  460. });
  461. dialog_div.appendChild(user_title_p);
  462. dialog_div.appendChild(tag_input);
  463. dialog_div.appendChild(save_button);
  464. dialog_div.appendChild(clear_button);
  465. dialog_div.appendChild(cancel_button);
  466. presentation_div.appendChild(dialog_div);
  467. return presentation_div;
  468. }
  469. resetSearchFrame() {
  470. let tags_list = document.getElementById('tagsList');
  471. if (tags_list) {
  472. tags_list.innerHTML = "";
  473. this.config.users_array.forEach((item, index) => {
  474. tags_list.appendChild(this.createListDiv(index, item));
  475. });
  476. }
  477. }
  478. removeSearchFrame(frame_id = 'my_search_bottom_layer_div') {
  479. let search_frame = document.getElementById(frame_id);
  480. if (search_frame) {
  481. search_frame.parentNode.removeChild(search_frame);
  482. }
  483. }
  484. cretaeSearchFrame() {
  485. let that = this;
  486. let bottom_layer_div = document.createElement('div');
  487. bottom_layer_div.id = 'my_search_bottom_layer_div';
  488. bottom_layer_div.addEventListener('click', function(event) {
  489. if (event.target === this) {
  490. that.removeSearchFrame();
  491. }
  492. });
  493. let search_frame = document.createElement('div');
  494. search_frame.id = 'searchFrame';
  495. bottom_layer_div.appendChild(search_frame);
  496. let search_input = document.createElement('input');
  497. search_input.id = 'myInputSearch';
  498. search_input.type = 'text';
  499. search_input.placeholder = this.lang.search_placeholder;
  500. search_input.value = "";
  501. search_input.addEventListener('focusin', () => {
  502. document.getElementById('tagsList').classList.add('list_show');
  503. this.searchEvent(search_input);
  504. });
  505. setTimeout(function() {
  506. try {
  507. search_input.focus();
  508. search_input.select();
  509. } catch(e) {
  510. console.error(e);
  511. }
  512. }, 200);
  513. search_frame.appendChild(search_input);
  514. let tags_list = document.createElement('div');
  515. tags_list.id = 'tagsList';
  516. for (let i = 0; i < this.config.users_array.length; i ++) {
  517. tags_list.appendChild(this.createListDiv(i, this.config.users_array[i]));
  518. }
  519. search_frame.appendChild(tags_list);
  520. return bottom_layer_div;
  521. }
  522. createListDiv(id_number, users_obj) {
  523. let list_div = document.createElement('div');
  524. list_div.id = 'tags_' + id_number;
  525. list_div.className = 'ins_list_item';
  526. list_div.textContent = users_obj.tag;
  527. list_div.addEventListener('mouseenter', function() {
  528. for (let ele of document.querySelectorAll('#tagsList div')) {
  529. ele.classList.remove('ins_highlight');
  530. }
  531. this.classList.add('ins_highlight');
  532. });
  533. list_div.addEventListener('click', function() {
  534. location.pathname = users_obj.id.replace(/^@/, '/');
  535. });
  536. return list_div;
  537. }
  538. searchEvent(input_dom) {
  539. let list_arr = [];
  540. for (let ele of document.querySelectorAll('#tagsList div')) {
  541. let arr_obj = {
  542. 'eleContainer': ele.textContent,
  543. 'ele': ele
  544. };
  545. list_arr.push(arr_obj);
  546. }
  547. let current_index = 0;
  548. input_dom.addEventListener('keyup', (event) => {
  549. document.getElementById('tagsList').classList.add('list_show');
  550. let search_val;
  551. switch (event.keyCode) {
  552. case 38:
  553. case 40:
  554. case 37:
  555. case 39:
  556. event.returnValue = false;
  557. break;
  558. case 13:
  559. this.showList[current_index].click();
  560. break;
  561. default:
  562. search_val = input_dom.value;
  563. this.showList = [];
  564. list_arr.forEach((item) => {
  565. if (item.eleContainer.indexOf(search_val) !== -1) {
  566. item.ele.classList.remove('ins_hide');
  567. this.showList.push(item.ele);
  568. } else {
  569. item.ele.classList.add('ins_hide');
  570. }
  571. });
  572. current_index = 0;
  573. break;
  574. }
  575. this.showList.forEach(function(item, index) {
  576. if (index === current_index) {
  577. item.classList.add('ins_highlight');
  578. document.getElementById('tagsList').scrollTop = item.offsetTop;
  579. } else {
  580. item.classList.remove('ins_highlight');
  581. }
  582. });
  583. let list_height = 25 * this.showList.length;
  584. if (list_height < 250) {
  585. document.getElementById('tagsList').style.height = list_height + 'px';
  586. } else {
  587. document.getElementById('tagsList').style.height = '250px';
  588. }
  589. });
  590. input_dom.addEventListener('keydown', (event) => {
  591. if (event.keyCode === 38) {
  592. current_index --;
  593. if (current_index < 0) {
  594. current_index = 0;
  595. }
  596. } else if (event.keyCode === 40) {
  597. current_index ++;
  598. if (current_index >= this.showList.length) {
  599. current_index = this.showList.length - 1;
  600. }
  601. }
  602. this.showList.forEach(function(item, index) {
  603. if (index === current_index) {
  604. item.classList.add('ins_highlight');
  605. document.getElementById('tagsList').scrollTop = item.offsetTop;
  606. } else {
  607. item.classList.remove('ins_highlight');
  608. }
  609. });
  610. });
  611. }
  612. createNoteSpan(user_id, an_class_name = "") {
  613. let note_span = document.createElement('span');
  614. note_span.className = 'ins_tag_span';
  615. if (an_class_name) {
  616. note_span.classList.add(an_class_name);
  617. }
  618. note_span.textContent = this.getUserFormatTag(user_id);
  619. return note_span;
  620. }
  621. }
  622. function save_Event(user_id, note_obj) {
  623. for (let ele of document.querySelectorAll(selector.homepage.article)) {
  624. let ele_id = "";
  625. if (ele.querySelector(selector.homepage.id)) {
  626. ele_id = ele.querySelector(selector.homepage.id).textContent;
  627. }
  628. let ele_reprint_id = "";
  629. if (ele.querySelector(selector.homepage.reprint_a)) {
  630. ele_reprint_id = ele.querySelector(selector.homepage.reprint_a).href.replace(location.origin + '/', '@');
  631. }
  632. if (ele_id == user_id) {
  633. note_obj.doneHandle(user_id, ele, selector.homepage.show_name);
  634. }
  635. if (ele_reprint_id == user_id) {
  636. note_obj.doneHandle(user_id, ele, selector.homepage.reprint_name);
  637. }
  638. for (let ele_at_user of ele.querySelectorAll(selector.homepage.at)) {
  639. let ele_at_user_id = ele_at_user.href.replace(location.origin + '/', '@');
  640. if (ele_at_user_id == user_id) {
  641. note_obj.doneHandle(user_id, ele_at_user, "");
  642. }
  643. }
  644. }
  645. for (let user_ele of document.querySelectorAll(selector.userpage.main)) {
  646. let user_ele_id = user_ele.querySelector(selector.userpage.id).textContent;
  647. if (user_ele_id == user_id) {
  648. note_obj.doneHandle(user_id, user_ele, selector.userpage.show_name);
  649. }
  650. }
  651. for (let user_frame_ele of document.querySelectorAll(selector.homepage.user_frame)) {
  652. let user_frame_ele_id = user_frame_ele.querySelector(selector.userpage.id).textContent;
  653. if (user_frame_ele_id == user_id) {
  654. note_obj.doneHandle(user_id, user_frame_ele, selector.homepage.show_name);
  655. }
  656. }
  657. for (let blockquote_ele of document.querySelectorAll(selector.homepage.blockquote)) {
  658. let blockquote_ele_id = blockquote_ele.querySelector(selector.homepage.id).textContent;
  659. if (blockquote_ele_id == user_id) {
  660. note_obj.doneHandle(user_id, blockquote_ele, selector.homepage.show_name);
  661. }
  662. }
  663. }
  664. function init(twitter_config) {
  665. let style_dom = document.createElement('style');
  666. style_dom.type = 'text/css';
  667. style_dom.innerHTML = STYLE_VALUE;
  668. document.body.appendChild(style_dom);
  669. let modify_style_dom = document.createElement('style');
  670. modify_style_dom.type = 'text/css';
  671. modify_style_dom.innerHTML = modify_style;
  672. document.body.appendChild(modify_style_dom);
  673. let lang_str = document.documentElement.lang;
  674. let lang_value;
  675. switch (lang_str) {
  676. case 'zh':
  677. case 'zh-cn':
  678. case 'zh-CN':
  679. lang_value = LANG.ZH_CN;
  680. break;
  681. case 'zh-hk':
  682. case 'zh-HK':
  683. case 'zh-tw':
  684. case 'zh-TW':
  685. case 'zh-Hant':
  686. lang_value = LANG.ZH_TW;
  687. break;
  688. case 'en':
  689. default:
  690. lang_value = LANG.EN;
  691. break;
  692. }
  693. let note_obj = new Twitter_Note(twitter_config, lang_value);
  694. let expand_box = document.createElement('div');
  695. expand_box.className = 'expand_box';
  696. expand_box.onmouseenter = function() {
  697. this.classList.add('show_expand_box');
  698. };
  699. expand_box.onmouseleave = function() {
  700. this.classList.remove('show_expand_box');
  701. };
  702. let search_btn = document.createElement('span');
  703. search_btn.id = 'expandSpan';
  704. search_btn.title = note_obj.lang.search_placeholder;
  705. search_btn.addEventListener('click', function(event) {
  706. event.stopPropagation();
  707. document.body.appendChild(note_obj.cretaeSearchFrame());
  708. });
  709. expand_box.appendChild(search_btn);
  710. document.body.appendChild(expand_box);
  711. document.querySelector(selector.root).arrive(selector.homepage.article, {fireOnAttributesModification: true, existing: true}, function() {
  712. if (this.querySelector(selector.homepage.id)) {
  713. let user_id = this.querySelector(selector.homepage.id).textContent;
  714. if (this.querySelector(selector.homepage.tool_bar)) {
  715. this.querySelector(selector.homepage.tool_bar).appendChild(note_obj.createNoteBtn(user_id, function() {
  716. save_Event(user_id, note_obj);
  717. }, 'my_twitter_note_btn css-1dbjc4n'));
  718. }
  719. note_obj.doneHandle(user_id, this, selector.homepage.show_name);
  720. }
  721. if (this.querySelector(selector.homepage.reprint_a)) {
  722. let reprint_id = this.querySelector(selector.homepage.reprint_a).href.replace(location.origin + '/', '@');
  723. note_obj.doneHandle(reprint_id, this, selector.homepage.reprint_name);
  724. }
  725. if (this.querySelector(selector.homepage.blockquote)) {
  726. let blockquote_user = this.querySelector(selector.homepage.blockquote);
  727. let blockquote_user_id = blockquote_user.querySelector(selector.homepage.id).textContent;
  728. note_obj.doneHandle(blockquote_user_id, blockquote_user, selector.homepage.show_name);
  729. }
  730. for (let at_user of this.querySelectorAll(selector.homepage.at)) {
  731. let at_user_id = at_user.href.replace(location.origin + '/', '@');
  732. note_obj.doneHandle(at_user_id, at_user);
  733. }
  734. });
  735. document.querySelector(selector.root).arrive(selector.userpage.main, {fireOnAttributesModification: true, existing: true}, function() {
  736. let user_id = this.querySelector(selector.userpage.id).textContent;
  737. var follow_note_btn;
  738. if (this.querySelector(selector.userpage.follow)) {
  739. follow_note_btn = note_obj.createNoteBtn(user_id, function() {
  740. save_Event(user_id, note_obj);
  741. }, 'my_before_follow_note_btn css-901oao');
  742. this.querySelector(selector.userpage.follow).insertAdjacentElement('afterbegin', follow_note_btn);
  743. }
  744. note_obj.doneHandle(user_id, this, selector.userpage.show_name);
  745. let user_id_change = new MutationObserver(() => {
  746. let new_user_id = this.querySelector(selector.userpage.id).textContent;
  747. if (follow_note_btn) {
  748. follow_note_btn.parentNode.removeChild(follow_note_btn);
  749. follow_note_btn = note_obj.createNoteBtn(new_user_id, function() {
  750. save_Event(new_user_id, note_obj);
  751. }, 'my_before_follow_note_btn css-901oao');
  752. this.querySelector(selector.userpage.follow).insertAdjacentElement('afterbegin', follow_note_btn);
  753. }
  754. note_obj.doneHandle(new_user_id, this, selector.userpage.show_name);
  755. });
  756. let user_id_change_container = this.querySelector(selector.userpage.main_user_id);
  757. let user_id_change_option = {
  758. 'subtree': true,
  759. 'characterData': true
  760. };
  761. user_id_change.observe(user_id_change_container, user_id_change_option);
  762. });
  763. document.querySelector(selector.root).arrive(selector.homepage.user_frame, {fireOnAttributesModification: true, existing: true}, function() {
  764. let user_id = this.querySelector(selector.userpage.id).textContent;
  765. note_obj.doneHandle(user_id, this, selector.homepage.show_name);
  766. });
  767. }
  768. Promise.all([GM_getValue('twitter_config')]).then(function(data) {
  769. let twitter_config = {
  770. users_array: []
  771. };
  772. if (data[0] !== undefined) {
  773. twitter_config = data[0];
  774. }
  775. init(twitter_config);
  776. }).catch(function(e) {
  777. console.error('Script error.');
  778. console.error(e);
  779. });
  780. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址