1/******************************************************************************* 2 * Copyright 2017 Adobe 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 ******************************************************************************/ 16if (window.Element && !Element.prototype.closest) { 17 // eslint valid-jsdoc: "off" 18 Element.prototype.closest = 19 function(s) { 20 "use strict"; 21 var matches = (this.document || this.ownerDocument).querySelectorAll(s); 22 var el = this; 23 var i; 24 do { 25 i = matches.length; 26 while (--i >= 0 && matches.item(i) !== el) { 27 // continue 28 } 29 } while ((i < 0) && (el = el.parentElement)); 30 return el; 31 }; 32} 33 34if (window.Element && !Element.prototype.matches) { 35 Element.prototype.matches = 36 Element.prototype.matchesSelector || 37 Element.prototype.mozMatchesSelector || 38 Element.prototype.msMatchesSelector || 39 Element.prototype.oMatchesSelector || 40 Element.prototype.webkitMatchesSelector || 41 function(s) { 42 "use strict"; 43 var matches = (this.document || this.ownerDocument).querySelectorAll(s); 44 var i = matches.length; 45 while (--i >= 0 && matches.item(i) !== this) { 46 // continue 47 } 48 return i > -1; 49 }; 50} 51 52if (!Object.assign) { 53 Object.assign = function(target, varArgs) { // .length of function is 2 54 "use strict"; 55 if (target === null) { 56 throw new TypeError("Cannot convert undefined or null to object"); 57 } 58 59 var to = Object(target); 60 61 for (var index = 1; index < arguments.length; index++) { 62 var nextSource = arguments[index]; 63 64 if (nextSource !== null) { 65 for (var nextKey in nextSource) { 66 if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) { 67 to[nextKey] = nextSource[nextKey]; 68 } 69 } 70 } 71 } 72 return to; 73 }; 74} 75 76(function(arr) { 77 "use strict"; 78 arr.forEach(function(item) { 79 if (Object.prototype.hasOwnProperty.call(item, "remove")) { 80 return; 81 } 82 Object.defineProperty(item, "remove", { 83 configurable: true, 84 enumerable: true, 85 writable: true, 86 value: function remove() { 87 this.parentNode.removeChild(this); 88 } 89 }); 90 }); 91})([Element.prototype, CharacterData.prototype, DocumentType.prototype]); 92 93/******************************************************************************* 94 * Copyright 2022 Adobe 95 * 96 * Licensed under the Apache License, Version 2.0 (the "License"); 97 * you may not use this file except in compliance with the License. 98 * You may obtain a copy of the License at 99 * 100 * http://www.apache.org/licenses/LICENSE-2.0 101 * 102 * Unless required by applicable law or agreed to in writing, software 103 * distributed under the License is distributed on an "AS IS" BASIS, 104 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 105 * See the License for the specific language governing permissions and 106 * limitations under the License. 107 ******************************************************************************/ 108(function(document) { 109 "use strict"; 110 111 window.CMP = window.CMP || {}; 112 window.CMP.utils = (function() { 113 var NS = "cmp"; 114 115 /** 116 * Reads options data from the Component wrapper element, defined via {@code data-cmp-*} data attributes 117 * 118 * @param {HTMLElement} element The component element to read options data from 119 * @param {String} is The component identifier 120 * @returns {String[]} The options read from the component data attributes 121 */ 122 var readData = function(element, is) { 123 var data = element.dataset; 124 var options = []; 125 var capitalized = is; 126 capitalized = capitalized.charAt(0).toUpperCase() + capitalized.slice(1); 127 var reserved = ["is", "hook" + capitalized]; 128 129 for (var key in data) { 130 if (Object.prototype.hasOwnProperty.call(data, key)) { 131 var value = data[key]; 132 133 if (key.indexOf(NS) === 0) { 134 key = key.slice(NS.length); 135 key = key.charAt(0).toLowerCase() + key.substring(1); 136 137 if (reserved.indexOf(key) === -1) { 138 options[key] = value; 139 } 140 } 141 } 142 } 143 return options; 144 }; 145 146 /** 147 * Set up the final properties of a component by evaluating the transform function or fall back to the default value on demand 148 * @param {String[]} options the options to transform 149 * @param {Object} properties object of properties of property functions 150 * @returns {Object} transformed properties 151 */ 152 var setupProperties = function(options, properties) { 153 var transformedProperties = {}; 154 155 for (var key in properties) { 156 if (Object.prototype.hasOwnProperty.call(properties, key)) { 157 var property = properties[key]; 158 if (options && options[key] != null) { 159 if (property && typeof property.transform === "function") { 160 transformedProperties[key] = property.transform(options[key]); 161 } else { 162 transformedProperties[key] = options[key]; 163 } 164 } else { 165 transformedProperties[key] = properties[key]["default"]; 166 } 167 } 168 } 169 return transformedProperties; 170 }; 171 172 173 return { 174 readData: readData, 175 setupProperties: setupProperties 176 }; 177 }()); 178}(window.document)); 179 180/******************************************************************************* 181 * Copyright 2022 Adobe 182 * 183 * Licensed under the Apache License, Version 2.0 (the "License");
184 * you may not use this file except in compliance with the License. 185 * You may obtain a copy of the License at 186 * 187 * http://www.apache.org/licenses/LICENSE-2.0 188 * 189 * Unless required by applicable law or agreed to in writing, software 190 * distributed under the License is distributed on an "AS IS" BASIS, 191 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 192 * See the License for the specific language governing permissions and 193 * limitations under the License. 194 ******************************************************************************/ 195(function(document) { 196 "use strict"; 197 198 window.CMP = window.CMP || {}; 199 window.CMP.image = window.CMP.image || {}; 200 window.CMP.image.dynamicMedia = (function() { 201 var autoSmartCrops = {}; 202 var SRC_URI_TEMPLATE_WIDTH_VAR = "{.width}"; 203 var SRC_URI_TEMPLATE_DPR_VAR = "{dpr}"; 204 var SRC_URI_DPR_OFF = "dpr=off"; 205 var SRC_URI_DPR_ON = "dpr=on,{dpr}"; 206 var dpr = window.devicePixelRatio || 1; 207 var config = { 208 minWidth: 20 209 }; 210 211 /** 212 * get auto smart crops from dm 213 * @param {String} src the src uri 214 * @returns {{}} the smart crop json object 215 */ 216 var getAutoSmartCrops = function(src) { 217 var request = new XMLHttpRequest(); 218 var url = src.split(SRC_URI_TEMPLATE_WIDTH_VAR)[0] + "?req=set,json"; 219 request.open("GET", url, false); 220 request.onload = function() { 221 if (request.status >= 200 && request.status < 400) { 222 // success status 223 var responseText = request.responseText; 224 var rePayload = new RegExp(/^(?:\/\*jsonp\*\/)?\s*([^()]+)\(([\s\S]+),\s*"[0-9]*"\);?$/gmi); 225 var rePayloadJSON = new RegExp(/^{[\s\S]*}$/gmi); 226 var resPayload = rePayload.exec(responseText); 227 var payload; 228 if (resPayload) { 229 var payloadStr = resPayload[2]; 230 if (rePayloadJSON.test(payloadStr)) { 231 payload = JSON.parse(payloadStr); 232 } 233 234 } 235 // check "relation" - only in case of smartcrop preset 236 if (payload && payload.set.relation && payload.set.relation.length > 0) { 237 for (var i = 0; i < payload.set.relation.length; i++) { 238 autoSmartCrops[parseInt(payload.set.relation[i].userdata.SmartCropWidth)] = 239 ":" + payload.set.relation[i].userdata.SmartCropDef; 240 } 241 } 242 } else { 243 // error status 244 } 245 }; 246 request.send(); 247 return autoSmartCrops; 248 }; 249 250 /** 251 * Build and return the srcset value based on the available auto smart crops 252 * @param {String} src the src uri 253 * @param {Object} smartCrops the smart crops object 254 * @returns {String} the srcset 255 */ 256 var getSrcSet = function(src, smartCrops) { 257 var srcset; 258 var keys = Object.keys(smartCrops); 259 if (keys.length > 0) { 260 srcset = []; 261 for (var key in autoSmartCrops) { 262 srcset.push(src.replace(SRC_URI_TEMPLATE_WIDTH_VAR, smartCrops[key]) + " " + key + "w"); 263 } 264 } 265 return srcset.join(","); 266 }; 267 268 /** 269 * Get the optimal width based on the available sizes 270 * @param {[Number]} sizes the available sizes 271 * @param {Number} width the element width 272 * @returns {String} the optimal width 273 */ 274 function getOptimalWidth(sizes, width) { 275 var len = sizes.length; 276 var key = 0; 277 278 while ((key < len - 1) && (sizes[key] < width)) { 279 key++; 280 } 281 282 return sizes[key] !== undefined ? sizes[key].toString() : width; 283 } 284 285 /** 286 * Get the width of an element or parent element if the width is smaller than the minimum width 287 * @param {HTMLElement} component the image component 288 * @param {HTMLElement | Node} parent the parent element 289 * @returns {Number} the width of the element 290 */ 291 var getWidth = function(component, parent) { 292 var width = component.offsetWidth; 293 while (width < config.minWidth && parent && !component._autoWidth) { 294 width = parent.offsetWidth; 295 parent = parent.parentNode; 296 } 297 return width; 298 }; 299 300 /** 301 * Set the src and srcset attribute for a Dynamic Media Image which auto smart crops enabled. 302 * @param {HTMLElement} component the image component 303 * @param {{}} properties the component properties 304 */ 305 var setDMAttributes = function(component, properties) { 306 // for v3 we first have to turn the dpr on
307 var src = properties.src.replace(SRC_URI_DPR_OFF, SRC_URI_DPR_ON); 308 src = src.replace(SRC_URI_TEMPLATE_DPR_VAR, dpr); 309 var smartCrops = {}; 310 var width; 311 if (properties["smartcroprendition"] === "SmartCrop:Auto") { 312 smartCrops = getAutoSmartCrops(src); 313 } 314 var hasWidths = (properties.widths && properties.widths.length > 0) || Object.keys(smartCrops).length > 0; 315 if (hasWidths) { 316 var image = component.querySelector("img"); 317 var elemWidth = getWidth(component, component.parentNode); 318 if (properties["smartcroprendition"] === "SmartCrop:Auto") { 319 image.setAttribute("srcset", CMP.image.dynamicMedia.getSrcSet(src, smartCrops)); 320 width = getOptimalWidth(Object.keys(smartCrops, elemWidth)); 321 image.setAttribute("src", CMP.image.dynamicMedia.getSrc(src, smartCrops[width])); 322 } else { 323 width = getOptimalWidth(properties.widths, elemWidth); 324 image.setAttribute("src", CMP.image.dynamicMedia.getSrc(src, width)); 325 } 326 } 327 }; 328 329 /** 330 * Get the src attribute based on the optimal width 331 * @param {String} src the src uri 332 * @param {String} width the element width 333 * @returns {String} the final src attribute 334 */ 335 var getSrc = function(src, width) { 336 if (src.indexOf(SRC_URI_TEMPLATE_WIDTH_VAR) > -1) { 337 src = src.replace(SRC_URI_TEMPLATE_WIDTH_VAR, width); 338 } 339 return src; 340 }; 341 342 343 return { 344 getAutoSmartCrops: getAutoSmartCrops, 345 getSrcSet: getSrcSet, 346 getSrc: getSrc, 347 setDMAttributes: setDMAttributes, 348 getWidth: getWidth 349 }; 350 }()); 351 document.dispatchEvent(new CustomEvent("core.wcm.components.commons.site.image.dynamic-media.loaded")); 352}(window.document)); 353 354/******************************************************************************* 355 * Copyright 2016 Adobe 356 * 357 * Licensed under the Apache License, Version 2.0 (the "License"); 358 * you may not use this file except in compliance with the License. 359 * You may obtain a copy of the License at 360 * 361 * http://www.apache.org/licenses/LICENSE-2.0 362 * 363 * Unless required by applicable law or agreed to in writing, software 364 * distributed under the License is distributed on an "AS IS" BASIS, 365 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 366 * See the License for the specific language governing permissions and 367 * limitations under the License. 368 ******************************************************************************/ 369(function() { 370 "use strict"; 371 372 var NS = "cmp"; 373 var IS = "image"; 374 375 var EMPTY_PIXEL = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"; 376 var LAZY_THRESHOLD_DEFAULT = 0; 377 var SRC_URI_TEMPLATE_WIDTH_VAR = "{.width}"; 378 var SRC_URI_TEMPLATE_WIDTH_VAR_ASSET_DELIVERY = "width={width}"; 379 var SRC_URI_TEMPLATE_DPR_VAR = "{dpr}"; 380 381 var selectors = { 382 self: "[data-" + NS + '-is="' + IS + '"]', 383 image: '[data-cmp-hook-image="image"]', 384 map: '[data-cmp-hook-image="map"]', 385 area: '[data-cmp-hook-image="area"]' 386 }; 387 388 var lazyLoader = { 389 "cssClass": "cmp-image__image--is-loading", 390 "style": { 391 "height": 0, 392 "padding-bottom": "" // will be replaced with % ratio 393 } 394 }; 395 396 var properties = { 397 /** 398 * An array of alternative image widths (in pixels). 399 * Used to replace a {.width} variable in the src property with an optimal width if a URI template is provided. 400 * 401 * @memberof Image 402 * @type {Number[]} 403 * @default [] 404 */ 405 "widths": { 406 "default": [], 407 "transform": function(value) { 408 var widths = []; 409 value.split(",").forEach(function(item) { 410 item = parseFloat(item); 411 if (!isNaN(item)) { 412 widths.push(item); 413 } 414 }); 415 return widths; 416 } 417 }, 418 /** 419 * Indicates whether the image should be rendered lazily. 420 * 421 * @memberof Image 422 * @type {Boolean} 423 * @default false 424 */ 425 "lazy": { 426 "default": false, 427 "transform": function(value) { 428 return !(value === null || typeof value === "undefined"); 429 } 430 }, 431 /** 432 * Indicates image is DynamicMedia image. 433 * 434 * @memberof Image 435 * @type {Boolean} 436 * @default false 437 */ 438 "dmimage": { 439 "default": false, 440 "transform": function(value) { 441 return !(value === null || typeof value === "undefined"); 442 } 443 }, 444 /** 445 * The lazy threshold. 446 * This is the number of pixels, in advance of becoming visible, when an lazy-loading image should begin 447 * to load. 448 * 449 * @memberof Image 450 * @type {Number} 451 * @default 0 452 */ 453 "lazythreshold": { 454 "default": 0, 455 "transform": function(value) { 456 var val = parseInt(value); 457 if (isNaN(val)) { 458 return LAZY_THRESHOLD_DEFAULT; 459 } 460 return val; 461 } 462 }, 463 /** 464 * The image source. 465 * 466 * Can be a simple image source, or a URI template representation that 467 * can be variable expanded - useful for building an image configuration with an alternative width. 468 * e.g. '/path/image.coreimg{.width}.jpeg/1506620954214.jpeg' 469 * 470 * @memberof Image 471 * @type {String} 472 */ 473 "src": { 474 "transform": function(value) { 475 return decodeURIComponent(value); 476 } 477 } 478 }; 479 480 var devicePixelRatio = window.devicePixelRatio || 1; 481 482 function Image(config) { 483 var that = this; 484 485 var smartCrops = {}; 486 487 var useAssetDelivery = false;
488 var srcUriTemplateWidthVar = SRC_URI_TEMPLATE_WIDTH_VAR; 489 490 function init(config) { 491 // prevents multiple initialization 492 config.element.removeAttribute("data-" + NS + "-is"); 493 494 // check if asset delivery is used 495 if (config.options.src && config.options.src.indexOf(SRC_URI_TEMPLATE_WIDTH_VAR_ASSET_DELIVERY) >= 0) { 496 useAssetDelivery = true; 497 srcUriTemplateWidthVar = SRC_URI_TEMPLATE_WIDTH_VAR_ASSET_DELIVERY; 498 } 499 500 that._properties = CMP.utils.setupProperties(config.options, properties); 501 cacheElements(config.element); 502 // check image is DM asset; if true try to make req=set 503 if (config.options.src && Object.prototype.hasOwnProperty.call(config.options, "dmimage") && (config.options["smartcroprendition"] === "SmartCrop:Auto")) { 504 smartCrops = CMP.image.dynamicMedia.getAutoSmartCrops(config.options.src); 505 } 506 507 if (!that._elements.noscript) { 508 return; 509 } 510 511 that._elements.container = that._elements.link ? that._elements.link : that._elements.self; 512 513 unwrapNoScript(); 514 515 if (that._properties.lazy) { 516 addLazyLoader(); 517 } 518 519 if (that._elements.map) { 520 that._elements.image.addEventListener("load", onLoad); 521 } 522 523 window.addEventListener("resize", onWindowResize); 524 ["focus", "click", "load", "transitionend", "animationend", "scroll"].forEach(function(name) { 525 document.addEventListener(name, that.update); 526 }); 527 528 that._elements.image.addEventListener("cmp-image-redraw", that.update); 529 530 that._interSectionObserver = new IntersectionObserver(function(entries, interSectionObserver) { 531 entries.forEach(function(entry) { 532 if (entry.intersectionRatio > 0) { 533 that.update(); 534 } 535 }); 536 }); 537 that._interSectionObserver.observe(that._elements.self); 538 539 that.update(); 540 } 541 542 function loadImage() { 543 var hasWidths = (that._properties.widths && that._properties.widths.length > 0) || Object.keys(smartCrops).length > 0; 544 var replacement; 545 if (Object.keys(smartCrops).length > 0) { 546 var optimalWidth = getOptimalWidth(Object.keys(smartCrops), false); 547 replacement = smartCrops[optimalWidth]; 548 } else { 549 replacement = hasWidths ? (that._properties.dmimage ? "" : ".") + getOptimalWidth(that._properties.widths, true) : ""; 550 } 551 if (useAssetDelivery) { 552 replacement = replacement !== "" ? ("width=" + replacement.substring(1)) : ""; 553 } 554 var url = that._properties.src.replace(srcUriTemplateWidthVar, replacement); 555 url = url.replace(SRC_URI_TEMPLATE_DPR_VAR, devicePixelRatio); 556 557 var imgSrcAttribute = that._elements.image.getAttribute("src"); 558 559 if (url !== imgSrcAttribute) { 560 if (imgSrcAttribute === null || imgSrcAttribute === EMPTY_PIXEL) { 561 that._elements.image.setAttribute("src", url); 562 } else { 563 var urlTemplateParts = that._properties.src.split(srcUriTemplateWidthVar); 564 // check if image src was dynamically swapped meanwhile (e.g. by Target) 565 var isImageRefSame = imgSrcAttribute.startsWith(urlTemplateParts[0]); 566 if (isImageRefSame && urlTemplateParts.length > 1) { 567 isImageRefSame = imgSrcAttribute.endsWith(urlTemplateParts[urlTemplateParts.length - 1]); 568 } 569 if (isImageRefSame) { 570 that._elements.image.setAttribute("src", url); 571 if (!hasWidths) { 572 window.removeEventListener("scroll", that.update); 573 } 574 } 575 } 576 } 577 if (that._lazyLoaderShowing) { 578 that._elements.image.addEventListener("load", removeLazyLoader); 579 } 580 that._interSectionObserver.unobserve(that._elements.self); 581 } 582 583 function getOptimalWidth(widths, useDevicePixelRatio) { 584 var container = that._elements.self; 585 var containerWidth = container.clientWidth; 586 while (containerWidth === 0 && container.parentNode) { 587 container = container.parentNode; 588 containerWidth = container.clientWidth; 589 } 590 591 var dpr = useDevicePixelRatio ? devicePixelRatio : 1; 592 var optimalWidth = containerWidth * dpr; 593 var len = widths.length; 594 var key = 0; 595 596 while ((key < len - 1) && (widths[key] < optimalWidth)) { 597 key++; 598 } 599 600 return widths[key].toString(); 601 } 602 603 function addLazyLoader() { 604 var width = that._elements.image.getAttribute("width"); 605 var height = that._elements.image.getAttribute("height"); 606 607 if (width && height) { 608 var ratio = (height / width) * 100; 609 var styles = lazyLoader.style; 610 611 styles["padding-bottom"] = ratio + "%"; 612 613 for (var s in styles) { 614 if (Object.prototype.hasOwnProperty.call(styles, s)) { 615 that._elements.image.style[s] = styles[s]; 616 } 617 } 618 } 619 that._elements.image.setAttribute("src", EMPTY_PIXEL); 620 that._elements.image.classList.add(lazyLoader.cssClass); 621 that._lazyLoaderShowing = true; 622 } 623 624 function unwrapNoScript() { 625 var markup = decodeNoscript(that._elements.noscript.textContent.trim()); 626 var parser = new DOMParser(); 627 628 // temporary document avoids requesting the image before removing its src 629 var temporaryDocument = parser.parseFromString(markup, "text/html"); 630 var imageElement = temporaryDocument.querySelector(selectors.image); 631 imageElement.removeAttribute("src"); 632 that._elements.container.insertBefore(imageElement, that._elements.noscript); 633 634 var mapElement = temporaryDocument.querySelector(selectors.map); 635 if (mapElement) { 636 that._elements.container.insertBefore(mapElement, that._elements.noscript); 637 } 638 639 that._elements.noscript.parentNode.removeChild(that._elements.noscript); 640 if (that._elements.container.matches(selectors.image)) { 641 that._elements.image = that._elements.container; 642 } else { 643 that._elements.image = that._elements.container.querySelector(selectors.image); 644 } 645 646 that._elements.map = that._elements.container.querySelector(selectors.map); 647 that._elements.areas = that._elements.container.querySelectorAll(selectors.area); 648 } 649 650 function removeLazyLoader() { 651 that._elements.image.classList.remove(lazyLoader.cssClass); 652 for (var property in lazyLoader.style) { 653 if (Object.prototype.hasOwnProperty.call(lazyLoader.style, property)) { 654 that._elements.image.style[property] = ""; 655 } 656 } 657 that._elements.image.removeEventListener("load", removeLazyLoader); 658 that._lazyLoaderShowing = false;
659 } 660 661 function isLazyVisible() { 662 if (that._elements.container.offsetParent === null) { 663 return false; 664 } 665 666 var wt = window.pageYOffset; 667 var wb = wt + document.documentElement.clientHeight; 668 var et = that._elements.container.getBoundingClientRect().top + wt; 669 var eb = et + that._elements.container.clientHeight; 670 671 return eb >= wt - that._properties.lazythreshold && et <= wb + that._properties.lazythreshold; 672 } 673 674 function resizeAreas() { 675 if (that._elements.areas && that._elements.areas.length > 0) { 676 for (var i = 0; i < that._elements.areas.length; i++) { 677 var width = that._elements.image.width; 678 var height = that._elements.image.height; 679 680 if (width && height) { 681 var relcoords = that._elements.areas[i].dataset.cmpRelcoords; 682 if (relcoords) { 683 var relativeCoordinates = relcoords.split(","); 684 var coordinates = new Array(relativeCoordinates.length); 685 686 for (var j = 0; j < coordinates.length; j++) { 687 if (j % 2 === 0) { 688 coordinates[j] = parseInt(relativeCoordinates[j] * width); 689 } else { 690 coordinates[j] = parseInt(relativeCoordinates[j] * height); 691 } 692 } 693 694 that._elements.areas[i].coords = coordinates; 695 } 696 } 697 } 698 } 699 } 700 701 function cacheElements(wrapper) { 702 that._elements = {}; 703 that._elements.self = wrapper; 704 var hooks = that._elements.self.querySelectorAll("[data-" + NS + "-hook-" + IS + "]"); 705 706 for (var i = 0; i < hooks.length; i++) { 707 var hook = hooks[i]; 708 var capitalized = IS; 709 capitalized = capitalized.charAt(0).toUpperCase() + capitalized.slice(1); 710 var key = hook.dataset[NS + "Hook" + capitalized]; 711 that._elements[key] = hook; 712 } 713 } 714 715 function onWindowResize() { 716 that.update(); 717 resizeAreas(); 718 } 719 720 function onLoad() { 721 resizeAreas(); 722 } 723 724 that.update = function() { 725 if (that._properties.lazy) { 726 if (isLazyVisible()) { 727 loadImage(); 728 } 729 } else { 730 loadImage(); 731 } 732 }; 733 734 if (config && config.element) { 735 init(config); 736 } 737 } 738 739 function onDocumentReady() { 740 var elements = document.querySelectorAll(selectors.self); 741 for (var i = 0; i < elements.length; i++) { 742 new Image({ element: elements[i], options: CMP.utils.readData(elements[i], IS) }); 743 } 744 745 var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver; 746 var body = document.querySelector("body"); 747 var observer = new MutationObserver(function(mutations) { 748 mutations.forEach(function(mutation) { 749 // needed for IE 750 var nodesArray = [].slice.call(mutation.addedNodes); 751 if (nodesArray.length > 0) { 752 nodesArray.forEach(function(addedNode) { 753 if (addedNode.querySelectorAll) { 754 var elementsArray = [].slice.call(addedNode.querySelectorAll(selectors.self)); 755 elementsArray.forEach(function(element) { 756 new Image({ element: element, options: CMP.utils.readData(element, IS) }); 757 }); 758 } 759 }); 760 } 761 }); 762 }); 763 764 observer.observe(body, { 765 subtree: true, 766 childList: true, 767 characterData: true 768 }); 769 } 770 771 var documentReady = document.readyState !== "loading" ? Promise.resolve() : new Promise(function(resolve) { 772 document.addEventListener("DOMContentLoaded", resolve); 773 }); 774 775 Promise.all([documentReady]).then(onDocumentReady); 776 /* 777 on drag & drop of the component into a parsys, noscript's content will be escaped multiple times by the editor which creates 778 the DOM for editing; the HTML parser cannot be used here due to the multiple escaping 779 */ 780 function decodeNoscript(text) { 781 text = text.replace(/&(amp;)*lt;/g, "<"); 782 text = text.replace(/&(amp;)*gt;/g, ">"); 783 return text; 784 } 785 786})(); 787
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.