Search code examples
javascriptgoogle-chrome-extension

How do I restrict context menus to appear only for certain selected text in a Chrome extension?


I made a very simple chrome extension which allows users to highlight a DOI number, right-click and choose "Resolve DOI", and it sends them to the associated web page. Right now, this is done in background.html with:

chrome.contextMenus.create({
"title" : "Resolve DOI",
"type" : "normal",
"contexts" : ["selection"],
"onclick" : getClickHandler()
});

I would like to restrict the context menu option to only appear if the text they highlight begins with "10." Any suggestions on how to do this? Do I need to wait for the Context Menus module to become more advanced?


Solution

  • You would need to control content menu creation from a content script. Dynamic menu creation/deletion should execute pretty fast and the delay will be unnoticeable for a user.

    • Add mousedown event listener in a content script and check there whether selection satisfies your pattern.
    • Based on whether or not selection matches the patterrn, send a request to a background page asking to create or delete the menu.

    Something along those lines (not tested):

    content_script.js:

    document.addEventListener("mousedown", function(event){
        var selection = window.getSelection().toString();
        if(selection.match(/^10\./)) {
            chrome.extension.sendRequest({cmd: "create_menu"});
        } else {
            chrome.extension.sendRequest({cmd: "delete_menu"});
        }
    }, true); 
    

    background.html:

    chrome.extension.onRequest.addListener(function(request) {
        if(request.cmd == "create_menu") {
            chrome.contextMenus.removeAll(function() {
                chrome.contextMenus.create({
                    "title" : "Resolve DOI",
                    "type" : "normal",
                    "contexts" : ["selection"],
                    "onclick" : getClickHandler()
                });
            });
        } else if(request.cmd == "delete_menu") {
            chrome.contextMenus.removeAll();
        }
    });