2

I'm trying to figure out how to write a simple Chrome extension which allows to transliterate web pages from one alphabet to another. Unfortunately Google's documentation on Chrome extensions is pretty much confusing for a beginner. I've seen a lot of similar questions here, f.ex. Replace text in website with Chrome content script extension, but still can't get it clear. In a trial run I'm trying to replace all "a"'s in the page with "Z"'s.

Here's my Manifest.json:

{
  "name": "My Chrome extension",
  "version": "0.1",
  "browser_action": {
    "default_icon": "icon.png"
},

"permissions": [
    "tabs", "http://*/*", "https://*/*"
],

"content_scripts": [{
    "matches": ["http://*/*", "https://*/*"],
    "js": ["myscript.js"]
}]

}

Myscript.js:

chrome.browserAction.onClicked.addListener(function(tab) {
chrome.tabs.executeScript(
  null, {code:"document.body.innerHTML = document.body.innerHTML.replace(new RegExp("a", "g"), "Z")"});
});

But this fails to work. If I include only one line into Myscript.js:

document.body.innerHTML = document.body.innerHTML.replace(new RegExp("a", "g"), "Z");

then all 'a' letters get replaced with 'Z' as soon as the page has loaded, but this is not my goal, as I want to get it working only after the extension button is pressed.

Any help will be much appreciated.

Community
  • 1
  • 1
user1274925
  • 59
  • 1
  • 9
  • Warning: Using `document.body.innerHTML = ...` will remove all of the existing event listeners, as well as non-attribute properties. – Rob W Mar 17 '12 at 09:16

2 Answers2

1

You've set up your extension to inject your code using a content script. A content script will get injected into any page that matches your matches field. What you want is to only inject the script if they click on your Browser action. For this you can either have a background page that listens for the chrome.browserAction.onClicked event and reacts to it. Or you can have a default page for your Browser Action that injects the code into the page and if your put window.close as part of the script this will stop any popup from occuring and allow you to avoid using a background page (Im big on avoiding using a background page when ever possible).

For an example of the first method, check out this sample....
http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/browserAction/make_page_red/

And here's an example of the second method (which is a modified version of the set_page_color sample)...
manifest.json

{
  "name": "A browser action that changes the page color.",
  "version": "1.0",
  "permissions": [
    "tabs", "http://*/*", "https://*/*"
  ],
  "browser_action": {
      "default_title": "Set this page's color.",
      "default_icon": "icon.png",
      "default_popup": "popup.html"
  },
  "manifest_version": 2
} 

popup.html

<!doctype html>
<html>
  <head>
    <script src="popup.js"></script>
  </head>
  <body>
  </body>
</html>

popup.js

chrome.tabs.executeScript(null,{file:"injectedCode.js"});
window.close();

injectedCode.js

// This was just a quick look at changing text on a page
// there could be more tags you should ignore and there could be a better way of doing this all together
var ignoreTags = ["NOSCRIPT","SCRIPT","STYLE"];
var nodeIterator = document.createNodeIterator(
    document,
    NodeFilter.SHOW_TEXT,
    function (node){
      var parentTag = node.parentNode.tagName.toUpperCase();
      if ( ignoreTags.indexOf(parentTag)==-1 ) {return true} else {return false};
    },
    false
);

var node;
while ( (node = nodeIterator.nextNode()) ) {
   node.data = node.data.replace(/a/g, 'z');
}

NOTE
As Rob W points out in the comments chrome.tabs and chrome.browserAction are not usable in a content script which is why the chrome.browserAction.onClicked has to be used in a background page.

PAEz
  • 8,366
  • 2
  • 34
  • 27
  • @Rob W Try it, for me no pop up occurs...only the pointer gets a busy icon (hour glass) for a split second. I agree that the background method is more correct and neater, but Im so sick of extensions having background pages for the smallest of things....heres hoping the Event page comes..... – PAEz Mar 17 '12 at 09:34
  • The popup will be opened, but it's closes so fast that it's usually not noticeable. +1 for explaining two methods to implement it correctly. However, you didn't explain why the first method didn't work. That's because the `chrome.tabs` and `chrome.browserAction` APIs are not available in Content Scripts. – Rob W Mar 17 '12 at 09:38
  • @Rob W Did you try it? Ive got extremely good eyesight and NOTHING pops up...Windows XP, Chrome 19.somtheing or other. – PAEz Mar 17 '12 at 09:40
  • Open `chrome://extensions/`, then expand your test extension. Spam-click on the browser action button. `popup.html` shows up for a split second. The window *is* created **and** displayed, but removed so fast that it's usualy not visible. – Rob W Mar 17 '12 at 09:47
  • @Rob W OK I see it getting created in the `chrome://extensions/` page, but there is no popup created under the browser action icon....pity browser actions couldnt just have a js setting like the background page can now. – PAEz Mar 17 '12 at 09:51
  • I have removed my first comment, since you got confused with it. My statement was not "A permanent popup is shown", but "a popup is also added" (so, the browser action might be slower, compared to an event listener). – Rob W Mar 17 '12 at 09:53
  • Many thanks to you PAEz for your latest piece of code!! It came it when I'd just started writing a JS script for the same purpose to try it on a test page and then incorporate into the extension, but you were the first. Many thanks again! – user1274925 Mar 17 '12 at 19:45
0

The code in myscript.js is what gets injected into the page. It doesn't work how you currently have it set up because you are automatically injecting into every page the code that injects in to select pages. You need to move the myscript.js code into a background_page which will then only inject when the button is clicked.

https://code.google.com/chrome/extensions/background_pages.html

abraham
  • 46,583
  • 10
  • 100
  • 152
  • Thank you, but it didn't work either. I added the line "background_page": "background.html" to my manifest.json and tried both versions of background.html, neither of which worked. May be there's something wrong with the script? – user1274925 Mar 17 '12 at 01:26
  • What do you mean by "both versions of background.html"? – abraham Mar 17 '12 at 04:05
  • Hereby I meant that I moved the code from myscript.js to background.html, and there was 2 versions of myscript.js. – user1274925 Mar 17 '12 at 18:42