Greasyfork - Add notes to the script

Add a note for scripts to help identify and search

As of 2020-08-26. See the latest version.

  1. // ==UserScript==
  2. // @name Greasyfork - Add notes to the script
  3. // @name:zh-CN Greasyfork - 为脚本添加备注
  4. // @name:zh-TW Greasyfork - 為腳本新增備註
  5. // @namespace https://greatest.deepsurf.us/zh-CN/users/193133-pana
  6. // @homepage https://www.sailboatweb.com
  7. // @version 1.1.0
  8. // @description Add a note for scripts to help identify and search
  9. // @description:zh-CN 为脚本添加备注功能,以帮助识别和搜索
  10. // @description:zh-TW 為腳本新增備註功能,以幫助識別和搜尋
  11. // @author pana
  12. // @license GNU General Public License v3.0 or later
  13. // @include http*://*greatest.deepsurf.us/*
  14. // @include http*://*sleazyfork.org/*
  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 script',
  26. 'modify_button_text': 'Modify note',
  27. 'modify_button_title': 'Modify notes for the script',
  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. 'DOWN_ARROW': 'url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iaXNvLTg4NTktMSI/Pgo8IS0tIEdlbmVyYXRvcjogQWRvYmUgSWxsdXN0cmF0b3IgMTkuMC4wLCBTVkcgRXhwb3J0IFBsdWctSW4gLiBTVkcgVmVyc2lvbjogNi4wMCBCdWlsZCAwKSAgLS0+CjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgdmVyc2lvbj0iMS4xIiBpZD0iTGF5ZXJfMSIgeD0iMHB4IiB5PSIwcHgiIHZpZXdCb3g9IjAgMCA0OTEuOTk2IDQ5MS45OTYiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDQ5MS45OTYgNDkxLjk5NjsiIHhtbDpzcGFjZT0icHJlc2VydmUiPgo8Zz4KCTxnPgoJCTxwYXRoIGQ9Ik00ODQuMTMyLDEyNC45ODZsLTE2LjExNi0xNi4yMjhjLTUuMDcyLTUuMDY4LTExLjgyLTcuODYtMTkuMDMyLTcuODZjLTcuMjA4LDAtMTMuOTY0LDIuNzkyLTE5LjAzNiw3Ljg2bC0xODMuODQsMTgzLjg0OCAgICBMNjIuMDU2LDEwOC41NTRjLTUuMDY0LTUuMDY4LTExLjgyLTcuODU2LTE5LjAyOC03Ljg1NnMtMTMuOTY4LDIuNzg4LTE5LjAzNiw3Ljg1NmwtMTYuMTIsMTYuMTI4ICAgIGMtMTAuNDk2LDEwLjQ4OC0xMC40OTYsMjcuNTcyLDAsMzguMDZsMjE5LjEzNiwyMTkuOTI0YzUuMDY0LDUuMDY0LDExLjgxMiw4LjYzMiwxOS4wODQsOC42MzJoMC4wODQgICAgYzcuMjEyLDAsMTMuOTYtMy41NzIsMTkuMDI0LTguNjMybDIxOC45MzItMjE5LjMyOGM1LjA3Mi01LjA2NCw3Ljg1Ni0xMi4wMTYsNy44NjQtMTkuMjI0ICAgIEM0OTEuOTk2LDEzNi45MDIsNDg5LjIwNCwxMzAuMDQ2LDQ4NC4xMzIsMTI0Ljk4NnoiLz4KCTwvZz4KPC9nPgo8Zz4KPC9nPgo8Zz4KPC9nPgo8Zz4KPC9nPgo8Zz4KPC9nPgo8Zz4KPC9nPgo8Zz4KPC9nPgo8Zz4KPC9nPgo8Zz4KPC9nPgo8Zz4KPC9nPgo8Zz4KPC9nPgo8Zz4KPC9nPgo8Zz4KPC9nPgo8Zz4KPC9nPgo8Zz4KPC9nPgo8Zz4KPC9nPgo8L3N2Zz4K)',
  61. 'UP_ARROW': 'url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iaXNvLTg4NTktMSI/Pgo8IS0tIEdlbmVyYXRvcjogQWRvYmUgSWxsdXN0cmF0b3IgMTkuMC4wLCBTVkcgRXhwb3J0IFBsdWctSW4gLiBTVkcgVmVyc2lvbjogNi4wMCBCdWlsZCAwKSAgLS0+CjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgdmVyc2lvbj0iMS4xIiBpZD0iTGF5ZXJfMSIgeD0iMHB4IiB5PSIwcHgiIHZpZXdCb3g9IjAgMCA0OTIuMDAyIDQ5Mi4wMDIiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDQ5Mi4wMDIgNDkyLjAwMjsiIHhtbDpzcGFjZT0icHJlc2VydmUiPgo8Zz4KCTxnPgoJCTxwYXRoIGQ9Ik00ODQuMTM2LDMyOC40NzNMMjY0Ljk4OCwxMDkuMzI5Yy01LjA2NC01LjA2NC0xMS44MTYtNy44NDQtMTkuMTcyLTcuODQ0Yy03LjIwOCwwLTEzLjk2NCwyLjc4LTE5LjAyLDcuODQ0ICAgIEw3Ljg1MiwzMjguMjY1QzIuNzg4LDMzMy4zMzMsMCwzNDAuMDg5LDAsMzQ3LjI5N2MwLDcuMjA4LDIuNzg0LDEzLjk2OCw3Ljg1MiwxOS4wMzJsMTYuMTI0LDE2LjEyNCAgICBjNS4wNjQsNS4wNjQsMTEuODI0LDcuODYsMTkuMDMyLDcuODZzMTMuOTY0LTIuNzk2LDE5LjAzMi03Ljg2bDE4My44NTItMTgzLjg1MmwxODQuMDU2LDE4NC4wNjQgICAgYzUuMDY0LDUuMDYsMTEuODIsNy44NTIsMTkuMDMyLDcuODUyYzcuMjA4LDAsMTMuOTYtMi43OTIsMTkuMDI4LTcuODUybDE2LjEyOC0xNi4xMzIgICAgQzQ5NC42MjQsMzU2LjA0MSw0OTQuNjI0LDMzOC45NjUsNDg0LjEzNiwzMjguNDczeiIvPgoJPC9nPgo8L2c+CjxnPgo8L2c+CjxnPgo8L2c+CjxnPgo8L2c+CjxnPgo8L2c+CjxnPgo8L2c+CjxnPgo8L2c+CjxnPgo8L2c+CjxnPgo8L2c+CjxnPgo8L2c+CjxnPgo8L2c+CjxnPgo8L2c+CjxnPgo8L2c+CjxnPgo8L2c+CjxnPgo8L2c+CjxnPgo8L2c+Cjwvc3ZnPgo=)',
  62. };
  63. const STYLE_VALUE = `
  64. .my_greasyfork_note_btn {
  65. margin-left: 10px;
  66. }
  67. .list_show, .show_separator {
  68. display: block !important;
  69. }
  70. #presentation_div_for_user {
  71. display: flex;
  72. position: fixed;
  73. background-color: rgba(0, 0, 0, .5);
  74. top: 0;
  75. bottom: 0;
  76. left: 0;
  77. right: 0;
  78. z-index: 1;
  79. align-items: center;
  80. justify-content: center;
  81. }
  82. .dialog_div_for_user {
  83. position: relative;
  84. width: 400px;
  85. background-color: #fff;
  86. border: 0 solid #000;
  87. border-radius: 12px;
  88. display: flex;
  89. flex-direction: column;
  90. }
  91. .user_title_span_for_user {
  92. min-height: 48px;
  93. text-align: center;
  94. border: 1px solid #efefef;
  95. color: #003399;
  96. font-weight: bold;
  97. background-color: rgba(0, 0, 0, 0);
  98. border-top-left-radius: 12px;
  99. border-top-right-radius: 12px;
  100. }
  101. .tag_input_for_user {
  102. min-height: 32px;
  103. margin: 5px;
  104. border: 1px solid #cc6666;
  105. padding-left: 5px;
  106. }
  107. .button_for_user {
  108. min-height: 48px;
  109. cursor: pointer;
  110. border: 1px solid #efefef;
  111. background-color: rgba(0, 0, 0, 0);
  112. }
  113. .cancel_button_for_user {
  114. border-bottom-left-radius: 12px;
  115. border-bottom-right-radius: 12px;
  116. }
  117. #searchFrame {
  118. position: relative;
  119. margin-left: 15px;
  120. }
  121. #myInputSearch {
  122. width: 175px;
  123. height: 25px;
  124. border: 1px solid #999;
  125. border-radius: 3px;
  126. padding: 0 3px;
  127. position: relative;
  128. }
  129. #dropDowns {
  130. width: 15px;
  131. height: 15px;
  132. background-repeat: no-repeat;
  133. background-size: 12px auto;
  134. position: absolute;
  135. top: 8px;
  136. right: 2px;
  137. }
  138. .ins_down_arrow {
  139. background-image: ${ICON.DOWN_ARROW};
  140. }
  141. .ins_up_arrow {
  142. background-image: ${ICON.UP_ARROW};
  143. }
  144. #tagsList {
  145. width: 180px;
  146. height: 220px;
  147. overflow-y: scroll;
  148. text-align: left;
  149. border: 1px solid #999;
  150. display: none;
  151. position: absolute;
  152. top: 27px;
  153. background-color: #fff;
  154. z-index: 1;
  155. }
  156. .ins_list_item {
  157. cursor: pointer;
  158. color: #000;
  159. padding-left: 5px;
  160. }
  161. .ins_highlight {
  162. background-color: #6699cc;
  163. }
  164. .ins_hide {
  165. display: none;
  166. }
  167. .ins_tag_span {
  168. margin-left: 20px;
  169. color: #336699;
  170. }
  171. .my_note_btn_hide {
  172. display: none;
  173. }
  174. ol.script-list li:hover .my_greasyfork_note_btn {
  175. display: inline !important;
  176. }
  177. .citrus-gfork-tag {
  178. margin-left: 0px;
  179. }
  180. tr:hover .my_greasyfork_note_btn {
  181. display: inline !important;
  182. }
  183. `;
  184. class Greasyfork_Note {
  185. constructor(config, lang, show_list = []) {
  186. this.config = config;
  187. this.lang = lang;
  188. this.showList = show_list;
  189. }
  190. createNoteBtn(script_id, callback, class_name = "my_greasyfork_note_btn") {
  191. let btn = document.createElement('a');
  192. btn.className = class_name;
  193. btn.target = '_self';
  194. btn.href = 'javascript:;';
  195. if (this.judgeScripts(script_id)) {
  196. btn.textContent = this.lang.modify_button_text;
  197. btn.title = this.lang.modify_button_title;
  198. } else {
  199. btn.textContent = this.lang.add_button_text;
  200. btn.title = this.lang.add_button_title;
  201. }
  202. btn.addEventListener('click', () => {
  203. document.body.appendChild(this.createNoteFrame(script_id, () => {
  204. if (this.judgeScripts(script_id)) {
  205. btn.textContent = this.lang.modify_button_text;
  206. btn.title = this.lang.modify_button_title;
  207. } else {
  208. btn.textContent = this.lang.add_button_text;
  209. btn.title = this.lang.add_button_title;
  210. }
  211. if (typeof(callback) == 'function') {
  212. callback();
  213. }
  214. }));
  215. });
  216. return btn;
  217. }
  218. judgeScripts(script_id) {
  219. if (this.getScriptIndex(script_id) == -1) {
  220. return false;
  221. }
  222. return true;
  223. }
  224. getScriptIndex(script_id) {
  225. for (let i in this.config.scripts_array) {
  226. if (script_id == this.config.scripts_array[i].id) {
  227. return i;
  228. }
  229. }
  230. return -1;
  231. }
  232. getScriptTag(script_id) {
  233. if (this.judgeScripts(script_id)) {
  234. return this.config.scripts_array[this.getScriptIndex(script_id)].tag;
  235. }
  236. return '';
  237. }
  238. getScriptFormatTag(script_id) {
  239. if (this.judgeScripts(script_id)) {
  240. return '[' + this.getScriptTag(script_id) + ']';
  241. }
  242. return '';
  243. }
  244. writeScripts(script_id, tag_value) {
  245. if (this.judgeScripts(script_id)) {
  246. let index = this.getScriptIndex(script_id);
  247. if (tag_value) {
  248. this.config.scripts_array[index].tag = tag_value;
  249. } else {
  250. this.config.scripts_array.splice(index, 1);
  251. }
  252. } else {
  253. if (tag_value) {
  254. let temp_scripts_obj = {
  255. 'id': script_id,
  256. 'tag': tag_value
  257. };
  258. this.config.scripts_array.push(temp_scripts_obj);
  259. }
  260. }
  261. GM_setValue('greasyfork_config', this.config);
  262. }
  263. removeNoteFrame(frame_id = 'presentation_div_for_user') {
  264. let temp_ele = document.getElementById(frame_id);
  265. temp_ele.parentNode.removeChild(temp_ele);
  266. }
  267. createNoteFrame(script_id, callback) {
  268. let that = this;
  269. let presentation_div = document.createElement('div');
  270. presentation_div.id = 'presentation_div_for_user';
  271. presentation_div.addEventListener('click', function (event) {
  272. if (event.target === this) {
  273. that.removeNoteFrame();
  274. }
  275. });
  276. let dialog_div = document.createElement('div');
  277. dialog_div.className = 'dialog_div_for_user';
  278. let user_title_p = document.createElement('button');
  279. user_title_p.className = 'user_title_span_for_user';
  280. user_title_p.textContent = "ID: " + script_id;
  281. let tag_input = document.createElement('input');
  282. tag_input.className = 'tag_input_for_user';
  283. tag_input.type = 'text';
  284. tag_input.placeholder = this.lang.input_placeholder;
  285. if (this.judgeScripts(script_id)) {
  286. tag_input.value = this.config.scripts_array[this.getScriptIndex(script_id)].tag;
  287. } else {
  288. tag_input.value = '';
  289. }
  290. tag_input.addEventListener('keyup', (e) => {
  291. if (e.keyCode === 13) {
  292. this.writeScripts(script_id, tag_input.value);
  293. this.resetSearchFrame();
  294. if (typeof(callback) == 'function') {
  295. callback();
  296. }
  297. this.removeNoteFrame();
  298. }
  299. });
  300. setTimeout(function() {
  301. try {
  302. tag_input.focus();
  303. tag_input.select();
  304. } catch(e) {
  305. console.error(e);
  306. }
  307. }, 200);
  308. let save_button = document.createElement('button');
  309. save_button.className = 'button_for_user';
  310. save_button.type = 'button';
  311. save_button.innerText = this.lang.save_button_text;
  312. save_button.addEventListener('click', () => {
  313. this.writeScripts(script_id, tag_input.value);
  314. this.resetSearchFrame();
  315. if (typeof(callback) == 'function') {
  316. callback();
  317. }
  318. this.removeNoteFrame();
  319. });
  320. let clear_button = document.createElement('button');
  321. clear_button.className = 'button_for_user';
  322. clear_button.type = 'button';
  323. clear_button.innerText = this.lang.clear_button_text;
  324. clear_button.addEventListener('click', () => {
  325. this.writeScripts(script_id, '');
  326. this.resetSearchFrame();
  327. if (typeof(callback) == 'function') {
  328. callback();
  329. }
  330. this.removeNoteFrame();
  331. });
  332. let cancel_button = document.createElement('button');
  333. cancel_button.className = 'button_for_user cancel_button_for_user';
  334. cancel_button.type = 'button';
  335. cancel_button.innerText = this.lang.cancel_button_text;
  336. cancel_button.addEventListener('click', () => {
  337. this.removeNoteFrame();
  338. });
  339. dialog_div.appendChild(user_title_p);
  340. dialog_div.appendChild(tag_input);
  341. dialog_div.appendChild(save_button);
  342. dialog_div.appendChild(clear_button);
  343. dialog_div.appendChild(cancel_button);
  344. presentation_div.appendChild(dialog_div);
  345. return presentation_div;
  346. }
  347. resetSearchFrame() {
  348. let tags_list = document.getElementById('tagsList');
  349. if (tags_list) {
  350. tags_list.innerHTML = "";
  351. this.config.scripts_array.forEach((item, index) => {
  352. tags_list.appendChild(this.createListDiv(index, item));
  353. });
  354. }
  355. }
  356. cretaeSearchFrame() {
  357. let search_frame = document.createElement('div');
  358. search_frame.id = 'searchFrame';
  359. let search_input = document.createElement('input');
  360. search_input.id = 'myInputSearch';
  361. search_input.type = 'text';
  362. search_input.placeholder = this.lang.search_placeholder;
  363. search_input.value = "";
  364. search_input.addEventListener('focusin', () => {
  365. document.getElementById('tagsList').classList.add('list_show');
  366. let arrow = document.getElementById('dropDowns');
  367. arrow.classList.remove('ins_down_arrow');
  368. arrow.classList.add('ins_up_arrow');
  369. this.searchEvent(search_input);
  370. });
  371. search_frame.appendChild(search_input);
  372. let dropdowns = document.createElement('div');
  373. dropdowns.id = 'dropDowns';
  374. dropdowns.className = 'ins_down_arrow';
  375. dropdowns.addEventListener('click', function() {
  376. let tags_list = document.getElementById('tagsList');
  377. if (tags_list.classList.contains('list_show')) {
  378. tags_list.classList.remove('list_show');
  379. } else {
  380. tags_list.classList.add('list_show');
  381. }
  382. if (this.classList.contains('ins_up_arrow')) {
  383. this.classList.remove('ins_up_arrow');
  384. } else {
  385. this.classList.add('ins_up_arrow');
  386. }
  387. if (this.classList.contains('ins_down_arrow')) {
  388. this.classList.remove('ins_down_arrow');
  389. } else {
  390. this.classList.add('ins_down_arrow');
  391. }
  392. });
  393. search_frame.appendChild(dropdowns);
  394. let tags_list = document.createElement('div');
  395. tags_list.id = 'tagsList';
  396. for (let i = 0; i < this.config.scripts_array.length; i ++) {
  397. tags_list.appendChild(this.createListDiv(i, this.config.scripts_array[i]));
  398. }
  399. search_frame.appendChild(tags_list);
  400. document.body.onclick = function(e){
  401. e = e || window.event;
  402. let target = e.target || e.srcElement;
  403. if(target !== document.getElementById('dropDowns') && target !== document.getElementById('tagsList') && target !== document.getElementById('myInputSearch')){
  404. document.getElementById('tagsList').classList.remove('list_show');
  405. let arrow = document.getElementById('dropDowns');
  406. arrow.classList.remove('ins_up_arrow');
  407. arrow.classList.add('ins_down_arrow');
  408. }
  409. };
  410. return search_frame;
  411. }
  412. createListDiv(id_number, scripts_obj) {
  413. let list_div = document.createElement('div');
  414. list_div.id = 'tags_' + id_number;
  415. list_div.className = 'ins_list_item';
  416. list_div.textContent = scripts_obj.tag;
  417. list_div.addEventListener('mouseenter', function() {
  418. for (let ele of document.querySelectorAll('#tagsList div')) {
  419. ele.classList.remove('ins_highlight');
  420. }
  421. this.classList.add('ins_highlight');
  422. });
  423. list_div.addEventListener('click', function() {
  424. location.pathname = location.pathname.replace(/^(\/[\w-]+)\/?.*/i, "$1" + "/scripts/" + scripts_obj.id);
  425. });
  426. return list_div;
  427. }
  428. searchEvent(input_dom) {
  429. let list_arr = [];
  430. for (let ele of document.querySelectorAll('#tagsList div')) {
  431. let arr_obj = {
  432. 'eleContainer': ele.textContent,
  433. 'ele': ele
  434. };
  435. list_arr.push(arr_obj);
  436. }
  437. let current_index = 0;
  438. input_dom.addEventListener('keyup', (event) => {
  439. document.getElementById('tagsList').classList.add('list_show');
  440. let arrow = document.getElementById('dropDowns');
  441. arrow.classList.remove('ins_down_arrow');
  442. arrow.classList.add('ins_up_arrow');
  443. let search_val;
  444. switch (event.keyCode) {
  445. case 38:
  446. case 40:
  447. case 37:
  448. case 39:
  449. event.returnValue = false;
  450. break;
  451. case 13:
  452. this.showList[current_index].click();
  453. break;
  454. default:
  455. search_val = input_dom.value;
  456. this.showList = [];
  457. list_arr.forEach((item) => {
  458. if (item.eleContainer.indexOf(search_val) !== -1) {
  459. item.ele.classList.remove('ins_hide');
  460. this.showList.push(item.ele);
  461. } else {
  462. item.ele.classList.add('ins_hide');
  463. }
  464. });
  465. current_index = 0;
  466. break;
  467. }
  468. this.showList.forEach(function(item, index) {
  469. if (index === current_index) {
  470. item.classList.add('ins_highlight');
  471. document.getElementById('tagsList').scrollTop = item.offsetTop;
  472. } else {
  473. item.classList.remove('ins_highlight');
  474. }
  475. });
  476. let list_height = 22 * this.showList.length;
  477. if (list_height < 220) {
  478. document.getElementById('tagsList').style.height = list_height + 'px';
  479. } else {
  480. document.getElementById('tagsList').style.height = '220px';
  481. }
  482. });
  483. input_dom.addEventListener('keydown', (event) => {
  484. if (event.keyCode === 38) {
  485. current_index --;
  486. if (current_index < 0) {
  487. current_index = 0;
  488. }
  489. } else if (event.keyCode === 40) {
  490. current_index ++;
  491. if (current_index >= this.showList.length) {
  492. current_index = this.showList.length - 1;
  493. }
  494. }
  495. this.showList.forEach(function(item, index) {
  496. if (index === current_index) {
  497. item.classList.add('ins_highlight');
  498. document.getElementById('tagsList').scrollTop = item.offsetTop;
  499. } else {
  500. item.classList.remove('ins_highlight');
  501. }
  502. });
  503. });
  504. }
  505. createNoteSpan(script_id, an_class_name = "") {
  506. let note_span = document.createElement('span');
  507. note_span.className = 'ins_tag_span';
  508. if (an_class_name) {
  509. note_span.classList.add(an_class_name);
  510. }
  511. note_span.textContent = this.getScriptFormatTag(script_id);
  512. return note_span;
  513. }
  514. }
  515. function init(greasyfork_config) {
  516. let pathname = location.pathname;
  517. let style_dom = document.createElement('style');
  518. style_dom.type = 'text/css';
  519. style_dom.innerHTML = STYLE_VALUE;
  520. document.body.appendChild(style_dom);
  521. let lang_str = document.documentElement.lang;
  522. let lang_value;
  523. switch (lang_str) {
  524. case 'zh':
  525. case 'zh-cn':
  526. case 'zh-CN':
  527. lang_value = LANG.ZH_CN;
  528. break;
  529. case 'zh-hk':
  530. case 'zh-HK':
  531. case 'zh-tw':
  532. case 'zh-TW':
  533. lang_value = LANG.ZH_TW;
  534. break;
  535. case 'en':
  536. default:
  537. lang_value = LANG.EN;
  538. break;
  539. }
  540. let note_obj = new Greasyfork_Note(greasyfork_config, lang_value);
  541. let search_li = document.createElement('li');
  542. search_li.appendChild(note_obj.cretaeSearchFrame());
  543. document.querySelector('#site-nav nav').insertAdjacentElement('afterbegin', search_li);
  544. if (/^\/[\w-]+\/scripts\/\d+-/i.test(pathname)) {
  545. let script_id = /^\/[\w-]+\/scripts\/(\d+)-/i.exec(pathname)[1];
  546. if (document.getElementById('script-feedback-suggestion')) {
  547. document.getElementById('script-feedback-suggestion').appendChild(note_obj.createNoteBtn(script_id, function() {
  548. if (document.querySelector('#script-info h2 > span')) {
  549. let span_dom = document.querySelector('#script-info h2 > span');
  550. if (note_obj.judgeScripts(script_id)) {
  551. span_dom.textContent = note_obj.getScriptFormatTag(script_id);
  552. } else {
  553. document.querySelector('#script-info h2').removeChild(span_dom);
  554. }
  555. } else {
  556. if (note_obj.judgeScripts(script_id)) {
  557. document.querySelector('#script-info h2').appendChild(note_obj.createNoteSpan(script_id));
  558. }
  559. }
  560. }));
  561. }
  562. if (note_obj.judgeScripts(script_id)) {
  563. document.querySelector('#script-info h2').appendChild(note_obj.createNoteSpan(script_id));
  564. }
  565. } else if (/^\/[\w-]+\/scripts/i.test(pathname) || /^\/[\w-]+\/users\/\d+/i.test(pathname)) {
  566. let browse_list = document.querySelectorAll('ol.script-list li');
  567. for (let ele of browse_list) {
  568. let script_id = ele.getAttribute('data-script-id');
  569. if (script_id) {
  570. if (ele.querySelector('dd.script-list-author span')) {
  571. ele.querySelector('dd.script-list-author span').appendChild(note_obj.createNoteBtn(script_id, function() {
  572. if (ele.querySelector('h2 > .ins_tag_span')) {
  573. let span_dom = ele.querySelector('h2 .ins_tag_span');
  574. if (note_obj.judgeScripts(script_id)) {
  575. span_dom.textContent = note_obj.getScriptFormatTag(script_id);
  576. } else {
  577. ele.querySelector('h2').removeChild(span_dom);
  578. }
  579. } else {
  580. if (note_obj.judgeScripts(script_id)) {
  581. ele.querySelector('.name-description-separator').after(note_obj.createNoteSpan(script_id));
  582. }
  583. }
  584. }, 'my_greasyfork_note_btn my_note_btn_hide'));
  585. }
  586. if (note_obj.judgeScripts(script_id)) {
  587. ele.querySelector('.name-description-separator').after(note_obj.createNoteSpan(script_id));
  588. }
  589. }
  590. }
  591. document.querySelectorAll('#script-table tbody tr').forEach(item => {
  592. let script_title = item.querySelector('.thetitle a');
  593. if (script_title) {
  594. let script_id = script_title.href.match(/\d+$/) && script_title.href.match(/\d+$/)[0];
  595. note_obj.judgeScripts(script_id) && script_title.after(note_obj.createNoteSpan(script_id, 'citrus-gfork-tag'));
  596. let p_dom = item.querySelector('.theauthor') || item.querySelector('.ins_tag_span') || script_title;
  597. script_id && p_dom.after(note_obj.createNoteBtn(script_id, () => {
  598. let tag_dom = item.querySelector('.ins_tag_span');
  599. if (tag_dom) {
  600. if (note_obj.judgeScripts(script_id)) {
  601. tag_dom.textContent = note_obj.getScriptFormatTag(script_id);
  602. } else {
  603. tag_dom.remove();
  604. }
  605. } else {
  606. note_obj.judgeScripts(script_id) && script_title.after(note_obj.createNoteSpan(script_id, 'citrus-gfork-tag'));
  607. }
  608. }, 'my_greasyfork_note_btn my_note_btn_hide'));
  609. }
  610. });
  611. }
  612. }
  613. Promise.all([GM_getValue('greasyfork_config')]).then(function(data) {
  614. let greasyfork_config = {
  615. scripts_array: []
  616. };
  617. if (data[0] !== undefined) {
  618. greasyfork_config = data[0];
  619. }
  620. init(greasyfork_config);
  621. }).catch(function(e) {
  622. console.error('Script error.');
  623. console.error(e);
  624. });
  625. })();