问题
I have a simple chrome extension, my goal is to hover any img or video or audio tags, get a context menu with my extension item by the rightclicking on the img, video or audio.
So the problem is that when some img are inside or behind div, i can't get my context menu item because it doesn't match my contexts. The same thing sometimes happens with the video and audio. My question is there any approach to write my own context rather than using google`s "image", "video", "audio".
I`ve already have sometimes working extension, so i need to fix this problem with some of the images.
var contextMenuItem = {
"id": "printData",
"title": "print",
"contexts": ["image", "audio", "video"]
};
chrome.contextMenus.removeAll(function() {
chrome.contextMenus.create(contextMenuItem)
});
chrome.contextMenus.onClicked.addListener(function(mediaData){
if (mediaData.menuItemId == "printData") {
console.log(mediaData)
}
});
So what I want is to my context menu item displaying when i hower any image on the page. Because now it works maybe 50% of the time. Thanks
回答1:
No, there's no way to add a custom context.
What you can do is register an additional menu item on "page"
context with a separate id
and dynamically show/hide it by using a mousedown
event listener in the content script. The listener will be triggered before contextmenu
event and will notify the background script if the event's target includes img/media inside. The background script will use chrome.contextMenus API to toggle the menu item.
content script:
// true means 'useCapture' mode (the first event phase)
window.addEventListener('mousedown', e => button === 2 && beforeContextMenu(e), true);
window.addEventListener('keydown', e => {
if (e.key === 'ContextMenu' ||
e.key === 'F10' && e.shiftKey && !e.altKey && !e.ctrlKey && !e.metaKey) {
beforeContextMenu(e);
}
}, true);
function beforeContextMenu(e) {
const el = !e.target.matches('img, video, audio') &&
e.target.querySelector('img, video, audio');
chrome.runtime.sendMessage({
contextMenu: el ? el.currentSrc || el.src : '',
});
}
background script:
chrome.runtime.onMessage.addListener((message, sender) => {
if (message.contextMenu) {
chrome.contextMenus.create({
id: 'printData:page',
title: 'print',
contexts: ['page'],
}, ignoreChromeError);
} else if (message.contextMenu === '') {
chrome.contextMenus.remove('printData:page', ignoreChromeError);
}
});
chrome.runtime.onInstalled.addListener(() => {
chrome.contextMenus.create({
id: 'printData',
title: 'print',
contexts: ['image', 'audio', 'video'],
}, ignoreChromeError);
});
chrome.contextMenus.onClicked.addListener(e => {
if (e.menuItemId.startsWith('printData')) {
console.log(e);
}
});
function ignoreChromeError() {
return chrome.runtime.lastError;
}
This simplified example will toggle the menu item globally for all tabs, though. Chrome API cannot toggle the menu per tab so the closest thing you may want to implement is using documentUrlPatterns to specify the tab URLs, but that's an edge case that's probably not worth pursuing.
来源:https://stackoverflow.com/questions/58639878/is-there-any-way-to-define-own-contexts-for-context-menu-item-google-chrome-ext