Chrome 在contextMenu镶边中使用所选文本(清单版本3)

bmvo0sr5  于 2022-12-06  发布在  Go
关注(0)|答案(2)|浏览(182)

我正在尝试将chrome扩展从清单版本2重写为清单版本3。
该扩展的作用是使用选定的文本创建一个特定的URL。它会根据选定的文本在Chrome浏览器的contextMenu中添加一个项目,当用户单击该项目时,URL将在一个新窗口中打开。
我使用一个content_script和一个document事件侦听器,在每次所选文本发生变化时(在选择文本时经常发生),向backgroundscript发送一条消息。
这就是我的content_script.js。从清单2到清单3,我没有做任何更改。

//Add event listener: checks for selectionchanges by user 
document.addEventListener('selectionchange', function() {
    var selection = window.getSelection().toString().trim();
    chrome.runtime.sendMessage({
        request: 'updateContextMenu',
        selection: selection
    });
});

在我的后台脚本中,我为这些消息添加了一个侦听器。它检查菜单项是否存在。如果存在,它将更新该项,如果不存在,它将创建该项。
在清单版本2中,我是这样做的:

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 {
            var options = {
                title: "Open '%s' in Service-Now",
                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);
            }
        }
    }
});

但是对于manifest版本3,我需要做一些改变。我在onclick属性上得到了一个错误,所以我把它改成了一个事件侦听器。(显然我不能window.open从service_worker调用www.example.com,所以我也必须改变它,但这不是我的问题。

chrome.contextMenus.onClicked.addListener(function(clickData, tab) {
    var sn_url = get_servicenow_url(clickData.selectionText);

    console.log("debug: open URL " + sn_url);
    Clients.openWindow(sn_url, '_blank');
    //window.open(sn_url, '_blank');
});

除此之外,我还有一个错误:
事件处理程序出错:TypeError:调用contextMenus时出错。update([integer|字符串] id,对象updateProperties,可选函数回调):参数“updateProperties”处出错:意外属性:请输入您的密码://////
根据chrome文档contextMenus.update应该接受与contextMenus. create相同的参数。但是它并不接受,因为这是文档对contextMenu. update的声明。注意ID是单独提到的。
PARAMETERS id(字符串|number)-要更新的项目的ID。
updateProperties(object)-要更新的属性。接受与contextMenus.create函数相同的值。
其中contextMenus.create id定义为可能的createProperties之一
createProperties(object)id(字符串可选)-分配给此项目的唯一ID。对于事件页面是必需的。不能与此扩展的另一个ID相同。
我不能留下ID,因为创建需要它,我不能把ID放在我的数组中,因为对于更新,它需要是命令中单独的第一件事。
https://developer.chrome.com/docs/extensions/reference/contextMenus/#method-update\

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 
            } // else: No contextmenu ID, so nothing to remove
        } else {
            var options = {
                id: "OpenSnow", //mandatory for createMenu
                title: "Open '%s' in Service-Now",
                contexts: ["selection"]
            };
            if (cmid != null) {
                chrome.contextMenus.update(options);
            } else {
                // Create new menu, and remember the ID
                cmid = chrome.contextMenus.create(options);
                console.log("debug: first time creation" + );
            }
        }
    }
});

当我尝试运行此代码块时,出现以下错误:
事件处理程序出错:TypeError:调用contextMenus时出错。update([integer|字符串] id,对象updateProperties,可选函数回调):没有匹配的签名。在chrome-扩展名://adpocbbofaopmokkheddloekfodplnnk/background.js:110:37
也就是这一行代码:

chrome.contextMenus.update(options);

但将该行更改为调用id:

chrome.contextMenus.update(cmid, options);

chrome.contextMenus.update(id: "OpenSnow", options);

两者又给予我不同的错误。
如果有人能帮我找出清单版本3代码中的错误,那将非常有帮助。或者如果有一个更好的方法来做这件事,在更新选定的文本时没有那么多的消息发送,那也会工作,我愿意接受建议。

idfiyjo8

idfiyjo81#

事实证明,它比我以前的解决方案简单得多。我不再需要内容脚本了。在service_worker中,我创建了一个菜单项,使用%s来显示所选文本,它只在有选择时显示,并且在安装扩展时创建一次。
然后,我创建了一个侦听器,用于在单击上下文菜单项时运行必要的代码。

//define contextMenuItem
var contextMenuItem = {

    "id": "OpenSN",
    "title": "Open %s in ServiceNow",
    "contexts": ["selection"]
};

//on installation of chrome extension: create contextMenuItem
chrome.runtime.onInstalled.addListener(() => {
  chrome.contextMenus.create({
    id: "OpenSN",
    title: "Open %s in Service-Now",
    contexts: ["selection"]
  });
});


//add listener for click on self defined menu item
chrome.contextMenus.onClicked.addListener(function(clickData){
    if (clickData.menuItemId == "OpenSN" && clickData.selectionText) {
        //run code here
    }
})
t2a7ltrp

t2a7ltrp2#

如果选取的文字出现在页面上,则会将它传递给***onClickData.selectionText***中***各种***内容类型的侦听程式。
更多信息:https://developer.chrome.com/docs/extensions/reference/contextMenus/
您可以使用下列程式码来使用不同类型的快显功能表:

清单.json:

"background": {
    "service_worker": "background.js"
  },
  ...
  "permissions": [
    "contextMenus"
  ],

背景.js:

const types = [
  "all",
  "page",
  "frame",
  "selection",
  "link",
  "editable",
  "image",
  "video",
  "audio",
  "browser_action",
  "page_action",
  "action"
];

chrome.runtime.onInstalled.addListener(reason => {
  types.forEach(type => {
    console.log(type, reason);
    chrome.contextMenus.create({
      id: `${type}_TYPE_MENUITEM_ID`,
      title: `Add ${type} with “%s“ to my service`,
      contexts: [type],
      visible: true
    });
    chrome.contextMenus.onClicked.addListener((clickData) => {
      if (clickData.menuItemId === `${type}_TYPE_MENUITEM_ID`) {
        console.log(`Clicked as: ${type}`);
        console.log(clickData);
      }
    });
  });
});

相关问题