Word and Text Replace

Replaces text with other text.

  1. // ==UserScript==
  2. // @name Word and Text Replace
  3. // @namespace https://github.com/erickRecai
  4. // @version 1.05.03
  5. // @description Replaces text with other text.
  6. // @author guyRicky
  7.  
  8. // @match *://*/*
  9. // @noframes
  10.  
  11. // @exclude *://docs.google.com/*
  12. // @exclude *://drive.google.com/*
  13. // @exclude *://mail.google.com/*
  14.  
  15. // @require https://code.jquery.com/jquery-3.4.1.min.js
  16. // @require https://greasyfork.org/scripts/381859-waitforkeyelements-by-brocka/code/WaitForKeyElements%20by%20BrockA.js?version=689364
  17.  
  18. // @licence CC-BY-NC-SA-4.0; https://creativecommons.org/licenses/by-nc-sa/4.0/
  19. // @licence GPL-3.0-or-later; http://www.gnu.org/licenses/gpl-3.0.txt
  20. // ==/UserScript==
  21. /* jshint esversion: 6 */
  22.  
  23. (function () {
  24. 'use strict';
  25.  
  26. if(0){/*
  27. last update: 7/04/2020
  28.  
  29. == todo ==
  30. 1. comment on iframes.
  31. 1. script execution flow with FHD.
  32. 1. separate counter for each execution instance.
  33.  
  34. 10. case: 2 text nodes have the same parent block.
  35.  
  36. == issues ==
  37. - certain text nodes aren't accessed with markCheckedElement enabled. (multiple text nodes)
  38.  
  39. == how it works ==
  40. 1a. calls processPage() once for each major run.
  41. 1b. creates list of specific text nodes then checks each against all rules.
  42. 1ba. with special replace enabled, if delete or full replace match, check stops after the first special match.
  43. - this excludes elements previously checked.
  44. - changes text based on matches.
  45. 1c. after checking a text node against all rules, applies a 'checked' class to the element containing the text node.
  46.  
  47. 2a. dlt1 and dlt2 completely replaces text by default, option to change.
  48.  
  49. == notification notes ==
  50. 1e. elements checked by title attributes are processed in a separate block.
  51. 5a. notifications only work for those sites enabled with filters.
  52.  
  53. == version history ==
  54. == 1.05.03 ==
  55. - custom execution time
  56. - some clean up.
  57.  
  58. == code markers ==
  59. AA. initial setup
  60. AB. replace rules
  61. AC. special rules
  62. BA. script options
  63. BB. notif code block
  64. CA. processPage()
  65. CB. execution control
  66. DA. script button
  67. DB. support functions
  68. */}
  69. // ==== AA. initial setup =====================================================================|
  70.  
  71. const scriptPrefix = "rplt-";
  72. const scriptTag = "RPLT";
  73.  
  74. let runScript = 1;
  75. runScript = getOptionState("enable-"+ scriptPrefix +"script", runScript);
  76.  
  77. if (runScript) {
  78.  
  79. let enableConsoleMessages = 1; // default 0; set to 1 to show console messages.
  80. enableConsoleMessages = getOptionState("log-"+ scriptPrefix +"msg", enableConsoleMessages);
  81.  
  82. let enabledMessages =
  83. //"MA|"+ // any rule matches
  84. "TT-MA|"+ // page title match.
  85. "TXT-MA|"+ // all text matches.
  86. "DLT1|"+ // delete1 matches.
  87. "DLT2|"+ // delete2 matches
  88. "FR1|"+ // full replace matches.
  89. //"CH-TT|"+ // changed text.
  90.  
  91. "RUNT|"+ // runtime messages (amount of time to execute)
  92. "EXEC|"+ // execution messages (when code is executed)
  93. "\\bST\\b|"+ //script option change update
  94. "GEN$|"+ // general messages
  95. "^1"; // high priority messages
  96. let logAll = 0; // if 1, logs all titles from blocks.
  97. logAll = getOptionState("log-"+ scriptPrefix +"all", logAll);
  98. if (logAll) {
  99. enabledMessages = enabledMessages.concat("|title");
  100. }
  101. const enabledMessagesRegex = new RegExp(enabledMessages); // used in consolelog().
  102.  
  103. consolelog("#### ("+ scriptTag +") text replace script began. ####", "EXEC");
  104.  
  105. // ==== AB. replace rules =================================================================|
  106.  
  107. let replaceRules = [
  108. //[//i, ""], // rule template
  109. // basic examples:
  110. //[/commit/i, "dog"],
  111. //[/branch/i, "turtle"],
  112. //[/file/i, "birdie"],
  113. //[/\w/g, "a"], //replaces all characters with "a".
  114. //[/(.|\W)+/i, "text"], //replaces all text instances with "text".
  115. ];
  116.  
  117. // ==== AC. special rules =================================================================|
  118.  
  119. const enableSpecialRules = 1;
  120. if (enableSpecialRules) {
  121. // example of including a rule list defined in a spearate script.
  122. if (unsafeWindow.globalListName) {
  123. replaceRules = replaceRules.concat(unsafeWindow.globalListName);
  124. }
  125. }
  126. //consolelog(replaceRules,"all rules"); //test: double check rule contents
  127.  
  128. // ==== BA. script options ================================================================|
  129.  
  130. const classWhitelist = /notif-hidden|notif-text|tag-inst|-counter/i;
  131. // text nodes with parent elements with these classes are excluded.
  132.  
  133. const generateRecheckButton = 1;
  134.  
  135. let dynamicChecking = 1; // default 1; set to 1 to run the script automatically when new image elements are detected.
  136. dynamicChecking = getOptionState("enable-"+ scriptPrefix +"dynamic-checking", dynamicChecking);
  137. // setting to 0 would make this run a few more times when dynamically checking.
  138. // ==== checked in processPage() ====
  139. // managable with optional Script Options userscript.
  140. let logRuntimes = 1; // default 0; set to 1 to log function runtimes to the console.
  141. let markCheckedElements = 1; // default 1; set to 0 if certain sites start appearing weirdly.
  142.  
  143. let enableSpecialReplace = 1;
  144. let fullDelete = 0; // default 1; if 1, text is completely replaced.
  145. let addTag = 1; // if fullDelete is active, adds a tag without replacing.
  146.  
  147. // ==== BB. notif code ====================================================================|
  148.  
  149. // 'script options' options
  150. let enableExecCounter = 0;
  151. enableExecCounter = getOptionState("enable-"+ scriptPrefix +"counter", enableExecCounter);
  152. let enableNotifications = 0;
  153. enableNotifications = getOptionState("enable-"+ scriptPrefix +"notifs", enableNotifications);
  154. let autohideNotifs = 0; // default 0; notifs disappear after a set period of time. used in createNotif()
  155. let startCollapsed = 1; //default 1;
  156.  
  157. // notif css variables.
  158. const notifsHex = "#ddd";
  159. const notifsOpacity = .4; // default .4; set to a value between 0 and 1, 1 is no transparency, .5 is 50% transparency.
  160. const notifsWidth = 120; // default 120; width in pixels of each notification.
  161.  
  162. let notifContainerId = "notif-main-container";
  163.  
  164. // generate notif container if needed.
  165. if ((enableExecCounter || enableNotifications) && !jQuery("#"+ notifContainerId).length) {
  166.  
  167. // ==== setting/checking initial visual state of notifs ====
  168.  
  169. // constrolled exclusively by local storage or the default value.
  170. const localStorageName = "notif start collapsed";
  171. if (window.localStorage.getItem(localStorageName)) {
  172. startCollapsed = window.localStorage.getItem(localStorageName);
  173. startCollapsed = (startCollapsed == "true");
  174. }
  175.  
  176. const visibleClass = "notif-visible";
  177. const hiddenClass = "notif-hidden1";
  178. let startingStateClass = visibleClass;
  179. let otherStartingStateClass = hiddenClass;
  180. if (startCollapsed) {
  181. startingStateClass = hiddenClass;
  182. otherStartingStateClass = visibleClass;
  183. }
  184.  
  185. // ==== create container ==============================================================|
  186. /*
  187. [ notif main container
  188. [notif1] - counters
  189. [hide] - button
  190. [open] - button
  191. [close] - button
  192. [clear] - button
  193. [notif2
  194. [dlt-container]
  195. [ll-container]
  196. [ot-container]
  197. ]
  198.  
  199. ]
  200. - hide: makes visible open | hides close, clear, notif2
  201. - open: makes visible hide, close, clear, notif2 | hides open
  202. - close: deletes notif main container.
  203. - clear: empties notif-container2
  204. */
  205.  
  206. const openButtonId = "notif-open";
  207. const hideButtonId = "notif-hide";
  208.  
  209. let notificationsElement =
  210. "<div id='"+ notifContainerId +"'>"+
  211. "<div id='notif-container1'></div>"+
  212. "<div id='"+ hideButtonId +"' class='notif-red notif-rounded-block "+ startingStateClass +"'>notif hide</div>"+
  213. "<div id='"+ openButtonId +"' class='notif-green notif-rounded-block "+ otherStartingStateClass +"'>notif open</div>"+
  214. "<div id='notif-close' class='notif-gray notif-rounded-block "+ startingStateClass +"'>close notif[]</div>"+
  215. "<div id='notif-clear' class='notif-orange notif-rounded-block "+ startingStateClass +"'>clear notif</div>"+
  216. "<div id='notif-container2' class=' "+ startingStateClass +"'>"+
  217. "<div id='dlt-container'></div>"+
  218. "<div id='ll-container' class='notif-hidden1'></div>"+
  219. "<div id='ot-container' class='notif-hidden1'</div>"+
  220. "</div>"+
  221. "</div>";
  222. jQuery("body").prepend(notificationsElement);
  223.  
  224. let textReaderElement =
  225. "<div id='notif-text-overlay' class='notif-text-hidden'></div>";
  226. jQuery("body").prepend(textReaderElement);
  227.  
  228. jQuery('#notif-container2').on( {
  229. mouseenter: function () {
  230. let notifText = jQuery(this).find(".notif-text").text();
  231. let notifClassList = this.className;
  232. if (/red/.test(notifClassList)) {
  233. jQuery("#notif-text-overlay").addClass("notif-red");
  234. }else if (/orange/.test(notifClassList)) {
  235. jQuery("#notif-text-overlay").addClass("notif-orange");
  236. }else if (/yellow/.test(notifClassList)) {
  237. jQuery("#notif-text-overlay").addClass("notif-yellow");
  238. }else {
  239. jQuery("#notif-text-overlay").addClass("notif-gray");
  240. }
  241. jQuery("#notif-text-overlay").text(notifText);
  242. jQuery("#notif-text-overlay").addClass("notif-text-visible");
  243. },
  244. mouseleave: function () {
  245. jQuery("#notif-text-overlay").removeClass("notif-text-visible");
  246. jQuery("#notif-text-overlay").removeClass("notif-red");
  247. jQuery("#notif-text-overlay").removeClass("notif-orange");
  248. }
  249. }, '.notif-instance');
  250.  
  251. // ==== close ====
  252. jQuery("#notif-close").click(function(){
  253. jQuery("#"+notifContainerId).remove();
  254. //console.log("RPL notif close clicked. ("+notifContainerId+")");
  255. });
  256.  
  257. // ==== clears container2 which contains notif instances. ====
  258. function clearNotif(){
  259. jQuery("#notif-container2").empty();
  260. }
  261. jQuery("#notif-clear").click(clearNotif);
  262.  
  263. // ==== open/hide events ==============================================================|
  264.  
  265. const mainSelector = "#notif-container2, #"+ hideButtonId +", #notif-close, #notif-clear";
  266.  
  267. jQuery("#"+ hideButtonId).click(function () {
  268. //console.log(hideButtonId);
  269. window.localStorage.setItem(localStorageName, true);
  270.  
  271. switchClasses(
  272. mainSelector,
  273. "#"+ openButtonId,
  274. visibleClass,
  275. hiddenClass
  276. );
  277. });
  278.  
  279. jQuery("#"+ openButtonId).click(function () {
  280. //console.log(openButtonId);
  281. window.localStorage.setItem(localStorageName, false);
  282.  
  283. switchClasses(
  284. mainSelector,
  285. "#"+ openButtonId,
  286. hiddenClass,
  287. visibleClass
  288. );
  289. });
  290.  
  291. function switchClasses(mainSelector, subSelector, removedClass, newClass) {
  292. jQuery(mainSelector).removeClass(removedClass);
  293. jQuery(mainSelector).addClass(newClass);
  294. jQuery(subSelector).removeClass(newClass);
  295. jQuery(subSelector).addClass(removedClass);
  296. }
  297.  
  298. // ==== CSS ===========================================================================|
  299. if(1){var notifsCss =
  300. `<style type="text/css">
  301. #`+ notifContainerId +` {
  302. width: `+ notifsWidth +`px;
  303. max-height: 50%;
  304. margin: 0 2px 2px;
  305. display: block;
  306.  
  307. line-height: initial;
  308. color: #000;
  309. opacity: `+ notifsOpacity +`;
  310. position: fixed;
  311. top: 0px;
  312. right: 0px;
  313. z-index: 9999;
  314. overflow-y: auto;
  315. }
  316. #`+ notifContainerId +`:hover {
  317. opacity: 1;
  318. }
  319.  
  320. .notif-rounded-block {
  321. display: block;
  322. padding: 2px;
  323. border-radius: 3px;
  324. margin-top: 2px;
  325.  
  326. font-size: 11px !important;
  327. font-weight: bold;
  328. text-align: center;
  329. cursor: pointer;
  330. }
  331.  
  332. .s-counter {
  333. display: block;
  334. padding: 2px;
  335. border-radius: 4px;
  336. margin-top: 2px;
  337.  
  338. background: #ddd;
  339. font-size: 11px !important;
  340. font-weight: bold;
  341. text-align: center;
  342. }
  343.  
  344. .notif-text-hidden {
  345. display:none;
  346. }
  347. .notif-text-visible {
  348. display: block;
  349. max-width: 50%;
  350. padding: 5px;
  351. border: #999 solid 2px;
  352. border-radius: 10px;
  353.  
  354. position: fixed;
  355. top: 5px;
  356. left: 5px;
  357. z-index: 999999;
  358.  
  359.  
  360. font-size: 15px !important;
  361. font-weight: bold !important;
  362. text-align: center !important;
  363. color: black !important;
  364. }
  365.  
  366. .notif-instance {
  367. display: block;
  368. padding: 2px;
  369. border-radius: 4px;
  370. margin-top: 2px;
  371.  
  372. background: `+ notifsHex +`;
  373. font-size: 11px !important;
  374. font-weight: bold;
  375. text-align: center;
  376. cursor: pointer;
  377. }
  378.  
  379. .notif-instance div{/* div holding the rule.*/
  380. max-height: 12px;
  381. padding: 0px;
  382. margin: 0px;
  383. border: 0px;
  384.  
  385. overflow: hidden;
  386. word-break: break-all;
  387. }
  388. .notif-hidden{ /* meant to hide the rule */
  389. opacity: .1;
  390. }
  391. .notif-hidden:hover {
  392. opacity: 1;
  393. }
  394.  
  395. .notif-red {
  396. background: #f67066;
  397. }
  398. .notif-orange {
  399. background: #ffc107; //yellowish
  400. }
  401. .notif-yellow {
  402. background: #ffc107; //yellowish
  403. }
  404. .notif-green {
  405. background: #62bb66;
  406. }
  407. .notif-gray {
  408. background: #777;
  409. }
  410.  
  411. /* collapsible classes */
  412. .notif-hidden1 {
  413. display: none !important;
  414. }
  415. .notif-visible {
  416. display: block !important;
  417. }
  418.  
  419. div#ll-container, div#ot-container {
  420. border-top: solid black 3px;
  421. }
  422. </style>`;
  423. }
  424. jQuery(document.body).append(notifsCss);
  425. }
  426.  
  427. if(enableExecCounter) {
  428. jQuery("#notif-container1").prepend("<div id='"+ scriptTag +"-counter' class='s-counter .notif-rounded-block'>T No text nodes found.</div>");
  429. }
  430.  
  431. // resets lastIndex on tests with global modifiers.
  432. RegExp.prototype.regexTest = function(testString){
  433. //consolelog("## regexTest() ##", 1);
  434. if (this.test(testString)) {
  435. if (/.\/i?g/.test(this) && this.lastIndex) {//regex global modifier needs to be reset.
  436. //consolelog("## last index: "+ this.lastIndex +" ##", 1);
  437. this.lastIndex = 0;
  438. }
  439. return true;
  440. }
  441. return false;
  442. };
  443.  
  444. NodeList.prototype.forEach = Array.prototype.forEach;
  445. // ==== CA. processPage() =================================================================|
  446.  
  447. // ==== processPage() globals ====
  448. let titleChecked = 0; // if the page title was checked or not.
  449. let fullCheck = 0;
  450.  
  451. // ==== counters ====
  452. let nodeCounter = 0; // counts text nodes.
  453. let deleteMatches = 0;
  454. let fullReplaceMatches = 0;
  455. let executionCounter = 0; // the number of times processPage() was executed.
  456.  
  457. function processPage() {
  458. executionCounter++;
  459.  
  460. logRuntimes = getOptionState("log-"+ scriptPrefix +"runtimes", logRuntimes);
  461. if (logRuntimes) {
  462. var startTime = performance.now();
  463. }
  464.  
  465. let rulesNum = replaceRules.length;
  466.  
  467. // per element variables
  468. let ruleMatched = 0;
  469.  
  470. // ==== checks the title of the page ==================================================|
  471. if(1){
  472. let titleText = jQuery("title").text();
  473. if (titleText && !titleChecked) {
  474. for (let index = 0; index < rulesNum; index++) {
  475. if (replaceRules[index][0].regexTest(titleText)) {
  476. consolelog(scriptTag +" (title match): "+ titleText +" | "+ replaceRules[index][0], "TT-MA");
  477. titleText = titleText.replace(replaceRules[index][0], replaceRules[index][1]);
  478. jQuery("title").text(titleText);
  479. }
  480. }
  481. titleChecked = 1;
  482. }
  483. }
  484.  
  485. // ==== selects specified text elements ===============================================|
  486. if(1){
  487. const excludedElements = /CODE|SCRIPT|STYLE|TEXTAREA/i;
  488. const checkClassRegex = new RegExp(scriptPrefix +"node","i");
  489. var textWalker = document.createTreeWalker(
  490. document.body,
  491. NodeFilter.SHOW_TEXT,
  492. {
  493. acceptNode: function (node) {
  494. if (node.nodeValue.trim() &&
  495. !excludedElements.test(node.parentNode.nodeName) && // exclude scripts and style elements
  496. (fullCheck || !checkClassRegex.test(node.parentNode.classList)) && // exclude checked elements
  497. !classWhitelist.test(node.parentNode.classList)) {
  498. return NodeFilter.FILTER_ACCEPT;
  499. }
  500. return NodeFilter.FILTER_SKIP;
  501. }
  502. },
  503. false
  504. );
  505. }
  506. let textNode = textWalker.nextNode();
  507.  
  508. // ==== for each textNode =============================================================|
  509. while (textNode) {
  510.  
  511. let nodeText = textNode.nodeValue; // is changed based on matches.
  512. if (!fullCheck) {
  513. let immediateParentNode = textNode.parentNode; // element containing the text node.
  514. nodeCounter++;
  515. markCheckedElements = getOptionState(scriptPrefix +"mark-checked", markCheckedElements);
  516. if (markCheckedElements) {
  517. immediateParentNode.classList.add(scriptPrefix +"node-"+ nodeCounter); //prefix
  518. }
  519. }
  520.  
  521. // ==== for each rule =============================================================|
  522. for (let index = 0; index < rulesNum; index++) {
  523.  
  524. let currentRuleRegex = replaceRules[index][0];
  525. let replacementValue = replaceRules[index][1];
  526.  
  527. if (currentRuleRegex.regexTest(nodeText.trim())) {
  528. ruleMatched = 1;
  529. let matchPrefix = "GEN0";
  530. consolelog("("+ scriptTag +") (n)"+ nodeCounter +" (match): "+ nodeText.trim() +" | "+ currentRuleRegex, "TXT-MA");
  531.  
  532. const disableReplace = 0; // test: check what is checked through each run.
  533. if (!disableReplace) {
  534. enableSpecialReplace = getOptionState("enable-special-replace", enableSpecialReplace);
  535. // ==== delete1 match =================================================|
  536. if (enableSpecialReplace && (/DELETE1/.test(replacementValue) || /DELETE2/.test(replacementValue)) ) {
  537. deleteMatches++;
  538.  
  539. matchPrefix = "DLT99";
  540. if (/DELETE1/.test(replacementValue) && !/DELETE1/.test(nodeText)) {
  541. matchPrefix = "DLT1";
  542. }else if (/DELETE2/.test(replacementValue) && !/DELETE2/.test(nodeText)) {
  543. matchPrefix = "DLT2";
  544. }
  545. consolelog("("+ scriptTag +") ("+ matchPrefix +") n"+ nodeCounter +" (match): "+ nodeText.trim() +" | "+ currentRuleRegex, matchPrefix);
  546. createNotif(nodeCounter +" "+ matchPrefix, currentRuleRegex, nodeText);
  547.  
  548. fullDelete = getOptionState("enable-full-delete", fullDelete);
  549. addTag = getOptionState("add-tag", addTag);
  550. const tagRegex = new RegExp("^\\["+matchPrefix);
  551.  
  552. if (fullDelete) {
  553. nodeText = "## "+ matchPrefix +" ##"; // replaces the text completely.
  554. break;
  555. }else if (addTag && !tagRegex.text(nodeText)) {
  556. nodeText = "["+ matchPrefix +"]: " + nodeText; // prepends DLT1 or DLT2
  557. }
  558. }
  559. // ==== full replace match ============================================|
  560. if (enableSpecialReplace && /^FR1/.test(replacementValue)) {
  561. fullReplaceMatches++;
  562. matchPrefix = "FR1";
  563. consolelog("("+ scriptTag +") ("+ matchPrefix +") n"+ nodeCounter +" (match): "+ nodeText.trim() +" | "+ currentRuleRegex, matchPrefix);
  564. createNotif(nodeCounter +" "+ matchPrefix, currentRuleRegex, nodeText);
  565.  
  566. nodeText = replacementValue;
  567. break;
  568. }
  569. // ==== base case =====================================================|
  570. nodeText = nodeText.replace(currentRuleRegex, replacementValue);
  571. } // end if (!disableReplace)
  572. }
  573. } // end for (each rule) ==========================================================|
  574.  
  575. if (ruleMatched) { // modify text block.
  576. ruleMatched = 0;
  577. textNode.nodeValue = nodeText;
  578. consolelog("("+ scriptTag +") (n)"+ nodeCounter +" (text): "+ nodeText.trim(), "CH-TT");
  579. }
  580. textNode = textWalker.nextNode();
  581. } // end while (textNode) =============================================================|
  582.  
  583. if (!fullCheck) {
  584. // ==== update counter ====
  585. let counterText = "T DLT:"+ deleteMatches +" | FR:"+ fullReplaceMatches +" | N:"+ nodeCounter + " | EX:"+ executionCounter;
  586. jQuery("#"+ scriptTag +"-counter").text(counterText);
  587. if (nodeCounter) {
  588. jQuery("#"+ scriptTag +"-counter").addClass("notif-green");
  589. }
  590. }else { //end fullCheck.
  591. fullCheck = 0;
  592. }
  593.  
  594. //consolelog("## ("+ scriptTag +") execution #"+ executionCounter +" ##", "EXEC");
  595. // script option handles if this is displayed or not.
  596. if (logRuntimes) {
  597. const endTime = performance.now();
  598. const runTime = ((endTime - startTime) / 1000).toFixed(2);
  599. if (runTime > 1) {
  600. consolelog('('+ scriptTag +') finished after ' + runTime + ' seconds.', "RUNT");
  601. }else {
  602. consolelog('('+ scriptTag +') finished in less than 1 second.', "RUNT");
  603. }
  604. }
  605. } //end function function replaceText()
  606.  
  607. // ==== CB. execution control =============================================================|
  608. //console.log("("+ scriptTag +") EXEC: Initial run.");
  609. //processPage();
  610. let runWhenReady = 0;
  611. runWhenReady = getOptionState("run-when-ready", runWhenReady);
  612. if (runWhenReady) {
  613. jQuery(document).ready(function() { //after DOM has loaded.
  614. consolelog("("+ scriptTag +") EXEC: document.ready()", "EXEC");
  615. //fullCheck = 1;
  616. processPage();
  617. });
  618. }
  619.  
  620. let runWhenLoaded = 1;
  621. runWhenLoaded = getOptionState("run-when-loaded", runWhenLoaded);
  622. if (runWhenLoaded) {
  623. jQuery(window).on("load", function() { //after all initial images are loaded.
  624. consolelog("("+ scriptTag +") EXEC: window.load()", "EXEC");
  625. //fullCheck = 1;
  626. processPage();
  627. });
  628. }
  629. if (dynamicChecking) {
  630. jQuery(document).ready(waitForKeyElements("img", processPage));
  631. }
  632.  
  633. // ==== DA. script button =================================================================|
  634.  
  635. let buttonsContainerId = "ctb-container1";
  636. if (generateRecheckButton && jQuery("#"+ buttonsContainerId).length) {
  637. jQuery("#"+ buttonsContainerId).prepend("<div id='"+ scriptTag +"-reset' class='ctb-blue ctb-rounded-block'>run "+ scriptTag +"</div>"); //added to beginning
  638. //jQuery("#"+ scriptTag +"-reset").click(processPage);
  639. jQuery("#"+ scriptTag +"-reset").click(function() {
  640. fullCheck = 1;
  641. processPage();
  642. });
  643. }
  644.  
  645. // ==== DB. support functions =============================================================|
  646.  
  647. function createNotif(notifLabel, notifRule, notifText) { //msg1 needs to match notifTypes
  648. enableNotifications = getOptionState("enable-"+ scriptPrefix +"notifs", enableNotifications);
  649. if (enableNotifications) {
  650. let additionalClass = "notif-gray";
  651. let notifContainer = "ot-container";
  652. if (/dlt/i.test(notifLabel)) {
  653. additionalClass = "notif-red";
  654. notifContainer = "dlt-container";
  655. }
  656.  
  657. let newNotif =
  658. "<div class='notif-instance "+ additionalClass +"'><div>t n"+ notifLabel +"</div>"+
  659. "<div class='notif-hidden'>"+ notifRule +"</div>"+
  660. "<div class='notif-text' hidden>"+ notifText+"</div>"+ // to be displayed at the bottom left.
  661. "</div>";
  662.  
  663. let enabledNotifTypesRegex = /./;
  664. if (enabledNotifTypesRegex.test(notifLabel)) {
  665. jQuery("#"+ notifContainer).append(newNotif);
  666. jQuery(".notif-instance").click(function(){
  667. jQuery("#notif-container2").empty();
  668. });
  669.  
  670. if (!/dlt/i.test(notifLabel)) {
  671. jQuery("#ot-container").removeClass("notif-hidden1");
  672. }
  673.  
  674. autohideNotifs = getOptionState("autohide-notifications", autohideNotifs);
  675. if (autohideNotifs) {
  676. const notifDuration = 10; // default 10; amount of seconds notifications are displayed before disappearing.
  677. setTimeout(function() {
  678. jQuery(".notif-instance").remove();
  679. }, notifDuration*1000);
  680. }
  681. }
  682. }
  683. } // end function creatNotif()
  684.  
  685. function consolelog(text, messageType) {
  686. if (enableConsoleMessages && enabledMessagesRegex.test(messageType)) {
  687. console.log(text);
  688. }
  689. }
  690.  
  691. // ==== script end ========================================================================|
  692. consolelog("#### ("+ scriptTag +") text replace script is active. ####", "EXEC");
  693.  
  694. } // end if (runScript)
  695.  
  696. // ============================================================================================|
  697.  
  698. // = getOptionState(, );
  699. // used to update option if 'script option' is set.
  700. function getOptionState(idName, currentState) {
  701. if (document.getElementById(idName)) {
  702. return document.getElementById(idName).checked;
  703. }
  704. return currentState;
  705. }
  706. })();