Block_Obj

BLOCK_OBJ

当前为 2020-07-28 提交的版本,查看 最新版本

此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.cn-greasyfork.org/scripts/407543/831530/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.7.4
  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-bottom: 2px;
  81. margin-top: 2px;
  82. }
  83. .block_obj_separator_symbol {
  84. background-color: #303030;
  85. height: 2px;
  86. margin-bottom: 5px;
  87. margin-top: 5px;
  88. min-width: 400px;
  89. }
  90. .block_obj_input_div {
  91. margin-top: 5px;
  92. }
  93. .block_obj_input {
  94. background-color: #C0C0C0;
  95. border: 1px solid #C0C0C0;
  96. color: #000;
  97. font-size: 13px;
  98. min-height: 15px;
  99. margin-left: 5px;
  100. margin-right: 5px;
  101. padding-left: 4px;
  102. }
  103. .block_obj_keyword_input {
  104. width: 150px;
  105. }
  106. .block_obj_input_btn {
  107. background-color: #3da9cc;
  108. border-radius: 3px;
  109. border: 1px solid #73C9E5;
  110. box-shadow: 0 0 4px #73C9E5;
  111. color: #FFF;
  112. cursor: pointer;
  113. display: inline-block;
  114. min-height: 15px;
  115. line-height: normal;
  116. margin-left: 5px;
  117. text-align: center;
  118. vertical-align: bottom;
  119. white-space: nowrap;
  120. width: 30px;
  121. }
  122. .block_obj_list_div {
  123. margin-top: 5px;
  124. }
  125. .block_obj_list_textarea_div {
  126. border: 1px dotted #00A1D6;
  127. margin-top: 3px;
  128. max-height: 60px;
  129. min-height: 3px;
  130. overflow: auto;
  131. }
  132. .block_obj_list_textarea_div::-webkit-scrollbar {
  133. background-color: #979797;
  134. border-radius: 5px;
  135. width: 10px;
  136. }
  137. .block_obj_list_textarea_div::-webkit-scrollbar-thumb {
  138. background-color: #404040;
  139. border-radius: 5px;
  140. }
  141. .block_obj_button_clicked {
  142. color: #000;
  143. }
  144. .block_obj_child_span {
  145. background-color: #3D3D3D;
  146. border-radius: 5px;
  147. border: 1px solid #3D3D3D;
  148. display: inline-block;
  149. margin: 3px;
  150. padding: 2px;
  151. min-height: 18px;
  152. }
  153. .block_obj_child_text {
  154. border-right: 1px solid #A9181C;
  155. margin-right: 4px;
  156. padding-right: 4px;
  157. }
  158. .block_obj_child_del {
  159. color: #A9181C;
  160. cursor: pointer;
  161. }
  162. .block_obj_list_textarea_expand {
  163. max-height: 720px;
  164. }
  165. .block_obj_li_hide {
  166. display: none;
  167. }
  168. .block_obj_reg_input {
  169. width: 100px;
  170. }
  171. .block_obj_modifier_input {
  172. width: 50px;
  173. }
  174. .block_obj_button {
  175. background-color: #FB7299;
  176. border-radius: 4px;
  177. border: 1px solid #FB7299;
  178. color: #FFF;
  179. cursor: pointer;
  180. margin-top: 5px;
  181. padding: 2px 4px;
  182. position: relative;
  183. min-height: 17px;
  184. line-height: normal;
  185. }
  186. .block_obj_save_button {
  187. float: right;
  188. margin-right: 5px;
  189. }
  190. .block_obj_cancel_button {
  191. float: left;
  192. margin-left: 5px;
  193. }
  194. .block_obj_expand_box {
  195. bottom: 0px;
  196. height: 6vh;
  197. position: fixed;
  198. right: -6vw;
  199. transition: 0.5s;
  200. width: 12vw;
  201. z-index: 99999;
  202. }
  203. .block_obj_show_expand_box {
  204. right: 0;
  205. width: 6vw;
  206. }
  207. .block_obj_expand_span {
  208. background-color: #00A1D6;
  209. border-radius: 19px;
  210. border: 1px solid #00A1D6;
  211. bottom: 1vh;
  212. color: #FFF;
  213. cursor: pointer;
  214. display: block;
  215. font-size: 13px;
  216. height: 38px;
  217. line-height: 38px;
  218. position: absolute;
  219. right: 1vw;
  220. text-align: center;
  221. width: 38px;
  222. z-index: 99999;
  223. }
  224. .block_obj_expand_span:hover {
  225. box-shadow: 0 0 5px 1px green;
  226. }
  227. .block_obj_move_right {
  228. margin-left: 15px;
  229. }
  230. .block_obj_none {
  231. display: none !important;
  232. }
  233. .block_obj_hidden {
  234. visibility: hidden !important;
  235. }
  236. .block_obj_presentation_div {
  237. display: flex;
  238. position: fixed;
  239. background-color: rgba(0, 0, 0, .5);
  240. top: 0;
  241. bottom: 0;
  242. left: 0;
  243. right: 0;
  244. z-index: 100000;
  245. align-items: center;
  246. justify-content: center;
  247. }
  248. .block_obj_dialog_div {
  249. position: relative;
  250. width: 400px;
  251. background-color: #4e5654;
  252. border: 0 solid #000;
  253. border-radius: 12px;
  254. display: flex;
  255. flex-direction: column;
  256. }
  257. .block_obj_big_bang_top_part {
  258. margin-top: 5px;
  259. margin-bottom: 5px;
  260. }
  261. .block_obj_big_bang_h3 {
  262. font-size: 20px;
  263. color: #fff;
  264. margin-left: 5px;
  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. }
  289. .block_obj_big_bang_text_selected {
  290. background-color: #3636b1 !important;
  291. }
  292. .block_obj_big_bang_bottom_part {
  293. margin-top: 5px;
  294. margin-bottom: 5px;
  295. text-align: center;
  296. }
  297. .block_obj_big_bang_add_btn, .block_obj_big_bang_copy_btn {
  298. display: inline-block;
  299. padding: 10px;
  300. color: #fff;
  301. background-color: #325561;
  302. cursor: pointer;
  303. border-radius: 99px;
  304. margin-left: 20px;
  305. margin-right: 20px;
  306. }
  307. .block_obj_big_bang_add_btn:hover, .block_obj_big_bang_copy_btn:hover {
  308. color: #2a2a92;
  309. }
  310. `;
  311. class Block_Obj {
  312. constructor(config_key, reg_key_array = []) {
  313. this.wrapDiv = null;
  314. this.mainFieldset = null;
  315. this.ulNode = null;
  316. this.style = null;
  317. this.saveField = [];
  318. this.onSave = null;
  319. this.onChange = null;
  320. this.field = [];
  321. this.configKey = config_key;
  322. this.regKeyArray = reg_key_array;
  323. this.config = this.readConfig();
  324. }
  325. init(initialization) {
  326. if (! this.id) {
  327. this.id = initialization.id ? 'blockObj_' + initialization.id : 'blockObj_' + Block_Obj.count;
  328. ! initialization.id && Block_Obj.count ++;
  329. }
  330. this.display = initialization.display ? true : false;
  331. if (initialization.events) {
  332. if (typeof(initialization.events['save']) === 'function') {
  333. this.onSave = initialization.events['save'];
  334. }
  335. if (typeof(initialization.events['change']) === 'function') {
  336. this.onChange = initialization.events['change'];
  337. }
  338. }
  339. this.style = document.createElement('style');
  340. this.style.type = 'text/css';
  341. this.style.innerHTML = BLOCK_STYLE;
  342. document.body.appendChild(this.style);
  343. if (initialization.style && typeof(initialization.style) === 'string') {
  344. let external_style = document.createElement('style');
  345. external_style.type = 'text/css';
  346. external_style.innerHTML = initialization.style;
  347. document.body.appendChild(external_style);
  348. }
  349. ! this.wrapDiv && this.createSettingsPanel();
  350. this.field = initialization.field;
  351. this.settingsPanel();
  352. initialization.menu && typeof(GM_registerMenuCommand) === 'function' && GM_registerMenuCommand(initialization.menu, () => this.expandWrap());
  353. typeof(GM_addValueChangeListener) === 'function' && GM_addValueChangeListener(this.configKey, (_name, _old_value, new_value, remote) => {
  354. if (remote) {
  355. this.destroyAndRebuild(new_value);
  356. typeof(this.onChange) === 'function' && this.onChange(this.getConfig());
  357. }
  358. });
  359. let expand_box = document.createElement('div');
  360. expand_box.className = 'block_obj_expand_box';
  361. expand_box.onmouseenter = function() {
  362. this.classList.add('block_obj_show_expand_box');
  363. };
  364. expand_box.onmouseleave = function() {
  365. this.classList.remove('block_obj_show_expand_box');
  366. };
  367. let expand_span = document.createElement('span');
  368. expand_span.id = this.id + '_expandSpan';
  369. expand_span.className = 'block_obj_expand_span';
  370. expand_span.textContent = '屏蔽';
  371. expand_span.title = '显示屏蔽设置';
  372. expand_span.addEventListener('click', () => this.expandWrap());
  373. expand_box.appendChild(expand_span);
  374. document.body.appendChild(expand_box);
  375. }
  376. settingsPanel() {
  377. if (Array.isArray(this.field)) {
  378. this.field.forEach(ele => {
  379. if (! this.wrapDiv.querySelector('#' + this.id + '_' + (ele.id ? ele.id : ''))) {
  380. switch (ele.type.toLowerCase()) {
  381. case 'separator':
  382. case 's':
  383. this.insertSeparator(ele.id, ele.label, ele.title, ele.classname);
  384. break;
  385. case 'br':
  386. case 'b':
  387. this.insertBr(ele.classname);
  388. break;
  389. case 'input':
  390. case 'i':
  391. this.insertInput(ele.id, ele.list_id, false, ele.label, ele.title, ele.placeholder, ele.classname, ele.campare);
  392. break;
  393. case 'reg_input':
  394. case 'ri':
  395. this.insertInput(ele.id, ele.list_id, true, ele.label, ele.title, ele.placeholder, ele.classname, ele.campare, ele.modifier_label, ele.modifier_placeholder);
  396. break;
  397. case 'list':
  398. case 'l':
  399. this.insertList(ele.id, (this.config[ele.id] == null ? ele.default : this.config[ele.id]), ele.label, ele.title, ele.classname);
  400. break;
  401. case 'checkbox':
  402. case 'c':
  403. default:
  404. this.insertCheckbox(ele.id, ele.label, ele.title, (this.config[ele.id] == null ? ele.default : this.config[ele.id]), ele.classname, ele.move_right);
  405. break;
  406. }
  407. }
  408. });
  409. }
  410. let save_button = this.createSpanBtn('block_obj_button block_obj_save_button', '保存并关闭', '保存设置并关闭设置窗口', e => {
  411. this.expandWrap();
  412. this.saveConfig();
  413. });
  414. let only_save_button = this.createSpanBtn('block_obj_button block_obj_save_button', '仅保存', '仅保存设置', e => {
  415. only_save_button.textContent = '已保存';
  416. save_timer && window.clearTimeout(save_timer);
  417. var save_timer = window.setTimeout(() => {
  418. only_save_button.textContent = '仅保存';
  419. }, 1000);
  420. this.saveConfig();
  421. });
  422. let cancel_button = this.createSpanBtn('block_obj_button block_obj_cancel_button', '取消', '关闭设置窗口', e => {
  423. this.expandWrap();
  424. cancel_timer && window.clearTimeout(cancel_timer);
  425. var cancel_timer = window.setTimeout(() => {
  426. this.display = false;
  427. this.destroyAndRebuild();
  428. }, 800);
  429. e.stopPropagation();
  430. });
  431. this.ulNode.appendChild(save_button);
  432. this.ulNode.appendChild(only_save_button);
  433. this.ulNode.appendChild(cancel_button);
  434. document.body.appendChild(this.wrapDiv);
  435. }
  436. getConfig() {
  437. let real_config = {};
  438. Object.assign(real_config, this.config);
  439. this.regKeyArray.forEach(key => {
  440. real_config[key] = this.convertArray(real_config[key]);
  441. });
  442. return real_config;
  443. }
  444. readConfig() {
  445. let config = {};
  446. if (typeof(GM_getValue) === 'function' && this.configKey) {
  447. config = GM_getValue(this.configKey, {});
  448. }
  449. return config;
  450. }
  451. saveConfig() {
  452. this.saveField.forEach(item => {
  453. if (item.type == 'checkbox') {
  454. this.config[item.key] = document.getElementById(this.id + '_' + item.key).checked;
  455. } else if (item.type == 'list') {
  456. this.config[item.key] = this.extractList(this.id + '_' + item.key);
  457. }
  458. });
  459. typeof(GM_setValue) && GM_setValue(this.configKey, this.config);
  460. typeof(this.onSave) === 'function' && this.onSave(this.getConfig());
  461. }
  462. createSettingsPanel() {
  463. this.wrapDiv = document.createElement('div');
  464. this.wrapDiv.id = this.id + '_wrapDiv';
  465. this.wrapDiv.className = 'block_obj_wrap_div ' + (this.display ? 'block_obj_show_wrap' : 'block_obj_hidden_wrap');
  466. this.mainFieldset = document.createElement('fieldset');
  467. this.mainFieldset.id = this.id + '_mainFieldset';
  468. this.mainFieldset.className = 'block_obj_main_fieldset';
  469. this.wrapDiv.appendChild(this.mainFieldset);
  470. this.ulNode = document.createElement('ul');
  471. this.ulNode.id = this.id + '_ulNode';
  472. this.ulNode.className = 'block_obj_ul_node';
  473. this.mainFieldset.appendChild(this.ulNode);
  474. document.body.appendChild(this.wrapDiv);
  475. }
  476. destroyAndRebuild(new_config = null) {
  477. this.config = new_config || this.config;
  478. document.body.removeChild(this.wrapDiv);
  479. this.createSettingsPanel();
  480. this.settingsPanel();
  481. }
  482. expandWrap() {
  483. let panel = document.getElementById(this.id + '_wrapDiv');
  484. let button = document.getElementById(this.id + '_expandSpan');
  485. if (panel) {
  486. if (panel.classList.contains('block_obj_show_wrap')) {
  487. this.display = false;
  488. panel.classList.remove('block_obj_show_wrap');
  489. panel.classList.add('block_obj_hidden_wrap');
  490. if (button) {
  491. button.title = '显示屏蔽设置';
  492. }
  493. } else {
  494. this.display = true;
  495. panel.classList.remove('block_obj_hidden_wrap');
  496. panel.classList.add('block_obj_show_wrap');
  497. if (button) {
  498. button.title = '隐藏屏蔽设置';
  499. }
  500. }
  501. }
  502. }
  503. insertCheckbox(id, label = '', title = '', checked = false, classname = null, move_right = false) {
  504. let checkbox_li = document.createElement('li');
  505. checkbox_li.className = 'block_obj_checkbox_li';
  506. classname && checkbox_li.classList.add(classname);
  507. move_right && checkbox_li.classList.add('block_obj_move_right');
  508. let checkbox_input = document.createElement('input');
  509. checkbox_input.type = 'checkbox';
  510. checkbox_input.className = 'block_obj_checkbox_input';
  511. checkbox_input.id = this.id + '_' + id;
  512. checkbox_input.checked = checked ? true : false;
  513. let checkbox_label = document.createElement('label');
  514. checkbox_label.className = 'block_obj_checkbox_label';
  515. checkbox_label.setAttribute('for', this.id + '_' + id);
  516. checkbox_label.textContent = label;
  517. checkbox_label.title = title;
  518. checkbox_li.appendChild(checkbox_input);
  519. checkbox_li.appendChild(checkbox_label);
  520. this.ulNode.appendChild(checkbox_li);
  521. this.saveField.push({
  522. 'key': id,
  523. 'type': 'checkbox'
  524. });
  525. }
  526. insertSeparator(id = null, label = null, title = null, li_classname = null) {
  527. let separator_li = document.createElement('li');
  528. separator_li.className = 'block_obj_separator_li';
  529. li_classname && separator_li.classList.add('block_obj_' + li_classname);
  530. let separator_div = document.createElement('div');
  531. if (id) {
  532. separator_div.id = this.id + '_' + id;
  533. }
  534. if (label) {
  535. separator_div.className = 'block_obj_separator_text';
  536. separator_div.textContent = label;
  537. } else {
  538. separator_div.className = 'block_obj_separator_symbol';
  539. }
  540. separator_div.title = title ? title : '';
  541. separator_li.appendChild(separator_div);
  542. this.ulNode.appendChild(separator_li);
  543. }
  544. insertBr(classname = null) {
  545. let br = document.createElement('br');
  546. br.className = classname ? classname : '';
  547. this.ulNode.appendChild(br);
  548. }
  549. insertInput(id, list_id, is_reg = false, label = '', title = '', placeholder = '', li_classname = null, campare = null, modifier_label = '', modifier_placeholder = '') {
  550. let input_li = document.createElement('li');
  551. input_li.className = li_classname ? 'block_obj_' + li_classname : '';
  552. let input_div = document.createElement('div');
  553. input_div.className = 'block_obj_input_div';
  554. let input_span = document.createElement('span');
  555. input_span.className = 'block_obj_input_span';
  556. input_span.textContent = label;
  557. input_div.appendChild(input_span);
  558. let input = document.createElement('input');
  559. input.id = this.id + '_' + id;
  560. input.title = title;
  561. input.placeholder = placeholder;
  562. input.type = 'text';
  563. input.className = is_reg ? 'block_obj_input block_obj_reg_input' : 'block_obj_input block_obj_keyword_input';
  564. input_span.appendChild(input);
  565. let modifier_span = document.createElement('span');
  566. modifier_span.textContent = modifier_label;
  567. is_reg && input_div.appendChild(modifier_span);
  568. let modifier_input = document.createElement('input');
  569. modifier_input.placeholder = modifier_placeholder;
  570. modifier_input.type = 'text';
  571. modifier_input.className = 'block_obj_input block_obj_modifier_input';
  572. modifier_span.appendChild(modifier_input);
  573. let the_list_id = this.id + '_' + list_id;
  574. input.addEventListener('keyup', e => {
  575. if (e.keyCode === 13) {
  576. is_reg ? this.addRegListItem(input, modifier_input, the_list_id) : this.addListItem(input, the_list_id, campare);
  577. }
  578. });
  579. modifier_input.addEventListener('keyup', e => {
  580. e.keyCode === 13 && this.addRegListItem(input, modifier_input, the_list_id);
  581. });
  582. let add_btn = this.createSpanBtn('block_obj_input_btn', '添加', '添加内容到列表中', e => {
  583. if (is_reg ? this.addRegListItem(input, modifier_input, the_list_id) : this.addListItem(input, the_list_id, campare)) {
  584. this.buttonClicked(add_btn, '添加成功', 'block_obj_button_clicked');
  585. }
  586. });
  587. let delete_btn = this.createSpanBtn('block_obj_input_btn', '删除', '从列表中删除符合的项目', e => {
  588. if (is_reg ? this.delRegListItem(input, modifier_input, the_list_id) : this.delListItem(input, the_list_id)) {
  589. this.buttonClicked(delete_btn, '删除成功', 'block_obj_button_clicked');
  590. }
  591. });
  592. let clear_btn = this.createSpanBtn('block_obj_input_btn', '清空', '清空列表', e => {
  593. document.getElementById(the_list_id).innerHTML = '';
  594. this.buttonClicked(clear_btn, '清除成功', 'block_obj_button_clicked');
  595. });
  596. let copy_btn = this.createSpanBtn('block_obj_input_btn', '复制', '复制列表', e => {
  597. if (typeof(GM_setClipboard) == 'function') {
  598. GM_setClipboard(this.extractList(the_list_id).toString(), 'text');
  599. this.buttonClicked(copy_btn, '复制成功', 'block_obj_button_clicked');
  600. } else {
  601. alert('GM_setClipboard is not an interface.');
  602. }
  603. });
  604. let expand_btn = this.createSpanBtn('block_obj_input_btn', '展开', '展开列表', e => {
  605. li_classname && this.toggleList('block_obj_' + li_classname);
  606. if (expand_btn.textContent == '展开') {
  607. expand_btn.textContent = '恢复';
  608. expand_btn.title = '收缩列表';
  609. } else {
  610. expand_btn.textContent = '展开';
  611. expand_btn.title = '展开列表';
  612. }
  613. });
  614. input_div.appendChild(add_btn);
  615. input_div.appendChild(delete_btn);
  616. input_div.appendChild(clear_btn);
  617. input_div.appendChild(copy_btn);
  618. input_div.appendChild(expand_btn);
  619. input_li.appendChild(input_div);
  620. this.ulNode.appendChild(input_li);
  621. }
  622. insertList(id, save_array = [], label = '', title = '', li_classname = '') {
  623. let list_li = document.createElement('li');
  624. list_li.className = li_classname ? 'block_obj_' + li_classname : '';
  625. let list_div = document.createElement('div');
  626. list_div.className = 'block_obj_list_div';
  627. list_div.textContent = label;
  628. list_div.title = title;
  629. let list_textarea_div = document.createElement('div');
  630. list_textarea_div.id = this.id + '_' + id;
  631. list_textarea_div.className = 'block_obj_list_textarea_div';
  632. for (let item of save_array) {
  633. item && list_textarea_div.insertAdjacentElement('afterbegin', this.createListItem(item));
  634. }
  635. list_div.appendChild(list_textarea_div);
  636. list_li.appendChild(list_div);
  637. this.ulNode.appendChild(list_li);
  638. this.saveField.push({
  639. 'key': id,
  640. 'type': 'list'
  641. });
  642. }
  643. addListItem(input, list_id, campare = null) {
  644. let text_value = input.value;
  645. if (text_value) {
  646. let text_arr = this.stringToArray(text_value);
  647. let save_arr = this.extractList(list_id);
  648. text_arr.forEach(item => {
  649. let status = true;
  650. if (typeof(campare) === 'function') {
  651. let temp_status = campare(item);
  652. if (typeof(temp_status) === 'boolean') {
  653. status = temp_status;
  654. }
  655. }
  656. if (status) {
  657. ! save_arr.includes(item) && document.getElementById(list_id).insertAdjacentElement('afterbegin', this.createListItem(item));
  658. }
  659. });
  660. input.value = '';
  661. return true;
  662. }
  663. return false;
  664. }
  665. delListItem(input, list_id) {
  666. let text_value = input.value;
  667. if (text_value) {
  668. let del_status = false;
  669. let text_arr = this.stringToArray(text_value);
  670. let save_arr = this.extractList(list_id);
  671. text_arr.forEach(item => {
  672. if (save_arr.includes(item)) {
  673. let total_child = document.getElementById(list_id).getElementsByClassName('block_obj_child_span');
  674. try {
  675. document.getElementById(list_id).removeChild(total_child[total_child.length - 1 - save_arr.indexOf(item)]);
  676. del_status = true;
  677. } catch(e) {
  678. del_status = false;
  679. console.error('Block_Obj: Error deleting element.');
  680. console.error(e);
  681. }
  682. }
  683. });
  684. if (del_status) {
  685. input.value = '';
  686. return true;
  687. }
  688. }
  689. return false;
  690. }
  691. addRegListItem(reg_input, modifier_input, list_id) {
  692. let reg_value = reg_input.value;
  693. let modifier_value = modifier_input.value;
  694. if (reg_value) {
  695. try {
  696. let reg_obj = new RegExp(reg_value, modifier_value);
  697. let save_arr = this.extractList(list_id);
  698. ! save_arr.includes(reg_obj.toString()) && document.getElementById(list_id).insertAdjacentElement('afterbegin', this.createListItem(reg_obj.toString()));
  699. reg_input.value = '';
  700. modifier_input.value = '';
  701. return true;
  702. } catch(e) {
  703. console.error('Block_Obj: Invalid regular expression.');
  704. console.error(e);
  705. }
  706. }
  707. return false;
  708. }
  709. delRegListItem(reg_input, modifier_input, list_id) {
  710. let reg_value = reg_input.value;
  711. let modifier_value = modifier_input.value;
  712. if (reg_value) {
  713. let del_status = false;
  714. try {
  715. let reg_obj = new RegExp(reg_value, modifier_value);
  716. let save_arr = this.extractList(list_id);
  717. if (save_arr.includes(reg_obj.toString())) {
  718. let total_child = document.getElementById(list_id).getElementsByClassName('block_obj_child_span');
  719. document.getElementById(list_id).removeChild(total_child[total_child.length - 1 - save_arr.indexOf(reg_obj.toString())]);
  720. del_status = true;
  721. }
  722. } catch(e) {
  723. del_status = false;
  724. console.error('Block_Obj: Invalid regular expression or error deleting element.');
  725. console.error(e);
  726. }
  727. if (del_status) {
  728. reg_input.value = '';
  729. modifier_input.value = '';
  730. return true;
  731. }
  732. return false;
  733. }
  734. }
  735. createSpanBtn(classname, label, title, callback) {
  736. let btn_span = this.createBasicBtn('span', label, title, classname);
  737. btn_span.addEventListener('click', e => typeof(callback) === 'function' && callback(e));
  738. return btn_span;
  739. }
  740. createListItem(text_value) {
  741. let child_span = document.createElement('span');
  742. child_span.className = 'block_obj_child_span';
  743. let text_span = document.createElement('span');
  744. text_span.className = 'block_obj_child_text';
  745. text_span.textContent = text_value.length > 9 ? text_value.slice(0, 3) + '...' + text_value.slice(-3) : text_value;
  746. if (text_value.length > 9) {
  747. text_span.title = text_value;
  748. }
  749. let del_span = document.createElement('span');
  750. del_span.textContent = 'X';
  751. del_span.title = '移除';
  752. del_span.className = 'block_obj_child_del';
  753. del_span.addEventListener('click', e => child_span.remove());
  754. child_span.appendChild(text_span);
  755. child_span.appendChild(del_span);
  756. return child_span;
  757. }
  758. createBasicBtn(type, text, title, classname) {
  759. let btn_type = 'span';
  760. if (typeof(type) === 'string') {
  761. switch (type.toLowerCase()) {
  762. case 'div':
  763. case 'd':
  764. btn_type = 'div';
  765. break;
  766. case 'a':
  767. btn_type = 'a';
  768. break;
  769. case 'button':
  770. btn_type = 'button';
  771. break;
  772. case 'input':
  773. btn_type = 'input';
  774. break;
  775. case 'i':
  776. btn_type = 'i';
  777. break;
  778. case 'b':
  779. btn_type = 'b';
  780. break;
  781. case 'span':
  782. case 's':
  783. default:
  784. btn_type = 'span';
  785. break;
  786. }
  787. }
  788. let btn = document.createElement(btn_type);
  789. btn.textContent = text ? text : '';
  790. btn.title = title ? title : '';
  791. btn.className = classname ? classname : '';
  792. return btn;
  793. }
  794. createBlockBtn(value, list_id, classname, type = 'span', text = '', title = '', campare = null) {
  795. let block_btn = this.createBasicBtn(type, text, title, classname);
  796. block_btn.addEventListener('click', e => {
  797. e.stopPropagation();
  798. if (value && list_id) {
  799. let status = true;
  800. if (typeof(campare) === 'function') {
  801. let temp_status = campare(value);
  802. if (typeof(temp_status) === 'boolean') {
  803. status = temp_status;
  804. }
  805. }
  806. if (status) {
  807. let the_list_id = this.id + '_' + list_id;
  808. let save_arr = this.extractList(the_list_id);
  809. ! save_arr.includes(value) && document.getElementById(the_list_id) && document.getElementById(the_list_id).insertAdjacentElement('afterbegin', this.createListItem(value));
  810. }
  811. }
  812. this.saveConfig();
  813. });
  814. return block_btn;
  815. }
  816. createBigBangBtn(value, list_id, classname, type = 'span', text = '', title = '', campare = null) {
  817. let big_bang_btn = this.createBasicBtn(type, text, title, classname);
  818. big_bang_btn.addEventListener('click', e => {
  819. e.stopPropagation();
  820. if (value && list_id) {
  821. let the_list_id = this.id + '_' + list_id;
  822. this.injectionBigBangPanel(value, the_list_id, campare);
  823. }
  824. });
  825. return big_bang_btn;
  826. }
  827. injectionBigBangPanel(value, list_id, campare = null) {
  828. let presentation_div = document.createElement('div');
  829. presentation_div.id = this.id + '_presentationDiv';
  830. presentation_div.className = 'block_obj_presentation_div';
  831. presentation_div.addEventListener('click', function(event) {
  832. if (event.target === this) {
  833. if (presentation_div) {
  834. presentation_div.remove();
  835. }
  836. }
  837. });
  838. let dialog_div = document.createElement('div');
  839. dialog_div.className = 'block_obj_dialog_div';
  840. presentation_div.appendChild(dialog_div);
  841. let top_part = document.createElement('div');
  842. top_part.className = 'block_obj_big_bang_top_part';
  843. let h3 = document.createElement('h3');
  844. h3.className = 'block_obj_big_bang_h3';
  845. h3.textContent = '大爆炸';
  846. top_part.appendChild(h3);
  847. let deselect_btn = this.createSpanBtn('block_obj_big_bang_deselect_btn', '取消选择', '取消全部已选择的内容', e => {
  848. e.stopPropagation();
  849. let select_arr = document.querySelectorAll('.block_obj_big_bang_text_selected');
  850. for (let s of select_arr) {
  851. s.classList.remove('block_obj_big_bang_text_selected');
  852. }
  853. });
  854. top_part.appendChild(deselect_btn);
  855. let value_array = value.replace(/\s| /gi, '').split('');
  856. let middle_part = document.createElement('div');
  857. middle_part.className = 'block_obj_big_bang_middle_part';
  858. let node_array = value_array.map((ele, index) => {
  859. let ele_node = this.createBasicBtn('span', ele, '', 'block_obj_big_bang_text');
  860. ele_node.setAttribute('data-index', index);
  861. ele_node.addEventListener('click', e => {
  862. e.stopPropagation();
  863. 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');
  864. });
  865. return ele_node;
  866. });
  867. node_array.forEach(item => {
  868. middle_part.appendChild(item);
  869. });
  870. let bottom_part = document.createElement('div');
  871. bottom_part.className = 'block_obj_big_bang_bottom_part';
  872. let add_btn = this.createSpanBtn('block_obj_big_bang_add_btn', '添加', '添加选择的内容到列表中', e => {
  873. e.stopPropagation();
  874. let text_value = this.getSelectedText('block_obj_big_bang_text_selected');
  875. if (text_value && list_id) {
  876. let text_arr = this.stringToArray(text_value);
  877. let save_arr = this.extractList(list_id);
  878. text_arr.forEach(item => {
  879. let status = true;
  880. if (typeof(campare) === 'function') {
  881. let temp_status = campare(item);
  882. if (typeof(temp_status) === 'boolean') {
  883. status = temp_status;
  884. }
  885. }
  886. if (status) {
  887. ! save_arr.includes(item) && document.getElementById(list_id).insertAdjacentElement('afterbegin', this.createListItem(item));
  888. }
  889. });
  890. this.saveConfig();
  891. presentation_div.remove();
  892. }
  893. });
  894. bottom_part.appendChild(add_btn);
  895. let copy_btn = this.createSpanBtn('block_obj_big_bang_copy_btn', '复制', '复制选择的内容到剪贴板中', e => {
  896. e.stopPropagation();
  897. let text_value = this.getSelectedText('block_obj_big_bang_text_selected');
  898. if (text_value) {
  899. GM_setClipboard(text_value, 'text');
  900. presentation_div.remove();
  901. }
  902. });
  903. bottom_part.appendChild(copy_btn);
  904. dialog_div.appendChild(top_part);
  905. dialog_div.appendChild(middle_part);
  906. dialog_div.appendChild(bottom_part);
  907. document.body.appendChild(presentation_div);
  908. }
  909. getSelectedText(classname) {
  910. let selected_array = document.getElementsByClassName(classname);
  911. let last_index = -1;
  912. let text_value = '';
  913. for (let selected of selected_array) {
  914. let index = selected.getAttribute('data-index') || -1;
  915. if (Number(index) == last_index + 1) {
  916. text_value += selected.textContent;
  917. } else {
  918. text_value = text_value ? text_value + ',' + selected.textContent : selected.textContent;
  919. }
  920. last_index = Number(index);
  921. }
  922. return text_value;
  923. }
  924. buttonClicked(button, click_title, click_class) {
  925. let original_title = button.title;
  926. button.title = click_title;
  927. click_class && button.classList.add(click_class);
  928. timer && window.clearTimeout(timer);
  929. var timer = window.setTimeout(() => {
  930. button.title = original_title;
  931. button.classList.remove(click_class);
  932. }, 1000);
  933. }
  934. extractList(list_id) {
  935. let re_arr = [];
  936. let list_dom = document.getElementById(list_id);
  937. let list_arr = list_dom.getElementsByClassName('block_obj_child_text');
  938. for (let i = list_arr.length - 1; i >= 0; i --) {
  939. list_arr[i].title ? re_arr.push(list_arr[i].title) : re_arr.push(list_arr[i].textContent);
  940. }
  941. return re_arr;
  942. }
  943. stringToArray(text_string) {
  944. let temp_array = text_string.split(',');
  945. let return_array = [];
  946. for (let i = 0, l = temp_array.length; i < l; i ++) {
  947. for (let j = i + 1; j < l; j ++) {
  948. if (temp_array[i] === temp_array[j]) {
  949. ++ i;
  950. j = i;
  951. }
  952. }
  953. return_array.push(temp_array[i]);
  954. }
  955. return return_array;
  956. }
  957. toggleList(li_classname) {
  958. for (let li of this.ulNode.querySelectorAll('li')) {
  959. if (li.classList.contains(li_classname)) {
  960. let list_textarea_div = li.querySelector('.block_obj_list_textarea_div');
  961. if (list_textarea_div) {
  962. 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');
  963. }
  964. } else {
  965. li.classList.contains('block_obj_li_hide') ? li.classList.remove('block_obj_li_hide') : li.classList.add('block_obj_li_hide');
  966. }
  967. }
  968. for (let br of this.ulNode.querySelectorAll('br')) {
  969. br.classList.contains('block_obj_li_hide') ? br.classList.remove('block_obj_li_hide') : br.classList.add('block_obj_li_hide');
  970. }
  971. }
  972. convertArray(string_array) {
  973. let re_arr = [];
  974. if (Array.isArray(string_array)) {
  975. for (let i in string_array) {
  976. try {
  977. let new_reg = new RegExp(string_array[i].replace(/^\/|\/[a-z]*$/gi, ''), string_array[i].replace(/^\/.*\/[^a-z]*/i, ''));
  978. re_arr.push(new_reg);
  979. } catch(e) {
  980. console.error('Block_Obj: The transformation contains invalid regular expressions.');
  981. console.error(e);
  982. }
  983. }
  984. }
  985. return re_arr;
  986. }
  987. }
  988. Block_Obj.count = 0;
  989. Block_Obj.fn = {
  990. 'hideOperation': (node, hide_status, method = 0) => {
  991. if (node && node instanceof HTMLElement) {
  992. if (hide_status) {
  993. if (method === 0) {
  994. node.classList.add('block_obj_none');
  995. } else if (method === 1) {
  996. node.classList.add('block_obj_hidden');
  997. } else if (method === 2) {
  998. node.style.display = 'none';
  999. } else if (method === 3) {
  1000. node.style.visibility = 'hidden';
  1001. }
  1002. } else {
  1003. if (method === 0) {
  1004. node.classList.remove('block_obj_none');
  1005. } else if (method === 1) {
  1006. node.classList.remove('block_obj_hidden');
  1007. } else if (method === 2) {
  1008. node.style.display = '';
  1009. } else if (method === 3) {
  1010. node.style.visibility = '';
  1011. }
  1012. }
  1013. }
  1014. }
  1015. };