Search code examples
google-chromegoogle-chrome-extensiondom-events

Chrome extension context menu only works once


I'm writing my first Chrome extension, it uses context menus (right-click and options come up). When text is highlighted and the ExtensionName option is selected from the right-click menu, it opens up a new tab and passes that as a query to a directory that my organization has. The issue is that it only works once. The option in the context menu still appears when text is highlighted and right-clicked, but selecting the ExtensionName option fails to produce another tab with the directory results.

I would like to for the user to be able to use this as many times as needed in a browser session, just like most other Chrome extensions. Reloading the extension in Chrome extension menu fixes the issue. I assume it has something to do with the event handling that occurs in my background script rightclick.js. I'm not as familiar with event handling in JavaScript or in the context of Chrome, so any help would be appreciated.

manifest.json

{
    "name": "ExtensionName",
    "description": "Right-click text to search the given directory.",
    "manifest_version": 2,
    "version": "1.0",
    "permissions": ["contextMenus"],
    "icons": {
        "16": "icon-bitty.png",
        "48": "icon-small.png",
        "128": "icon-large.png"
    },
    "background": {
        "scripts": ["rightclick.js"]
    }
}

rightclick.js

var selection_callbacks = []; 

chrome.extension.onMessage.addListener(function (request) { 
    var callback = selection_callbacks.shift(); 
    callback(request); 
});


function getSelection(callback) { 
    selection_callbacks.push(callback); 
    chrome.tabs.executeScript(null, { file:"selection.js" }); 
};

function createDirectoryRequest(selectText) {
    var form = document.createElement("form");
    form.setAttribute("method", "post");
    form.setAttribute("action", "THE URL FOR THE DIRECTORY GOES HERE");
    form.setAttribute("target", "_blank");

    var hiddenField = document.createElement("input");
    hiddenField.setAttribute("id", "search_generic_search_terms);");        
    hiddenField.setAttribute("name", "search[generic_search_terms]");
    hiddenField.setAttribute("value", selectText);
    form.appendChild(hiddenField);
    document.body.appendChild(form);        
    form.submit();

}

chrome.contextMenus.create({title: 'ExtensionName "%s"', 
                    contexts:["selection"], 
                    onclick: function(info, tab){ createDirectoryRequest(info.selectionText); }})

selection.js

chrome.extension.sendResponse(window.getSelection().toString());

I know this probably isn't a difficult problem, I'm just incredibly new to this so any help would be appreciated.


Solution

  • The issue here is that you're trying to submit a form several times with different values. Based on Submitting HTML form multiple times with different values, all you have to do is to give the target of your forms a unique value and open a new tab prior to submitting the form:

    rightclick.js

    var i = 0;
    
    function createDirectoryRequest(selectText) {
        var form = document.createElement("form");
        form.setAttribute("method", "post");
        form.setAttribute("action", "THE URL FOR THE DIRECTORY GOES HERE");
    
        // unique target for each form; open it in a new tab
        form.setAttribute("target", "window" + i);
        window.open("THE URL FOR THE DIRECTORY GOES HERE", "window" + i);
        i++;
    
        var hiddenField = document.createElement("input");
        hiddenField.setAttribute("id", "search_generic_search_terms);");        
        hiddenField.setAttribute("name", "search[generic_search_terms]");
        hiddenField.setAttribute("value", selectText);
        form.appendChild(hiddenField);
        document.body.appendChild(form);        
        form.submit();
    }
    

    Note that you could create only one form, and simply change its attributes before submitting, rather than creating a brand new form every time:

    var i = 0;
    
    var form = document.createElement("form");
    form.setAttribute("method", "post");
    form.setAttribute("action", "THE URL FOR THE DIRECTORY GOES HERE");
    
    var hiddenField = document.createElement("input");
    hiddenField.setAttribute("id", "search_generic_search_terms);");        
    hiddenField.setAttribute("name", "search[generic_search_terms]");
    form.appendChild(hiddenField);
    document.body.appendChild(form);   
    
    function createDirectoryRequest(selectText) {
        form.setAttribute("target", "window" + i);
        window.open("THE URL FOR THE DIRECTORY GOES HERE", "window" + i);
        i++;
    
        hiddenField.setAttribute("value", selectText);    
        form.submit();
    }