dba*_*osa 16 javascript contextmenu google-chrome-extension
我正在尝试根据所选内容在Chrome上下文菜单中创建条目.我在Stackoverflow上发现了几个关于此的问题,对于所有这些问题,答案是:使用带有"mousedown"监听器的内容脚本,该监听器查看当前选择并创建上下文菜单.
我实现了这个,但它并不总是有效.有时所有日志消息都表示上下文菜单已按我的意愿修改,但出现的上下文菜单未更新.
基于此,我怀疑这是一个竞争条件:有时chrome会在代码完全运行之前开始渲染上下文菜单.
我尝试将eventListener添加到"contextmenu"和"mouseup".当用户使用鼠标选择文本时,后者会触发,因此它会在出现之前更改上下文菜单(甚至是秒).即使使用这种技术,我仍然会看到同样的错误!
这种情况在Chrome 22.0.1229.94(Mac)中经常发生,有时在Chromium 20.0.1132.47(linux)中发生,并且在2分钟内尝试在Windows(Chrome 22.0.1229.94)上没有发生.
到底发生了什么?我该如何解决这个问题?还有其他解决方法吗?
这是我的代码的简化版本(不是那么简单,因为我保留了日志消息):
{
"name": "Test",
"version": "0.1",
"permissions": ["contextMenus"],
"content_scripts": [{
"matches": ["http://*/*", "https://*/*"],
"js": ["content_script.js"]
}],
"background": {
"scripts": ["background.js"]
},
"manifest_version": 2
}
Run Code Online (Sandbox Code Playgroud)
function loadContextMenu() {
var selection = window.getSelection().toString().trim();
chrome.extension.sendMessage({request: 'loadContextMenu', selection: selection}, function (response) {
console.log('sendMessage callback');
});
}
document.addEventListener('mousedown', function(event){
if (event.button == 2) {
loadContextMenu();
}
}, true);
Run Code Online (Sandbox Code Playgroud)
function SelectionType(str) {
if (str.match("^[0-9]+$"))
return "number";
else if (str.match("^[a-z]+$"))
return "lowercase string";
else
return "other";
}
chrome.extension.onMessage.addListener(function(msg, sender, sendResponse) {
console.log("msg.request = " + msg.request);
if (msg.request == "loadContextMenu") {
var type = SelectionType(msg.selection);
console.log("selection = " + msg.selection + ", type = " + type);
if (type == "number" || type == "lowercase string") {
console.log("Creating context menu with title = " + type);
chrome.contextMenus.removeAll(function() {
console.log("contextMenus.removeAll callback");
chrome.contextMenus.create(
{"title": type,
"contexts": ["selection"],
"onclick": function(info, tab) {alert(1);}},
function() {
console.log("ContextMenu.create callback! Error? " + chrome.extension.lastError);});
});
} else {
console.log("Removing context menu")
chrome.contextMenus.removeAll(function() {
console.log("contextMenus.removeAll callback");
});
}
console.log("handling message 'loadContextMenu' done.");
}
sendResponse({});
});
Run Code Online (Sandbox Code Playgroud)
Rob*_*b W 31
该contextMenus
API是用来定义上下文菜单项.在打开上下文菜单之前不需要调用它.因此,不是在contextmenu事件上创建条目,而是使用该selectionchange
事件不断更新contextmenu条目.
我将展示一个简单的示例,该示例仅在上下文菜单条目中显示所选文本,以显示条目已很好地同步.
使用此内容脚本:
document.addEventListener('selectionchange', function() {
var selection = window.getSelection().toString().trim();
chrome.runtime.sendMessage({
request: 'updateContextMenu',
selection: selection
});
});
Run Code Online (Sandbox Code Playgroud)
在后台,我们将仅创建一次contextmenu条目.之后,我们更新contextmenu项(使用我们得到的ID chrome.contextMenus.create
).
当选择为空时,如果需要,我们删除上下文菜单条目.
// 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);
}
}
}
});
Run Code Online (Sandbox Code Playgroud)
为了简化这个例子,我假设只有一个上下文菜单条目.如果要支持更多条目,请创建数组或散列以存储ID.
chrome.contextMenus
API调用的数量,请缓存参数的相关值.然后,使用简单的===
比较来检查是否需要创建/更新contextMenu项.chrome.contextMenus
方法都是异步的.要调试代码,传递一个回调函数的.create
,.remove
或.update
方法. 归档时间: |
|
查看次数: |
9138 次 |
最近记录: |