0

I am currently writing a simple chrome extension that replaces custom words.
Yes, I have also seen those various questions that are asking similar questions, but something is lacking and I cannot find it. I am very new to javascript and I am doing this for an assignment.

In my chrome extension, I have two textboxes (replace from and replace to) and a submit button. What I am trying to achieve, currently, is assigning the replace variables in content.js from the values in the two textboxes in the chrome extension when the button in the chrome extension is clicked upon, however, the console is printing that the button does not exist, even though I have attempted to take measures to avoid that.

What I have so far:
Manifest.json

{
  "manifest_version": 2,
  "name": "Word replacer",
  "description": "Change words!",
  "version": "1.0",

  "browser_action": {
    "default_popup": "popup.html"
  },

  "content_scripts": [
      {
        "run_at": "document_start",
        "js": [
            "content.js"
        ],
      "matches": [
            "*://*/*"
        ]
      }
  ]
}

HTML

<html>
   <head>
     <script type="text/javascript" src="content.js"></script>
     <--some CSS now-->
  </head>
  <body>
      <h1>Word replacer</h1>
      <div id="container">
          <form id="frm">
             Text to replace:<br>
             <input id="toReplace" type="text"><br>
             Replace with:<br>
             <input id="replaceWith" type="text"><br>
             <input id="rplBtn" type="submit" value="Submit" style="float: right;">
        </form>    
     </div>
  </body>
</html>

content.js

var elements = document.getElementsByTagName('*');
var replaceTo=new RegExp("test","gi"); 
var replaceFrom=new RegExp("/test/gi","gi"); //These two are already assigned for testing purposes



console.log("out");
if(document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', function () {
        console.log("in");
        for (var i = 0; i < elements.length; i++) {
            var element = elements[i];

            for (var j = 0; j < element.childNodes.length; j++) {
                var node = element.childNodes[j];

                if (node.nodeType === 3) {
                  var text = node.nodeValue;

                   var replacedText = text.replace(replaceFrom, replaceTo);

                   if (replacedText !== text) {
                       element.replaceChild(document.createTextNode(replacedText), node);
                    }
                }
            }
        }


   }
   )}
   if (document.readyState ==="interactive") {
       console.log(0);
       document.addEventListener('DOMContentLoaded', function () {
      console.log(1);
        var btn = document.getElementById('rplBtn');
        console.log(2);
        btn.addEventListener("click", function() {
            console.log(3);
             console.log("clicked");
             replaceTo = new RegExp(document.getElementById("replaceWith").innerHTML,"gi");
             replaceFrom = new RegExp(document.getElementById("toReplace").innerHTML,"gi");
             window.location.reload(true);
        })});
  }


Since this is a lot of code, let me tell you what things I have changed after looking at examples from others. Normally, the console doesn't print beyond "out" (this is from content.js), but if I set the run_at property to "document_start", all instances of "/test/gi" are replaced with "test" as they are supposed to.
However, the button is still not recognised, so I tried to only look for the button when readyState is "interactive", however, the compiler doesn't seem to reach there as 0 is not printed.

Can you help me solving this as I have tried pretty much all I could think of in the past 6 hours.

Thank you,

newuser
  • 1
  • 1
  • Remove run_at and DOMContentLoaded listeners and readyState checks. You're overcomplicating things. – wOxxOm Sep 30 '17 at 10:57
  • Hmm, after I removed the listeners,the checks and run_at, nothing changed, words do get replaced, however getElementById('rplBtn') still returns null. This just means those listeners weren't doing anything. You can view the new content.js code via this link: [https://pastebin.com/WLqD7bfk](https://pastebin.com/WLqD7bfk) . Any ideas? – newuser Sep 30 '17 at 11:33
  • Oh, right. Ok, so I've tried to use MutationObserver (this is all very new to me) but I think I ran into a similar problem. To select the target node, I used querySelector('#rplBtn'), but now this is returning null. You can view the implementation of the the observer using this link: [https://pastebin.com/0y2DymVA](https://pastebin.com/0y2DymVA). N.B. I have commented the section where I use getElementbyId, so only the replacement for loop runs and the MutationObserver. What am I missing this time? – newuser Sep 30 '17 at 12:13
  • I replaced my code for the MutationObserver with your (really-impressive-which-is-beyond-me) code, as such [https://pastebin.com/HaGv9q4c](https://pastebin.com/HaGv9q4c). But this time the console doesn't print beyond 'a', even if I interact with the button after opening the chrome extension. I tried change the querySelector to '.input' but that didn't change anything so I reverted back to '.container'. Are there any parameters (except id) that I am supposed to change? – newuser Sep 30 '17 at 12:38
  • I have now removed that line, but the console is still not printing beyond 'a'. – newuser Sep 30 '17 at 13:08
  • Uhm, forget MutationObserver. I've re-read the question. You apparently try to run content script in the popup window, which is very weird. The popup is a separate page so it should use its own separate script, not a content script (those are for web pages). Also, the ` – wOxxOm Sep 30 '17 at 13:14
  • I am very lost now. I now understand why getElementById didn't work before (as the document was different). I have removed the content_scripts from manifest and moved the script tag. But now the content.js doesn't run, there is no console output and no replacement of words. This is the new code: [manifest.json](https://pastebin.com/GK2xG6rc), [popup.html](https://pastebin.com/vmvxr9bs) and [content.js](https://pastebin.com/ZQbxZiDb). I have to run right now, so I may not respond in the next 2 hours. – newuser Sep 30 '17 at 13:28
  • Rightclick the popup and click Inspect. The popup is a separate page so it has its own devtools, – wOxxOm Sep 30 '17 at 13:29
  • Alright, the button is now functioning, but the replacement does not take place anymore. The reason I used content script was to replace custom phrases in DOM of the website, like the Cloud to Butt extension but this extension allows the user to choose the words they want to replace. – newuser Sep 30 '17 at 13:40
  • Well then you need the popup.js script to save the values in chrome.storage.local and a different content.js declared in "content_scripts" (in manifest) to read the saved values and use them to process the web page. – wOxxOm Sep 30 '17 at 13:58
  • Thank you wOxxOm, I finally understand what went wrong and I have finished my project, thanks to you. – newuser Oct 01 '17 at 10:02

0 Answers0