I want my Chrome extension to add an element to the right-click context menu, allowing the user to change the background color of the right-clicked element.
manifest.json:
{
"manifest_version": 3,
"name": "Mouse Tracker",
"description": "Tracks the mouse position and adds a right click context menu item to get the cursor position and currently hovered element and change the background color of that element to red.",
"default_locale": "en",
"version": "1.0",
"background": {
"service_worker": "background.js"
},
"permissions": [
"contextMenus",
"activeTab"
],
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["content.js"]
}
]
}
background.js:
chrome.runtime.onInstalled.addListener(function () {
chrome.contextMenus.create({
id: "change-color",
title: "Change background to red",
contexts: ["all"]
});
});
chrome.contextMenus.onClicked.addListener(function (info, tab) {
if (info.menuItemId == "change-color") {
chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) {
chrome.tabs.sendMessage(tabs[0].id, { command: "change_color" }, function (response) { });
});
}
});
I tried two approaches to my content.js file:
content.js #1:
let element;
//Detecting when an element is hovered
document.addEventListener('mouseover', function (e) {
element = e.target
});
chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
if (request.command == "change_color") {
sendResponse({ result: 'success' });
element.style.backgroundColor = "red";
}
});
I thought the mouseover
events would stop while the mouse was within the right-click context menu. But instead, the element right clicked on is not the one selected (turned red). Rather, whatever element was beneath the cursor underneath the context menu is selected.
content.js #2: (suffers same exact problem)
let mouseX = 0;
let mouseY = 0;
let element;
document.onmousemove = function (e) {
mouseX = e.clientX;
mouseY = e.clientY;
element = document.elementFromPoint(mouseX, mouseY);
console.log(element)
}
chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
if (request.command == "change_color") {
element.style.backgroundColor = "red";
sendResponse({ result: 'success' });
}
});
I thought I might be able to use the context menu API to detect when the menu opens and closes but that doesn't seem to be possible:
content.js #3:
let mouseX = 0;
let mouseY = 0;
let element;
let contextOpen = false
document.onmousemove = function (e) {
if (!contextOpen) {
mouseX = e.clientX;
mouseY = e.clientY;
element = document.elementFromPoint(mouseX, mouseY);
console.log(element)
}
}
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
if (request.command == "change_color") {
element.style.backgroundColor = "red";
sendResponse({result: 'success'});
}
if (request.command == "menu_open") {
contextOpen = true
sendResponse({result: 'success'});
}
if (request.command == "menu_close") {
contextOpen = false
sendResponse({result: 'success'});
}
});
I could not seem to find an event to listen to within background.js
to send those commands.
Is there any solution?