Dynamic extension context menu that depends on selected text

后端 未结 1 548
后悔当初
后悔当初 2020-11-27 14:19

I am trying to create entries on the Chrome context menu based on what is selected. I found several questions about this on Stackoverflow, and for all of them the answer is:

相关标签:
1条回答
  • 2020-11-27 15:01

    The contextMenus API is used to define context menu entries. It does not need to be called right before a context menu is opened. So, instead of creating the entries on the contextmenu event, use the selectionchange event to continuously update the contextmenu entry.

    I will show a simple example which just displays the selected text in the context menu entry, to show that the entries are synchronized well.

    Use this content script:

    document.addEventListener('selectionchange', function() {
        var selection = window.getSelection().toString().trim();
        chrome.runtime.sendMessage({
            request: 'updateContextMenu',
            selection: selection
        });
    });
    

    At the background, we're going to create the contextmenu entry only once. After that, we update the contextmenu item (using the ID which we get from chrome.contextMenus.create).
    When the selection is empty, we remove the context menu entry if needed.

    // ID to manage the context menu entry
    var cmid;
    var cm_clickHandler = function(clickData, tab) {
        alert('Selected ' + clickData.selectionText + ' in ' + tab.url);
    };
    
    chrome.runtime.onMessage.addListener(function(msg, sender, sendResponse) {
        if (msg.request === 'updateContextMenu') {
            var type = msg.selection;
            if (type == '') {
                // Remove the context menu entry
                if (cmid != null) {
                    chrome.contextMenus.remove(cmid);
                    cmid = null; // Invalidate entry now to avoid race conditions
                } // else: No contextmenu ID, so nothing to remove
            } else { // Add/update context menu entry
                var options = {
                    title: type,
                    contexts: ['selection'],
                    onclick: cm_clickHandler
                };
                if (cmid != null) {
                    chrome.contextMenus.update(cmid, options);
                } else {
                    // Create new menu, and remember the ID
                    cmid = chrome.contextMenus.create(options);
                }
            }
        }
    });
    

    To keep this example simple, I assumed that there's only one context menu entry. If you want to support more entries, create an array or hash to store the IDs.

    Tips

    • Optimization - To reduce the number of chrome.contextMenus API calls, cache the relevant values of the parameters. Then, use a simple === comparison to check whether the contextMenu item need to be created/updated.
    • Debugging - All chrome.contextMenus methods are asynchronous. To debug your code, pass a callback function to the .create, .remove or .update methods.
    0 讨论(0)
提交回复
热议问题