google-chrome-extensionaddeventlistenerchrome-extension-manifest-v3custom-contextmenu

How to make chrome.contextMenus.onClicked.addListener distinguish for different context menu ids?


While developing contextmenu based extension for Chrome, i'm facing a situation where invoking chrome.contextMenus.onClicked.addListener in a loop adds action cumulatively for each subcontext menu item.

So, when subcontextmenu is clicked it triggers event listener for all subcontext menus, instead for the context menu which was clicked.

     var parent;
     chrome.runtime.onInstalled.addListener(() => {
        parent = chrome.contextMenus.create({"title": "CCM", "id":"CCM", "contexts":["selection"]});
     });


     Object.keys(msgs).forEach(function(key) {
        chrome.runtime.onInstalled.addListener(() => {
        var createCM = chrome.contextMenus.create(
            {"title": "subcontextmenu"+key, "id":"scm"+key, "parentId": parent, "contexts":["selection"]});
        }); 
        chrome.contextMenus.onClicked.addListener(function(info,tab){openAction(info,tab,JSON.stringify(msgs[key]['msg']));}
        );  
     });

In the above example, msgs is a JSON object containing message to be displayed when each subcontextmenu is clicked. Also, the msgs JSON context is bound to change dynamically. So, we can't tweak openAction to hardcode the numbers and associate the messages.

Hope my question is clear. Any help for clearing this confusion will be a great time saver for me.


Solution

  • Use one listener for onInstalled and onClicked (it provides menuItemId in its parameter).

    chrome.runtime.onInstalled.addListener(() => {
      chrome.contextMenus.create({title: 'CCM', id: 'CCM', contexts: ['selection']});
      Object.keys(msgs).forEach(key => {
        chrome.contextMenus.create({
          title: 'subcontextmenu' + key,
          id: 'scm' + key,
          parentId: 'CCM',
          contexts: ['selection'],
        });
      });
    });
    
    chrome.contextMenus.onClicked.addListener((info, tab) => {
      openAction(info, tab, JSON.stringify(msgs[info.menuItemId].msg));
    });