Skip to content

Instantly share code, notes, and snippets.

@foobear
Last active May 26, 2023 20:51
Show Gist options
  • Save foobear/f19f2cca87eaf005922323fe04f993c7 to your computer and use it in GitHub Desktop.
Save foobear/f19f2cca87eaf005922323fe04f993c7 to your computer and use it in GitHub Desktop.
JavaScript bookmarklet to click an element and copy its text contents. See https://makandracards.com/makandra/46962
(function() {
var overlay = document.createElement('div');
Object.assign(overlay.style, {
position: 'fixed',
top: 0,
left: 0,
width: '100vw',
height: '100vh',
zIndex: 99999999,
background: 'transparent',
cursor: 'crosshair'
});
document.body.append(overlay);
function getElement(event) {
overlay.style.pointerEvents = 'none';
var element = document.elementFromPoint(event.clientX, event.clientY);
overlay.style.pointerEvents = 'auto';
return element;
}
document.addEventListener('mousemove', function(event) {
var element = getElement(event);
if (!element) return;
var position = element.getBoundingClientRect();
Object.assign(overlay.style, {
background: 'rgba(0, 128, 255, 0.25)',
outline: '1px solid rgba(0, 128, 255, 0.5)',
top: '' + position.top + 'px',
left: '' + position.left + 'px',
width: '' + position.width + 'px',
height: '' + position.height + 'px'
});
});
overlay.addEventListener('click', function(event) {
var element = getElement(event);
var text = element.textContent || element.value;
text = text.replace(/\n[ \n]+\n/g, "\n").replace(/\n\n+/g, "\n\n").replace(/^\n+|\n+$/g, '');
if (!text.match("\n")) text = text.replace(/^ +| +$/, '')
window.prompt('Press Ctrl+C to copy', text);
document.body.removeChild(overlay);
});
})()
@jbyler
Copy link

jbyler commented May 26, 2023

It sounds like you prefer to prompt the user so they can decide whether or not to copy. I (for the moment at least) prefer to have it copy automatically, so I made a version that does that.

One other fix / improvement: I made it so that if you run the bookmarklet twice in a row (without selecting an element) you don't get into a stuck state that forces a page reload.

Here's my version:

javascript:void(function() {
  const overlayId = "copy-element-bookmarklet-overlay";

  const previousOverlay = document.getElementById(overlayId);
  previousOverlay && document.removeChild(previousOverlay);

  const overlay = document.createElement('div');
  overlay.id = overlayId;
  Object.assign(overlay.style, {
    position: 'fixed',
    top: 0,
    left: 0,
    width: '100vw',
    height: '100vh',
    zIndex: 99999999,
    background: 'transparent',
    cursor: 'crosshair'
  });
  document.body.append(overlay);

  function getElement(event) {
    overlay.style.pointerEvents = 'none';
    var element = document.elementFromPoint(event.clientX, event.clientY);
    overlay.style.pointerEvents = 'auto';

    return element;
  }

  /* https://jsfiddle.net/jdhenckel/km7prgv4/3/ */
  function copyToClip(doc, html = null, text = null) {
      function listener(e) {
        html && e.clipboardData.setData("text/html", html);
        text && e.clipboardData.setData("text/plain", text);
        e.preventDefault();
      }
      doc.addEventListener("copy", listener);
      doc.execCommand("copy");
      doc.removeEventListener("copy", listener);
  };

  document.addEventListener('mousemove', function(event) {
    var element = getElement(event);
    if (!element) return;

    var position = element.getBoundingClientRect();

    Object.assign(overlay.style, {
      background: 'rgba(0, 128, 255, 0.25)',
      outline: '1px solid rgba(0, 128, 255, 0.5)',
      top: '' + position.top + 'px',
      left: '' + position.left + 'px',
      width: '' + position.width + 'px',
      height: '' + position.height + 'px'
    });
  });

  overlay.addEventListener('click', function(event) {
    var element = getElement(event);
    var text = element.textContent || element.value;
    text = text.replace(/\n[ \n]+\n/g, "\n").replace(/\n\n+/g, "\n\n").replace(/^\n+|\n+$/g, '');
    if (!text.match("\n")) text = text.replace(/^ +| +$/, '');

    copyToClip(document, null, text);

    document.body.removeChild(overlay);
  });
}) ()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment