-
-
Save panzi/ada827827a01fb61fe562e10111cdb61 to your computer and use it in GitHub Desktop.
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)}()) |
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.
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.
Update: Handle SVG <image href="...">
elements.
Update: Prefer parsing of img.srcset
and picking the biggest image over using img.currentSrc
and img.src
.
Update: Always assume hit body and documentElement, because sometimes somehow hit test on that fails.
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.