1/* Minification failed. Returning unminified contents. 2(518,26-33): run-time error JS1300: Strict-mode does not allow assignment to undefined variables: exports 3 */ 4// adapted from https://css-tricks.com/snippets/jquery/smooth-scrolling/ 5$(function () { 6 $(document).on("click", 'a[href*="#"]:not([href="#"])', function () { 7 if (location.pathname.replace(/^\//, '') == this.pathname.replace(/^\//, '') && location.hostname == this.hostname) { 8 var target = $(this.hash); 9 target = target.length ? target : $('[name=' + this.hash.slice(1) + ']'); 10 if (target.length) { 11 // see if any elements (e.g headers) are marked with fixedTopElementForAnchorScroll. These elements affect our scroll location 12 // as a naive implementation will end up covering the scroll target with the fixed element 13 var $fixedTopElement = $(".fixedTopElementForAnchorScroll"); 14 var fixedTopElementHeight = $fixedTopElement.outerHeight() || 0; 15 $('html, body').animate({ 16 scrollTop: target.offset().top - fixedTopElementHeight 17 }, 1000); 18 return false; 19 } 20 } 21 }); 22});; 23// Modified by Spotlight 24// - allows us to measure the img element itself, rather than its parent. Useful for when an img is height:100%; width:auto 25// - allows us to delay the init (e.g. until a gallery has move and resizes items around the page) 26; (function (window, document) { 27 'use strict'; 28 29 var addEvent = (function () { 30 if (document.addEventListener) { 31 return function addStandardEventListener(el, eventName, fn) { 32 return el.addEventListener(eventName, fn, false); 33 }; 34 } 35 else { 36 return function addIEEventListener(el, eventName, fn) { 37 return el.attachEvent('on' + eventName, fn); 38 }; 39 } 40 })(); 41 42 var defaultWidths = [96, 130, 165, 200, 235, 270, 304, 340, 375, 410, 445, 485, 520, 555, 590, 625, 660, 695, 736]; 43 44 var getKeys = typeof Object.keys === 'function' ? Object.keys : function (object) { 45 var keys = [], 46 key; 47 48 for (key in object) { 49 keys.push(key); 50 } 51 52 return keys; 53 }; 54 55 var applyEach = function (collection, callbackEach) { 56 var i = 0, 57 length = collection.length, 58 new_collection = []; 59 60 for (; i < length; i++) { 61 new_collection[i] = callbackEach(collection[i], i); 62 } 63 64 return new_collection; 65 }; 66 67 var returnFn = function (value) { return value; }; 68 var noop = function () {}; 69 var trueFn = function () { return true; }; 70 71 var debounce = function (fn, wait) { 72 var timeout; 73 return function () { 74 var context = this, args = arguments; 75 var later = function () { 76 timeout = null; 77 fn.apply(context, args); 78 }; 79 clearTimeout(timeout); 80 timeout = setTimeout(later, wait); 81 }; 82 }; 83 84 85 /* 86 Construct a new Imager instance, passing an optional configuration object. 87 88 Example usage: 89 90 { 91 // Available widths for your images 92 availableWidths: [Number], 93 94 // Selector to be used to locate your div placeholders 95 selector: '', 96 97 // Class name to give your resizable images 98 className: '', 99 100 // If set to true, Imager will update the src attribute of the relevant images 101 onResize: Boolean, 102 103 // Toggle the lazy load functionality on or off 104 lazyload: Boolean, 105 106 // Used alongside the lazyload feature (helps performance by setting a higher delay) 107 scrollDelay: Number 108 } 109 110 @param {object} configuration settings 111 @return {object} instance of Imager 112 */ 113 var Imager = function (elements, opts) { 114 var self = this; 115 var doc = document; 116 117 opts = opts || {}; 118 119 if (elements !== undefined) { 120 121 // selector string (not elements) 122 if (typeof elements === 'string') { 123 opts.selector = elements; 124 elements = undefined; 125 } 126 127 // 'opts' object (not elements) 128 else if (typeof elements.length === 'undefined') { 129 opts = elements; 130 elements = undefined; 131 } 132 } 133
134 this.viewportHeight = doc.documentElement.clientHeight; 135 this.selector = !elements ? (opts.selector || '.delayed-image-load') : null; 136 this.className = opts.className || 'image-replace'; 137 this.gif = doc.createElement('img'); 138 this.gif.src = 'data:image/gif;base64,R0lGODlhEAAJAIAAAP///wAAACH5BAEAAAAALAAAAAAQAAkAAAIKhI+py+0Po5yUFQA7'; 139 this.gif.className = this.className; 140 this.gif.alt = ''; 141 this.lazyloadOffset = opts.lazyloadOffset || 0; 142 this.scrollDelay = opts.scrollDelay || 250; 143 this.onResize = opts.hasOwnProperty('onResize') ? opts.onResize : true; 144 this.lazyload = opts.hasOwnProperty('lazyload') ? opts.lazyload : false; 145 this.scrolled = false; 146 this.availablePixelRatios = opts.availablePixelRatios || [1, 2]; 147 this.availableWidths = opts.availableWidths || defaultWidths; 148 this.onImagesReplaced = opts.onImagesReplaced || noop; 149 this.widthsMap = {}; 150 this.refreshPixelRatio(); 151 this.widthInterpolator = opts.widthInterpolator || returnFn; 152 this.measureParent = opts.measureParent; 153 this.autoStart = opts.autoStart == null ? true : opts.autoStart; 154 155 // Needed as IE8 adds a default `width`/`height` attribute⦠156 this.gif.removeAttribute('height'); 157 this.gif.removeAttribute('width'); 158 159 if (typeof this.availableWidths !== 'function') { 160 if (typeof this.availableWidths.length === 'number') { 161 this.widthsMap = Imager.createWidthsMap(this.availableWidths, this.widthInterpolator, this.devicePixelRatio); 162 } 163 else { 164 this.widthsMap = this.availableWidths; 165 this.availableWidths = getKeys(this.availableWidths); 166 } 167 168 this.availableWidths = this.availableWidths.sort(function (a, b) { 169 return a - b; 170 }); 171 } 172 173 this.divs = []; 174 this.add(elements || this.selector); 175 this.ready(opts.onReady); 176 177 if (this.autoStart) { 178 setTimeout(function () { 179 self.init(); 180 }, 0); 181 } 182 }; 183 184 Imager.prototype.add = function (elementsOrSelector) { 185 186 elementsOrSelector = elementsOrSelector || this.selector; 187 var elements = typeof elementsOrSelector === 'string' ? 188 document.querySelectorAll(elementsOrSelector) : // Selector 189 elementsOrSelector; // Elements (NodeList or array of Nodes) 190 191 if (elements && elements.length) { 192 var additional = applyEach(elements, returnFn); 193 this.changeDivsToEmptyImages(additional); 194 this.divs = this.divs.concat(additional); 195 } 196 }; 197 198 Imager.prototype.scrollCheck = function () { 199 var self = this; 200 var offscreenImageCount = 0; 201 var elements = []; 202 203 if (this.scrolled) { 204 // collects a subset of not-yet-responsive images and not offscreen anymore 205 applyEach(this.divs, function (element) { 206 if (self.isPlaceholder(element)) { 207 ++offscreenImageCount; 208 209 if (self.isThisElementOnScreen(element)) { 210 elements.push(element); 211 } 212 } 213 }); 214 215 if (offscreenImageCount === 0) { 216 window.clearInterval(self.interval); 217 } 218 219 this.changeDivsToEmptyImages(elements); 220 this.scrolled = false; 221 } 222 }; 223 224 Imager.prototype.init = function () { 225 var self = this; 226 227 this.initialized = true; 228 var filterFn = trueFn; 229 230 if (this.lazyload) { 231 this.registerScrollEvent(); 232 233 this.scrolled = true; 234 self.scrollCheck(); 235 236 filterFn = function (element) { 237 return self.isPlaceholder(element) === false; 238 }; 239 } 240 else { 241 this.checkImagesNeedReplacing(this.divs); 242 } 243 244 if (this.onResize) { 245 this.registerResizeEvent(filterFn);
246 } 247 248 this.onReady(); 249 }; 250 251 /** 252 * Executes a function when Imager is ready to work 253 * It acts as a convenient/shortcut for `new Imager({ onReady: fn })` 254 * 255 * @since 0.3.1 256 * @param {Function} fn 257 */ 258 Imager.prototype.ready = function (fn) { 259 this.onReady = fn || noop; 260 }; 261 262 Imager.prototype.createGif = function (element) { 263 // if the element is already a responsive image then we don't replace it again 264 if (element.className.match(new RegExp('(^| )' + this.className + '( |$)'))) { 265 return element; 266 } 267 268 var elementClassName = element.getAttribute('data-class'); 269 var elementWidth = element.getAttribute('data-width'); 270 var gif = this.gif.cloneNode(false); 271 272 if (elementWidth) { 273 gif.width = elementWidth; 274 gif.setAttribute('data-width', elementWidth); 275 } 276 277 gif.className = (elementClassName ? elementClassName + ' ' : '') + this.className; 278 gif.setAttribute('data-src', element.getAttribute('data-src')); 279 gif.setAttribute('alt', element.getAttribute('data-alt') || this.gif.alt); 280 281 element.parentNode.replaceChild(gif, element); 282 283 return gif; 284 }; 285 286 Imager.prototype.changeDivsToEmptyImages = function (elements) { 287 var self = this; 288 289 applyEach(elements, function (element, i) { 290 elements[i] = self.createGif(element); 291 }); 292 293 if (this.initialized) { 294 this.checkImagesNeedReplacing(elements); 295 } 296 }; 297 298 /** 299 * Indicates if an element is an Imager placeholder 300 * 301 * @since 1.3.1 302 * @param {HTMLImageElement} element 303 * @returns {boolean} 304 */ 305 Imager.prototype.isPlaceholder = function (element) { 306 return element.src === this.gif.src; 307 }; 308 309 /** 310 * Returns true if an element is located within a screen offset. 311 * 312 * @param {HTMLElement} element 313 * @returns {boolean} 314 */ 315 Imager.prototype.isThisElementOnScreen = function (element) { 316 // document.body.scrollTop was working in Chrome but didn't work on Firefox, so had to resort to window.pageYOffset 317 // but can't fallback to document.body.scrollTop as that doesn't work in IE with a doctype (?) so have to use document.documentElement.scrollTop 318 var elementOffsetTop = 0; 319 var offset = Imager.getPageOffset() + this.lazyloadOffset; 320 321 if (element.offsetParent) { 322 do { 323 elementOffsetTop += element.offsetTop; 324 } 325 while (element = element.offsetParent); 326 } 327 328 return elementOffsetTop < (this.viewportHeight + offset); 329 }; 330 331 Imager.prototype.checkImagesNeedReplacing = function (images, filterFn) { 332 var self = this; 333 filterFn = filterFn || trueFn; 334 335 if (!this.isResizing) { 336 this.isResizing = true; 337 this.refreshPixelRatio(); 338 339 applyEach(images, function (image) { 340 if (filterFn(image)) { 341 self.replaceImagesBasedOnScreenDimensions(image); 342 } 343 }); 344 345 this.isResizing = false; 346 this.onImagesReplaced(images); 347 } 348 }; 349 350 /** 351 * Upgrades an image from an empty placeholder to a fully sourced image element 352 * 353 * @param {HTMLImageElement} image 354 */ 355 Imager.prototype.replaceImagesBasedOnScreenDimensions = function (image) { 356 var computedWidth, naturalWidth; 357 358 naturalWidth = Imager.getNaturalWidth(image); 359 computedWidth = typeof this.availableWidths === 'function' ? this.availableWidths(image) 360 : this.determineAppropriateResolution(image); 361 362 image.width = computedWidth; 363 364 if (!this.isPlaceholder(image) && computedWidth <= naturalWidth) { 365 return; 366 } 367 368 image.src = this.changeImageSrcToUseNewImageDimensions(image.getAttribute('data-src'), computedWidth); 369 image.removeAttribute('width'); 370 image.removeAttribute('height'); 371 }; 372 373 Imager.prototype.determineAppropriateResolution = function (image) { 374 return Imager.getClosestValue(image.getAttribute('data-width') || (this.measureParent ? image.parentNode.clientWidth : image.clientWidth), this.availableWidths); 375 }; 376 377 /** 378 * Updates the device pixel ratio value used by Imager 379 * 380 * It is performed before each replacement loop, in case a user zoomed in/out 381 * and thus updated the `window.devicePixelRatio` value. 382 * 383 * @api 384 * @since 1.0.1 385 */ 386 Imager.prototype.refreshPixelRatio = function refreshPixelRatio() { 387 this.devicePixelRatio = Imager.getClosestValue(Imager.getPixelRatio(), this.availablePixelRatios); 388 }; 389 390 Imager.prototype.changeImageSrcToUseNewImageDimensions = function (src, selectedWidth) { 391 return src 392 .replace(/{width}/g, Imager.transforms.width(selectedWidth, this.widthsMap)) 393 .replace(/{pixel_ratio}/g, Imager.transforms.pixelRatio(this.devicePixelRatio)); 394 }; 395 396 Imager.getPixelRatio = function getPixelRatio(context) { 397 return (context || window)['devicePixelRatio'] || 1; 398 }; 399 400 Imager.createWidthsMap = function createWidthsMap (widths, interpolator, pixelRatio) { 401 var map = {}, 402 i = widths.length; 403 404 while (i--) { 405 map[widths[i]] = interpolator(widths[i], pixelRatio); 406 } 407 408 return map; 409 }; 410 411 Imager.transforms = { 412 pixelRatio: function (value) { 413 return value === 1 ? '' : '-' + value + 'x'; 414 }, 415 width: function (width, map) { 416 return map[width] || width; 417 } 418 }; 419 420 /** 421 * Returns the closest upper value. 422 * 423 * ```js 424 * var candidates = [1, 1.5, 2]; 425 * 426 * Imager.getClosestValue(0.8, candidates); // -> 1 427 * Imager.getClosestValue(1, candidates); // -> 1 428 * Imager.getClosestValue(1.3, candidates); // -> 1.5 429 * Imager.getClosestValue(3, candidates); // -> 2 430 * ``` 431 * 432 * @api 433 * @since 1.0.1 434 * @param {Number} baseValue 435 * @param {Array.<Number>} candidates 436 * @returns {Number} 437 */ 438 Imager.getClosestValue = function getClosestValue(baseValue, candidates) { 439 var i = candidates.length, 440 selectedWidth = candidates[i - 1]; 441 442 baseValue = parseFloat(baseValue); 443 444 while (i--) { 445 if (baseValue <= candidates[i]) { 446 selectedWidth = candidates[i]; 447 } 448 } 449 450 return selectedWidth; 451 }; 452 453 Imager.prototype.registerResizeEvent = function (filterFn) { 454 var self = this; 455 456 addEvent(window, 'resize', debounce(function () { 457 self.checkImagesNeedReplacing(self.divs, filterFn);
458 }, 100)); 459 }; 460 461 Imager.prototype.registerScrollEvent = function () { 462 var self = this; 463 464 this.scrolled = false; 465 466 this.interval = window.setInterval(function () { 467 self.scrollCheck(); 468 }, self.scrollDelay); 469 470 addEvent(window, 'scroll', function () { 471 self.scrolled = true; 472 }); 473 474 addEvent(window, 'resize', function () { 475 self.viewportHeight = document.documentElement.clientHeight; 476 self.scrolled = true; 477 }); 478 }; 479 480 Imager.getPageOffsetGenerator = function getPageVerticalOffset(testCase) { 481 if (testCase) { 482 return function () { return window.pageYOffset; }; 483 } 484 else { 485 return function () { return document.documentElement.scrollTop; }; 486 } 487 }; 488 489 /** 490 * Returns the naturalWidth of an image element. 491 * 492 * @since 1.3.1 493 * @param {HTMLImageElement} image 494 * @return {Number} Image width in pixels 495 */ 496 Imager.getNaturalWidth = (function () { 497 if ('naturalWidth' in (new Image())) { 498 return function (image) { 499 return image.naturalWidth; 500 }; 501 } 502 // non-HTML5 browsers workaround 503 return function (image) { 504 var imageCopy = document.createElement('img'); 505 imageCopy.src = image.src; 506 return imageCopy.width; 507 }; 508 })(); 509 510 // This form is used because it seems impossible to stub `window.pageYOffset` 511 Imager.getPageOffset = Imager.getPageOffsetGenerator(Object.prototype.hasOwnProperty.call(window, 'pageYOffset')); 512 513 // Exporting for testing and convenience purpose 514 Imager.applyEach = applyEach; 515 Imager.addEvent = addEvent; 516 Imager.debounce = debounce; 517 518 /* global module, exports: true, define */ 519 if (typeof module === 'object' && typeof module.exports === 'object') { 520 // CommonJS, just export 521 module.exports = exports = Imager; 522 } else if (typeof define === 'function' && define.amd) { 523 // AMD support 524 define(function () { return Imager; }); 525 } else if (typeof window === 'object') { 526 // If no AMD and we are in the browser, attach to window 527 window.Imager = Imager; 528 } 529 /* global -module, -exports, -define */ 530 531}(window, document)); 532; 533window.mainImagerInstance = new Imager({ 534 availableWidths: [50, 100, 200, 320, 400, 600, 768, 800, 1024, 1280, 1366, 1600, 2048], 535 widthInterpolator: function(width, pixelRatio) { 536 return width * pixelRatio; 537 }, 538 availablePixelRatios: [1, 1.5, 2], 539 onImagesReplaced: function (images) { 540 $(images).each(function (index, elem) { 541 $(elem).closest(".ubeimage").addClass("ubeimageLoaded"); 542 }); 543 }, 544 measureParent: false 545});; 546var Sunlight = Sunlight || {}; 547 548Sunlight.Utils = Sunlight.Utils || {}; 549 550Sunlight.Utils.isMobile = function () { 551 return window.innerWidth < 768; 552};
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.