Block_Obj

屏蔽内容对象库

此脚本不应直接安装,它是一个供其他脚本使用的外部库。如果您需要使用该库,请在脚本元属性加入:// @require https://update.gf.qytechs.cn/scripts/407543/963893/Block_Obj.js

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

QingJ © 2025

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