最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Chrome Extension Context Menu: how to append div to page after clicking menu item - Stack Overflow

programmeradmin1浏览0评论

Playing around with building a Chrome extension. At the moment I've put together a context menu item. When the context menu item is clicked, it fires itemClicked() in my background script context_menu.js:

function itemClicked(info, tab) {
     alert("clicked");
}

The alert fires. I can also do stuff like sending ajax requests through itemClicked()

However, I can't append any elements to the page (or DOM manipulation of any sort). Even something as basic as this doesn't work:

  var d = document.createElement('div');
  d.setAttribute("css", "width: 100px; height: 100px; background-color: red; position: fixed; top: 70px; left: 30px; z-index: 99999999999;");
  document.body.appendChild(d); 

So I tried to add the same code to a content script:

chrome.contextMenus.onClicked.addListener(function(OnClickData info, tabs.Tab tab) {
  //code to append the input here
});

But it still won't work. What am I doing wrong?

How can I get the context menu to append something to the page after clicking?

Thanks so much!

Edit: here is my manifest.json (removed the irrelevant stuff like name/description...etc)

{


  "permissions": [
    "activeTab",        
    "tabs",
    "cookies",
    "contextMenus"
  ],

  "background": {
    "scripts": ["context_menu.js"]
  },
  "browser_action": {
    "default_icon": "icon16.png",
    "default_css": "popup.css",
    "default_popup": "popup.html"
  },

  "content_scripts": [
    {      
      "matches": ["<all_urls>"],
      "js": ["vendor/jquery-1.8.2.min.js", "config.js", "content_script.js"]   
    }
  ],

  "web_accessible_resources": ["popup.html"]

}

Playing around with building a Chrome extension. At the moment I've put together a context menu item. When the context menu item is clicked, it fires itemClicked() in my background script context_menu.js:

function itemClicked(info, tab) {
     alert("clicked");
}

The alert fires. I can also do stuff like sending ajax requests through itemClicked()

However, I can't append any elements to the page (or DOM manipulation of any sort). Even something as basic as this doesn't work:

  var d = document.createElement('div');
  d.setAttribute("css", "width: 100px; height: 100px; background-color: red; position: fixed; top: 70px; left: 30px; z-index: 99999999999;");
  document.body.appendChild(d); 

So I tried to add the same code to a content script:

chrome.contextMenus.onClicked.addListener(function(OnClickData info, tabs.Tab tab) {
  //code to append the input here
});

But it still won't work. What am I doing wrong?

How can I get the context menu to append something to the page after clicking?

Thanks so much!

Edit: here is my manifest.json (removed the irrelevant stuff like name/description...etc)

{


  "permissions": [
    "activeTab",        
    "tabs",
    "cookies",
    "contextMenus"
  ],

  "background": {
    "scripts": ["context_menu.js"]
  },
  "browser_action": {
    "default_icon": "icon16.png",
    "default_css": "popup.css",
    "default_popup": "popup.html"
  },

  "content_scripts": [
    {      
      "matches": ["<all_urls>"],
      "js": ["vendor/jquery-1.8.2.min.js", "config.js", "content_script.js"]   
    }
  ],

  "web_accessible_resources": ["popup.html"]

}
Share Improve this question edited Nov 11, 2013 at 20:58 Michelle asked Nov 11, 2013 at 20:44 MichelleMichelle 2,7122 gold badges25 silver badges35 bronze badges 4
  • Background scripts aren't allowed access to the DOM, so you shouldn't expect that to work. But I'm not seeing why the content script wouldn't accomplish that. Could you post your manifest.json? – Teepeemm Commented Nov 11, 2013 at 20:47
  • Instead of having the content script listen for the event, have you tried having the background script inject the necessary code? – Teepeemm Commented Nov 11, 2013 at 21:38
  • @Teepeemm that actually works - thanks. Can I inject a content script that won't run unless it is called via executeScript? (from my understanding, content scripts automatically run every time a tab is loaded) – Michelle Commented Nov 11, 2013 at 22:24
  • actually the injected content script only worked when I set an alert... It still won't allow for any DOM manipulation :/ – Michelle Commented Nov 11, 2013 at 22:38
Add a comment  | 

1 Answer 1

Reset to default 20

You have probably misunderstood the concept of a background page (and its younger, more resource-friendly and preferred sibling: event page) and that of a content script.

content scripts:

  • Are bound to a specific web-page loaded into a tab.
  • Live in an isolated world (JS context), but have direct access to the web-pages DOM.
  • Can communicate with the background page (see Message Passing).

background pages:

  • Are bound to your extension (there is max. 1 background (or event) page for each extension).
  • Are always somewhere in the background (event pages "take a nap" from time to time, but you can always wake them up).
  • Do not have direct access to any web-page.
  • Can communicate with the content scripts (and other views) (see Message Passing).
  • Can do cool stuff (because they have access to cool chrome.* APIs).

The chrome.contentMenus API is available only to a background page. Thus, you have to create any context menu and listen for onClicked events there (in the background page).
Once a context menu has been clicked, you can use Programmatic Injection to inject some code (or a content script) into the active tab's web-page.

Below is the source code of a sample extension that demonstrates this method.

manifest.json:

{
    "manifest_version": 2,
    "name":    "Test Extension",
    "version": "0.0",

    "background": {
        "persistent": false,   // <-- let's make it an event page
        "scripts": ["background.js"]
    },

    "permissions": [
        "contextMenus",
        "activeTab"   // <-- here, sufficient for our purpose
    ]
}

background.js:

/* Create a context-menu */
chrome.contextMenus.create({
    id: "myContextMenu",   // <-- mandatory with event-pages
    title: "Click me",
    contexts: ["all"]
});

/* Register a listener for the `onClicked` event */
chrome.contextMenus.onClicked.addListener(function(info, tab) {
    if (tab) {
        /* Create the code to be injected */
        var code = [
            'var d = document.createElement("div");',
            'd.setAttribute("style", "'
                + 'background-color: red; '
                + 'width: 100px; '
                + 'height: 100px; '
                + 'position: fixed; '
                + 'top: 70px; '
                + 'left: 30px; '
                + 'z-index: 9999; '
                + '");',
            'document.body.appendChild(d);'
        ].join("\n");

        /* Inject the code into the current tab */
        chrome.tabs.executeScript(tab.id, { code: code });
    }
});

(If your injected code is complicated enough, it might be a better idea to inject a .js file. More info on Programmatic Injection.)

发布评论

评论列表(0)

  1. 暂无评论