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.image = window.CMP.image || {}; 21 window.CMP.image.dynamicMedia = (function() { 22 var autoSmartCrops = {}; 23 var SRC_URI_TEMPLATE_WIDTH_VAR = "{.width}"; 24 var SRC_URI_TEMPLATE_DPR_VAR = "{dpr}"; 25 var dpr = window.devicePixelRatio || 1; 26 var config = { 27 minWidth: 20 28 }; 29 30 /** 31 * get auto smart crops from dm 32 * @param {String} src the src uri 33 * @returns {{}} the smart crop json object 34 */ 35 var getAutoSmartCrops = function(src) { 36 var request = new XMLHttpRequest(); 37 var url = src.split(SRC_URI_TEMPLATE_WIDTH_VAR)[0] + "?req=set,json"; 38 request.open("GET", url, false); 39 request.onload = function() { 40 if (request.status >= 200 && request.status < 400) { 41 // success status 42 var responseText = request.responseText; 43 var rePayload = new RegExp(/^(?:\/\*jsonp\*\/)?\s*([^()]+)\(([\s\S]+),\s*"[0-9]*"\);?$/gmi); 44 var rePayloadJSON = new RegExp(/^{[\s\S]*}$/gmi); 45 var resPayload = rePayload.exec(responseText); 46 var payload; 47 if (resPayload) { 48 var payloadStr = resPayload[2]; 49 if (rePayloadJSON.test(payloadStr)) { 50 payload = JSON.parse(payloadStr); 51 } 52 53 } 54 // check "relation" - only in case of smartcrop preset 55 if (payload && payload.set.relation && payload.set.relation.length > 0) { 56 for (var i = 0; i < payload.set.relation.length; i++) { 57 autoSmartCrops[parseInt(payload.set.relation[i].userdata.SmartCropWidth)] = 58 ":" + payload.set.relation[i].userdata.SmartCropDef; 59 } 60 } 61 } else { 62 // error status 63 } 64 }; 65 request.send(); 66 return autoSmartCrops; 67 }; 68 69 /** 70 * Build and return the srcset value based on the available auto smart crops 71 * @param {String} src the src uri 72 * @param {Object} smartCrops the smart crops object 73 * @returns {String} the srcset 74 */ 75 var getSrcSet = function(src, smartCrops) { 76 var srcset; 77 var keys = Object.keys(smartCrops); 78 if (keys.length > 0) { 79 srcset = []; 80 for (var key in autoSmartCrops) { 81 srcset.push(src.replace(SRC_URI_TEMPLATE_WIDTH_VAR, smartCrops[key]) + " " + key + "w"); 82 } 83 } 84 return srcset.join(","); 85 }; 86 87 /** 88 * Get the optimal width based on the available sizes 89 * @param {[Number]} sizes the available sizes 90 * @param {Number} width the element width 91 * @returns {String} the optimal width 92 */ 93 function getOptimalWidth(sizes, width) { 94 var len = sizes.length; 95 var key = 0; 96 97 while ((key < len - 1) && (sizes[key] < width)) { 98 key++; 99 } 100 101 return sizes[key] !== undefined ? sizes[key].toString() : width; 102 } 103 104 /** 105 * Get the width of an element or parent element if the width is smaller than the minimum width 106 * @param {HTMLElement} component the image component 107 * @param {HTMLElement | Node} parent the parent element 108 * @returns {Number} the width of the element 109 */ 110 var getWidth = function(component, parent) { 111 var width = component.offsetWidth; 112 while (width < config.minWidth && parent && !component._autoWidth) { 113 width = parent.offsetWidth; 114 parent = parent.parentNode; 115 } 116 return width; 117 }; 118 119 /** 120 * Set the src and srcset attribute for a Dynamic Media Image which auto smart crops enabled. 121 * @param {HTMLElement} component the image component 122 * @param {{}} properties the component properties 123 */ 124 var setDMAttributes = function(component, properties) { 125 var src = properties.src.replace(SRC_URI_TEMPLATE_DPR_VAR, dpr); 126 var smartCrops = {}; 127 var width; 128 if (properties["smartcroprendition"] === "SmartCrop:Auto") { 129 smartCrops = getAutoSmartCrops(src); 130 } 131 var hasWidths = (properties.widths && properties.widths.length > 0) || Object.keys(smartCrops).length > 0; 132 if (hasWidths) { 133 var image = component.querySelector("img"); 134 var elemWidth = getWidth(component, component.parentNode); 135 if (properties["smartcroprendition"] === "SmartCrop:Auto") { 136 image.setAttribute("srcset", CMP.image.dynamicMedia.getSrcSet(src, smartCrops)); 137 width = getOptimalWidth(Object.keys(smartCrops, elemWidth)); 138 image.setAttribute("src", CMP.image.dynamicMedia.getSrc(src, smartCrops[width])); 139 } else { 140 width = getOptimalWidth(properties.widths, elemWidth); 141 image.setAttribute("src", CMP.image.dynamicMedia.getSrc(src, width)); 142 } 143 } 144 }; 145 146 /** 147 * Get the src attribute based on the optimal width 148 * @param {String} src the src uri 149 * @param {String} width the element width 150 * @returns {String} the final src attribute 151 */ 152 var getSrc = function(src, width) { 153 if (src.indexOf(SRC_URI_TEMPLATE_WIDTH_VAR) > -1) { 154 src = src.replace(SRC_URI_TEMPLATE_WIDTH_VAR, width); 155 } 156 return src; 157 }; 158 159 160 return { 161 getAutoSmartCrops: getAutoSmartCrops, 162 getSrcSet: getSrcSet, 163 getSrc: getSrc, 164 setDMAttributes: setDMAttributes, 165 getWidth: getWidth 166 }; 167 }()); 168 document.dispatchEvent(new CustomEvent("core.wcm.components.c
168ommons.site.image.dynamic-media.loaded")); 169}(window.document));
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.