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 var COMP_SELECTOR = '.s7dm-dynamic-media'; 23 var 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 var responsiveViewerCSS = 's7responsiveViewer'; //defined in responsive.css 34 35 $(document).ready(function(){ 36 //do nothing if there is no component due to no asset yet or DM disabled 37 if ($(COMP_SELECTOR).length > 0) { 38 var viewers = new S7dmUtils.Viewer(); 39 var viewerRootPath = $(COMP_SELECTOR).data('viewer-path'); 40 var pageLocale = $(COMP_SELECTOR).data('page-locale'); 41 var s7i18nPath = '/libs/dam/components/scene7/common/clientlibs/i18n.js'; 42 if (typeof Granite != 'undefined' && typeof Granite.I18n != 'undefined') { 43 Granite.I18n.setLocale(pageLocale); 44 s7i18nPath = Granite.HTTP.externalize(s7i18nPath); 45 } 46 $('head').append('<script type="text/javascript" src="' + s7i18nPath + '"></script>'); 47 viewers.load(VIEWER_JS, viewerRootPath) 48 .ready({ 49 success: initViewers, 50 fail: failViewerLoader 51 }); 52 } 53 }); 54 55 /** 56 * Viewer intialization for interactive media component 57 */ 58 function initViewers(){ 59 var components = $(COMP_SELECTOR); 60 components.each(function(){ 61 setupViewer($(this)); 62 }); 63 } 64 65 function videoChapterInit(data, viewerCustom) { 66 const compId = viewerCustom.containerId; 67 const videoPlayer = viewerCustom.getComponent("videoPlayer"); 68 const compElement = document.getElementById(compId); 69 const navigation = videoPlayer.getNavigation(); 70 if(navigation && compElement.querySelectorAll('.s7chapterbutton').length < 1) { 71 if($('#chapter-scroll-height').length < 1){ 72 $('body').append(`<input type="hidden" id="chapter-scroll-height" style="margin-top:calc(var(--space-xl) * 8);" />`); 73 } 74 const controlBar = viewerCustom.getComponent("controls"); 75 controlBar.attachView(videoPlayer, false); 76 let htmlStr = ''; 77 navigation && navigation['items'].forEach(function(nav, key) { 78 htmlStr += `<div class="chapter" data-start="${nav.start}" data-end="${nav.end}" data-index="${key}" data-id="${nav.id}" tabindex='0'><span>${nav.data}</span></div>`; 79 }); 80 let chapterTitle = 'Chapters'; 81 let separatorStyle = ''; 82 const dmVideo = $('#'+compId).closest('.dm-custom-parameter'); 83 if(dmVideo.length){ 84 if(dmVideo.data('chapterTitle') && dmVideo.data('chapterTitle').length){ 85 chapterTitle = dmVideo.data('chapterTitle'); 86 } 87 if(dmVideo.data('chapterSeparatorStyle') && dmVideo.data('chapterSeparatorStyle').length){ 88 separatorStyle = dmVideo.data('chapterSeparatorStyle'); 89 } 90 } 91 const separator = `<div class="separator ${separatorStyle}"><div class="cmp-separator"><hr></div></div>`;
92 const chapterListHeader = `<div class="chapter-title"> 93 <div class="chapter-title--label">${chapterTitle}</div> 94 <div class="global-link cmp-global-link-icon-secondary"> 95 <ul> 96 <li> 97 <a href="javascript:void(0)"> 98 <span>close</span> 99 <span class="material-symbols-rounded close-icon">close</span> 100 </a> 101 </li> 102 </ul> 103 </div> 104 </div>`; 105 const chapterList = `<div class="chapter-list hide" data-description="Scene7ComponentHolder" data-component="chapter list section"> 106 ${chapterListHeader} 107 ${separator} 108 <div class="chapter-list-wrapper"> 109 ${htmlStr} 110 </div> 111 </div>`; 112 113 // Create a new button element 114 const chapterNav = document.createElement('div'); 115 chapterNav.setAttribute('data-namespace', 's7classic'); 116 chapterNav.setAttribute('data-description', 'Scene7ComponentHolder'); 117 chapterNav.setAttribute('data-component', 'ChapterButton'); 118 chapterNav.setAttribute('class','chapternav s7button s7chapterbutton'); 119 chapterNav.id = compId+'_chapterNavButton' 120 chapterNav.innerHTML = `<div class="chapters" 121 data-description='Scene7ComponentHolder' 122 data-component='ChapterButton' 123 role='button' 124 lang='en' 125 title='chapter list' 126 aria-label='chapter list' 127 tabindex='0'></div>${chapterList}`; 128 129 controlBar.component.innerContainer.append(chapterNav); 130 131 // Define functionality for the new button 132 chapterNav.onclick = function (e) { 133 chapterListHideShow(e,chapterNav, compId); 134 }; 135 136 chapterNav.onkeydown = function(event) { 137 // If the user presses the "Enter" key on the keyboard 138 if (event.key === "Enter") { 139 // Cancel the default action, if needed 140 event.preventDefault(); 141 // Trigger the button element with a click 142 chapterListHideShow(event,chapterNav, compId); 143 } 144 }; 145 146 chapterNav.onmousedown = function() { 147 chapterNav.setAttribute("state", "down"); 148 } 149 150 chapterNav.onmouseup = function() { 151 chapterNav.setAttribute("state", "up"); 152 } 153 154 chapterNav.ontouchstart = function() { 155 chapterNav.setAttribute("state", "down"); 156 } 157 158 chapterNav.ontouchend = function() { 159 chapterNav.setAttribute("state", "up"); 160 } 161 162 const hoverTooltip = new s7sdk.SimpleToolTip(chapterNav.querySelector('.chapters'),"chapter list"); 163 164 chapterNav.querySelectorAll('.chapter').forEach(function(chapter) { 165 chapter.onclick = function () { 166 videoPlayer.seek(chapter.dataset.start); 167 videoPlayer.play(); 168 }; 169 chapter.onkeydown = function(event) { 170 // If the user presses the "Enter" key on the keyboard 171 if (event.key === "Enter") { 172 videoPlayer.seek(chapter.dataset.start); 173 videoPlayer.play(); 174 $(event.currentTarget).closest('.s7innercontrolbarcontainer').find('.s7playpausebutton').focus(); 175 } 176 } 177 }); 178 179 $('#'+compId).on('mouseenter touchstart', function(){ 180 $(this).closest('.cmp-extended-modal__container').addClass('cmp-overflow-visible'); 181 $(this).closest('.cmp-extended-modal__container__body').addClass('cmp-overflow-visible'); 182 }); 183 184 $('#'+compId).on('mouseleave', function(){ 185 $(this).closest('.cmp-extended-modal__container').removeClass('cmp-overflow-visible'); 186 $(this).closest('.cmp-extended-modal__container__body').removeClass('cmp-overflow-visible'); 187 }); 188 189 if($(window).width() <= 1024 && $('#'+compId+'>.s7container').attr('mode') !== 'fullscreen'){ 190 $('#'+compId).find('.chapter-list').width($('#'+compId).width()); 191 } 192 193 $(window).on('resize', () => { 194 $('#'+compId).closest('.cmp-extended-modal__container').removeClass('cmp-overflow-visible'); 195 $('#'+compId).closest('.cmp-extended-modal__container__body').removeClass('cmp-overflow-visible'); 196 if($(window).width() <= 1024 && $('#'+compId+'>.s7container').attr('mode') !== 'fullscreen'){ 197 $('#'+compId).find('.chapter-list').width($('#'+compId).width()); 198 } else{ 199 $('#'+compId).find('.chapter-list').attr('style', ''); 200 } 201 }); 202 203 $('.chapter-list').find('.chapter:last').on('keydown',function(e) { 204 // If the user presses the "Enter" key on the keyboard 205 if (e.key === "Tab") { 206 $(this).closest('.s7chapterbutton').find('.chapters').focus(); 207 } 208 }); 209 210 if(window.DMvideoLoadIcons){ 211 window.DMvideoLoadIcons(); 212 } 213 } 214 } 215 216 function chapterListHideShow(e,chapterNav,compId){ 217 if(e.target.className !== 'chapter-title--label') { 218 chapterNav.querySelector('.chapter-list').classList.toggle('hide'); 219 220 if(chapterNav.getAttribute("selected") && chapterNav.getAttribute("selected") == "true"){ 221 chapterNav.setAttribute("selected", "false"); 222 }else{ 223 chapterNav.setAttribute("selected", "true"); 224 } 225 226 if($(chapterNav.querySelector('.chapter-list')).hasClass('hide')) { 227 $(chapterNav).find('.chapters').focus(); 228 } 229 230 if($(window).width() <= 1024 && $('#'+compId+'>.s7container').attr('mode') !== 'fullscreen'){ 231 $('#'+compId).find('.chapter-list').width($('#'+compId).width()); 232 } else{ 233 $('#'+compId).find('.chapter-list').attr('style', ''); 234 } 235 236 if($('#'+compId).find('.chapter-list').height() >= parseFloat($("#chapter-scroll-height").css("margin-top").replace("px", ""))){ 237 $('#'+compId).find('.chapter-list-wrapper').addClass('is-scrollable'); 238 }else{ 239 $('#'+compId).find('.chapter-list-wrapper').removeClass('is-scrollable'); 240 } 241 } 242 } 243 244 function fmt(ms){ 245 const d=new Date(ms), h=d.getUTCHours(), 246 m=String(d.getUTCMinutes()).padStart(2,'0'), 247 s=String(d.getUTCSeconds()).padStart(2,'0'); 248 return h>0 ? `${h}:${m}:${s}` : `${m}:${s}`; 249 } 250 251 // Define an event handler function to update the videotime for VideoPlayer changes
252 function onNotifyVideoTime(viewerCustom){ 253 const videoPlayer = viewerCustom.getComponent("videoPlayer"); 254 const controlBar = viewerCustom.getComponent("controls"); 255 controlBar.attachView(videoPlayer, false); 256 let customTime; 257 if(viewerCustom.videoTime.getPlayedTime()){ 258 customTime = new Date(viewerCustom.videoTime.getPlayedTime()); 259 }else{ 260 customTime = new Date(viewerCustom.videoTime.getDuration()); 261 } 262 const minute = (customTime.getUTCMinutes() < 10 ? '0' : '') + customTime.getUTCMinutes(); 263 const second = (customTime.getUTCSeconds() < 10 ? '0' : '') + customTime.getUTCSeconds(); 264 const hour = String(customTime.getUTCHours()); 265 if($("#"+controlBar.compId).find(".s7customTimer").length){ 266 $("#"+controlBar.compId).find(".s7customTimer").html(fmt(customTime.getTime())); 267 }else{ 268 $("#"+controlBar.compId).find(".s7videotime").append(`<div class="s7customTimer">${fmt(customTime.getTime())}</div>`); 269 } 270 if($("#"+controlBar.compId).find(".chapter-list-wrapper").length){ 271 const $chapterList = $("#"+controlBar.compId).find(".chapter-list-wrapper"); 272 const $chapter = $chapterList.find('.chapter'); 273 $chapter.each(function() { 274 const start = parseFloat($(this).data('start')); 275 const end = parseFloat($(this).data('end')); 276 if (start <= viewerCustom.videoTime.getPlayedTime() && end >= viewerCustom.videoTime.getPlayedTime()) { 277 $(this).addClass('active'); 278 } else { 279 $(this).removeClass('active'); 280 } 281 }); 282 } 283 284 } 285 286 function updatePlayTime(viewerCustom){ 287 const compId = viewerCustom.containerId; 288 const videoPlayer = viewerCustom.getComponent("videoPlayer"); 289 const duration = fmt(viewerCustom.videoTime.getDuration()); 290 const $component = $("#" + compId); 291 if ($component.parents(".panelcontainer.cmp-panelcontainer-featureblock-video.cmp-video-no-timer").length || $component.parents(".cmp-video-no-timer").length) { 292 return; 293 } 294 const $timer = $("#" + videoPlayer.compId).find(".current_play_time"); 295 if ($timer.length) { 296 $timer.text(duration); 297 } else { 298 $("#" + videoPlayer.compId).append(`<div class="current_play_time">${duration}</div>`); 299 } 300 } 301 302 function setupCustomTabOrder(viewer) { 303 const $container = $("#" + viewer.containerId); 304 const controls = [$container.find(".s7playpausebutton") , $container.find(".s7mutebutton") , $container.find(".s7verticalvolume .s7knob") , $container.find(".s7videoscrubber .s7knob") , $container.find(".s7closedcaptionbutton") , $container.find(".s7fullscreenbutton")]; 305 controls.forEach(($control, index) => { 306 if (!$control.length) { 307 return; 308 } 309 $control.on("keydown.customtab", function(e) { 310 if (e.key !== "Tab") { 311 return; 312 } 313 if (e.shiftKey) { 314 if (index === 0) { 315 return; 316 } 317 e.preventDefault(); 318 controls[index - 1].focus(); 319 } else { 320 if (index === controls.length - 1) { 321 return; 322 } 323 e.preventDefault(); 324 controls[index + 1].focus(); 325 } 326 }); 327 }); 328 } 329 330 331 /** 332 * Setup viewer based on component 333 * @param component a div component contains viewer config 334 */ 335 function setupViewer(component){ 336 var compId = component.attr('id'); 337 var viewer = S7dmUtils[compId], 338 assetType = component.data('asset-type'), 339 mode = component.data('mode'), 340 stageSize = component.data('stagesize'); 341 342 if (typeof viewer != 'undefined' && viewer != null) { 343 viewer.dispose(); 344 S7dmUtils[compId] = null; 345 component.removeClass(responsiveViewerCSS); 346 } 347 component.html(''); 348 var viewerType = component.data('viewer-type'); 349 350 if (viewerType) { 351 352 var viewerParams = buildViewerParams(component);
353 var viewerSettings = { 354 'containerId' : component.attr('id'), 355 'params': viewerParams, 356 "handlers":{ 357 "initComplete":function() { 358 if($('body').hasClass('elements-dynamic-video')){ 359 const videoPlayer = viewer.getComponent("videoPlayer"); 360 var dcTitle = "Closed Caption Button"; 361 if(!viewer.isCaption){ 362 const closedCaptionButton = viewer.getComponent("closedCaptionButton"); 363 $("#"+closedCaptionButton.compId).addClass("s7closedCaptionDisabled"); 364 closedCaptionButton.component.toolTipSelected = "Closed Caption not Available"; 365 closedCaptionButton.component.toolTipUnselected = "Closed Caption not Available"; 366 dcTitle = "Closed Caption Button Disable" 367 } 368 const container = document.getElementById(viewer.containerId); 369 if (container) { 370 const ccBtnElem = container.querySelector('[data-component="ClosedCaptionButton"].s7closedcaptionbutton'); 371 if (ccBtnElem) { 372 ccBtnElem.addEventListener('click', function() { 373 if (document.body.getAttribute('data-cmp-data-layer-enabled') !== undefined) { 374 window.adobeDataLayer.push({ 375 event: "cmp:click", 376 attributes: { 377 "@type": "global/components/globalcomponents/navigation/global-link/v1/global-link/link", 378 "dc:title": dcTitle, 379 "parentId": "internal", 380 "xdm:linkTarget": "_self", 381 "xdm:linkType": "internal", 382 "xdm:linkURL": "#" 383 } 384 }); 385 } 386 }); 387 } 388 } 389 390 // Add an event listener for the VideoPlayer navigation/chapters change event 391 videoPlayer.addEventListener(s7sdk.event.VideoEvent.NOTF_NAVIGATION, function(event){ 392 videoChapterInit(event.s7event.data, viewer); 393 const videoScrubber = viewer.getComponent('videoScrubber'); 394 videoScrubber.setNavigation(event.s7event.data); // Forcing to load again while we have resize. 395 }, false); 396 397 // Add an event listener for the VideoPlayer volume change event 398 videoPlayer.addEventListener(s7sdk.event.VideoEvent.NOTF_VOLUME, function(event){ 399 // This event is used to update model issue with volume & timer. 400 const controlBar = viewer.getComponent("controls"); 401 if(!$("#"+controlBar.compId).find(".s7customTimer").length){ 402 if(window.DMvideoLoadIcons){ 403 window.DMvideoLoadIcons(); 404 }
405 onNotifyVideoTime(viewer); 406 } 407 408 }, false); 409 410 // Add an event listener for the VideoPlayer notify ready event 411 videoPlayer.addEventListener(s7sdk.event.StatusEvent.NOTF_VIEW_READY, function(event){ 412 if(window.DMvideoLoadIcons){ 413 window.DMvideoLoadIcons(); 414 } 415 if(window.exitModalVideoUpdate && this.closest(".cmp-extended-modal")){ 416 window.exitModalVideoUpdate(); 417 } 418 updatePlayTime(viewer); 419 onNotifyVideoTime(viewer); 420 setupCustomTabOrder(viewer); 421 }, false); 422 423 // Add an event listener for the VideoPlayer duration change event 424 videoPlayer.addEventListener(s7sdk.event.VideoEvent.NOTF_DURATION, function(event){ 425 if(window.DMvideoLoadIcons){ 426 window.DMvideoLoadIcons(); 427 } 428 if(window.exitModalVideoUpdate && this.closest(".cmp-extended-modal")){ 429 window.exitModalVideoUpdate(); 430 } 431 updatePlayTime(viewer);
432 onNotifyVideoTime(viewer); 433 }, false); 434 435 // Add an event listener for the VideoPlayer current time change event 436 videoPlayer.addEventListener(s7sdk.event.VideoEvent.NOTF_CURRENT_TIME, function(event){ 437 onNotifyVideoTime(viewer); 438 }, false); 439 440 /* In future if any resize issue comes we could test & use this by removing modal exitModalVideoUpdate funtion 441 // Create ParameterManager instance to handles modifiers 442 const params = new s7sdk.ParameterManager(); 443 // Create the Container component object 444 const container = viewer.getComponent('container'); 445 // Add an event listener for Container resize events 446 container.addEventListener(s7sdk.event.ResizeEvent.COMPONENT_RESIZE, function(event){ 447 videoPlayer.resize(event.s7event.w, event.s7event.h); 448 }, false);*/ 449 } 450 } 451 }, 452 }; 453 if (!(viewerType == 'FlyoutViewer' && stageSize)) { 454 component.addClass(responsiveViewerCSS); 455 } 456 viewer = new s7viewers[viewerType](viewerSettings); 457 if (typeof Granite != 'undefined' && typeof Granite.I18n != 'undefined') { 458 viewer.setLocalizedTexts(getLocalizedText()); //passing localized text to the viewer 459 } 460 S7dmUtils[compId] = viewer; 461 viewer.init(); 462 } 463 else if(assetType === 'image') { 464 if (component.data('breakpoints') || mode == 'smartcrop') { 465 component[0].removeAttribute('data-stagesize'); 466 buildResponsiveImage(component); 467 } 468 else { 469 component[0].removeAttribute('data-enablehd'); 470 buildImage(component); 471 } 472 } 473 474 } 475 476 /** 477 * Build Image and anchor when there is no viewer constructor defined for IMAGE ONLY 478 * @param component a div component contains viewer config 479 */ 480 function buildImage(component) { 481 var stageSize = component.data('stagesize'), 482 linkURL = component.data('linkurl'), 483 linkTarget = component.data('linktarget'), 484 title = component.data('title'), 485 altText = component.data('alt'), 486 imagePreset = component.data('imagepreset'), 487 imageServer = component.data('imageserver'), 488 modifiers = component.data('urlmodifiers'); 489 490 var imgSetup = { 491 'src': imageServer + component.data('asset-path') 492 } 493 if (imagePreset) { 494 imgSetup['src'] += '?$' + imagePreset + '$'; 495 } 496 if (modifiers) { 497 imgSetup['src'] += (imagePreset ? '&' : '?') + modifiers 498 } 499 500 if (stageSize) { 501 var stageSizeParts = stageSize.split(','); 502 imgSetup['width'] = stageSizeParts[0]; 503 if (stageSizeParts.length > 1) { 504 imgSetup['height'] = stageSizeParts[1]; 505 } 506 } 507 508 var imgComp = $('<img>', imgSetup); 509 //if there is link, wrap it around image 510 if (linkURL) { 511 var anchorSetup = { 512 'href': linkURL, 513 'target': linkTarget 514 }; 515 if (altText) { 516 anchorSetup['alt'] = altText; 517 anchorSetup['title'] = altText; // default to alt text 518 imgComp.attr('alt', altText); 519 } 520 if (title) { 521 anchorSetup['title'] = title; 522 } 523 var anchor = $('<a>', anchorSetup); 524 anchor.append(imgComp); 525 component.append(anchor); 526 } 527 else { 528 //Add alt text if it's set 529 if (altText) { 530 imgComp.attr('alt', altText); 531 } 532 component.append(imgComp); 533 } 534 535 } 536 537 /** 538 * Build responsive image 539 * @param component container 540 */ 541 function buildResponsiveImage(component) { 542 var imagePreset = component.data('imagepreset'), 543 imageServer = component.data('imageserver'), 544 linkURL = component.data('linkurl'), 545 linkTarget = component.data('linktarget'), 546 title = component.data('title'), 547 altText = component.data('alt'); 548 var modifiers = component.data('urlmodifiers'); 549 var respCon = $('<div>', { 'class': 's7responsiveContainer' }); 550 var respImgId = component.attr('id') + '_resp'; 551 var respImgSetup = {
552 'id': respImgId, 553 'src': "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7", 554 'data-src': imageServer + component.data('asset-path'), 555 'class': 'fluidimage', 556 'data-mode': component.data('mode'), 557 'data-breakpoints': component.data('breakpoints'), 558 'data-enablehd': component.data('enablehd') == "never" ? "never" : "always" 559 } 560 if (imagePreset) { 561 respImgSetup['data-src'] += '?$' + imagePreset + '$'; 562 } 563 if (modifiers) { 564 respImgSetup['data-src'] += (imagePreset ? '&' : '?') + modifiers 565 } 566 var respImg = $('<img>', respImgSetup); 567 //if there is link, wrap it around image 568 if (linkURL) { 569 var anchorSetup = { 570 'href': linkURL, 571 'target': linkTarget 572 }; 573 if (altText) { 574 anchorSetup['alt'] = altText; 575 anchorSetup['title'] = altText; // default to alt text 576 respImg.attr('alt', altText); 577 } 578 if (title) { 579 anchorSetup['title'] = title; 580 } 581 var anchor = $('<a>', anchorSetup); 582 anchor.append(respImg); 583 respCon.append(anchor); 584 } else { 585 if (altText) { 586 respImg.attr('alt', altText); 587 } 588 respCon.append(respImg); 589 } 590 component.append(respCon); 591 s7responsiveImage(document.getElementById(respImgId)); 592 } 593 594 /** 595 * @param component a div element with viewer setup 596 * @return viewer parameters in JSON 597 */ 598 function buildViewerParams(component) { 599 var assetPath = component.data('asset-path'), 600 assetType = component.data('asset-type'), 601 viewerType = component.data('viewer-type'), 602 imageserver = component.data('imageserver'), 603 videoserver = component.data('videoserver'), 604 contentserver = component.data('contenturl'), 605 config = component.data('config'), 606 wcmdisabled = component.data('wcmdisabled'), 607 stageSize = component.data('stagesize'), 608 viewerModifiers = component.data('viewermodifiers'), 609 isdms7 = component.data('dms7'); 610 611 var viewerParams = { 612 'asset': assetPath, 613 'serverurl': imageserver, 614 'contenturl': contentserver, 615 }; 616 //Add extra viewer modifiers if any 617 if (viewerModifiers) { 618 $.extend(viewerParams, getViewerModifiers(viewerModifiers)); 619 } 620 621 var isAuthor = !wcmdisabled && wcmdisabled != ''; 622 623 //Add cache=off when WCM is not disabled (author side) 624 if (isAuthor) { 625 viewerParams['asset'] += '?cache=off'; 626 } 627 if (stageSize) { 628 viewerParams['stagesize'] = stageSize; 629 } 630 if (viewerType == 'FlyoutViewer') { 631 viewerParams['imagereload'] = '1,breakpoint,100;320;480'; 632 } 633 if (assetPath.indexOf('/') != 0) { 634 viewerParams['aemmode'] = '0'; 635 } 636 637 //For video, we add videoserverurl 638 if (viewerType.indexOf('Video') >= 0 || viewerType.indexOf('Mixed') >= 0) { 639 viewerParams['videoserverurl'] = videoserver; 640 // force native if 641 // Asset is non-AVS video (apply to both DMS7 and DM Hybrid for playing progressively) OR 642 // (Asset is DMS7 video regardless of AVS or non-AVS AND the page is on author side) 643 if (assetType == 'video' || ((typeof isdms7 != 'undefined') && isAuthor)) { 644 viewerParams['playback'] = 'native'; 645 viewerParams['progressivebitrate'] = '20000'; 646 } 647 } 648 //check for viewer preset setup 649 if (typeof config != 'undefined' && config.length > 0) { 650 viewerParams['config'] = getViewerPresetPath(config); 651 } 652 // viewerParams['navigation'] = 'Scene7SharedAssets/adobe_qbc_final_nc'; 653 return viewerParams; 654 } 655 656 /** 657 * Parse viewer preset path for viewer-usable format 658 * @param config viewer preset path stored in the component node 659 * @return viewer-usable format viewer preset path 660 */ 661 function getViewerPresetPath(config) { 662 var configParts = config.split('|'); 663 return configParts[0]; 664 } 665 666 /** 667 * Parse viewer preset path for isCustom Preset flag 668 * @param config viewer preset string 669 * @return flag for custom preset 670 */ 671 function isCustomPreset(config) { 672 var configParts = config.split('|'); 673 return configParts[2]; 674 } 675 676 /** 677 * Fail viewer loader handler 678 */
679 function failViewerLoader(){ 680 console.log('S7Viewer is missing'); 681 } 682 683 /** 684 * Parse free-form viewer modifiers 685 * @param viewerModifiers string for free-form viewer modifiers 686 * @return JSON representing viewer modifiers 687 */ 688 function getViewerModifiers(viewerModifiers) { 689 var modifiers = {}; 690 if (viewerModifiers) { 691 var items = viewerModifiers.split('&'); 692 for (var i = 0; i < items.length; i++) { 693 //only when there is key=val pair 694 if (items[i].indexOf('=') > 0) { 695 var key = items[i].substring(0, items[i].indexOf('=')); 696 var val = items[i].substring(items[i].indexOf('=') + 1); 697 modifiers[key] = val; 698 } 699 } 700 } 701 return modifiers; 702 } 703 704 /** 705 * Get localized text for viewer from s7sdk_i18n.localizedText 706 * @return JSON for localized text 707 */ 708 function getLocalizedText() { 709 var localizedText = {}; 710 localizedText[Granite.I18n.getLocale()] = formatLocalizedText(s7sdk_i18n.localizedText); 711 localizedText['defaultLocale'] = Granite.I18n.getLocale(); 712 return localizedText; 713 } 714 715 /** 716 * Format localized text into a correct viewer format 717 * @param localizedText localized text parsed from s7sdk 718 * @return formatted localized text with correct key for viewer 719 */ 720 function formatLocalizedText(localizedText) { 721 var formatTexts = {}; 722 for (var compKey in localizedText) { 723 var compObj = localizedText[compKey]; 724 for (var symbolKey in compObj) { 725 var modKey = compKey + '.' + symbolKey; 726 var symbolVal = compObj[symbolKey]; 727 formatTexts[modKey] = symbolVal; 728 } 729 } 730 return formatTexts; 731 } 732 733}).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.