1/* 2 * ADOBE CONFIDENTIAL 3 * 4 * Copyright 2016 Adobe Systems Incorporated 5 * All Rights Reserved. 6 * 7 * NOTICE: All information contained herein is, and remains 8 * the property of Adobe Systems Incorporated and its suppliers, 9 * if any. The intellectual and technical concepts contained 10 * herein are proprietary to Adobe Systems Incorporated and its 11 * suppliers and may be covered by U.S. and Foreign Patents, 12 * patents in process, and are protected by trade secret or copyright law. 13 * Dissemination of this information or reproduction of this material 14 * is strictly forbidden unless prior written permission is obtained 15 * from Adobe Systems Incorporated. 16 */ 17 18(function() { 19 'use strict'; 20 21 22 const COMP_SELECTOR = '.s7dm-dynamic-media'; 23 const VIEWER_JS = { 24 'BasicZoomViewer': 'html5/js/BasicZoomViewer.js', 25 'FlyoutViewer': 'html5/js/FlyoutViewer.js', 26 'MixedMediaViewer': 'html5/js/MixedMediaViewer.js', 27 'SpinViewer': 'html5/js/SpinViewer.js', 28 'VideoViewer': 'html5/js/VideoViewer.js', 29 'ZoomViewer': 'html5/js/ZoomViewer.js', 30 'ZoomVerticalViewer': 'html5/js/ZoomVerticalViewer.js', 31 'Responsive': 'libs/responsive_image.js' 32 }; 33 const responsiveViewerCSS = 's7responsiveViewer'; //defined in responsive.css 34 35 36 37 $(document).ready(function(){ 38 //do nothing if there is no component due to no asset yet or DM disabled 39 if ($(COMP_SELECTOR).length > 0) { 40 const viewers = new S7dmUtils.Viewer(); 41 const viewerRootPath = $(COMP_SELECTOR).data('viewer-path'); 42 const pageLocale = $(COMP_SELECTOR).data('page-locale'); 43 let s7i18nPath = '/libs/dam/components/scene7/common/clientlibs/i18n.js'; 44 if (typeof Granite != 'undefined' && typeof Granite.I18n != 'undefined') { 45 Granite.I18n.setLocale(pageLocale); 46 s7i18nPath = Granite.HTTP.externalize(s7i18nPath); 47 } 48 $('head').append('<script type="text/javascript" src="' + s7i18nPath + '"></script>'); 49 viewers.load(VIEWER_JS, viewerRootPath) 50 .ready({ 51 success: initViewers, 52 fail: failViewerLoader 53 }); 54 } 55 }); 56 57 /** 58 * Viewer intialization for interactive media component 59 */ 60 function initViewers(){ 61 const components = $(COMP_SELECTOR); 62 components.each(function(){ 63 setupViewer($(this)); 64 }); 65 } 66 67 68 /** 69 * Setup viewer based on component 70 * @param component a div component contains viewer config 71 */ 72 function setupViewer(component){ 73 const compId = component.attr('id'); 74 let viewer = S7dmUtils[compId], 75 assetType = component.data('asset-type'), 76 mode = component.data('mode'), 77 stageSize = component.data('stagesize'); 78 79 if (typeof viewer != 'undefined' && viewer != null) { 80 viewer.dispose(); 81 S7dmUtils[compId] = null; 82 component.removeClass(responsiveViewerCSS); 83 } 84 component.html(''); 85 const viewerType = component.data('viewer-type'); 86 87 if (viewerType) { 88 89 const viewerParams = buildViewerParams(component); 90 const viewerSettings = { 'containerId' : component.attr('id'), 91 'params': viewerParams }; 92 if (!(viewerType === 'FlyoutViewer' && stageSize)) { 93 component.addClass(responsiveViewerCSS); 94 } 95 viewer = new s7viewers[viewerType](viewerSettings); 96 if (typeof Granite != 'undefined' && typeof Granite.I18n != 'undefined') { 97 viewer.setLocalizedTexts(getLocalizedText()); //passing localized text to the viewer 98 } 99 S7dmUtils[compId] = viewer; 100 viewer.init(); 101 } 102 else if(assetType === 'image') { 103 if (component.data('breakpoints') || mode === 'smartcrop') { 104 component[0].removeAttribute('data-stagesize'); 105 buildResponsiveImage(component); 106 } 107 else { 108 component[0].removeAttribute('data-enablehd'); 109 buildImage(component); 110 } 111 } 112 113 } 114 115 /** 116 * Build Image and anchor when there is no viewer constructor defined for IMAGE ONLY 117 * @param component a div component contains viewer config 118 */ 119 function buildImage(component) { 120 const stageSize = component.data('stagesize'), 121 linkURL = component.data('linkurl'), 122 linkTarget = component.data('linktarget'), 123 title = component.data('title'), 124 altText = component.data('alt'), 125 imagePreset = component.data('imagepreset'), 126 imageServer = component.data('imageserver'), 127 modifiers = component.data('urlmodifiers'); 128 129 const imgSetup = { 130 'src': imageServer + component.data('asset-path') 131 } 132 if (imagePreset) { 133 imgSetup['src'] += '?$' + imagePreset + '$'; 134 } 135 if (modifiers) { 136 imgSetup['src'] += (imagePreset ? '&' : '?') + modifiers 137 } 138 139 if (stageSize) { 140 const stageSizeParts = stageSize.split(','); 141 imgSetup['width'] = stageSizeParts[0]; 142 if (stageSizeParts.length > 1) { 143 imgSetup['height'] = stageSizeParts[1]; 144 } 145 } 146 147 const imgComp = $('<img>', imgSetup); 148 component.find('.image-skeleton')?.hide(); 149 //if there is link, wrap it around image 150 if (linkURL) { 151 const anchorSetup = { 152 'href': linkURL, 153 'target': linkTarget 154 }; 155 if (altText) { 156 anchorSetup['alt'] = altText; 157 anchorSetup['title'] = altText; // default to alt text 158 imgComp.attr('alt', altText); 159 } 160 if (title) { 161 anchorSetup['title'] = title; 162 } 163 const anchor = $('<a>
163', anchorSetup); 164 anchor.append(imgComp); 165 component.append(anchor); 166 } 167 else { 168 //Add alt text if it's set 169 if (altText) { 170 imgComp.attr('alt', altText); 171 } 172 else { 173 imgComp.attr('alt', ""); 174 } 175 component.append(imgComp); 176 } 177 178 } 179 180 /** 181 * Build responsive image 182 * @param component container 183 */ 184 function buildResponsiveImage(component) { 185 const imagePreset = component.data('imagepreset'), 186 imageServer = component.data('imageserver'), 187 linkURL = component.data('linkurl'), 188 linkTarget = component.data('linktarget'), 189 title = component.data('title'), 190 altText = component.data('alt'); 191 const modifiers = component.data('urlmodifiers'); 192 const respCon = $('<div>', { 'class': 's7responsiveContainer' }); 193 const respImgId = component.attr('id') + '_resp'; 194 const respImgSetup = {
195 'id': respImgId, 196 'src': "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7", 197 'data-src': imageServer + component.data('asset-path'), 198 'class': 'fluidimage', 199 'data-mode': component.data('mode'), 200 'data-breakpoints': component.data('breakpoints'), 201 'data-enablehd': component.data('enablehd') === "never" ? "never" : "always", 202 'decoding': "async", 203 'loading': component.hasClass('lazy-loading') ? "lazy" : undefined, 204 } 205 if (imagePreset) { 206 respImgSetup['data-src'] += '?$' + imagePreset + '$'; 207 } 208 if (modifiers) { 209 respImgSetup['data-src'] += (imagePreset ? '&' : '?') + modifiers 210 } 211 const respImg = $('<img>', respImgSetup); 212 component.find('.image-skeleton')?.hide(); 213 //if there is link, wrap it around image 214 if (linkURL) { 215 const anchorSetup = { 216 'href': linkURL, 217 'target': linkTarget 218 }; 219 if (altText) { 220 anchorSetup['alt'] = altText; 221 anchorSetup['title'] = altText; // default to alt text 222 respImg.attr('alt', altText); 223 } 224 if (title) { 225 anchorSetup['title'] = title; 226 } 227 const anchor = $('<a>', anchorSetup); 228 anchor.append(respImg); 229 respCon.append(anchor); 230 } else { 231 if (altText) { 232 respImg.attr('alt', altText); 233 } 234 else { 235 respImg.attr('alt', ""); 236 } 237 respCon.append(respImg); 238 } 239 component.append(respCon); 240 s7responsiveImage(document.getElementById(respImgId)); 241 } 242 243 /** 244 * @param component a div element with viewer setup 245 * @return viewer parameters in JSON 246 */ 247 function buildViewerParams(component) { 248 const assetPath = component.data('asset-path'), 249 assetType = component.data('asset-type'), 250 viewerType = component.data('viewer-type'), 251 imageserver = component.data('imageserver'), 252 videoserver = component.data('videoserver'), 253 contentserver = component.data('contenturl'), 254 config = component.data('config'), 255 wcmdisabled = component.data('wcmdisabled'), 256 stageSize = component.data('stagesize'), 257 viewerModifiers = component.data('viewermodifiers'), 258 isdms7 = component.data('dms7'); 259 260 const viewerParams = { 261 'asset': assetPath, 262 'serverurl': imageserver, 263 'contenturl': contentserver 264 }; 265 266 //Add extra viewer modifiers if any 267 if (viewerModifiers) { 268 $.extend(viewerParams, getViewerModifiers(viewerModifiers)); 269 } 270 271 const isAuthor = !wcmdisabled && wcmdisabled != ''; 272 273 //Add cache=off when WCM is not disabled (author side) 274 if (isAuthor) { 275 viewerParams['asset'] += '?cache=off'; 276 } 277 if (stageSize) { 278 viewerParams['stagesize'] = stageSize; 279 } 280 if (viewerType === 'FlyoutViewer') { 281 viewerParams['imagereload'] = '1,breakpoint,100;320;480'; 282 } 283 if (assetPath.indexOf('/') != 0) { 284 viewerParams['aemmode'] = '0'; 285 } 286 287 //For video, we add videoserverurl 288 if (viewerType.indexOf('Video') >= 0 || viewerType.indexOf('Mixed') >= 0) { 289 viewerParams['videoserverurl'] = videoserver; 290 // force native if 291 // Asset is non-AVS video (apply to both DMS7 and DM Hybrid for playing progressively) OR 292 // (Asset is DMS7 video regardless of AVS or non-AVS AND the page is on author side) 293 if (assetType === 'video' || ((typeof isdms7 != 'undefined') && isAuthor)) { 294 viewerParams['playback'] = 'native'; 295 viewerParams['progressivebitrate'] = '20000'; 296 } 297 } 298 //check for viewer preset setup 299 if (typeof config != 'undefined' && config.length > 0) { 300 viewerParams['config'] = getViewerPresetPath(config); 301 } 302 return viewerParams; 303 } 304 305 /** 306 * Parse viewer preset path for viewer-usable format 307 * @param config viewer preset path stored in the component node 308 * @return viewer-usable format viewer preset path 309 */ 310 function getViewerPresetPath(config) { 311 const configParts = config.split('|'); 312 return configParts[0]; 313 } 314 315 /** 316 * Parse viewer preset path for isCustom Preset flag 317 * @param config viewer preset string 318 * @return flag for custom preset 319 */ 320 function isCustomPreset(config) { 321 const configParts = config.split('|'); 322 return configParts[2]; 323 } 324 325 /** 326 * Fail viewer loader handler 327 */
328 function failViewerLoader(){ 329 console.log('S7Viewer is missing'); 330 } 331 332 /** 333 * Parse free-form viewer modifiers 334 * @param viewerModifiers string for free-form viewer modifiers 335 * @return JSON representing viewer modifiers 336 */ 337 function getViewerModifiers(viewerModifiers) { 338 const modifiers = {}; 339 if (viewerModifiers) { 340 const items = viewerModifiers.split('&'); 341 for (let i = 0; i < items.length; i++) { 342 //only when there is key=val pair 343 if (items[i].indexOf('=') > 0) { 344 const key = items[i].substring(0, items[i].indexOf('=')); 345 const val = items[i].substring(items[i].indexOf('=') + 1); 346 modifiers[key] = val; 347 } 348 } 349 } 350 return modifiers; 351 } 352 353 /** 354 * Get localized text for viewer from s7sdk_i18n.localizedText 355 * @return JSON for localized text 356 */ 357 function getLocalizedText() { 358 const localizedText = {}; 359 localizedText[Granite.I18n.getLocale()] = formatLocalizedText(s7sdk_i18n.localizedText); 360 localizedText['defaultLocale'] = Granite.I18n.getLocale(); 361 return localizedText; 362 } 363 364 /** 365 * Format localized text into a correct viewer format 366 * @param localizedText localized text parsed from s7sdk 367 * @return formatted localized text with correct key for viewer 368 */ 369 function formatLocalizedText(localizedText) { 370 const formatTexts = {}; 371 for (const compKey in localizedText) { 372 const compObj = localizedText[compKey]; 373 for (const symbolKey in compObj) { 374 const modKey = compKey + '.' + symbolKey; 375 const symbolVal = compObj[symbolKey]; 376 formatTexts[modKey] = symbolVal; 377 } 378 } 379 return formatTexts; 380 } 381 382}).call(this);
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.