🏠 Home 

You need to sign in or sign up before continuing.

Text Highlighter - Dynamic

Highlights User-defined Text


ติดตั้งสคริปต์นี้?
  1. // ==UserScript==
  2. // @name Text Highlighter - Dynamic
  3. // @namespace erosman
  4. // @author erosman and Jefferson "jscher2000" Scher
  5. // @version 1.7mo
  6. // @description Highlights User-defined Text
  7. // @include https://greasyfork.org/*
  8. // @grant GM_registerMenuCommand
  9. // @grant GM_setValue
  10. // @grant GM_getValue
  11. // ==/UserScript==
  12. /* --------- Note ---------
  13. This script highlights User-defined case-insensitive Text on a page.
  14. TO INCLUDE SITES (only Greasy Fork is initially included):
  15. Go to Add-ons - User Scripts ('Ctrl+ Shift + a' on Firefox)
  16. Click on the Script's Option
  17. Under User Settings Tab, Add Included/Excluded Pages that you want the script to run on
  18. Click OK
  19. Setting Keywords & Highlight Style:
  20. Click on drop-down triangle next to the GreaseMonkey Icon
  21. User Scripts Commands...
  22. Set Keywords
  23. Input keywords separated by comma
  24. Example: word 1,word 2,word 3
  25. Set Highlight Style
  26. Input the Highlight Style (use proper CSS)
  27. Example: color: #f00; font-weight: bold; background-color: #ffe4b5;
  28. Note: If you find that another script #####es with this script, set Text Highlighter to Execute first.
  29. Go to Add-ons - User Scripts ('Ctrl+ Shift + a' on Firefox)
  30. Right Click on the Script
  31. On the context menu click: Execute first
  32. On Add-ons - User Scripts, you can also Click on the Execution Order (top Right) and
  33. change the execution order so that Text Highlighter runs before those scripts that #####es with it.
  34. --------- History ---------
  35. 1.7mo Added MutationObserver (Jefferson "jscher2000" Scher)
  36. 1.7 Changed script from matching whole words to do partial word match
  37. similar to browser's FIND + escaped RegEx Quantifiers in keywords
  38. 1.6 Code Improvement, using test()
  39. 1.5 Code Improvement
  40. 1.4 Code Improvement + Added support for non-English Words
  41. 1.3 Code Improvement, 10x speed increase
  42. 1.2 Added User Script Commands, script can now be auto-updated without losing User Data
  43. 1.1 Total Code rewrite, Xpath pattern
  44. 1.0 Initial release
  45. */
  46. (function() { // anonymous function wrapper, used for error checking & limiting scope
  47. 'use strict';
  48. if (window.self !== window.top) { return; } // end execution if in a frame
  49. // setting User Preferences
  50. function setUserPref(varName, defaultVal, menuText, promtText, sep){
  51. GM_registerMenuCommand(menuText, function() {
  52. var val = prompt(promtText, GM_getValue(varName, defaultVal));
  53. if (val === null) { return; } // end execution if clicked CANCEL
  54. // prepare string of variables separated by the separator
  55. if (sep && val){
  56. var pat1 = new RegExp('\\s*' + sep + '+\\s*', 'g'); // trim space/s around separator & trim repeated separator
  57. var pat2 = new RegExp('(?:^' + sep + '+|' + sep + '+$)', 'g'); // trim starting & trailing separator
  58. val = val.replace(pat1, sep).replace(pat2, '');
  59. }
  60. val = val.replace(/\s{2,}/g, ' ').trim(); // remove multiple spaces and trim
  61. GM_setValue(varName, val);
  62. // Apply changes (immediately if there are no existing highlights, or upon reload to clear the old ones)
  63. if(!document.body.querySelector(".THmo")) THmo_doHighlight(document.body);
  64. else location.reload();
  65. });
  66. }
  67. // prepare UserPrefs
  68. setUserPref(
  69. 'keywords',
  70. 'word 1,word 2,word 3',
  71. 'Set Keywords',
  72. 'Set keywords separated by comma\t\t\t\t\t\t\t\r\n\r\nExample:\r\nword 1,word 2,word 3',
  73. ','
  74. );
  75. setUserPref(
  76. 'highlightStyle',
  77. 'color: #f00; background-color: #ffebcd;',
  78. 'Set Highlight Style',
  79. 'Set the Highlight Style (use proper CSS)\r\n\r\nExample:\r\ncolor: #f00; font-weight: bold; background-color: #ffe4b5;'
  80. );
  81. // Add MutationObserver to catch content added dynamically
  82. var THmo_MutOb = (window.MutationObserver) ? window.MutationObserver : window.WebKitMutationObserver;
  83. if (THmo_MutOb){
  84. var THmo_chgMon = new THmo_MutOb(function(mutationSet){
  85. mutationSet.forEach(function(mutation){
  86. for (var i=0; i<mutation.addedNodes.length; i++){
  87. if (mutation.addedNodes[i].nodeType == 1){
  88. THmo_doHighlight(mutation.addedNodes[i]);
  89. }
  90. }
  91. });
  92. });
  93. // attach chgMon to document.body
  94. var opts = {childList: true, subtree: true};
  95. THmo_chgMon.observe(document.body, opts);
  96. }
  97. // Main workhorse routine
  98. function THmo_doHighlight(el){
  99. var keywords = GM_getValue('keywords');
  100. if(!keywords) { return; } // end execution if not found
  101. var highlightStyle = GM_getValue('highlightStyle');
  102. if (!highlightStyle) highlightStyle = "color:#00f; font-weight:bold; background-color: #0f0;"
  103. var rQuantifiers = /[-\/\\^$*+?.()|[\]{}]/g;
  104. keywords = keywords.replace(rQuantifiers, '\\$&').split(',').join('|');
  105. var pat = new RegExp('(' + keywords + ')', 'gi');
  106. var span = document.createElement('span');
  107. // getting all text nodes with a few exceptions
  108. var snapElements = document.evaluate(
  109. './/text()[normalize-space() != "" ' +
  110. 'and not(ancestor::style) ' +
  111. 'and not(ancestor::script) ' +
  112. 'and not(ancestor::textarea) ' +
  113. 'and not(ancestor::code) ' +
  114. 'and not(ancestor::pre)]',
  115. el, null, XPathR###lt.UNORDERED_NODE_SNAPSHOT_TYPE, null);
  116. if (!snapElements.snapshotItem(0)) { return; } // end execution if not found
  117. for (var i = 0, len = snapElements.snapshotLength; i < len; i++) {
  118. var node = snapElements.snapshotItem(i);
  119. // check if it contains the keywords
  120. if (pat.test(node.nodeValue)) {
  121. // check that it isn't already highlighted
  122. if (node.className != "THmo" && node.parentNode.className != "THmo"){
  123. // create an element, replace the text node with an element
  124. var sp = span.cloneNode(true);
  125. sp.innerHTML = node.nodeValue.replace(pat, '<span style="' + highlightStyle + '" class="THmo">$1</span>');
  126. node.parentNode.replaceChild(sp, node);
  127. }
  128. }
  129. }
  130. }
  131. // first run
  132. THmo_doHighlight(document.body);
  133. })(); // end of anonymous function