1/******************************************************************************* 2 * Copyright 2022 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 ******************************************************************************/ 16(function(document) { 17 "use strict"; 18 19 window.CMP = window.CMP || {}; 20 window.CMP.utils = (function() { 21 var NS = "cmp"; 22 23 /** 24 * Reads options data from the Component wrapper element, defined via {@code data-cmp-*} data attributes 25 * 26 * @param {HTMLElement} element The component element to read options data from 27 * @param {String} is The component identifier 28 * @returns {String[]} The options read from the component data attributes 29 */ 30 var readData = function(element, is) { 31 var data = element.dataset; 32 var options = []; 33 var capitalized = is; 34 capitalized = capitalized.charAt(0).toUpperCase() + capitalized.slice(1); 35 var reserved = ["is", "hook" + capitalized]; 36 37 for (var key in data) { 38 if (Object.prototype.hasOwnProperty.call(data, key)) { 39 var value = data[key]; 40 41 if (key.indexOf(NS) === 0) { 42 key = key.slice(NS.length); 43 key = key.charAt(0).toLowerCase() + key.substring(1); 44 45 if (reserved.indexOf(key) === -1) { 46 options[key] = value; 47 } 48 } 49 } 50 } 51 return options; 52 }; 53 54 /** 55 * Set up the final properties of a component by evaluating the transform function or fall back to the default value on demand 56 * @param {String[]} options the options to transform 57 * @param {Object} properties object of properties of property functions 58 * @returns {Object} transformed properties 59 */ 60 var setupProperties = function(options, properties) { 61 var transformedProperties = {}; 62 63 for (var key in properties) { 64 if (Object.prototype.hasOwnProperty.call(properties, key)) { 65 var property = properties[key]; 66 if (options && options[key] != null) { 67 if (property && typeof property.transform === "function") { 68 transformedProperties[key] = property.transform(options[key]); 69 } else { 70 transformedProperties[key] = options[key]; 71 } 72 } else { 73 transformedProperties[key] = properties[key]["default"]; 74 } 75 } 76 } 77 return transformedProperties; 78 }; 79 80 81 return { 82 readData: readData, 83 setupProperties: setupProperties 84 }; 85 }()); 86}(window.document)); 87 88/******************************************************************************* 89 * Copyright 2022 Adobe 90 * 91 * Licensed under the Apache License, Version 2.0 (the "License"); 92 * you may not use this file except in compliance with the License. 93 * You may obtain a copy of the License at 94 * 95 * http://www.apache.org/licenses/LICENSE-2.0 96 * 97 * Unless required by applicable law or agreed to in writing, software 98 * distributed under the License is distributed on an "AS IS" BASIS, 99 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 100 * See the License for the specific language governing permissions and 101 * limitations under the License. 102 ******************************************************************************/ 103(function(document) { 104 "use strict"; 105 106 window.CMP = window.CMP || {}; 107 window.CMP.image = window.CMP.image || {}; 108 window.CMP.image.dynamicMedia = (function() { 109 var autoSmartCrops = {}; 110 var SRC_URI_TEMPLATE_WIDTH_VAR = "{.width}"; 111 var SRC_URI_TEMPLATE_DPR_VAR = "{dpr}";
112 var SRC_URI_DPR_OFF = "dpr=off"; 113 var SRC_URI_DPR_ON = "dpr=on,{dpr}"; 114 var dpr = window.devicePixelRatio || 1; 115 var config = { 116 minWidth: 20 117 }; 118 119 /** 120 * get auto smart crops from dm 121 * @param {String} src the src uri 122 * @returns {{}} the smart crop json object 123 */ 124 var getAutoSmartCrops = function(src) { 125 var request = new XMLHttpRequest(); 126 var url = src.split(SRC_URI_TEMPLATE_WIDTH_VAR)[0] + "?req=set,json"; 127 request.open("GET", url, false); 128 request.onload = function() { 129 if (request.status >= 200 && request.status < 400) { 130 // success status 131 var responseText = request.responseText; 132 var rePayload = new RegExp(/^(?:\/\*jsonp\*\/)?\s*([^()]+)\(([\s\S]+),\s*"[0-9]*"\);?$/gmi); 133 var rePayloadJSON = new RegExp(/^{[\s\S]*}$/gmi); 134 var resPayload = rePayload.exec(responseText); 135 var payload; 136 if (resPayload) { 137 var payloadStr = resPayload[2]; 138 if (rePayloadJSON.test(payloadStr)) { 139 payload = JSON.parse(payloadStr); 140 } 141 142 } 143 // check "relation" - only in case of smartcrop preset 144 if (payload && payload.set.relation && payload.set.relation.length > 0) { 145 for (var i = 0; i < payload.set.relation.length; i++) { 146 autoSmartCrops[parseInt(payload.set.relation[i].userdata.SmartCropWidth)] = 147 ":" + payload.set.relation[i].userdata.SmartCropDef; 148 } 149 } 150 } else { 151 // error status 152 } 153 }; 154 request.send(); 155 return autoSmartCrops; 156 }; 157 158 /** 159 * Build and return the srcset value based on the available auto smart crops 160 * @param {String} src the src uri 161 * @param {Object} smartCrops the smart crops object 162 * @returns {String} the srcset 163 */ 164 var getSrcSet = function(src, smartCrops) { 165 var srcset; 166 var keys = Object.keys(smartCrops); 167 if (keys.length > 0) { 168 srcset = []; 169 for (var key in autoSmartCrops) { 170 srcset.push(src.replace(SRC_URI_TEMPLATE_WIDTH_VAR, smartCrops[key]) + " " + key + "w"); 171 } 172 } 173 return srcset.join(","); 174 }; 175 176 /** 177 * Get the optimal width based on the available sizes 178 * @param {[Number]} sizes the available sizes 179 * @param {Number} width the element width 180 * @returns {String} the optimal width 181 */ 182 function getOptimalWidth(sizes, width) { 183 var len = sizes.length; 184 var key = 0; 185 186 while ((key < len - 1) && (sizes[key] < width)) { 187 key++; 188 } 189 190 return sizes[key] !== undefined ? sizes[key].toString() : width; 191 } 192 193 /** 194 * Get the width of an element or parent element if the width is smaller than the minimum width 195 * @param {HTMLElement} component the image component 196 * @param {HTMLElement | Node} parent the parent element 197 * @returns {Number} the width of the element 198 */ 199 var getWidth = function(component, parent) { 200 var width = component.offsetWidth; 201 while (width < config.minWidth && parent && !component._autoWidth) { 202 width = parent.offsetWidth; 203 parent = parent.parentNode; 204 } 205 return width; 206 }; 207 208 /** 209 * Set the src and srcset attribute for a Dynamic Media Image which auto smart crops enabled. 210 * @param {HTMLElement} component the image component 211 * @param {{}} properties the component properties 212 */ 213 var setDMAttributes = function(component, properties) { 214 // for v3 we first have to turn the dpr on
215 var src = properties.src.replace(SRC_URI_DPR_OFF, SRC_URI_DPR_ON); 216 src = src.replace(SRC_URI_TEMPLATE_DPR_VAR, dpr); 217 var smartCrops = {}; 218 var width; 219 if (properties["smartcroprendition"] === "SmartCrop:Auto") { 220 smartCrops = getAutoSmartCrops(src); 221 } 222 var hasWidths = (properties.widths && properties.widths.length > 0) || Object.keys(smartCrops).length > 0; 223 if (hasWidths) { 224 var image = component.querySelector("img"); 225 var elemWidth = getWidth(component, component.parentNode); 226 if (properties["smartcroprendition"] === "SmartCrop:Auto") { 227 image.setAttribute("srcset", CMP.image.dynamicMedia.getSrcSet(src, smartCrops)); 228 width = getOptimalWidth(Object.keys(smartCrops, elemWidth)); 229 image.setAttribute("src", CMP.image.dynamicMedia.getSrc(src, smartCrops[width])); 230 } else { 231 width = getOptimalWidth(properties.widths, elemWidth); 232 image.setAttribute("src", CMP.image.dynamicMedia.getSrc(src, width)); 233 } 234 } 235 }; 236 237 /** 238 * Get the src attribute based on the optimal width 239 * @param {String} src the src uri 240 * @param {String} width the element width 241 * @returns {String} the final src attribute 242 */ 243 var getSrc = function(src, width) { 244 if (src.indexOf(SRC_URI_TEMPLATE_WIDTH_VAR) > -1) { 245 src = src.replace(SRC_URI_TEMPLATE_WIDTH_VAR, width); 246 } 247 return src; 248 }; 249 250 251 return { 252 getAutoSmartCrops: getAutoSmartCrops, 253 getSrcSet: getSrcSet, 254 getSrc: getSrc, 255 setDMAttributes: setDMAttributes, 256 getWidth: getWidth 257 }; 258 }()); 259 document.dispatchEvent(new CustomEvent("core.wcm.components.commons.site.image.dynamic-media.loaded")); 260}(window.document)); 261 262/******************************************************************************* 263 * Copyright 2022 Adobe 264 * 265 * Licensed under the Apache License, Version 2.0 (the "License"); 266 * you may not use this file except in compliance with the License. 267 * You may obtain a copy of the License at 268 * 269 * http://www.apache.org/licenses/LICENSE-2.0 270 * 271 * Unless required by applicable law or agreed to in writing, software 272 * distributed under the License is distributed on an "AS IS" BASIS, 273 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 274 * See the License for the specific language governing permissions and 275 * limitations under the License. 276 ******************************************************************************/ 277(function(document) { 278 279 "use strict"; 280 281 window.CMP = window.CMP || {}; 282 window.CMP.image = window.CMP.image || {}; 283 window.CMP.image.v3 = (function() { 284 var IS = "image"; 285 286 var selectors = { 287 self: "[data-cmp-hook-image='imageV3']" 288 }; 289 290 var properties = { 291 "widths": { 292 "default": [], 293 "transform": function(value) { 294 var widths = []; 295 value.split(",").forEach(function(item) { 296 item = parseFloat(item); 297 if (!isNaN(item)) { 298 widths.push(item); 299 } 300 }); 301 return widths; 302 } 303 }, 304 "dmimage": { 305 "default": false, 306 "transform": function(value) { 307 return !(value === null || typeof value === "undefined"); 308 } 309 }, 310 "src": { 311 "transform": function(value) { 312 return decodeURIComponent(value); 313 } 314 }, 315 "smartcroprendition": "" 316 }; 317 318 function Image(config) { 319 var that = this; 320 /** 321 * Init the image if the image is from dynamic media 322 * @param {HTMLElement} component the image component 323 */ 324 that.initImage = function(component) { 325 var options = CMP.utils.readData(component, IS); 326 that._properties = CMP.utils.setupProperties(options, properties); 327 if (that._properties.dmimage) { 328 // use encoded src for dynamic media 329 that._properties.src = options["src"]; 330 CMP.image.dynamicMedia.setDMAttributes(component, that._properties); 331 } 332 }; 333 that.initImage(config.element); 334 } 335 336 return { 337 init: function() { 338 var elements = document.querySelectorAll(selectors.self); 339 for (var i = 0; i < elements.length; i++) { 340 new Image({ element: elements[i], options: CMP.utils.readData(elements[i], IS) }); 341 } 342 343 var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver; 344 var body = document.querySelector("body"); 345 var observer = new MutationObserver(function(mutations) { 346 mutations.forEach(function(mutation) { 347 // needed for IE 348 var nodesArray = [].slice.call(mutation.addedNodes); 349 if (nodesArray.length > 0) { 350 nodesArray.forEach(function(addedNode) { 351 if (addedNode.querySelectorAll) { 352 var elementsArray = [].slice.call(addedNode.querySelectorAll(selectors.self)); 353 elementsArray.forEach(function(element) { 354 new Image({ element: element, options: CMP.utils.readData(element, IS) }); 355 }); 356 } 357 }); 358 } 359 }); 360 }); 361 362 observer.observe(body, { 363 subtree: true, 364 childList: true, 365 characterData: true 366 }); 367 } 368 }; 369 }()); 370 371 var documentReady = document.readyState !== "loading" ? Promise.resolve() : new Promise(function(resolve) { 372 document.addEventListener("DOMContentLoaded", resolve); 373 }); 374 Promise.all([documentReady]).then(window.CMP.image.v3.init); 375}(window.document)); 376
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.