Skip to content

Instantly share code, notes, and snippets.

@kadamwhite
Last active July 17, 2024 17:54
Show Gist options
  • Save kadamwhite/03e6b12cf4e0e416983cce7995537307 to your computer and use it in GitHub Desktop.
Save kadamwhite/03e6b12cf4e0e416983cce7995537307 to your computer and use it in GitHub Desktop.
Bookmarklet: Annotate or circle things on the webpage
javascript:'use strict'%3B(()%3D>%7Bfunction l(%7Bx%3Ae%2Cy%3Af%7D)%7Bconst a%3Ddocument.createElement("div")%3Ba.style.position%3D"absolute"%3Ba.style.display%3D"none"%3Ba.style.border%3D"7px dotted hotpink"%3Ba.style.borderRadius%3D"1rem"%3Ba.style.display%3D"block"%3Ba.style.height%3D0%3Ba.style.left%3D%60%24%7Be%7Dpx%60%3Ba.style.top%3D%60%24%7Bf%7Dpx%60%3Ba.style.width%3D0%3Bconst b%3Ddocument.createElement("DIV")%3Bb.classList.add("annotation-label")%3Bb.contentEditable%3D!0%3Bb.style.background%3D"rgba(255%2C255%2C255%2C0.9)"%3Bb.style.transform%3D"translateY(-60%25)"%3Bb.style.color%3D"hotpink"%3Bb.style.display%3D"inline-block"%3Bb.style.minWidth%3D"100px"%3Bb.style.padding%3D"0.25rem 0.5rem"%3Bb.style.marginLeft%3D"0.75rem"%3Bb.style.fontWeight%3D800%3Bb.style.fontSize%3D"24px"%3Bb.style.whiteSpace%3D"nowrap"%3Ba.appendChild(b)%3Bb.addEventListener("pointerdown"%2Cc%3D>%7Bc.stopPropagation()%7D)%3Ba.addEventListener("contextmenu"%2Cc%3D>%7Bc.preventDefault()%3Ba.remove()%7D)%3Bconst g%3Dc%3D>%7Ba.style.display%3D"block"%3Ba.style.top%3D%60%24%7Bf<c.pageY%3Ff%3Ac.pageY%7Dpx%60%3Ba.style.left%3D%60%24%7Be<c.pageX%3Fe%3Ac.pageX%7Dpx%60%3Ba.style.height%3D%60%24%7BMath.round(Math.abs(c.pageY-f))%7Dpx%60%3Ba.style.width%3D%60%24%7BMath.round(Math.abs(c.pageX-e))%7Dpx%60%7D%2Ch%3Dc%3D>%7Bd.removeEventListener("pointermove"%2Cg)%3Bd.removeEventListener("pointerup"%2Ch)%3Ba.querySelector(".annotation-label")%3F.focus()%7D%2Ck%3Dc%3D>%7Bb.style.minWidth%3D0%3Bb.removeEventListener("blur"%2Ck)%7D%3Bb.addEventListener("blur"%2Ck)%3Bd.appendChild(a)%3Bd.addEventListener("pointermove"%2Cg)%3Bd.addEventListener("pointerup"%2Ch)%7Dconst d%3Ddocument.createElement("div")%3Bd.style.zIndex%3D1E3%3Bd.style.position%3D"absolute"%3Bd.style.top%3D0%3Bd.style.width%3D"100vw"%3Bd.style.height%3D%60%24%7Bdocument.body.scrollHeight%7Dpx%60%3Bdocument.body.appendChild(d)%3Bd.addEventListener("pointerdown"%2Ce%3D>%7B2!%3D%3De.button%26%26l(%7Bx%3Ae.pageX%2Cy%3Ae.pageY%7D)%7D)%7D)()%3Bvoid+0
/**
* Annotate a page with writeable labels.
*
* Script variant that doesn't reposition the circle (which is a rounded
* rectangle this time) when you release the mouse.
*
* This version (copy the bookmarklet code from the file above) will add
* a label field to each annotation, and you can right-click an annotation
* to remove it.
*/
(() => {
const blanket = document.createElement('div');
blanket.style.zIndex = 1000;
blanket.style.position = 'absolute';
blanket.style.top = 0;
blanket.style.width = '100vw';
blanket.style.height = `${ document.body.scrollHeight }px`;
const logEvent = ( evt ) => {
const partialEvent = {};
for ( const key in evt ) {
if ( key.match( /(X|Y)$/ ) ) {
partialEvent[ key ] = evt[ key ];
}
}
console.log( partialEvent );
}
function makeOutline( { x: startX, y: startY } ) {
const outline = document.createElement('div');
outline.style.position = 'absolute';
outline.style.display = 'none';
outline.style.border = '7px dotted hotpink';
outline.style.borderRadius = '1rem';
outline.style.display = 'block';
outline.style.height = 0;
outline.style.left = `${startX}px`;
outline.style.top = `${startY}px`;
outline.style.width = 0;
const label = document.createElement( 'DIV' );
label.classList.add( 'annotation-label' );
label.contentEditable = true;
label.style.background = 'rgba(255,255,255,0.9)';
label.style.transform = 'translateY(-60%)';
label.style.color = 'hotpink';
label.style.display = 'inline-block';
label.style.minWidth = '100px';
label.style.padding = '0.25rem 0.5rem';
label.style.marginLeft = '0.75rem';
label.style.fontWeight = 800;
label.style.fontSize = '24px';
label.style.whiteSpace = 'nowrap';
outline.appendChild( label );
label.addEventListener('pointerdown', ( evt ) => {
// Allow selecting label without passing up the chain.
evt.stopPropagation();
} );
const removeOnRightClick = ( evt ) => {
evt.preventDefault();
outline.remove();
};
outline.addEventListener( 'contextmenu', removeOnRightClick );
const updateOutline = ( evt ) => {
outline.style.display = 'block';
outline.style.top = `${ startY < evt.pageY ? startY : evt.pageY}px`;
outline.style.left = `${ startX < evt.pageX ? startX : evt.pageX}px`;
outline.style.height = `${Math.round( Math.abs( evt.pageY - startY ) )}px`;
outline.style.width = `${Math.round( Math.abs( evt.pageX - startX ) )}px`;
};
const finishOutline = ( evt ) => {
blanket.removeEventListener( 'pointermove', updateOutline );
blanket.removeEventListener( 'pointerup', finishOutline );
outline.querySelector( '.annotation-label' )?.focus();
};
const finishLabel = ( evt ) => {
label.style.minWidth = 0;
label.removeEventListener( 'blur', finishLabel );
};
label.addEventListener( 'blur', finishLabel );
blanket.appendChild( outline );
blanket.addEventListener( 'pointermove', updateOutline );
blanket.addEventListener( 'pointerup', finishOutline );
}
document.body.appendChild(blanket);
blanket.addEventListener('pointerdown', ( evt ) => {
if ( evt.button === 2 ) {
// Right click: take no action.
return;
}
makeOutline( {
x: evt.pageX,
y: evt.pageY,
} );
} );
})();
javascript:(function()%7B(()%3D>%7Blet e%3Ddocument.createElement("div")%3Be.style.zIndex%3D1e3%2Ce.style.position%3D"absolute"%2Ce.style.top%3D0%2Ce.style.width%3D"100vw"%2Ce.style.height%3D%60%24%7Bdocument.body.scrollHeight%7Dpx%60%3Blet t%2Cl%3Ddocument.createElement("div")%3Bl.style.position%3D"absolute"%2Cl.style.display%3D"none"%2Cl.style.border%3D"5px dotted hotpink"%2Cl.style.borderRadius%3D"45%25"%2Cl.style.pointerEvents%3D"none"%3Blet s%3De%3D>%7Bl.style.display%3D"block"%2Cl.style.top%3D%60%24%7Bt.y<e.pageY%3Ft.y%3Ae.pageY%7Dpx%60%2Cl.style.left%3D%60%24%7Bt.x<e.pageX%3Ft.x%3Ae.pageX%7Dpx%60%2Cl.style.height%3D%60%24%7BMath.round(Math.abs(e.pageY-t.y))%7Dpx%60%2Cl.style.width%3D%60%24%7BMath.round(Math.abs(e.pageX-t.x))%7Dpx%60%7D%3Be.addEventListener("pointerdown"%2Cp%3D>%7Bt%3D%7Bx%3Ap.pageX%2Cy%3Ap.pageY%7D%2Cl.style.display%3D"block"%2Cl.style.height%3D0%2Cl.style.left%3D%60%24%7Bt.x%7Dpx%60%2Cl.style.top%3D%60%24%7Bt.y%7Dpx%60%2Cl.style.width%3D0%2Ce.addEventListener("pointermove"%2Cs)%7D)%2Ce.addEventListener("pointerup"%2Ct%3D>%7Be.removeEventListener("pointermove"%2Cs)%7D)%2Cdocument.body.appendChild(e)%2Ce.appendChild(l)%7D)()%7D)()
(() => {
const blanket = document.createElement('div');
blanket.style.zIndex = 1000;
blanket.style.position = 'absolute';
blanket.style.top = 0;
blanket.style.width = '100vw';
blanket.style.height = `${ document.body.scrollHeight }px`;
let startCoords;
const outline = document.createElement('div');
outline.style.position = 'absolute';
outline.style.display = 'none';
outline.style.border = '5px dotted hotpink';
outline.style.borderRadius = '45%';
outline.style.pointerEvents = 'none';
const logEvent = ( evt ) => {
const partialEvent = {};
for ( const key in evt ) {
if ( key.match( /(X|Y)$/ ) ) {
partialEvent[ key ] = evt[ key ];
}
}
console.log( partialEvent );
}
const updateOutline = ( evt ) => {
outline.style.display = 'block';
outline.style.top = `${ startCoords.y < evt.pageY ? startCoords.y : evt.pageY}px`;
outline.style.left = `${ startCoords.x < evt.pageX ? startCoords.x : evt.pageX}px`;
outline.style.height = `${Math.round( Math.abs( evt.pageY - startCoords.y ) )}px`;
outline.style.width = `${Math.round( Math.abs( evt.pageX - startCoords.x ) )}px`;
};
blanket.addEventListener('pointerdown', ( evt ) => {
startCoords = {
x: evt.pageX,
y: evt.pageY,
};
outline.style.display = 'block';
outline.style.height = 0;
outline.style.left = `${startCoords.x}px`;
outline.style.top = `${startCoords.y}px`;
outline.style.width = 0;
blanket.addEventListener( 'pointermove', updateOutline );
} );
blanket.addEventListener( 'pointerup', ( evt ) => {
blanket.removeEventListener( 'pointermove', updateOutline );
} );
document.body.appendChild(blanket);
blanket.appendChild( outline );
})();
(()=>{let e=document.createElement("div");e.style.zIndex=1e3,e.style.position="absolute",e.style.top=0,e.style.width="100vw",e.style.height=`${document.body.scrollHeight}px`;let t,l=document.createElement("div");l.style.position="absolute",l.style.display="none",l.style.border="5px dotted hotpink",l.style.borderRadius="45%",l.style.pointerEvents="none";let s=e=>{l.style.display="block",l.style.top=`${t.y<e.pageY?t.y:e.pageY}px`,l.style.left=`${t.x<e.pageX?t.x:e.pageX}px`,l.style.height=`${Math.round(Math.abs(e.pageY-t.y))}px`,l.style.width=`${Math.round(Math.abs(e.pageX-t.x))}px`};e.addEventListener("pointerdown",p=>{t={x:p.pageX,y:p.pageY},l.style.display="block",l.style.height=0,l.style.left=`${t.x}px`,l.style.top=`${t.y}px`,l.style.width=0,e.addEventListener("pointermove",s)}),e.addEventListener("pointerup",t=>{e.removeEventListener("pointermove",s)}),document.body.appendChild(e),e.appendChild(l)})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment