5

I'm trying to make the most simple Chrome extension ever, but alas, I'm having big issues, would appreciate some help.

This is what I want it to do:

I select some text on a page and press the extension popup. When I do that, the background-color of the selected text is changed to yellow. When I click somewhere else (and the text is deselected) the background-color is removed.

How do I do that?

I found this code around here:

function makeEditableAndHighlight(colour) {
    var range, sel = window.getSelection();
    if (sel.rangeCount && sel.getRangeAt) {
        range = sel.getRangeAt(0);
    }
    document.designMode = "on";
    if (range) {
        sel.removeAllRanges();
        sel.addRange(range);
    }
    // Use HiliteColor since some browsers apply BackColor to the whole block
    if (!document.execCommand("HiliteColor", false, colour)) {
        document.execCommand("BackColor", false, colour);
    }
    document.designMode = "off";
}

function highlight(colour) {
    var range, sel;
    if (window.getSelection) {
        // IE9 and non-IE
        try {
            if (!document.execCommand("BackColor", false, colour)) {
                makeEditableAndHighlight(colour);
            }
        } catch (ex) {
            makeEditableAndHighlight(colour)
        }
    } else if (document.selection && document.selection.createRange) {
        // IE <= 8 case
        range = document.selection.createRange();
        range.execCommand("BackColor", false, colour);
    }
}

I don't really know how to work the background.js and the popup.js and the context_script.js .

I tried putting this code in the popup.js and calling it with highlight('yellow') but it didn't work. I also tried putting this code in the background.js and calling it from the popup.js with chrome.extension.getBackgroundPage().highlight('yellow'); but it didn't work.

In any case, even if this code works, it just changes the background-color of the selected text, but does not remove it when the text is de-selected.

In any case, just getting this first bit to work would be a great help.

In its current form, the code works like this: http://jsfiddle.net/LPnN2/12/ The problem is getting it to work with an extension.

This is my manifest.json:

{
   "background": {
      "scripts": [ "readit.js"]
   },


   "description": "Reads out selected text",
   "icons": {
      "128": "icon128.png",
      "16": "icon16.png",
      "48": "icon48.png"
   },
   "browser_action": {
      "default_icon": "icon48.png",
      "default_popup": "popup.html"
   },

   "content_scripts": [ {
   "js": [ "inject.js" ],
   "matches": [ "\u003Call_urls\u003E", "https://*/*" ]
   } ],

   "manifest_version": 2,
   "name": "Speak Me",
   "options_page": "options.html",
   "permissions": [ "contextMenus", "tabs", "notifications", "background" ],
   "update_url": "http://clients2.google.com/service/update2/crx",
   "version": "0.1"
}

I already have the extension doing something else (using TTS to read-out loud selected text via an API, but would love the text to also be higlighted, hence why I'm trying to implement this).

user2651560
  • 77
  • 2
  • 8

1 Answers1

2

The purpose of the content script is to gather data or make changes to the pages you are browsing using CSS and/or JavaScript. So what you need to do is put the makeEditableAndHighlight() and highlight() functions in a content script, and load it up in the manifest file like this:

"content_scripts": [
    {
        "matches" : [
            "<all_urls>"
        ],
        "js" : [
            "content.js"
        ]
    }
],

So then you just need to trigger the highlight() function. There are a few ways to do this, but one way is simply to call "executeScript()" in the background page. For example (and I admit this is quick and dirty), put this at the top of your content script:

highlight('yellow');

Then in your background.js file run the content script when the popup button is cliked, like this:

chrome.browserAction.onClicked.addListener(function() {
    chrome.tabs.executeScript(null, {file: "content.js"});
});

If you would like to select a color in a popup to be used for the highlighting then you'll need to use message passing to pass messages between the popup script and the content script, or to the background page and then the content script if you prefer.

I won't try and write the whole extension for you here, but hopefully that should give you a head start.

Also, if you're having a hard time wrapping your head around Extensions, you may find my blog post here to be helpful.

Jude Osborn
  • 1,788
  • 16
  • 24
  • I tried approaching your solution but it doesn't really work. I suspect it might be because `chrome.browserAction.onClicked.addListener` doesn't work if the popup also opens a dialog. How would I go around this issue? – user2651560 Aug 05 '13 at 21:37
  • Nevermind my previous comment. I learned how to execute a function in the background.js by calling it with getBackgroundPage from the popup.js. The function in the background is just a basic function which sends a message to the content.js - upon receiving that message, the content.js executes highlight function. Perfect. However, since you've been really helpful, now I must ask you for a thread to go about making it de-highlight once I deselect it. Is there a way to somehow restore the original or do I need to write a new JS function and execute that one too? How to time it on de-select only? – user2651560 Aug 05 '13 at 21:43
  • I did this inside the content.js: `function body() { document.getElementsByTagName("body")[0].addEventListener( "click", function(event){ highlight('white'); } ); }` Problem is this works... kinda weird. It only works if you specifically click on the selection, since if you click outside it, there would be no selection, hence nothing to which the `highlight('white');` function to change. – user2651560 Aug 05 '13 at 22:14
  • I'd suggest posting a separate question about de-selecting, because this is really a different problem that is probably more JavaScript generic than extension related. – Jude Osborn Aug 06 '13 at 01:02