I have a content script which, when an image element is right-clicked, sends a setTargetUrl message to a background.js script. The script, upon receiving the setTargetUrl message calls the rebuildContextMenu function which namely contains the following lines:
if (!(targetUrl.includes('youtube.com') || targetUrl.includes('youtu.be'))) buildContextMenuForImages();
if (targetUrl.includes('youtube.com') || targetUrl.includes('youtu.be'))
buildContextMenuForYouTube();
The content script contains the following function which is called when a right-click occurs:
async function handleRightClickWithoutGrid(e) {
if (logToConsole) console.log(`Target url sent: ${targetUrlSent}`);
// If the target url has already been sent then do nothing
if (!targetUrlSent) {
const { clientX: x, clientY: y } = e;
if (logToConsole) console.log(e);
// If right click is on image
const elementClicked = e.target;
const tag = elementClicked.tagName;
if (tag === 'IMG') {
if (domain.includes('youtube.com') || domain.includes('youtu.be')) {
// Get the video url
const videoUrl = absoluteUrl(getClosestAnchorHref(elementClicked));
//const videoId = new URL(videoUrl).searchParams.get('v');
//const downloadUrl = ytDownloadUrl + videoId;
await sendMessage('setTargetUrl', videoUrl);
if (logToConsole) console.log(`Video url: ${videoUrl}`);
} else {
if (window.getSelection) {
window.getSelection().removeAllRanges();
}
// Get the image url
const imgUrl = absoluteUrl(elementClicked.getAttribute('src'));
await sendMessage('setTargetUrl', imgUrl);
if (logToConsole) console.log(`Image url: ${imgUrl}`);
}
targetUrlSent = true;
} else {
const selectedText = getSelectedText();
if (logToConsole) console.log(selectedText);
// Send the selected text to background.js
await sendMessage('setSelection', { selection: selectedText });
}
// Dispatch the new event on the original target element
if (targetUrlSent) {
// Dispatch the new event on the original target element
setTimeout(() => {
// Create a new context menu event
const newEvent = new MouseEvent('contextmenu', {
bubbles: true,
cancelable: false,
view: window,
button: 2,
buttons: 2,
clientX: x,
clientY: y
});
// Dispatch the new event
elementClicked.dispatchEvent(newEvent);
if (logToConsole) console.log('New contextmenu event fired.');
if (logToConsole) console.log(`Default prevented: ${newEvent.defaultPrevented}`);
if (logToConsole) console.log(newEvent.target);
}, 1000); // Small delay to ensure proper event handling
}
} else {
targetUrlSent = false;
}
}
The problem I’m encountering is that the context menu is opened before the setTargetUrl has been sent and rebuildContextMenu called. If I add a e.preventDefault() then the context menu is never opened. Is there a solution to this? It appears as though the dispatch of the contextmenu event never takes place.