(function(w) { "use strict"; var uncode = 'uncodeAI', path = ';path=', doc = document, winWidth = w.innerWidth, screenWidth = screen.width, screenHeight = screen.height, cookies = {}, cssBreakpoint, cookieRecorded = false, looped = false, cookiesEnable = navigator.cookieEnabled; /** * Extract the uncode cookie values * * @return {Object} uncode cookie values */ var getuncodeCookies = function() { for (var index = 0, cookieParts = doc.cookie.split(';'), cookiePattern = /^\suncodeAI\.([^=]+)=(.*?)\s*$/, cookies = {}, cookie; index < cookieParts.length; ++index) { if (cookie = cookieParts[index].match(cookiePattern)) { cookies[cookie[1]] = cookie[2]; } } return cookies; } /** * Measure the window width in em * * @return {Number} Window width in em */ var measureWindowEmWidth = function(precision, f) { precision = Math.max(parseFloat(precision || 1, 10), .01); var docElement = doc.documentElement, createBlock = function() { var block = doc.createElement('div'), blockStyles = { 'width': '1px', 'height': '1px', 'display': 'inline-block' }; for (var property in blockStyles) { block.style[property] = blockStyles[property]; } return block; }, blockRow = doc.createElement('div'), block = blockRow.appendChild(createBlock()); blockRow.appendChild(createBlock()); docElement.appendChild(blockRow); var blockHeight = blockRow.clientHeight, ems = Math.floor(winWidth / blockHeight), delta = ems / 2, iteration = 0, iterations = [ems]; // Iteratetively resize the measurement block until the breakpoint is found (taking the given precision into account) while ((iteration++ < 1000) && ((Math.abs(delta) > precision) || (blockRow.clientHeight > blockHeight))) { ems += delta; block.style.width = ems + 'em'; delta /= ((blockRow.clientHeight > blockHeight) ? 1 : -1) * ((delta > 0) ? -2 : 2); iterations.push(ems); } // Remove the measurement elements docElement.removeChild(blockRow); return ems; } /** * Extract the image breakpoints * * @param {String} str Serialized breakpoints list * @return {Array} Ordered breakpoints list */ var getBreakpoints = function(str, emf) { // Split the breakpoint list and run through all breakpoints for (var index = 0, rawBreakpoints = (str || '').split(','), breakpointPattern = /(\d+(?:\.\d+)?)(px)?/i, breakpoints = [], match; index < rawBreakpoints.length; ++index) { // If this is a valid breakpoint definition (may have a "px" unit) if (match = rawBreakpoints[index].match(breakpointPattern)) { breakpoints.push(parseFloat(match[1], 10)); } } // Sort the breakpoints in ascending order return breakpoints.sort(function(a, b) { return a - b; }); } /** * Return the device pixel ratio * * @return {Number} Device pixel ratio */ var getDevicePixelRatio = function() { var ratio = ('devicePixelRatio' in w) ? w.devicePixelRatio : ((('deviceXDPI' in w) && ('logicalXDPI' in w)) ? (w.deviceXDPI / w.logicalXDPI) : 1); return ratio; } /** * Round a floating point value to a certain precision * * @param {Number} Floating point value * @param {Number} Precision * @param {Number} Rounded floating point value */ var roundToPrecision = function(em, precision) { return precision * Math.round(10 * em / precision) / 10; } if (cookiesEnable) cookies = getuncodeCookies(); if (cookies.images !== undefined) cookieRecorded = true; // Run through all document JavaScripts and find the uncode script (must reference a script file with ID attribute = "uncodeAI") for (var index = 0, scripts = doc.getElementsByTagName('script'); index < scripts.length; ++index) { if (scripts[index].id == uncode) { var pixelRatio = getDevicePixelRatio(); var imgBreakpoint = '2880'; var limitDensity = scripts[index].getAttribute('data-limit-density'); var secureFlag = location.protocol === 'https:' ? ';secure' : ''; pixelRatio = limitDensity && pixelRatio > 2 ? 2 : pixelRatio; path = path + scripts[index].getAttribute('data-home'); if (scripts[index].getAttribute('data-async') == 'true') cookiesEnable = false; // Set the general screen size cookie if (cookiesEnable) doc.cookie = uncode + '.screen=' + screenWidth + path + secureFlag; // + 'x' + screenHeight + '@' + pixelRatio + path; w.uncodeScreen = screenWidth; // Set the image engine cookie (if enabled) if (!scripts[index].getAttribute('data-disable-images')) { var breakpoints = getBreakpoints(scripts[index].getAttribute('data-breakpoints-images')); var useOrientationWidth = scripts[index].getAttribute('data-use-orientation-width'); var maximum = useOrientationWidth ? screenWidth : Math.max(screenWidth, screenHeight); var nextBreakpoint = null; maximum = pixelRatio > 1 ? (maximum * pixelRatio) : maximum; do { if (maximum > (nextBreakpoint = breakpoints.pop())) { break; } imgBreakpoint = nextBreakpoint; } while (breakpoints.length); } if (cookiesEnable) { doc.cookie = uncode + '.images=' + imgBreakpoint + path + secureFlag; } w.uncodeImages = imgBreakpoint; // Determine the uncode cookie values if (cookiesEnable) { cookies = getuncodeCookies(); cssBreakpoint = cookies.css || '-'; if ((!('css' in cookies) || !cookies.css || (cookies.css == '-')) && !scripts[index].getAttribute('data-disable-css')) { var emRatio = winWidth / measureWindowEmWidth(parseFloat(scripts[index].getAttribute('data-em-precision') || .5, 10) / 100); cssBreakpoint = screenWidth + 'x' + screenHeight + '@' + (Math.round(emRatio * 10) / 10); } doc.cookie = uncode + '.css=' + cssBreakpoint + path + secureFlag; } break; } } })(this);