Mohan
Mohan

Reputation: 141

chrome-extention replace the selected text

I m trying to port my firefox plugin to chrome and here is my sample code.

File: myscript.js (partial)

.
.
function init() {
  .
  .
  .
}
function myFunc(inp, option) {
  .
  .
  .
}

chrome.extension.onMessage.addListener(function (message, sender, response) {
    switch (message) {
        case "ITRANS":
            console.log("ITRANS");
            if (document.getSelection().baseNode != null){ 
                init();
                window.modifySelection(myFunc(window.getSelection().toString(), 0)); 
            }
            break;
        case "Devanagari":
            console.log("Devanagari");
            if (document.getSelection().baseNode != null){ 
                init();
                window.modifySelection(myFunc(window.getSelection().toString(), 1)); 
            }
            break;
        default:
            console.log("Default");
    }
});

File: background.js

var _selection_univ = chrome.contextMenus.create({
    "title": "INDIC 2 ITRANS",
    "id": "ITRANS",
    "onclick": reportclick,
    "contexts": ["selection"]
}, function () {
    console.log("Context Menu 1 ITRANS");
});
var _selection_univ = chrome.contextMenus.create({
    "title": "Eng 2 Devanagari",
    "id": "Devanagari",
    "onclick": reportclick,
    "contexts": ["selection"]
}, function () {
    console.log("Context Menu 2 Devanagari");
});

function reportclick(info, tab) {
    switch (info.menuItemId) {
        case "ITRANS":
        console.log("BG: ITRANS");
            chrome.tabs.sendMessage(tab.id, "ITRANS");
            break;
        case "Devanagari":
        console.log("BG: Devanagari");
            chrome.tabs.sendMessage(tab.id, "Devanagari");
            break;
        default:
            console.log("BG: Default");
    }
}

File: manifest.json

{
  "name": "Parivartan",
  "version": "0.8.2",
  "manifest_version": 2,
  "permissions":[
    "contextMenus",
    "<all_urls>",
    "tabs"
  ],
  "content_scripts": [
    {
      "matches": ["<all_urls>"],
      "js": ["myscript.js"],
      "all_frames": true
    }
  ],
  "background": {
    "scripts": ["background.js"]
   }
}

I am not able to figure out few things.

(1) Where should my init() function (which should run only once to inititialize my plugin globals) be placed.

(2) Replace the selected text with the output of a function. The above code does not work says "modifySelection" not found.

(3) How can call my functions if they are in a different (file2.js) file. At present I placed all my functions in a single file (myscript.js).

(4) How can I create menu within a menu.

I tried to search on google but could not find solutions to the above. Can anyone please help me.

-Mohan

Upvotes: 2

Views: 1467

Answers (1)

gkalpak
gkalpak

Reputation: 48211

(1) Where should my init() function (which should run only once to inititialize my plugin globals) be placed ?

Depending on your requirements there are two events that should cover your initialization needs:

chrome.runtime.onInstalled:

Fired when the extension is first installed, when the extension is updated to a new version, and when Chrome is updated to a new version.

E.g.: chrome.runtime.onInstalled.addListener(function() {...});

chrome.runtime.onStartup:

Fired when a profile that has this extension installed first starts up. This event is not fired when an incognito profile is started, even if this extension is operating in 'split' incognito mode.

E.g.: chrome.runtime.onStartup.addListener(function(details) {...});


(2) Replace the selected text with the output of a function. The above code does not work says "modifySelection" not found.

That is because the function modifySelection is not defined. Where did you get that name ? UPDATE:
Based on OP's feedback in comments, a simple modifySelection() function could look like this:

function modifySelection(newValue) {
    var range = document.getSelection().getRangeAt(0);
    range.deleteContents();
    range.insertNode(document.createTextNode(newValue));
}

(Note: It will only work properly if the selection involves TextNodes only. In other cases it might break the DOM, so more detailed parsing of the selection is required.)


(3) How can call my functions if they are in a different (file2.js) file. At present I placed all my functions in a single file (myscript.js).

You inject all the necessary files and then you call the functions as usual. I.e. all injected content scripts are executed in the same JS context. E.g.:

"content_scripts": [{
  "matches": ["<all_urls>"],
  "js": ["file1.js", "file2.js", ...],
  "all_frames": true
}],

In file1.js:

...
function funcInFile1() {...}
...

In file2.js:

...
var res = funcInFile1();
...

(Note: Content scripts are injected in the order in which they appear in the "js" array. Make sure each resource is available before calling it. E.g. trying to call funcInFile1() before injecting file1.js will result in error.)


(4) How can I create menu within a menu.

If by that you mean "create a submenu", there is an parentId attribute that you can include in the createProperties argument of the chrome.contextMenus.create function:

parentId:
The ID of a parent menu item; this makes the item a child of a previously added item.

See, also, this demo extension which does (among other things) exactly that.


Some final remarks

  1. chrome.extension.onMessage is deprecated. Please, use chrome.runtime.onMessage instead.

  2. Try using Event Pages (instead of background pages) when possible.

Upvotes: 1

Related Questions