55

I am trying to write a google chrome extension where I use a contextmenu. This contextmenu is available on editable elements only (input texts for example). When the contextmenu is clicked and executed I would like to retrieve in the callback function the element (the input text) on which the contextmenu has been executed in order to update the value associated to this input text.

Here is the skeleton of my extension:

function mycallback(info, tab) {
  // missing part that refers to the question:
  // how to retrieve elt which is assumed to be 
  // the element on which the contextMenu has been executed ?
  elt.value = "my new value"
}

var id = chrome.contextMenus.create({
        "title": "Click me",
        "contexts": ["editable"],
        "onclick": mycallback
    });

The parameters associated to the mycallback function contain no useful information to retrieve the right clicked element. It seems this is a known issue (http://code.google.com/p/chromium/issues/detail?id=39507) but there is no progress since several months. Does someone knows a workaround: without jquery and/or with jquery?

ThinkingStiff
  • 64,767
  • 30
  • 146
  • 239
Laurent
  • 14,122
  • 13
  • 57
  • 89
  • 2
    http://code.google.com/p/chromium/issues/detail?id=39507#c14 – c69 Oct 09 '11 at 13:09
  • Thanks for pointing this link to me but I have already seen this issue. I have tried the solution from comment #7 and by using document.activeElement I retrieve an HTMLBodyElement not the input text element on which the contextmenu has been executed. Also, the solution proposed by comment #14 with jquery does not work: I get a null value. – Laurent Oct 09 '11 at 13:32
  • 1
    is your content script sending messages to background script ? is background listening ? – c69 Oct 09 '11 at 14:50

1 Answers1

79

You can inject content script with contextmenu event listener and store element that was clicked:

manifest.json

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

content script.js

//content script
var clickedEl = null;

document.addEventListener("contextmenu", function(event){
    clickedEl = event.target;
}, true);

chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
    if(request == "getClickedEl") {
        sendResponse({value: clickedEl.value});
    }
});

background.js

//background
function mycallback(info, tab) {
    chrome.tabs.sendMessage(tab.id, "getClickedEl", {frameId: info.frameId}, data => {
        elt.value = data.value;
    });
}
wOxxOm
  • 65,848
  • 11
  • 132
  • 136
serg
  • 109,619
  • 77
  • 317
  • 330
  • 3
    Thanks a lot. The solution was to use a content script to retrieve and to alter the content of a field contained in the current tab. Indeed, the background script is isolated and has not access to the content of the current webpage. Then, from the content script it is possible to use document.activeElement – Laurent Oct 09 '11 at 15:21
  • 7
    onRequest and sendRequest are now deprecated. It should be onMessage and sendMessage. – juanignaciosl Nov 08 '14 at 10:32
  • 6
    Or even better, the [`contextmenu` event](https://developer.mozilla.org/en/docs/Web/Events/contextmenu). In which case you won't have to check `event.button == 2` – rvighne Jul 01 '16 at 17:51
  • 1
    If you only need focusable elements such as inputs, you can instead use `document.activeElement`. – Derek 朕會功夫 Jul 30 '16 at 17:24
  • Keep in mind that the `chrome.contextMenus.onClicked` handler will always execute first, so you can run into situations where the user right-clicks before the page is finished loading (hence before `mousedown` handler is registered), so when they select from the context menu it will fail. – thdoan Apr 28 '17 at 10:01
  • 6
    I got `Unchecked runtime.lastError: Could not establish connection. Receiving end does not exist.` – Aero Wang Mar 21 '20 at 17:02
  • @AeroWang "Receiving end does not exist" usually happens in either case: (1) you forgot to reload the content page after reloading the extension (2) you are on a page that is not white listed for content_scripts in the manifest. – user776686 Sep 29 '20 at 19:42
  • working with the same code, but my `event` has only `{isTrusted: true}` nothing else. any idea why is it happening? – Eular Sep 04 '22 at 14:01