Initial commit
This commit is contained in:
commit
4ae6b27809
4 changed files with 137 additions and 0 deletions
13
background.js
Normal file
13
background.js
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
browser.action.onClicked.addListener((tab) => {
|
||||||
|
// Inject the CSS for the hover highlight
|
||||||
|
browser.scripting.insertCSS({
|
||||||
|
target: { tabId: tab.id },
|
||||||
|
files: ["content.css"]
|
||||||
|
});
|
||||||
|
|
||||||
|
// Inject the JavaScript for the element picker
|
||||||
|
browser.scripting.executeScript({
|
||||||
|
target: { tabId: tab.id },
|
||||||
|
files: ["content.js"]
|
||||||
|
});
|
||||||
|
});
|
||||||
6
content.css
Normal file
6
content.css
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
.pep-hover-highlight {
|
||||||
|
outline: 3px dashed #0088ff !important;
|
||||||
|
outline-offset: -3px !important;
|
||||||
|
cursor: crosshair !important;
|
||||||
|
background-color: rgba(0, 136, 255, 0.1) !important;
|
||||||
|
}
|
||||||
100
content.js
Normal file
100
content.js
Normal file
|
|
@ -0,0 +1,100 @@
|
||||||
|
(function() {
|
||||||
|
if (window.pepActive) return;
|
||||||
|
window.pepActive = true;
|
||||||
|
|
||||||
|
let currentHovered = null;
|
||||||
|
|
||||||
|
function handleMouseOver(e) {
|
||||||
|
e.stopPropagation();
|
||||||
|
if (currentHovered) {
|
||||||
|
currentHovered.classList.remove('pep-hover-highlight');
|
||||||
|
}
|
||||||
|
currentHovered = e.target;
|
||||||
|
currentHovered.classList.add('pep-hover-highlight');
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleMouseOut(e) {
|
||||||
|
e.stopPropagation();
|
||||||
|
if (currentHovered) {
|
||||||
|
currentHovered.classList.remove('pep-hover-highlight');
|
||||||
|
currentHovered = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleClick(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
|
||||||
|
// Turn off picker mode
|
||||||
|
document.removeEventListener('mouseover', handleMouseOver, true);
|
||||||
|
document.removeEventListener('mouseout', handleMouseOut, true);
|
||||||
|
document.removeEventListener('click', handleClick, true);
|
||||||
|
window.pepActive = false;
|
||||||
|
|
||||||
|
if (currentHovered) {
|
||||||
|
currentHovered.classList.remove('pep-hover-highlight');
|
||||||
|
printElement(currentHovered);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function printElement(el) {
|
||||||
|
el.classList.add('pep-print-target');
|
||||||
|
|
||||||
|
// Walk up the DOM tree to tag all ancestors of the target
|
||||||
|
let current = el.parentElement;
|
||||||
|
const ancestors = [];
|
||||||
|
while (current && current !== document.body && current !== document.documentElement) {
|
||||||
|
current.classList.add('pep-print-ancestor');
|
||||||
|
ancestors.push(current);
|
||||||
|
current = current.parentElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inject CSS that hides siblings of the target and siblings of its ancestors
|
||||||
|
const style = document.createElement('style');
|
||||||
|
style.textContent = `
|
||||||
|
@media print {
|
||||||
|
/* Hide all siblings of the body, ancestors, and target */
|
||||||
|
body > *:not(.pep-print-ancestor):not(.pep-print-target),
|
||||||
|
.pep-print-ancestor > *:not(.pep-print-ancestor):not(.pep-print-target) {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Strip formatting from ancestors to prevent them from pushing the target around */
|
||||||
|
.pep-print-ancestor {
|
||||||
|
padding: 0 !important;
|
||||||
|
margin: 0 !important;
|
||||||
|
border: none !important;
|
||||||
|
background: transparent !important;
|
||||||
|
box-shadow: none !important;
|
||||||
|
position: static !important;
|
||||||
|
overflow: visible !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reset body constraints */
|
||||||
|
body {
|
||||||
|
padding: 0 !important;
|
||||||
|
margin: 0 !important;
|
||||||
|
min-height: 100vh !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
document.head.appendChild(style);
|
||||||
|
|
||||||
|
// Short delay to ensure browser applies the print CSS before opening dialog
|
||||||
|
setTimeout(() => {
|
||||||
|
window.print();
|
||||||
|
|
||||||
|
// Clean up the temporary styles and classes after the print dialog closes
|
||||||
|
setTimeout(() => {
|
||||||
|
el.classList.remove('pep-print-target');
|
||||||
|
ancestors.forEach(a => a.classList.remove('pep-print-ancestor'));
|
||||||
|
style.remove();
|
||||||
|
}, 1000);
|
||||||
|
}, 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Activate event listeners in the capture phase to override default page behaviors
|
||||||
|
document.addEventListener('mouseover', handleMouseOver, true);
|
||||||
|
document.addEventListener('mouseout', handleMouseOut, true);
|
||||||
|
document.addEventListener('click', handleClick, true);
|
||||||
|
})();
|
||||||
18
manifest.json
Normal file
18
manifest.json
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
{
|
||||||
|
"manifest_version": 3,
|
||||||
|
"name": "Print Element Picker",
|
||||||
|
"version": "1.0",
|
||||||
|
"description": "Interactively pick an element on the page and print only that element.",
|
||||||
|
"permissions": ["activeTab", "scripting"],
|
||||||
|
"action": {
|
||||||
|
"default_title": "Pick element to print"
|
||||||
|
},
|
||||||
|
"background": {
|
||||||
|
"scripts": ["background.js"]
|
||||||
|
},
|
||||||
|
"browser_specific_settings": {
|
||||||
|
"gecko": {
|
||||||
|
"id": "print-picker@yourdomain.com"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue