function urlsToAbsolute(nodeList) { if (!nodeList.length) { return []; } var attrName = 'href'; if (nodeList[0].__proto__ === HTMLImageElement.prototype || nodeList[0].__proto__ === HTMLScriptElement.prototype) { attrName = 'src'; } nodeList = [].map.call(nodeList, function(el, i) { var attr = el.getAttribute(attrName); // If no src/href is present, disregard. if (!attr) { return; } var absURL = /^(https?|data):/i.test(attr); if (absURL) { return el; } else { // Set the src/href attribute to an absolute version. if (attr.indexOf('/') != 0) { // src="images/test.jpg" el.setAttribute(attrName, document.location.origin + document.location.pathname + attr); } else if (attr.match(/^\/\//)) { // src="//static.server/test.jpg" el.setAttribute(attrName, document.location.protocol + attr); } else { el.setAttribute(attrName, document.location.origin + attr); } // Set the src/href attribute to an absolute version. Accessing // el['src']/el['href], the browser will stringify an absolute URL, but // we still need to explicitly set the attribute on the duplicate. return el; } }); return nodeList; } function screenshot (el) { urlsToAbsolute(document.images); urlsToAbsolute(document.querySelectorAll("link[rel='stylesheet']")); urlsToAbsolute(document.scripts); var toCapture = (el || document.documentElement).cloneNode(true); var template, blob; // Make screenshot read-only, no scrolling, and no selections. toCapture.style.pointerEvents = 'none'; toCapture.style.overflow = 'hidden'; toCapture.style.userSelect = 'none'; if (el) { var head = document.head.cloneNode(true); // Construct a bare-bones page w/ nothing else on it. // Keep the source element's dimensions. var style = window.getComputedStyle(el); toCapture.style.width = style.width; toCapture.style.height = style.height; template = ['', head.outerHTML, '', toCapture.outerHTML, '' ].join(''); } else { template = toCapture.outerHTML; } blob = new Blob([template], { type: 'text/html' }); window.open(window.URL.createObjectURL(blob)); }