1/* Slimmage 0.2.3-bg, use with ImageResizer. MIT/Apache2 dual licensed by Imazen and HiQ Finland */ 2 3(function (w) { //w==window 4 // Enable strict mode 5 "use strict"; 6 7 var s = window.slimmage || {}; 8 /** @expose **/ 9 window.slimmage = s; 10 if (s.verbose === undefined) /** @expose **/ s.verbose = true; 11 if (s.tryWebP === undefined) /** @expose **/ s.tryWebP = false; 12 if (s.readyCallback === undefined) /** @expose **/ s.readyCallback = null; 13 if (s.maxWidth === undefined) /** @expose **/ s.maxWidth = 2048; 14 if (s.widthStep === undefined) /** @expose **/ s.widthStep = 160; 15 if (s.jpegQuality === undefined) /** @expose **/ s.jpegQuality = 90; 16 if (s.jpegRetinaQuality === undefined) /** @expose **/ s.jpegRetinaQuality = 80; 17 18 var log = function () { if (w.slimmage.verbose && w.console && w.console.log) try { w.console.log.apply(w.console, arguments); } catch (e) { } }; 19 s.beginWebPTest = function () { 20 if (!s.tryWebP || s._testingWebP) return; 21 s._testingWebP = true; 22 23 var WebP = new Image(); 24 WebP.onload = WebP.onerror = function () { 25 s.webp = (WebP.height == 2); 26 }; 27 WebP.src = 'data:image/webp;base64,UklGRjoAAABXRUJQVlA4IC4AAACyAgCdASoCAAIALmk0mk0iIiIiIgBoSygABc6WWgAA/veff/0PP8bA//LwYAAA'; 28 }; 29 30 s.getCssValue = function (target, hyphenProp) { 31 var val = typeof (window.getComputedStyle) != "undefined" && window.getComputedStyle(target, null).getPropertyValue(hyphenProp); 32 if (!val && target.currentStyle) { 33 val = target.currentStyle[hyphenProp.replace(/([a-z])\-([a-z])/, function (a, b, c) { return b + c.toUpperCase(); })] || target.currentStyle[hyphenProp]; 34 } 35 return val; 36 }; 37 38 s.getCssPixels = function (target, hyphenProp) { 39 var val = s.getCssValue(target, hyphenProp); 40 41 //We can return pixels directly, but not other units 42 if (val.slice(-2) == "px") return parseFloat(val.slice(0, -2)); 43 44 // Some browsers (IE8, Firefox 28) read "none" when not set. A value of 45 // "none" is invalid and would cause an exception or be interpreted as 0. 46 if (val == "none") val = ""; 47 48 49 //Create a temporary sibling div to resolve units into pixels. 50 var temp = document.createElement("div"); 51 temp.style.overflow = temp.style.visibility = "hidden"; 52 temp.style.clear = "both"; 53 target.parentNode.appendChild(temp); 54 temp.style.width = val; 55 var pixels = temp.offsetWidth; 56 target.parentNode.removeChild(temp); 57 return pixels; 58 }; 59 60 s.nodesToArray = function (nodeList) { 61 var array = []; 62 // iterate backwards ensuring that length is an UInt32 63 for (var i = nodeList.length >>> 0; i--;) { 64 array[i] = nodeList[i]; 65 } 66 return array; 67 }; 68 //Expects virtual, not device pixel width 69 s.getImageSrcWithWidth = function (img, originalSrc, width) { 70 var data = { 71 webp: s.webp, 72 width: width, 73 dpr: window.devicePixelRatio || 1, 74 src: originalSrc 75 } 76 data.requestedWidth = Math.min(s.maxWidth, data.width * data.dpr), //Limit size to maxWidth. 77 data.quality = (data.dpr > 1.49) ? s.jpegRetinaQuality : s.jpegQuality; //Default quality 78 if (data.webp) data.quality = data.dpr > 1.49 ? 65 : 78; 79 80 //Minimize variants for caching improvements; round up to nearest multiple of widthStep 81 data.requestedWidth = data.requestedWidth - (data.requestedWidth % s.widthStep) + s.widthStep; //Will limit to 13 variations 82 83 var oldpixels = img.getAttribute("data-pixel-width") | 0; 84 85 if (s.adjustImageParameters && typeof (s.adjustImageParameters) === "function") { 86 s.adjustImageParameters(data); 87 } 88 89 if (data.requestedWidth > oldpixels) { 90 //Never request a smaller image once the larger one has already started loading 91 var newSrc = originalSrc.replace(/width=\d+/i, "width="
91+ data.requestedWidth).replace(/quality=[0-9]+/i, "quality=" + data.quality); 92 if (data.webp) newSrc = newSrc.replace(/format=[a-z]+/i, "format=webp"); 93 img.setAttribute("data-pixel-width", data.requestedWidth); 94 log("Slimming: updating " + newSrc); 95 return newSrc; 96 } 97 }; 98 s.adjustImageSrc = function (img, originalSrc) { 99 var newSrc = s.getImageSrcWithWidth(img, originalSrc, s.getCssPixels(img, "max-width")); 100 if (newSrc) img.src = newSrc; 101 }; 102 s.adjustBackgroundImage = function (elem, originalSrc) { 103 var newSrc = s.getImageSrcWithWidth(elem, originalSrc, s.getCssPixels(elem, "max-width")); 104 if (newSrc) elem.style.backgroundImage = "url(" + newSrc + ")"; 105 if (!elem.style.backgroundImage) elem.style.backgroundImage = "url(" + originalSrc + ")"; 106 } 107 108 s.checkResponsiveImages = function (delay) { 109 if (s.timeoutid > 0) w.clearTimeout(s.timeoutid); 110 s.timeoutid = 0; 111 if (delay && delay > 0) { 112 s.timeoutid = w.setTimeout(s.checkResponsiveImages, delay); 113 return; 114 } 115 var stopwatch = new Date().getTime(); 116 117 var newImages = 0; 118 //1. Copy images out of noscript tags, but hide 'src' attribute as data-src 119 var n = s.nodesToArray(w.document.getElementsByTagName("noscript")); 120 for (var i = 0, il = n.length; i < il; i++) { 121 var ns = n[i]; 122 if (ns.getAttribute("data-slimmage") !== null) { 123 124 var div = w.document.createElement('div'); 125 var contents = (ns.textContent || ns.innerHTML); 126 if (!contents || contents.replace(/[\s\t\r\n]+/, "").length == 0) { 127 //IE doesn't let us touch noscript, so we have to use attributes. 128 var img = new Image(); 129 for (var ai = 0; ai < ns.attributes.length; ai++) { 130 var a = ns.attributes[ai]; 131 if (a && a.specified && a.name.indexOf("data-img-") == 0) { 132 img.setAttribute(a.name.slice(9 - a.name.length), a.value); 133 } 134 } 135 div.appendChild(img); 136 } else { 137 //noscript isn't part of DOM, so we have to recreate it, unescaping html, src->data-src 138 div.innerHTML = contents.replace(/\s+src\s*=\s*(['"])/i, " data-src=$1"). 139 replace(/</g, '<').replace(/>/g, '>').replace(/&/g, '&'); 140 } 141 //Clear source values before we add it back to the dom, ensure data-slimmage is set. 142 var childImages = div.getElementsByTagName("img"); 143 for (var j = 0, jl = childImages.length; j < jl; j++) { 144 var ci = childImages[j]; 145 if (ci.src !== null && ci.src.length > 0) { 146 ci.setAttribute("data-src", ci.src); 147 ci.src = ""; 148 } 149 ci.setAttribute("data-slimmage", true); 150 ns.parentNode.insertBefore(ci, ns); 151 newImages++; 152 } 153 //2. Remove old noscript tags 154 ns.parentNode.removeChild(ns); 155 } 156 } 157 158 //3. Find images with data-slimmage and run adjustImageSrc. 159 var totalImages = 0; 160 var images = s.nodesToArray(w.document.getElementsByTagName("img")); 161 for (var i = 0, il = images.length; i < il; i++) { 162 if (images[i].getAttribute("data-slimmage") !== null) { 163 var originalSrc = images[i].getAttribute("data-src") || images[i].src; 164 s.adjustImageSrc(images[i], originalSrc); 165 totalImages++; 166 } 167 } 168 169 //4. Find elements with data-slimmage-bg and set CSS background-image 170 if (w.document.querySelectorAll) { 171 var bgImages = s.nodesToArray(w.document.querySelectorAll("[data-slimmage-bg]")) 172 for (var i = 0, il = bgImages.length; i < il; i++) { 173 var originalBg = bgImages[i].getAttribute("data-slimmage-bg"); 174 if (originalBg !== null) {
175 s.adjustBackgroundImage(bgImages[i], originalBg); 176 totalImages++; 177 } 178 } 179 } 180 181 //5. Callback when ready 182 if (typeof s.readyCallback === 'function') { 183 s.readyCallback(); 184 } 185 186 log("Slimmage: restored " + newImages + " images from noscript tags; sizing " + totalImages + " images. " + (new Date().getTime() - stopwatch) + "ms"); 187 }; 188 189 var h = s.checkResponsiveImages; 190 // Run on resize and domready (w.load as a fallback) 191 if (w.addEventListener) { 192 w.addEventListener("resize", function () { h(500); }, false); 193 w.addEventListener("DOMContentLoaded", function () { 194 h(); 195 // Run once only 196 w.removeEventListener("load", h, false); 197 }, false); 198 w.addEventListener("load", h, false); 199 } else if (w.attachEvent) { 200 w.attachEvent("onload", h); 201 } 202 //test for webp support 203 s.beginWebPTest(); 204}(this));
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.