在内容脚本得到响应之前,禁止启动上下文菜单
Prevent context menu from launching until content script gets a response back
(我将内容脚本称为cs.js,background.js称为ba.jsTR
场景:
点击oncontextmenu
,我需要确定页面的url及其阻止状态,并将其发送到ba.js。代码(cs.js:
var triggered = false;
window.oncontextmenu = function(event){
if(triggered) return;
chrome.runtime.sendMessage({
url: window.location.href,
blocked: isBlocked
}, function(response){ // after work has been done
triggered = true;
triggerEvent(window, "contextmenu", event); // line A
triggered = false; // line C
});
return false; // line B
};
问题是,当我得到响应时,上下文菜单已经显示给用户,而没有我想要的消息(因为我没有得到响应,这意味着ba.js还没有完成chrome.contextMenus.update
调用)。因此,作为一个解决方案,我有:
- 返回
false
以防止其显示(B行) - 使用
trigger
布尔值来确保在a行ItriggerEvent
(全局)时不会再次发送消息 - 然后重置C线上的
trigger
布尔值
然而,这种方法并不奏效。因此,我需要一种方法:
在上下文菜单操作中,从相关的cs.js向ba.js发送一条消息,根据仅对cs.js可用的某些参数更新上下文菜单,然后,仅在收到消息后,向用户显示上下文菜单
注意:我已经尝试过使用chrome.tabs.onUpdated
和其他朋友(这样我就可以检测到用户所在的当前页面,从而自己获得必要的参数),但是,我也无法使用它们来实现这一点。
ba.js
onMessage
:
chrome.runtime.onMessage.addListener(function(msg, sender, sendResponse){
if(typeof msg.url !== undefined){
url = msg.url; // global
isBlocked = msg.blocked; // global
action = isBlocked ? "Unblock" : "Block"; // global
chrome.contextMenus.update("blockSite", { // update action
title: action + " this site"
});
sendResponse("done"); // send confirmation
}
});
triggerEvent
代码:
function triggerEvent(node, eventName, obj){
var ev = new CustomEvent(eventName, obj || {});
node.dispatchEvent(ev);
}
更新:
所以,我使用了onActivated
,这次它运行得很好,除了一个大问题:
如果我打开一个新的选项卡,然后单击网站互动程序/键入网站地址,网站就会打开。然后,onActivated
侦听器不会启动(这当然是显而易见的)我不能使用onUpdated
,因为每当iframe更新时,即使在当前不活动的页面中,它也会触发。
我能做些什么来纠正这个错误?
您无法在Chrome中实际触发内置上下文菜单。因为这是Chrome用来授予某些临时权限(如activeTab
)的用户手势之一。
使用tabs.onActivated
和tabs.onUpdated
事件侦听器跟踪活动选项卡中的更改,并相应地更新上下文菜单。
-
持久背景页(默认模式):
var activeTabId; chrome.tabs.onActivated.addListener(function(info) { updateContextMenu(info.tabId) }); chrome.tabs.onUpdated.addListener(function(tabId, info, tab) { if (tabId == activeTabId) { updateContextMenu(tabId); } }); function updateContextMenu(tabId) { activeTabId = tabId; chrome.tabs.get(tabId, function(tab) { var isBlocked = checkBlockedState(tab.url); chrome.contextMenus.update("blockSite", { title: (isBlocked ? "Unblock" : "Block") + " this site" }); }); }
-
事件页面(
"persistent" : false
):chrome.tabs.onActivated.addListener(function(info) { updateContextMenu() }); chrome.tabs.onUpdated.addListener(function(tabId, info, tab) { chrome.tabs.query({active: true, currentWindow: true}, function(tabs) { if (tabs[0].id == tabId) { updateContextMenu(); } }); }); function updateContextMenu() { chrome.tabs.query({active: true, currentWindow: true}, function(tabs) { var isBlocked = checkBlockedState(tabs[0].url); chrome.contextMenus.update("blockSite", { title: (isBlocked ? "Unblock" : "Block") + " this site" }); }); }
- 我的jQuery插件参数没有正确启动,遇到了问题
- chrome扩展:尽管运行了at:documentidle,js脚本还是过早启动
- 从控制器返回后Ajax启动事件激发
- Meteor上的启动页面
- 如何防止网页加载后自动启动功能
- 如何从JavaScriptInterface启动Navigation Drawer
- window.on.scroll事件未启动
- 单击按钮后启动javascript提示
- 在javaservlet doPost方法中启动线程时,无法返回异常消息
- spine.js在启动时填充模型实例
- 如何在所有ng点击事件AngularJS上启动一个方法
- jQuery悬停在没有鼠标悬停的情况下启动
- SignalR客户端启动连接时如何设置用户
- 当我在form_for中的text_field_tag中点击Enter时,如何禁止发出POST请求
- Meteor:在启动时将html注入客户端文件
- Angular UI启动日期选择器问题
- 如何用低音量自动启动Youtube视频(iframe)
- jQuery mouseup在拖离链接后未启动
- 在同一选项卡中启动下载,而无需在Javascript中打开新选项卡或窗口
- 在内容脚本得到响应之前,禁止启动上下文菜单