Skip to content

Instantly share code, notes, and snippets.

@panzi
Last active January 14, 2020 02:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save panzi/ada827827a01fb61fe562e10111cdb61 to your computer and use it in GitHub Desktop.
Save panzi/ada827827a01fb61fe562e10111cdb61 to your computer and use it in GitHub Desktop.
Open clicked medium (image, video, audio, svg, ...) in a new tab. This handles transparent elements covering images or images via CSS background-image.
javascript:void(!function(){function e(e){for(var t=null,n=null,r=null,l=0;l<e.length;++l){var i=e[l].srcset;if(i){i=i.split(",");for(var a=0;a<i.length;++a){var o=i[a].trim().split(/\s+/g),u=o[1];if(u){var c=/^(\d+(?:\.\d*)?)([a-z])$/i.exec(u),s=c[2],d=+c[1];(s!==t||d>n)&&(t=s,n=d,r=o[0])}else r||(r=o[0],n=t=null)}}}return r?{url:r}:null}function t(t){switch(t.tagName.toUpperCase()){case"IMG":return e([t])||(t.currentSrc?{url:t.currentSrc}:t.src?{url:t.src}:null);case"CANVAS":return{url:t.toDataURL(),html:'<img src="'+t.toDataURL()+'"/>'};case"VIDEO":case"AUDIO":return t.currentSrc?{url:t.currentSrc}:null;case"SVG":var n=t.outerHTML.replace(/^<svg\b/i,e=>e+' xmlns="http://www.w3.org/2000/svg"');return{html:n,url:"data:image/svg+xml,"+encodeURIComponent(n)};case"IFRAME":if(t.src&&"about:blank"!==t.src)return{url:t.src};case"PICTURE":return e(t.querySelectorAll("source"));case"IMAGE":if("http://www.w3.org/2000/svg"===t.namespaceURI)return{url:t.href.baseVal};default:var r=getComputedStyle(t,null).backgroundImage;if(r&&/^url\(.*\)$/i.test(r))return{url:r.replace(/^url\("?([^"]*)"?\)$/i,(e,t)=>t)}}return null}var n={STYLE:!0,SCRIPT:!0,NOSCRIPT:!0,BR:!0,HR:!0,META:!0,TITLE:!0,LINK:!0,HEAD:!0,SOURCE:!0};window.addEventListener("click",function e(r){r.stopPropagation(),r.preventDefault(),window.removeEventListener("click",e,!0);var l,i=function e(r,l,i,a,o){for(var u,c,s=r.firstChild,d=o;s;){if(1===s.nodeType){var m=s.tagName.toUpperCase();if(!n.hasOwnProperty(m)){var p=getComputedStyle(s,null);if("visible"===p.visibility&&"none"!==p.display&&+p.opacity>0){var f=d,v=p.position,w=a||"fixed"===v||"sticky"===v;"static"!==v&&"initial"!==v&&(f=null);var g=e(s,l,i,w,f),I=s.getBoundingClientRect(),h=s===document.body||s===document.documentElement||I.left<=l&&I.top<=i&&I.left+I.width>=l&&I.top+I.height>=i;if(g&&(h||g.inFixed||"visible"===p.overflow))d=g;else if(h&&(!d||(u=d.style,c=p,!("static"!==u.position&&"auto"!==u.zIndex?"static"===c.position||"auto"===c.zIndex||+u.zIndex>+c.zIndex:"static"!==c.position&&"auto"!==c.zIndex)))){var b=t(s);b&&(d={element:s,style:p,medium:b,inFixed:w})}}}}s=s.nextSibling}return d}(document.documentElement,r.clientX,r.clientY,!1,null);if(l=i?i.medium:t(document.body)||t(document.documentElement))if(!l.html||l.url&&!window.chrome)window.open(l.url,"_blank");else{var a=window.open("","_blank");a.document.write(l.html),l.url&&a.document.write('<p><a href="'+l.url+'" accesskey="s" style="-webkit-appearance:button;appearance:button;color:initial;padding:0.5em;text-decoration:none;" download>Save…</a></p>'),a.document.close()}else alert("No medium found.")},!0)}())
@panzi
Copy link
Author

panzi commented Oct 28, 2017

Google Chrome: SVG and Canvas support isn't that good. It opens the image a new tab alright, but you need to use my provided save-button for saving. Ctrl+S does not work for that. This is because you can't open a data-URL via window.open() in Chrome and so I open a blank page and write some HTML to it that displays the image and a save-button.

@panzi
Copy link
Author

panzi commented Dec 10, 2017

Update: I found websites that set pointer-events: none on images which means that document.elementFromPoint() doesn't work. Therefore I wrote some JavaScript logic that traverses the whole DOM tree evaluating things like the bounding client rect, and styles like overflow, position, z-index, display, visibility, and opacity manually (while ignoring pointer-events). It works on the pages I tried it, but there is the chance my ad-hoc JavaScript might not evaluate everything correctly per specification.

@panzi
Copy link
Author

panzi commented Feb 10, 2018

Update: Handle <img srcset="..."> and <picture> elements (with <source srcset="..."> children). I don't evaluate media selectors or do anything complex. I mainly just guess what source to use.

@panzi
Copy link
Author

panzi commented Nov 11, 2019

Update: Handle SVG <image href="..."> elements.

@panzi
Copy link
Author

panzi commented Jan 9, 2020

Update: Prefer parsing of img.srcset and picking the biggest image over using img.currentSrc and img.src.

@panzi
Copy link
Author

panzi commented Jan 14, 2020

Update: Always assume hit body and documentElement, because sometimes somehow hit test on that fails.

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