Block_Obj

BLOCK_OBJ

当前为 2020-09-21 提交的版本,查看 最新版本

此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.cn-greasyfork.org/scripts/407543/850077/Block_Obj.js

  1. // ==UserScript==
  2. // @name Block_Obj
  3. // @namespace https://greasyfork.org/zh-CN/users/193133-pana
  4. // @homepage https://www.sailboatweb.com
  5. // @version 2.9.0
  6. // @description BLOCK_OBJ
  7. // @author pana
  8. // @license GNU General Public License v3.0 or later
  9. // ==/UserScript==
  10.  
  11. const BLOCK_STYLE = `
  12. .block_obj_wrap_div {
  13. background-color: #222222;
  14. border-radius: 3px;
  15. border: 1px solid #282A36;
  16. bottom: 6vh;
  17. box-shadow: 0 0 5px #282A36;
  18. color: #D3D3D3;
  19. font-size: 13px;
  20. margin: 0px;
  21. padding: 0px;
  22. position: fixed;
  23. text-align: left;
  24. transition: 0.8s;
  25. width: 520px;
  26. z-index: 99999;
  27. }
  28. .block_obj_show_wrap {
  29. display: block;
  30. right: 0;
  31. }
  32. .block_obj_hidden_wrap {
  33. right: -530px;
  34. }
  35. .block_obj_main_fieldset {
  36. border-radius: 3px;
  37. border: 3px groove #00A1D6;
  38. height: auto;
  39. margin: 8px;
  40. min-width: 300px;
  41. padding: 4px 9px 6px 9px;
  42. width: auto;
  43. }
  44. .block_obj_ul_node {
  45. list-style: none;
  46. padding-left: 0;
  47. margin: 0;
  48. }
  49. .block_obj_checkbox_li {
  50. display: inline-block;
  51. margin-top: 5px;
  52. }
  53. .block_obj_checkbox_input {
  54. clip: rect(0, 0, 0, 0);
  55. position: absolute;
  56. }
  57. .block_obj_checkbox_label {
  58. cursor: pointer;
  59. vertical-align: middle;
  60. }
  61. .block_obj_checkbox_input + label::before {
  62. background-color: silver;
  63. border-radius: 0.1em;
  64. color: #FFF;
  65. content: "\\a0";
  66. display: inline-block;
  67. height: 1em;
  68. line-height: 85%;
  69. margin-right: 0.5em;
  70. text-align: center;
  71. vertical-align: 0.2em;
  72. width: 1em;
  73. }
  74. .block_obj_checkbox_input:checked + label::before {
  75. background-color: #00A1D6;
  76. content: "\\2713";
  77. }
  78. .block_obj_separator_text {
  79. color: #FFB86C;
  80. margin-top: 5px;
  81. }
  82. .block_obj_separator_symbol {
  83. background-color: #303030;
  84. height: 2px;
  85. margin-bottom: 5px;
  86. margin-top: 5px;
  87. min-width: 400px;
  88. }
  89. .block_obj_input_div {
  90. margin-top: 5px;
  91. }
  92. .block_obj_input {
  93. background-color: #C0C0C0;
  94. border: 1px solid #C0C0C0;
  95. color: #000;
  96. font-size: 13px;
  97. min-height: 15px;
  98. margin-left: 5px;
  99. margin-right: 5px;
  100. padding-left: 4px;
  101. }
  102. .block_obj_keyword_input {
  103. width: 150px;
  104. }
  105. .block_obj_input_btn {
  106. background-color: #3da9cc;
  107. border-radius: 3px;
  108. border: 1px solid #73C9E5;
  109. box-shadow: 0 0 4px #73C9E5;
  110. color: #FFF;
  111. cursor: pointer;
  112. display: inline-block;
  113. min-height: 15px;
  114. margin-left: 5px;
  115. text-align: center;
  116. vertical-align: bottom;
  117. white-space: nowrap;
  118. width: 30px;
  119. }
  120. .block_obj_list_div {
  121. margin-top: 5px;
  122. }
  123. .block_obj_list_textarea_div {
  124. border: 1px dotted #00A1D6;
  125. margin-top: 3px;
  126. max-height: 60px;
  127. min-height: 3px;
  128. overflow: auto;
  129. }
  130. .block_obj_list_textarea_div::-webkit-scrollbar {
  131. background-color: #979797;
  132. border-radius: 5px;
  133. width: 10px;
  134. }
  135. .block_obj_list_textarea_div::-webkit-scrollbar-thumb {
  136. background-color: #404040;
  137. border-radius: 5px;
  138. }
  139. .block_obj_button_clicked {
  140. color: #000;
  141. }
  142. .block_obj_child_span {
  143. background-color: #3D3D3D;
  144. border-radius: 5px;
  145. border: 1px solid #3D3D3D;
  146. display: inline-block;
  147. margin: 3px;
  148. padding: 2px;
  149. min-height: 18px;
  150. }
  151. .block_obj_child_text {
  152. border-right: 1px solid #A9181C;
  153. margin-right: 4px;
  154. padding-right: 4px;
  155. }
  156. .block_obj_child_del {
  157. color: #A9181C;
  158. cursor: pointer;
  159. }
  160. .block_obj_list_textarea_expand {
  161. max-height: 720px;
  162. }
  163. .block_obj_li_hide {
  164. display: none;
  165. }
  166. .block_obj_reg_input {
  167. width: 100px;
  168. }
  169. .block_obj_modifier_input {
  170. width: 50px;
  171. }
  172. .block_obj_button {
  173. background-color: #FB7299;
  174. border-radius: 4px;
  175. border: 1px solid #FB7299;
  176. color: #FFF;
  177. cursor: pointer;
  178. margin-top: 5px;
  179. padding: 2px 4px;
  180. position: relative;
  181. min-height: 17px;
  182. }
  183. .block_obj_save_button {
  184. float: right;
  185. margin-right: 5px;
  186. }
  187. .block_obj_cancel_button {
  188. float: left;
  189. margin-left: 5px;
  190. }
  191. .block_obj_expand_box {
  192. bottom: 0px;
  193. height: 6vh;
  194. position: fixed;
  195. right: -6vw;
  196. transition: 0.5s;
  197. width: 12vw;
  198. z-index: 99999;
  199. }
  200. .block_obj_show_expand_box {
  201. right: 0;
  202. width: 6vw;
  203. }
  204. .block_obj_expand_span {
  205. background-color: #00A1D6;
  206. border-radius: 19px;
  207. border: 1px solid #00A1D6;
  208. bottom: 1vh;
  209. color: #FFF;
  210. cursor: pointer;
  211. display: block;
  212. font-size: 13px;
  213. height: 38px;
  214. line-height: 38px;
  215. position: absolute;
  216. right: 1vw;
  217. text-align: center;
  218. width: 38px;
  219. z-index: 99999;
  220. user-select: none;
  221. }
  222. .block_obj_expand_span:hover {
  223. box-shadow: 0 0 5px 1px green;
  224. }
  225. .block_obj_move_right {
  226. margin-left: 15px;
  227. }
  228. .block_obj_none {
  229. display: none !important;
  230. }
  231. .block_obj_hidden {
  232. visibility: hidden !important;
  233. }
  234. .block_obj_presentation_div {
  235. display: flex;
  236. position: fixed;
  237. background-color: rgba(0, 0, 0, .5);
  238. top: 0;
  239. bottom: 0;
  240. left: 0;
  241. right: 0;
  242. z-index: 100000;
  243. align-items: center;
  244. justify-content: center;
  245. }
  246. .block_obj_dialog_div {
  247. position: relative;
  248. width: 400px;
  249. background-color: #4e5654;
  250. border: 0 solid #000;
  251. border-radius: 12px;
  252. display: flex;
  253. flex-direction: column;
  254. }
  255. .block_obj_big_bang_top_part {
  256. margin-top: 5px;
  257. margin-bottom: 5px;
  258. }
  259. .block_obj_big_bang_h3 {
  260. font-size: 20px;
  261. color: #fff;
  262. margin-left: 5px;
  263. background-color: #4e5654;
  264. border-color: #4e5654;
  265. }
  266. .block_obj_big_bang_deselect_btn {
  267. float: right;
  268. margin-top: 5px;
  269. margin-right: 5px;
  270. color: #2a2a92;
  271. cursor: pointer;
  272. }
  273. .block_obj_big_bang_middle_part {
  274. margin-top: 5px;
  275. margin-bottom: 5px;
  276. max-height: 500px;
  277. overflow-y: auto;
  278. }
  279. .block_obj_big_bang_text {
  280. background-color: #3e3939;
  281. color: #fff;
  282. padding: 5px;
  283. margin: 4px;
  284. font-size: 16px;
  285. display: inline-block;
  286. border-radius: 99px;
  287. cursor: pointer;
  288. user-select: none;
  289. }
  290. .block_obj_big_bang_text_selected {
  291. background-color: #3636b1 !important;
  292. }
  293. .block_obj_big_bang_bottom_part {
  294. margin-top: 5px;
  295. margin-bottom: 5px;
  296. text-align: center;
  297. }
  298. .block_obj_big_bang_add_btn, .block_obj_big_bang_copy_btn {
  299. display: inline-block;
  300. padding: 10px;
  301. color: #fff;
  302. background-color: #325561;
  303. cursor: pointer;
  304. border-radius: 99px;
  305. margin-left: 20px;
  306. margin-right: 20px;
  307. }
  308. .block_obj_big_bang_add_btn:hover, .block_obj_big_bang_copy_btn:hover {
  309. color: #2a2a92;
  310. }
  311. `;
  312. class Block_Obj {
  313. constructor(config_key, reg_key_array = []) {
  314. this.wrapDiv = null;
  315. this.mainFieldset = null;
  316. this.ulNode = null;
  317. this.style = null;
  318. this.saveField = [];
  319. this.onSave = null;
  320. this.onChange = null;
  321. this.field = [];
  322. this.configKey = config_key;
  323. this.regKeyArray = reg_key_array;
  324. this.config = {};
  325. }
  326. async init(initialization) {
  327. if (! this.id) {
  328. this.id = initialization.id ? 'blockObj_' + initialization.id : 'blockObj_' + Block_Obj.count;
  329. ! initialization.id && Block_Obj.count ++;
  330. }
  331. this.config = await this.readConfig();
  332. this.regKeyArray.forEach(key => {
  333. if (this.config[key] === undefined) {
  334. this.config[key] = [];
  335. }
  336. });
  337. this.display = initialization.display ? true : false;
  338. if (initialization.events) {
  339. if (typeof(initialization.events['save']) === 'function') {
  340. this.onSave = initialization.events['save'];
  341. }
  342. if (typeof(initialization.events['change']) === 'function') {
  343. this.onChange = initialization.events['change'];
  344. }
  345. }
  346. this.style = document.createElement('style');
  347. this.style.innerHTML = BLOCK_STYLE;
  348. document.body.appendChild(this.style);
  349. if (initialization.style && typeof(initialization.style) === 'string') {
  350. let external_style = document.createElement('style');
  351. external_style.type = 'text/css';
  352. external_style.innerHTML = initialization.style;
  353. document.body.appendChild(external_style);
  354. }
  355. ! this.wrapDiv && this.createSettingsPanel();
  356. this.field = initialization.field;
  357. this.settingsPanel();
  358. Block_Obj.GM.registerMenuCommand(initialization.menu, () => this.expandWrap());
  359. Block_Obj.GM.addValueChangeListener(this.configKey, (_name, _old_value, new_value, remote) => {
  360. if (remote) {
  361. this.destroyAndRebuild(new_value);
  362. typeof(this.onChange) === 'function' && this.onChange(this.getConfig());
  363. }
  364. });
  365. let expand_box = document.createElement('div');
  366. expand_box.className = 'block_obj_expand_box';
  367. expand_box.onmouseenter = function() {
  368. this.classList.add('block_obj_show_expand_box');
  369. };
  370. expand_box.onmouseleave = function() {
  371. this.classList.remove('block_obj_show_expand_box');
  372. };
  373. let hover_button = {};
  374. if (initialization.hover_button) {
  375. Object.assign(hover_button, initialization.hover_button);
  376. }
  377. let expand_span = document.createElement('span');
  378. expand_span.id = this.id + '_expandSpan';
  379. expand_span.className = 'block_obj_expand_span';
  380. expand_span.textContent = hover_button.label == null ? '屏蔽' : hover_button.label;
  381. expand_span.title = hover_button.title == null ? '显示/隐藏屏蔽设置' : hover_button.title;
  382. expand_span.addEventListener('click', () => {
  383. this.expandWrap();
  384. if (hover_button.click && typeof(hover_button.click) === 'function') {
  385. hover_button.click(expand_span);
  386. }
  387. });
  388. expand_box.appendChild(expand_span);
  389. document.body.appendChild(expand_box);
  390. }
  391. settingsPanel() {
  392. if (Array.isArray(this.field)) {
  393. this.field.forEach(ele => {
  394. if (! this.wrapDiv.querySelector('#' + this.id + '_' + (ele.id ? ele.id : ''))) {
  395. switch (ele.type.toLowerCase()) {
  396. case 'separator':
  397. case 's':
  398. this.insertSeparator(ele.id, ele.label, ele.title, ele.classname);
  399. break;
  400. case 'br':
  401. case 'b':
  402. this.insertBr(ele.classname);
  403. break;
  404. case 'input':
  405. case 'i':
  406. this.insertInput(ele.list_id, ele.id, false, ele.label, ele.title, ele.placeholder, ele.classname, ele.campare);
  407. break;
  408. case 'reg_input':
  409. case 'ri':
  410. this.insertInput(ele.list_id, ele.id, true, ele.label, ele.title, ele.placeholder, ele.classname, ele.campare, ele.modifier_label, ele.modifier_placeholder);
  411. break;
  412. case 'list':
  413. case 'l':
  414. this.insertList(ele.id, (this.config[ele.id] == null ? ele.default : this.config[ele.id]), ele.label, ele.title, ele.classname);
  415. break;
  416. case 'checkbox':
  417. case 'c':
  418. default:
  419. this.insertCheckbox(ele.id, ele.label, ele.title, (this.config[ele.id] == null ? ele.default : this.config[ele.id]), ele.classname, ele.move_right);
  420. break;
  421. }
  422. }
  423. });
  424. }
  425. let save_button = this.createSpanBtn('block_obj_button block_obj_save_button', '保存并关闭', '保存设置并关闭设置窗口', e => {
  426. this.expandWrap();
  427. this.saveConfig();
  428. });
  429. let only_save_button = this.createSpanBtn('block_obj_button block_obj_save_button', '仅保存', '仅保存设置', e => {
  430. only_save_button.textContent = '已保存';
  431. save_timer && window.clearTimeout(save_timer);
  432. var save_timer = window.setTimeout(() => {
  433. only_save_button.textContent = '仅保存';
  434. }, 1000);
  435. this.saveConfig();
  436. });
  437. let cancel_button = this.createSpanBtn('block_obj_button block_obj_cancel_button', '取消', '关闭设置窗口', e => {
  438. this.expandWrap();
  439. cancel_timer && window.clearTimeout(cancel_timer);
  440. var cancel_timer = window.setTimeout(() => {
  441. this.display = false;
  442. this.destroyAndRebuild();
  443. }, 800);
  444. e.stopPropagation();
  445. });
  446. this.ulNode.appendChild(save_button);
  447. this.ulNode.appendChild(only_save_button);
  448. this.ulNode.appendChild(cancel_button);
  449. document.body.appendChild(this.wrapDiv);
  450. }
  451. getConfig() {
  452. let real_config = {};
  453. Object.assign(real_config, this.config);
  454. this.regKeyArray.forEach(key => {
  455. real_config[key] = this.convertArray(real_config[key]);
  456. });
  457. return real_config;
  458. }
  459. async readConfig() {
  460. let config = {};
  461. if (this.configKey) {
  462. config = await Block_Obj.GM.getValue(this.configKey, {});
  463. }
  464. return config;
  465. }
  466. saveConfig() {
  467. this.saveField.forEach(item => {
  468. if (item.type == 'checkbox') {
  469. this.config[item.key] = document.getElementById(this.id + '_' + item.key).checked;
  470. } else if (item.type == 'list') {
  471. this.config[item.key] = this.extractList(this.id + '_' + item.key);
  472. }
  473. });
  474. Block_Obj.GM.setValue(this.configKey, this.config);
  475. typeof(this.onSave) === 'function' && this.onSave(this.getConfig());
  476. }
  477. createSettingsPanel() {
  478. this.wrapDiv = document.createElement('div');
  479. this.wrapDiv.id = this.id + '_wrapDiv';
  480. this.wrapDiv.className = 'block_obj_wrap_div ' + (this.display ? 'block_obj_show_wrap' : 'block_obj_hidden_wrap');
  481. this.mainFieldset = document.createElement('fieldset');
  482. this.mainFieldset.id = this.id + '_mainFieldset';
  483. this.mainFieldset.className = 'block_obj_main_fieldset';
  484. this.wrapDiv.appendChild(this.mainFieldset);
  485. this.ulNode = document.createElement('ul');
  486. this.ulNode.id = this.id + '_ulNode';
  487. this.ulNode.className = 'block_obj_ul_node';
  488. this.mainFieldset.appendChild(this.ulNode);
  489. document.body.appendChild(this.wrapDiv);
  490. }
  491. destroyAndRebuild(new_config = null) {
  492. this.config = new_config || this.config;
  493. document.body.removeChild(this.wrapDiv);
  494. this.createSettingsPanel();
  495. this.settingsPanel();
  496. }
  497. expandWrap() {
  498. let panel = document.getElementById(this.id + '_wrapDiv');
  499. if (panel) {
  500. if (panel.classList.contains('block_obj_show_wrap')) {
  501. this.display = false;
  502. panel.classList.remove('block_obj_show_wrap');
  503. panel.classList.add('block_obj_hidden_wrap');
  504. } else {
  505. this.display = true;
  506. panel.classList.remove('block_obj_hidden_wrap');
  507. panel.classList.add('block_obj_show_wrap');
  508. }
  509. }
  510. }
  511. insertCheckbox(id, label = '', title = '', checked = false, classname = null, move_right = false) {
  512. let checkbox_li = document.createElement('li');
  513. checkbox_li.className = 'block_obj_checkbox_li';
  514. classname && checkbox_li.classList.add(classname);
  515. move_right && checkbox_li.classList.add('block_obj_move_right');
  516. let checkbox_input = document.createElement('input');
  517. checkbox_input.type = 'checkbox';
  518. checkbox_input.className = 'block_obj_checkbox_input';
  519. checkbox_input.id = this.id + '_' + id;
  520. checkbox_input.checked = checked ? true : false;
  521. let checkbox_label = document.createElement('label');
  522. checkbox_label.className = 'block_obj_checkbox_label';
  523. checkbox_label.setAttribute('for', this.id + '_' + id);
  524. checkbox_label.textContent = label;
  525. checkbox_label.title = title;
  526. checkbox_li.appendChild(checkbox_input);
  527. checkbox_li.appendChild(checkbox_label);
  528. this.ulNode.appendChild(checkbox_li);
  529. this.saveField.push({
  530. 'key': id,
  531. 'type': 'checkbox'
  532. });
  533. }
  534. insertSeparator(id = null, label = null, title = null, li_classname = null) {
  535. let separator_li = document.createElement('li');
  536. separator_li.className = 'block_obj_separator_li';
  537. li_classname && separator_li.classList.add('block_obj_' + li_classname);
  538. let separator_div = document.createElement('div');
  539. if (id) {
  540. separator_div.id = this.id + '_' + id;
  541. }
  542. if (label) {
  543. separator_div.className = 'block_obj_separator_text';
  544. separator_div.textContent = label;
  545. } else {
  546. separator_div.className = 'block_obj_separator_symbol';
  547. }
  548. separator_div.title = title ? title : '';
  549. separator_li.appendChild(separator_div);
  550. this.ulNode.appendChild(separator_li);
  551. }
  552. insertBr(classname = null) {
  553. let br = document.createElement('br');
  554. br.className = classname ? classname : '';
  555. this.ulNode.appendChild(br);
  556. }
  557. insertInput(list_id, id = null, is_reg = false, label = '', title = '', placeholder = '', li_classname = null, campare = null, modifier_label = '', modifier_placeholder = '') {
  558. let input_li = document.createElement('li');
  559. input_li.className = li_classname ? 'block_obj_' + li_classname : '';
  560. let input_div = document.createElement('div');
  561. input_div.className = 'block_obj_input_div';
  562. let input_span = document.createElement('span');
  563. input_span.className = 'block_obj_input_span';
  564. input_span.textContent = label;
  565. input_div.appendChild(input_span);
  566. let input = document.createElement('input');
  567. if (id) {
  568. input.id = this.id + '_' + id;
  569. }
  570. input.title = title;
  571. input.placeholder = placeholder;
  572. input.type = 'text';
  573. input.className = is_reg ? 'block_obj_input block_obj_reg_input' : 'block_obj_input block_obj_keyword_input';
  574. input_span.appendChild(input);
  575. let modifier_span = document.createElement('span');
  576. modifier_span.textContent = modifier_label;
  577. is_reg && input_div.appendChild(modifier_span);
  578. let modifier_input = document.createElement('input');
  579. if (id) {
  580. modifier_input.id = this.id + '_modifier_' + id;
  581. }
  582. modifier_input.placeholder = modifier_placeholder;
  583. modifier_input.type = 'text';
  584. modifier_input.className = 'block_obj_input block_obj_modifier_input';
  585. modifier_span.appendChild(modifier_input);
  586. let the_list_id = this.id + '_' + list_id;
  587. input.addEventListener('keyup', e => {
  588. if (e.keyCode === 13) {
  589. is_reg ? this.addRegListItem(input, modifier_input, the_list_id) : this.addListItem(input, the_list_id, campare);
  590. }
  591. });
  592. modifier_input.addEventListener('keyup', e => {
  593. e.keyCode === 13 && this.addRegListItem(input, modifier_input, the_list_id);
  594. });
  595. let add_btn = this.createSpanBtn('block_obj_input_btn', '添加', '添加内容到列表中', e => {
  596. if (is_reg ? this.addRegListItem(input, modifier_input, the_list_id) : this.addListItem(input, the_list_id, campare)) {
  597. this.buttonClicked(add_btn, '添加成功', 'block_obj_button_clicked');
  598. }
  599. });
  600. let delete_btn = this.createSpanBtn('block_obj_input_btn', '删除', '从列表中删除符合的项目', e => {
  601. if (is_reg ? this.delRegListItem(input, modifier_input, the_list_id) : this.delListItem(input, the_list_id)) {
  602. this.buttonClicked(delete_btn, '删除成功', 'block_obj_button_clicked');
  603. }
  604. });
  605. let clear_btn = this.createSpanBtn('block_obj_input_btn', '清空', '清空列表', _e => {
  606. document.getElementById(the_list_id).innerHTML = '';
  607. this.buttonClicked(clear_btn, '清除成功', 'block_obj_button_clicked');
  608. });
  609. let copy_btn = this.createSpanBtn('block_obj_input_btn', '复制', '复制列表', _e => {
  610. Block_Obj.GM.setClipboard(this.extractList(the_list_id).toString());
  611. this.buttonClicked(copy_btn, '复制成功', 'block_obj_button_clicked');
  612. });
  613. let expand_btn = this.createSpanBtn('block_obj_input_btn', '展开', '展开列表', _e => {
  614. li_classname && this.toggleList('block_obj_' + li_classname);
  615. if (expand_btn.textContent == '展开') {
  616. expand_btn.textContent = '恢复';
  617. expand_btn.title = '收缩列表';
  618. } else {
  619. expand_btn.textContent = '展开';
  620. expand_btn.title = '展开列表';
  621. }
  622. });
  623. input_div.appendChild(add_btn);
  624. input_div.appendChild(delete_btn);
  625. input_div.appendChild(clear_btn);
  626. input_div.appendChild(copy_btn);
  627. input_div.appendChild(expand_btn);
  628. input_li.appendChild(input_div);
  629. this.ulNode.appendChild(input_li);
  630. }
  631. insertList(id, save_array = [], label = '', title = '', li_classname = '') {
  632. let list_li = document.createElement('li');
  633. list_li.className = li_classname ? 'block_obj_' + li_classname : '';
  634. let list_div = document.createElement('div');
  635. list_div.className = 'block_obj_list_div';
  636. list_div.textContent = label;
  637. list_div.title = title;
  638. let list_textarea_div = document.createElement('div');
  639. list_textarea_div.id = this.id + '_' + id;
  640. list_textarea_div.className = 'block_obj_list_textarea_div';
  641. for (let item of save_array) {
  642. item && list_textarea_div.insertAdjacentElement('afterbegin', this.createListItem(item));
  643. }
  644. list_div.appendChild(list_textarea_div);
  645. list_li.appendChild(list_div);
  646. this.ulNode.appendChild(list_li);
  647. this.saveField.push({
  648. 'key': id,
  649. 'type': 'list'
  650. });
  651. }
  652. addListItem(input, list_id, campare = null) {
  653. let text_value = input.value;
  654. if (text_value) {
  655. let text_arr = this.stringToArray(text_value);
  656. let save_arr = this.extractList(list_id);
  657. text_arr.forEach(item => {
  658. let status = true;
  659. if (typeof(campare) === 'function') {
  660. let temp_status = campare(item);
  661. if (typeof(temp_status) === 'boolean') {
  662. status = temp_status;
  663. }
  664. }
  665. if (status) {
  666. ! save_arr.includes(item) && document.getElementById(list_id).insertAdjacentElement('afterbegin', this.createListItem(item));
  667. }
  668. });
  669. input.value = '';
  670. return true;
  671. }
  672. return false;
  673. }
  674. delListItem(input, list_id) {
  675. let text_value = input.value;
  676. if (text_value) {
  677. let del_status = false;
  678. let text_arr = this.stringToArray(text_value);
  679. let save_arr = this.extractList(list_id);
  680. text_arr.forEach(item => {
  681. if (save_arr.includes(item)) {
  682. let total_child = document.getElementById(list_id).getElementsByClassName('block_obj_child_span');
  683. try {
  684. document.getElementById(list_id).removeChild(total_child[total_child.length - 1 - save_arr.indexOf(item)]);
  685. del_status = true;
  686. } catch(e) {
  687. del_status = false;
  688. console.error('Block_Obj: Error deleting element.');
  689. console.error(e);
  690. }
  691. }
  692. });
  693. if (del_status) {
  694. input.value = '';
  695. return true;
  696. }
  697. }
  698. return false;
  699. }
  700. addRegListItem(reg_input, modifier_input, list_id) {
  701. let reg_value = reg_input.value;
  702. let modifier_value = modifier_input.value;
  703. if (reg_value) {
  704. try {
  705. let reg_obj = new RegExp(reg_value, modifier_value);
  706. let save_arr = this.extractList(list_id);
  707. ! save_arr.includes(reg_obj.toString()) && document.getElementById(list_id).insertAdjacentElement('afterbegin', this.createListItem(reg_obj.toString()));
  708. reg_input.value = '';
  709. modifier_input.value = '';
  710. return true;
  711. } catch(e) {
  712. console.error('Block_Obj: Invalid regular expression.');
  713. console.error(e);
  714. }
  715. }
  716. return false;
  717. }
  718. delRegListItem(reg_input, modifier_input, list_id) {
  719. let reg_value = reg_input.value;
  720. let modifier_value = modifier_input.value;
  721. if (reg_value) {
  722. let del_status = false;
  723. try {
  724. let reg_obj = new RegExp(reg_value, modifier_value);
  725. let save_arr = this.extractList(list_id);
  726. if (save_arr.includes(reg_obj.toString())) {
  727. let total_child = document.getElementById(list_id).getElementsByClassName('block_obj_child_span');
  728. document.getElementById(list_id).removeChild(total_child[total_child.length - 1 - save_arr.indexOf(reg_obj.toString())]);
  729. del_status = true;
  730. }
  731. } catch(e) {
  732. del_status = false;
  733. console.error('Block_Obj: Invalid regular expression or error deleting element.');
  734. console.error(e);
  735. }
  736. if (del_status) {
  737. reg_input.value = '';
  738. modifier_input.value = '';
  739. return true;
  740. }
  741. return false;
  742. }
  743. }
  744. createSpanBtn(classname, label, title, callback) {
  745. let btn_span = this.createBasicBtn('span', label, title, classname);
  746. btn_span.addEventListener('click', e => typeof(callback) === 'function' && callback(e));
  747. return btn_span;
  748. }
  749. createListItem(text_value) {
  750. let child_span = document.createElement('span');
  751. child_span.className = 'block_obj_child_span';
  752. let text_span = document.createElement('span');
  753. text_span.className = 'block_obj_child_text';
  754. text_span.textContent = text_value.length > 9 ? text_value.slice(0, 3) + '...' + text_value.slice(-3) : text_value;
  755. if (text_value.length > 9) {
  756. text_span.title = text_value;
  757. }
  758. let del_span = document.createElement('span');
  759. del_span.textContent = 'X';
  760. del_span.title = '移除';
  761. del_span.className = 'block_obj_child_del';
  762. del_span.addEventListener('click', e => child_span.remove());
  763. child_span.appendChild(text_span);
  764. child_span.appendChild(del_span);
  765. return child_span;
  766. }
  767. createBasicBtn(type, text, title, classname) {
  768. let btn_type = 'span';
  769. if (typeof(type) === 'string') {
  770. switch (type.toLowerCase()) {
  771. case 'div':
  772. case 'd':
  773. btn_type = 'div';
  774. break;
  775. case 'a':
  776. btn_type = 'a';
  777. break;
  778. case 'button':
  779. btn_type = 'button';
  780. break;
  781. case 'input':
  782. btn_type = 'input';
  783. break;
  784. case 'i':
  785. btn_type = 'i';
  786. break;
  787. case 'b':
  788. btn_type = 'b';
  789. break;
  790. case 'span':
  791. case 's':
  792. default:
  793. btn_type = 'span';
  794. break;
  795. }
  796. }
  797. let btn = document.createElement(btn_type);
  798. btn.textContent = text ? text : '';
  799. btn.title = title ? title : '';
  800. btn.className = classname ? classname : '';
  801. return btn;
  802. }
  803. createBlockBtn(value, list_id, classname, type = 'span', text = '', title = '', campare = null) {
  804. let block_btn = this.createBasicBtn(type, text, title, classname);
  805. block_btn.addEventListener('click', e => {
  806. e.stopPropagation();
  807. if (value && list_id) {
  808. let status = true;
  809. if (typeof(campare) === 'function') {
  810. let temp_status = campare(value);
  811. if (typeof(temp_status) === 'boolean') {
  812. status = temp_status;
  813. }
  814. }
  815. if (status) {
  816. let the_list_id = this.id + '_' + list_id;
  817. let save_arr = this.extractList(the_list_id);
  818. ! save_arr.includes(value) && document.getElementById(the_list_id) && document.getElementById(the_list_id).insertAdjacentElement('afterbegin', this.createListItem(value));
  819. }
  820. }
  821. this.saveConfig();
  822. });
  823. return block_btn;
  824. }
  825. createBigBangBtn(value, list_id, classname, type = 'span', text = '', title = '', campare = null) {
  826. let big_bang_btn = this.createBasicBtn(type, text, title, classname);
  827. big_bang_btn.addEventListener('click', e => {
  828. e.stopPropagation();
  829. if (value && list_id) {
  830. let the_list_id = this.id + '_' + list_id;
  831. this.injectionBigBangPanel(value, the_list_id, campare);
  832. }
  833. });
  834. return big_bang_btn;
  835. }
  836. injectionBigBangPanel(value, list_id, campare = null) {
  837. let presentation_div = document.createElement('div');
  838. presentation_div.id = this.id + '_presentationDiv';
  839. presentation_div.className = 'block_obj_presentation_div';
  840. presentation_div.addEventListener('click', function(event) {
  841. if (event.target === this) {
  842. if (presentation_div) {
  843. presentation_div.remove();
  844. }
  845. }
  846. });
  847. let dialog_div = document.createElement('div');
  848. dialog_div.className = 'block_obj_dialog_div';
  849. presentation_div.appendChild(dialog_div);
  850. let top_part = document.createElement('div');
  851. top_part.className = 'block_obj_big_bang_top_part';
  852. let h3 = document.createElement('h3');
  853. h3.className = 'block_obj_big_bang_h3';
  854. h3.textContent = '大爆炸';
  855. top_part.appendChild(h3);
  856. let deselect_btn = this.createSpanBtn('block_obj_big_bang_deselect_btn', '取消选择', '取消全部已选择的内容', e => {
  857. e.stopPropagation();
  858. let select_arr = document.querySelectorAll('.block_obj_big_bang_text_selected');
  859. for (let s of select_arr) {
  860. s.classList.remove('block_obj_big_bang_text_selected');
  861. }
  862. });
  863. top_part.appendChild(deselect_btn);
  864. let value_array = value.replace(/\s| /gi, '').split('');
  865. let middle_part = document.createElement('div');
  866. middle_part.className = 'block_obj_big_bang_middle_part';
  867. let node_array = value_array.map((ele, index) => {
  868. let ele_node = this.createBasicBtn('span', ele, '', 'block_obj_big_bang_text');
  869. ele_node.setAttribute('data-index', index);
  870. ele_node.addEventListener('click', e => {
  871. e.stopPropagation();
  872. ele_node.classList.contains('block_obj_big_bang_text_selected') ? ele_node.classList.remove('block_obj_big_bang_text_selected') : ele_node.classList.add('block_obj_big_bang_text_selected');
  873. });
  874. return ele_node;
  875. });
  876. node_array.forEach(item => {
  877. middle_part.appendChild(item);
  878. });
  879. let bottom_part = document.createElement('div');
  880. bottom_part.className = 'block_obj_big_bang_bottom_part';
  881. let add_btn = this.createSpanBtn('block_obj_big_bang_add_btn', '添加', '添加选择的内容到列表中', e => {
  882. e.stopPropagation();
  883. let text_value = this.getSelectedText('block_obj_big_bang_text_selected');
  884. if (text_value && list_id) {
  885. let text_arr = this.stringToArray(text_value);
  886. let save_arr = this.extractList(list_id);
  887. text_arr.forEach(item => {
  888. let status = true;
  889. if (typeof(campare) === 'function') {
  890. let temp_status = campare(item);
  891. if (typeof(temp_status) === 'boolean') {
  892. status = temp_status;
  893. }
  894. }
  895. if (status) {
  896. ! save_arr.includes(item) && document.getElementById(list_id).insertAdjacentElement('afterbegin', this.createListItem(item));
  897. }
  898. });
  899. this.saveConfig();
  900. presentation_div.remove();
  901. }
  902. });
  903. bottom_part.appendChild(add_btn);
  904. let copy_btn = this.createSpanBtn('block_obj_big_bang_copy_btn', '复制', '复制选择的内容到剪贴板中', e => {
  905. e.stopPropagation();
  906. let text_value = this.getSelectedText('block_obj_big_bang_text_selected');
  907. if (text_value) {
  908. Block_Obj.GM.setClipboard(text_value);
  909. presentation_div.remove();
  910. }
  911. });
  912. bottom_part.appendChild(copy_btn);
  913. dialog_div.appendChild(top_part);
  914. dialog_div.appendChild(middle_part);
  915. dialog_div.appendChild(bottom_part);
  916. document.body.appendChild(presentation_div);
  917. }
  918. getSelectedText(classname) {
  919. let selected_array = document.getElementsByClassName(classname);
  920. let last_index = -1;
  921. let text_value = '';
  922. for (let selected of selected_array) {
  923. let index = selected.getAttribute('data-index') || -1;
  924. if (Number(index) == last_index + 1) {
  925. text_value += selected.textContent;
  926. } else {
  927. text_value = text_value ? text_value + ',' + selected.textContent : selected.textContent;
  928. }
  929. last_index = Number(index);
  930. }
  931. return text_value;
  932. }
  933. buttonClicked(button, click_title, click_class) {
  934. let original_title = button.title;
  935. button.title = click_title;
  936. click_class && button.classList.add(click_class);
  937. timer && window.clearTimeout(timer);
  938. var timer = window.setTimeout(() => {
  939. button.title = original_title;
  940. button.classList.remove(click_class);
  941. }, 1000);
  942. }
  943. extractList(list_id) {
  944. let re_arr = [];
  945. let list_dom = document.getElementById(list_id);
  946. let list_arr = list_dom.getElementsByClassName('block_obj_child_text');
  947. for (let i = list_arr.length - 1; i >= 0; i --) {
  948. list_arr[i].title ? re_arr.push(list_arr[i].title) : re_arr.push(list_arr[i].textContent);
  949. }
  950. return re_arr;
  951. }
  952. stringToArray(text_string) {
  953. let temp_array = text_string.split(',');
  954. let return_array = [];
  955. for (let i = 0, l = temp_array.length; i < l; i ++) {
  956. for (let j = i + 1; j < l; j ++) {
  957. if (temp_array[i] === temp_array[j]) {
  958. ++ i;
  959. j = i;
  960. }
  961. }
  962. return_array.push(temp_array[i]);
  963. }
  964. return return_array;
  965. }
  966. toggleList(li_classname) {
  967. for (let li of this.ulNode.querySelectorAll('li')) {
  968. if (li.classList.contains(li_classname)) {
  969. let list_textarea_div = li.querySelector('.block_obj_list_textarea_div');
  970. if (list_textarea_div) {
  971. list_textarea_div.classList.contains('block_obj_list_textarea_expand') ? list_textarea_div.classList.remove('block_obj_list_textarea_expand') : list_textarea_div.classList.add('block_obj_list_textarea_expand');
  972. }
  973. } else {
  974. li.classList.contains('block_obj_li_hide') ? li.classList.remove('block_obj_li_hide') : li.classList.add('block_obj_li_hide');
  975. }
  976. }
  977. for (let br of this.ulNode.querySelectorAll('br')) {
  978. br.classList.contains('block_obj_li_hide') ? br.classList.remove('block_obj_li_hide') : br.classList.add('block_obj_li_hide');
  979. }
  980. }
  981. convertArray(string_array) {
  982. let re_arr = [];
  983. if (Array.isArray(string_array)) {
  984. for (let i = 0; i < string_array.length; i ++) {
  985. try {
  986. let new_reg = new RegExp(string_array[i].replace(/^\/|\/[a-z]*$/gi, ''), string_array[i].replace(/^\/.*\/[^a-z]*/i, ''));
  987. re_arr.push(new_reg);
  988. } catch(e) {
  989. console.error('Block_Obj: The transformation contains invalid regular expressions.');
  990. console.error(e);
  991. }
  992. }
  993. }
  994. return re_arr;
  995. }
  996. }
  997. Block_Obj.count = 0;
  998. Block_Obj.GM = {
  999. 'isError': false,
  1000. 'menuCount': 0,
  1001. 'error': message => {
  1002. if (! Block_Obj.GM.isError) {
  1003. Block_Obj.GM.isError = true;
  1004. alert('The required ' + message + ' method is incomplete!!!');
  1005. }
  1006. },
  1007. 'warn': message => {
  1008. console.warn('The required ' + message + ' method is incomplete!!!');
  1009. },
  1010. 'tips': message => {
  1011. console.info('Tips: ' + message);
  1012. },
  1013. 'info': () => {
  1014. if (typeof(GM_info) === 'object') {
  1015. return GM_info;
  1016. } else if (typeof(GM.info) === 'object') {
  1017. return GM.info;
  1018. } else {
  1019. Block_Obj.GM.warn('GM_info or GM.info');
  1020. return {
  1021. 'script': {
  1022. 'version': 0
  1023. },
  1024. 'scriptHandler': 'Unknown',
  1025. 'version': 0
  1026. };
  1027. }
  1028. },
  1029. 'getValue': (name, defaultValue) => {
  1030. if (typeof(GM_getValue) === 'function') {
  1031. return GM_getValue(name, defaultValue);
  1032. } else if (typeof(GM.getValue) === 'function') {
  1033. return GM.getValue(name, defaultValue);
  1034. } else {
  1035. Block_Obj.GM.error('GM_getValue or GM.getValue');
  1036. return null;
  1037. }
  1038. },
  1039. 'setValue': (name, value) => {
  1040. if (typeof(GM_setValue) === 'function') {
  1041. GM_setValue(name, value);
  1042. } else if (typeof(GM.setValue) === 'function') {
  1043. GM.setValue(name, value);
  1044. } else {
  1045. Block_Obj.GM.error('GM_setValue or GM.setValue');
  1046. }
  1047. },
  1048. 'deleteValue': async(name) => {
  1049. if (typeof(GM_deleteValue) === 'function') {
  1050. await GM_deleteValue(name);
  1051. } else if (typeof(GM.deleteValue) === 'function') {
  1052. await GM.deleteValue(name);
  1053. } else {
  1054. Block_Obj.GM.error('GM_deleteValue or GM.deleteValue');
  1055. }
  1056. },
  1057. 'listValues': () => {
  1058. if (typeof(GM_listValues) === 'function') {
  1059. return GM_listValues();
  1060. } else if (typeof(GM.listValues) === 'function') {
  1061. return GM.listValues();
  1062. } else {
  1063. Block_Obj.GM.error('GM_listValues or GM.listValues');
  1064. }
  1065. },
  1066. 'openInTab': (url, options) => {
  1067. if (typeof(GM_openInTab) === 'function') {
  1068. GM_openInTab(url, options);
  1069. } else if (typeof(GM.openItTab) === 'function') {
  1070. GM.openInTab(url, options.active);
  1071. } else {
  1072. Block_Obj.GM.error('GM_openInTab or GM.openInTab');
  1073. }
  1074. },
  1075. 'hasOpenIntTabMethods': () => {
  1076. return typeof(GM_openInTab) === 'function' || typeof(GM.openItTab) === 'function';
  1077. },
  1078. 'hasRegisterMenuCommandMethods': () => {
  1079. return typeof(GM_registerMenuCommand) === 'function';
  1080. },
  1081. 'hasAddValueChangeListenerMethods': () => {
  1082. return typeof(GM_addValueChangeListener) === 'function';
  1083. },
  1084. 'registerMenuCommand': (name, fn) => {
  1085. let menuId = null;
  1086. if (typeof(GM_registerMenuCommand) === 'function') {
  1087. if (Block_Obj.GM.info().scriptHandler === 'Violentmonkey') {
  1088. Block_Obj.GM.menuCount ++;
  1089. GM_registerMenuCommand(Block_Obj.GM.menuCount + '.' + name, fn);
  1090. menuId = Block_Obj.GM.menuCount + '.' + name;
  1091. } else if (Block_Obj.GM.info().scriptHandler === 'Tampermonkey') {
  1092. menuId = GM_registerMenuCommand(name, fn);
  1093. }
  1094. } else {
  1095. Block_Obj.GM.warn('GM_registerMenuCommand');
  1096. }
  1097. return menuId;
  1098. },
  1099. 'unregisterMenuCommand': menuId => {
  1100. if (typeof(GM_unregisterMenuCommand) === 'function') {
  1101. GM_unregisterMenuCommand(menuId);
  1102. if (Block_Obj.GM.info().scriptHandler === 'Violentmonkey') {
  1103. Block_Obj.GM.menuCount --;
  1104. if (Block_Obj.fn.compare('2.12.5', Block_Obj.GM.info().version)) {
  1105. Block_Obj.GM.tips('Maybe you should update Violentmonkey to 2.12.5 or higher.');
  1106. }
  1107. }
  1108. } else {
  1109. Block_Obj.GM.warn('GM_unregisterMenuCommand');
  1110. }
  1111. },
  1112. 'addValueChangeListener': (name, callback) => {
  1113. if (typeof(GM_addValueChangeListener) === 'function') {
  1114. return GM_addValueChangeListener(name, callback);
  1115. } else {
  1116. Block_Obj.GM.warn('GM_addValueChangeListener');
  1117. return null;
  1118. }
  1119. },
  1120. 'removeValueChangeListener': listenerId => {
  1121. if (typeof(GM_removeValueChangeListener) === 'function') {
  1122. GM_removeValueChangeListener(listenerId);
  1123. } else {
  1124. Block_Obj.GM.warn('GM_removeValueChangeListener');
  1125. }
  1126. },
  1127. 'setClipboard': text => {
  1128. if (typeof(GM_setClipboard) === 'function') {
  1129. GM_setClipboard(text);
  1130. } else if (typeof(GM.setClipboard) === 'function') {
  1131. GM.setClipboard(text);
  1132. } else {
  1133. Block_Obj.GM.error('GM_setClipboard or GM.setClipboard');
  1134. }
  1135. }
  1136. };
  1137. Block_Obj.fn = {
  1138. 'hideOperation': (node, hide_status, method = 0) => {
  1139. if (node && node instanceof HTMLElement) {
  1140. if (hide_status) {
  1141. if (method === 0) {
  1142. node.classList.add('block_obj_none');
  1143. } else if (method === 1) {
  1144. node.classList.add('block_obj_hidden');
  1145. } else if (method === 2) {
  1146. node.style.display = 'none';
  1147. } else if (method === 3) {
  1148. node.style.visibility = 'hidden';
  1149. }
  1150. } else {
  1151. if (method === 0) {
  1152. node.classList.remove('block_obj_none');
  1153. } else if (method === 1) {
  1154. node.classList.remove('block_obj_hidden');
  1155. } else if (method === 2) {
  1156. node.style.display = '';
  1157. } else if (method === 3) {
  1158. node.style.visibility = '';
  1159. }
  1160. }
  1161. }
  1162. },
  1163. compare(str1, str2, symbol = '.', equal = false) {
  1164. let arr1 = str1.split(symbol);
  1165. let arr2 = str2.split(symbol);
  1166. let compare_status = false;
  1167. let len = arr1.length < arr2.length ? arr1.length : arr2.length;
  1168. for (let i = len - 1; i >= 0; i --) {
  1169. if (Number(arr1[i]) > Number(arr2[i])) {
  1170. compare_status = true;
  1171. } else if (equal && Number(arr1[i]) == Number(arr2[i])) {
  1172. compare_status = true;
  1173. } else {
  1174. compare_status = false;
  1175. }
  1176. }
  1177. return compare_status;
  1178. },
  1179. 'getVersion': () => '2.9.0'
  1180. };