1 2// CANVA 3function extractYouTubeVideoId(input) { 4 if (!input) { 5 return ''; 6 } 7 8 var value = String(input).trim(); 9 if (!value) { 10 return ''; 11 } 12 13 // Raw id 14 if (/^[a-zA-Z0-9_-]{11}$/.test(value)) { 15 return value; 16 } 17 18 // URL formats 19 var patterns = [ 20 /[?&]v=([a-zA-Z0-9_-]{11})/, 21 /youtu\.be\/([a-zA-Z0-9_-]{11})/, 22 /youtube\.com\/embed\/([a-zA-Z0-9_-]{11})/, 23 /youtube\.com\/shorts\/([a-zA-Z0-9_-]{11})/ 24 ]; 25 26 for (var i = 0; i < patterns.length; i++) { 27 var match = value.match(patterns[i]); 28 if (match && match[1]) { 29 return match[1]; 30 } 31 } 32 33 return ''; 34} 35 36function extractVimeoVideoId(input) { 37 if (!input) { 38 return ''; 39 } 40 41 var value = String(input).trim(); 42 if (!value) { 43 return ''; 44 } 45 46 if (/^\d+$/.test(value)) { 47 return value; 48 } 49 50 var patterns = [ 51 /vimeo\.com\/(?:video\/)?(\d+)/, 52 /player\.vimeo\.com\/video\/(\d+)/, 53 /vimeo\.com\/channels\/[^/]+\/(\d+)/, 54 /vimeo\.com\/groups\/[^/]+\/videos\/(\d+)/ 55 ]; 56 57 for (var i = 0; i < patterns.length; i++) { 58 var match = value.match(patterns[i]); 59 if (match && match[1]) { 60 return match[1]; 61 } 62 } 63 64 return ''; 65} 66 67function ensureYouTubeFloatingWindow() { 68 if (document.getElementById('canva-youtube-window')) { 69 return; 70 } 71 72 var style = document.createElement('style'); 73 style.setAttribute('data-canva-youtube-style', '1'); 74 style.textContent = ` 75 #canva-youtube-window.canva-hidden { display: none !important; } 76 #canva-youtube-window { 77 position: fixed; 78 inset: 0; 79 background: rgba(0, 0, 0, 0.9); 80 z-index: 99999; 81 justify-content: center; 82 align-items: flex-start; 83 padding: 50px 20px; 84 overflow: auto; 85 }
86 #canva-youtube-window:not(.canva-hidden) { display: flex; } 87 #canva-youtube-window .canva-youtube-content { 88 position: relative; 89 width: 80vw; 90 max-height: 80vh; 91 background: transparent; 92 padding: 0; 93 } 94 #canva-youtube-window .canva-youtube-close { 95 position: absolute; 96 right: -6px; 97 top: -40px; 98 color: #fff; 99 font-size: 36px; 100 line-height: 1; 101 cursor: pointer; 102 user-select: none; 103 z-index: 1; 104 } 105 #canva-youtube-window .canva-youtube-holder { 106 position: relative; 107 padding-bottom: 56.25%; 108 height: 0; 109 overflow: hidden; 110 } 111 #canva-youtube-window .canva-youtube-holder iframe { 112 position: absolute; 113 inset: 0; 114 width: 100%; 115 height: 100%; 116 border: 0; 117 }`; 118 document.head.appendChild(style); 119 120 var wrapper = document.createElement('div'); 121 wrapper.id = 'canva-youtube-window'; 122 wrapper.className = 'canva-hidden'; 123 wrapper.innerHTML = ` 124 <div class="canva-youtube-content"> 125 <span class="canva-youtube-close" aria-label="Cerrar">×</span> 126 <div class="canva-youtube-holder" id="canva-youtube-holder"></div> 127 </div>`; 128 document.body.appendChild(wrapper); 129 130 function closeYouTubeFloatingWindow() { 131 var holder = document.getElementById('canva-youtube-holder'); 132 if (holder) { 133 holder.innerHTML = ''; 134 } 135 wrapper.classList.add('canva-hidden'); 136 } 137 138 wrapper.querySelector('.canva-youtube-close').addEventListener('click', closeYouTubeFloatingWindow); 139 wrapper.addEventListener('click', function (event) { 140 if (event.target === wrapper) { 141 closeYouTubeFloatingWindow(); 142 } 143 }); 144 document.addEventListener('keydown', function (event) { 145 if (event.key === 'Escape' && !wrapper.classList.contains('canva-hidden')) { 146 closeYouTubeFloatingWindow(); 147 } 148 }); 149 150 window.closeCanvaYouTubeFloatingWindow = closeYouTubeFloatingWindow; 151} 152 153function openYouTubeFloatingWindow(videoInput) { 154 ensureYouTubeFloatingWindow(); 155 var videoId = extractYouTubeVideoId(videoInput); 156 if (!videoId) { 157 return; 158 } 159 160 var wrapper = document.getElementById('canva-youtube-window'); 161 var holder = document.getElementById('canva-youtube-holder'); 162 if (!wrapper || !holder) { 163 return; 164 } 165 166 var videoURL = 'https://www.youtube.com/embed/' + videoId + '?autoplay=1&rel=0'; 167 holder.innerHTML = '<iframe src="' + videoURL + '" allow="autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>'; 168 wrapper.classList.remove('canva-hidden'); 169} 170 171function openVimeoFloatingWindow(videoInput) { 172 ensureYouTubeFloatingWindow(); 173 var videoId = extractVimeoVideoId(videoInput); 174 if (!videoId) { 175 return; 176 } 177 178 var wrapper = document.getElementById('canva-youtube-window'); 179 var holder = document.getElementById('canva-youtube-holder'); 180 if (!wrapper || !holder) { 181 return; 182 } 183 184 var videoURL = 'https://player.vimeo.com/video/' + videoId + '?autoplay=1&title=0&byline=0&portrait=0'; 185 holder.innerHTML = '<iframe src="' + videoURL + '" allow="autoplay; fullscreen; picture-in-picture" allowfullscreen></iframe>'; 186 wrapper.classList.remove('canva-hidden'); 187} 188 189function enforceInlineMobileVideos() { 190 $('.canva video').each(function () { 191 var video = this; 192 video.setAttribute('playsinline', ''); 193 video.setAttribute('webkit-playsinline', ''); 194 if (!video.getAttribute('preload')) { 195 video.setAttribute('preload', 'metadata'); 196 } 197 video.muted = true; 198 video.defaultMuted = true; 199 video.playsInline = true; 200 }); 201} 202 203function syncMobileVideoPlayback() { 204 enforceInlineMobileVideos(); 205 206 $('.canva video').each(function () { 207 var video = this; 208 var $video = $(video); 209 var isVisible = $video.is(':visible'); 210 var isInHiddenSlide = false; 211 212 var flexItem = $video.closest('.canvasflex'); 213 if (flexItem.length && !flexItem.hasClass('active')) { 214 isInHiddenSlide = true; 215 } 216 217 var carouselItem = $video.closest('.carousel .item'); 218 if (carouselItem.length && !carouselItem.hasClass('active')) { 219 isInHiddenSlide = true; 220 } 221 222 var swiperSlide = $video.closest('.canva-peek-swiper .swiper-slide'); 223 if (swiperSlide.length && !swiperSlide.hasClass('swiper-slide-active')) { 224 isInHiddenSlide = true; 225 } 226 227 if (!isVisible || isInHiddenSlide) { 228 video.pause(); 229 return; 230 } 231 232 if (video.autoplay) { 233 var promise = video.play(); 234 if (promise && typeof promise.catch === 'function') { 235 promise.catch(function () { }); 236 } 237 } 238 }); 239} 240 241function scheduleMobileVideoPlaybackSync() { 242 syncMobileVideoPlayback(); 243 requestAnimationFrame(function () { 244 syncMobileVideoPlayback(); 245 }); 246 setTimeout(function () { 247 syncMobileVideoPlayback(); 248 }, 120); 249 setTimeout(function () { 250 syncMobileVideoPlayback(); 251 }, 320); 252} 253 254$(window).on('resize', function (e) { 255 doScale(); 256 scheduleMobileVideoPlaybackSync(); 257}); 258$(document).ready(function () { 259 enforceInlineMobileVideos(); 260 scheduleMobileVideoPlaybackSync(); 261 doScale(); 262 loadFonts(); 263 $('body').on('click', '.layer', function (e) { 264 e.preventDefault(); 265 e.stopPropagation(); 266 var layer = $(this); 267 var action = layer.attr('data-action'); 268 if (action && action != 'none') { 269 var target = layer.attr('data-target'); 270 var link = layer.attr('data-link'); 271 var info = layer.attr('data-info'); 272 273 switch (action) { 274 case 'url': 275 if (target && target == 'blank') { 276 window.open(link, target).focus(); 277 } else { 278 window.open(link, '_self'); 279 } 280 break; 281 282 case 'section': 283 if (target && target == 'blank') { 284 window.open(link, target).focus(); 285 } else if (target && target == 'modal') { 286 open_modal(link, 'ajaxmodal', ''); 287 } else { 288 window.open(link, '_self'); 289 } 290 break; 291 292 case 'whatsapp':
293 window.open('https://api.whatsapp.com/send?phone=' + link, target).focus(); 294 break; 295 296 case 'phone': 297 window.open('tel:' + link); 298 break; 299 300 case 'email': 301 window.open('mailto:' + link); 302 break; 303 304 case 'gotoslide': 305 var slideNumber = parseInt(link, 10); 306 if (!isNaN(slideNumber) && slideNumber > 0) { 307 // 0) Swiper peek mode 308 var peekSlider = layer.closest('.canva-peek-swiper'); 309 if (peekSlider.length) { 310 var targetIndex = slideNumber - 1; 311 var swiperInstance = peekSlider.data('swiper') || (peekSlider.get(0) && peekSlider.get(0).swiper); 312 if (swiperInstance) { 313 if (swiperInstance.params && swiperInstance.params.loop && typeof swiperInstance.slideToLoop === 'function') { 314 swiperInstance.slideToLoop(targetIndex); 315 } else if (typeof swiperInstance.slideTo === 'function') { 316 swiperInstance.slideTo(targetIndex); 317 } 318 doScale(); 319 scheduleMobileVideoPlaybackSync(); 320 break; 321 } 322 } 323 324 // 1) Website/keynote mode (containers with id canvawebsite{rnd}{n}) 325 var container = layer.closest('[id^="canvawebsite"]'); 326 if (!container.length) { 327 container = layer.closest('.canvawebsite'); 328 } 329 var rnd = container.attr('data-rnd'); 330 var new_container = rnd ? container.siblings('#canvawebsite' + rnd + slideNumber) : $(); 331 if (new_container[0]) { 332 container.hide(); 333 new_container.show(); 334 doScale(); 335 scheduleMobileVideoPlaybackSync(); 336 break; 337 } 338 339 // 2) Bootstrap carousel mode 340 var carousel = layer.closest('.carousel'); 341 if (carousel.length) { 342 var targetIndex = slideNumber - 1; 343 if (typeof carousel.carousel === 'function') { 344 carousel.carousel(targetIndex); 345 } else { 346 var items = carousel.find('.carousel-inner .item'); 347 var indicators = carousel.find('.carousel-indicators li'); 348 items.removeClass('active').eq(targetIndex).addClass('active'); 349 indicators.removeClass('active').eq(targetIndex).addClass('active'); 350 } 351 doScale(); 352 scheduleMobileVideoPlaybackSync(); 353 break; 354 } 355 356 // 3) Accordion/flexslider mode (data-order is 0-based) 357 var flexslider = layer.closest('.flexslider'); 358 if (flexslider.length) { 359 var order = slideNumber - 1; 360 var active = flexslider.find('.canvasflex.active'); 361 var next = flexslider.find('.canvasflex[data-order="' + order + '"]'); 362 if (next.length) { 363 active.removeClass('active'); 364 next.addClass('active'); 365 doScale(); 366 scheduleMobileVideoPlaybackSync(); 367 } 368 } 369 } 370 break; 371 372 case 'html': 373 break; 374 375 case 'pdf': 376 break; 377 378 case 'video': 379 break; 380 381 case 'youtube': 382 openYouTubeFloatingWindow(link); 383 break; 384 case 'vimeo': 385 openVimeoFloatingWindow(link); 386 break; 387 388 case 'gmap': 389 break; 390 } 391 } 392 }); 393 394 $('body').on('mouseenter', '.canvashover .flexslider li', function (e) { 395 if (!$(this).hasClass('active')) { 396 $(this).siblings().removeClass('active'); 397 $(this).addClass('active'); 398 scheduleMobileVideoPlaybackSync(); 399 } 400 }); 401 402 $('body').on('slid.bs.carousel', '.carousel', function () { 403 scheduleMobileVideoPlaybackSync(); 404 }); 405 406 $('body').on('transitionend webkitTransitionEnd', '.flexslider .canvasflex', function () { 407 if ($(this).hasClass('active')) { 408 scheduleMobileVideoPlaybackSync(); 409 } 410 }); 411}); 412 413function loadFont(aval) { 414 const regex = /^custom\d+$/i; 415 const value = aval.replaceAll('"', '').replaceAll("'", "").replaceAll(', sans-serif', '').replaceAll(' !important', ''); 416 var fontlink = `https://fonts.googleapis.com/css?family=${value}`; 417 if (regex.test(aval)) { 418 //Custom font 419 fontlink = server + `customfont?family=${value}`; 420 } 421 const link = document.createElement('link'); 422 link.setAttribute('rel', 'stylesheet'); 423 link.setAttribute('href', fontlink); 424 document.head.appendChild(link); 425} 426 427//Loads gfonts family 428function loadFonts() { 429 const loaded = []; 430 $('.layercontent').each(function () { 431 var content = $(this); 432 aval = content.css('font-family'); 433 if (aval) { 434 if (!loaded.includes(aval)) { 435 loaded.push(aval); 436 loadFont(aval); 437 } 438 } 439 }); 440} 441 442 443function doScale(id = '') { 444 $('.canva' + id).each(function () { 445 var canva = $(this); 446 var parent = canva.parent(); 447 //Use reference to resize based on other div instead of parent size (for accordion) 448 var pwidth = parent.width(); 449 var pheight = parent.height(); 450 451 if (canva.attr('data-reference')) { 452 var reference = $(canva.attr('data-reference')); 453 pwidth = reference.width(); 454 pheight = reference.height(); 455 } 456 457 var scale = Math.min( 458 pwidth / canva.attr('width'), 459 pheight / canva.attr('height') 460 ); 461 if (canva.attr('width') * scale < pwidth) { 462 scale = pwidth / canva.attr('width'); 463 } 464 canva.css({ 465 transformOrigin: 'top left', 466 transform: "translate(0%,0%) scale(" + scale + ")" 467 }); 468 canva.css('opacity', 1); 469 var peekSlide = canva.closest('.canva-peek-swiper .swiper-slide'); 470 var shouldAnimateLayers = !peekSlide.length || peekSlide.hasClass('swiper-slide-active'); 471 // Restart layer animations every time the canvas is shown/scaled (initial paint, 472 // slide switch, resize), so public view reliably plays them. 473 canva.find('.layer').each(function () { 474 var layer = $(this); 475 var animationName = String(layer.attr('data-animate') || '').trim(); 476 if (!animationName || animationName === 'none') { 477 return; 478 } 479 var layerStyleAttr = String(layer.attr('style') || '').toLowerCase(); 480 var hasInlineDuration = /(?:^|;
480)\s*(?:-webkit-)?animation-duration\s*:/.test(layerStyleAttr); 481 var hasInlineDelay = /(?:^|;)\s*(?:-webkit-)?animation-delay\s*:/.test(layerStyleAttr); 482 var hasInlineIterations = /(?:^|;)\s*(?:-webkit-)?animation-iteration-count\s*:/.test(layerStyleAttr); 483 var hasInlineDirection = /(?:^|;)\s*(?:-webkit-)?animation-direction\s*:/.test(layerStyleAttr); 484 var hasInlineTiming = /(?:^|;)\s*(?:-webkit-)?animation-timing-function\s*:/.test(layerStyleAttr); 485 var animTarget = layer.find('.layeranim').first(); 486 if (!animTarget.length) { 487 animTarget = layer.find('.layercontent').first(); 488 } 489 if (!animTarget.length) { 490 return; 491 } 492 if (!shouldAnimateLayers) { 493 animTarget.removeClass('animated'); 494 return; 495 } 496 var animationOverrides = {}; 497 if (hasInlineDuration) { 498 var inlineDuration = String(layer.css('animation-duration') || '').trim(); 499 if (inlineDuration && inlineDuration !== '0s' && inlineDuration !== '0ms') { 500 animationOverrides['animation-duration'] = inlineDuration; 501 animationOverrides['-webkit-animation-duration'] = inlineDuration; 502 } 503 } 504 if (hasInlineDelay) { 505 var inlineDelay = String(layer.css('animation-delay') || '').trim(); 506 if (inlineDelay) { 507 animationOverrides['animation-delay'] = inlineDelay; 508 animationOverrides['-webkit-animation-delay'] = inlineDelay; 509 } 510 } 511 if (hasInlineIterations) { 512 var inlineIterations = String(layer.css('animation-iteration-count') || '').trim(); 513 if (inlineIterations) { 514 animationOverrides['animation-iteration-count'] = inlineIterations; 515 animationOverrides['-webkit-animation-iteration-count'] = inlineIterations; 516 } 517 } 518 if (hasInlineDirection) { 519 var inlineDirection = String(layer.css('animation-direction') || '').trim(); 520 if (inlineDirection) { 521 animationOverrides['animation-direction'] = inlineDirection; 522 animationOverrides['-webkit-animation-direction'] = inlineDirection; 523 } 524 } 525 if (hasInlineTiming) { 526 var inlineTiming = String(layer.css('animation-timing-function') || '').trim(); 527 if (inlineTiming) { 528 animationOverrides['animation-timing-function'] = inlineTiming; 529 animationOverrides['-webkit-animation-timing-function'] = inlineTiming; 530 } 531 } 532 if (Object.keys(animationOverrides).length) { 533 animTarget.css(animationOverrides); 534 } 535 var prevAnimation = String(animTarget.attr('data-current-animation') || '').trim(); 536 if (prevAnimation && prevAnimation !== animationName) { 537 animTarget.removeClass(prevAnimation); 538 } 539 animTarget.removeClass('animated'); 540 animTarget.removeClass(animationName); 541 if (animTarget.get(0)) { 542 void animTarget.get(0).offsetWidth; 543 } 544 animTarget.addClass(animationName + ' animated'); 545 if (!hasInlineDuration) { 546 var resolvedDuration = String(animTarget.css('animation-duration') || '').trim(); 547 if (!resolvedDuration || resolvedDuration === '0s' || resolvedDuration === '0ms') { 548 animTarget.css({ 549 'animation-duration': '1s', 550 '-webkit-animation-duration': '1s' 551 }); 552 } 553 } 554 animTarget.attr('data-current-animation', animationName); 555 }); 556 557 parent.height(canva.height() * scale); 558 }); 559} 560 561 562function initializeFlexslider(canvasId, interval, loop) { 563 $(document).ready(function () { 564 var time = interval * 1000; 565 var order = 1; 566 var timerId = setInterval(function () { nextSlide(); }, time); 567 $(canvasId + ' .flexslider').on('mouseenter', function () { 568 clearInterval(timerId); 569 }); 570 $(canvasId + ' .flexslider').on('mouseleave', function () { 571 timerId = setInterval(function () { nextSlide(); }, time); 572 }); 573 function nextSlide() { 574 var active = $(canvasId + ' .flexslider .canvasflex.active'); 575 var next = $(canvasId + ' .flexslider .canvasflex[data-order=' + order + ']'); 576 if (next.length) { 577 active.removeClass('active'); 578 next.addClass('active'); 579 order = (order % $(canvasId + ' .flexslider .canvasflex').length) + 1; 580 scheduleMobileVideoPlaybackSync(); 581 } else { 582 if (loop) { 583 order = 0; 584 $(canvasId + ' .flexslider .canvasflex').removeClass('active'); 585 $(canvasId + ' .flexslider .canvasflex[data-order=0]').addClass('active'); 586 scheduleMobileVideoPlaybackSync(); 587 } 588 } 589 } 590 }); 591} 592 593window.addEventListener('keydown', function (event) { 594 var target = event.target; 595 var isTypingContext = false;
596 if (target) { 597 var tag = (target.tagName || '').toLowerCase(); 598 isTypingContext = target.isContentEditable || tag === 'input' || tag === 'textarea' || tag === 'select'; 599 } 600 601 var isCmdCtrl = !!(event.metaKey || event.ctrlKey); 602 var key = String(event.key || '').toLowerCase(); 603 if (!isCmdCtrl || key !== 'm' || isTypingContext) { 604 return; 605 } 606 607 event.preventDefault(); 608 event.stopPropagation(); 609 610 if (typeof window.toggleAddSlideTemplatePicker === 'function') { 611 window.toggleAddSlideTemplatePicker(); 612 return; 613 } 614 615 var addSlideButton = document.querySelector('.add-slide-button'); 616 if (addSlideButton && typeof addSlideButton.click === 'function') { 617 addSlideButton.click(); 618 } 619}, true); 620 621// Canva layer tooltips (public website only): delegated, independent from Bootstrap tooltip. 622(function () { 623 function initCanvaLayerTooltipsPublic() { 624 var layerSelector = '.canva .layer[data-tooltip]'; 625 var bubbleId = 'canva-layer-tooltip-bubble'; 626 var bubble = document.getElementById(bubbleId); 627 if (!bubble) { 628 bubble = document.createElement('div'); 629 bubble.id = bubbleId; 630 bubble.className = 'canva-layer-tooltip-bubble'; 631 document.body.appendChild(bubble); 632 } 633 634 function positionBubble(clientX, clientY) { 635 if (!bubble || bubble.style.display !== 'block') { 636 return; 637 } 638 var x = Number.isFinite(clientX) ? clientX : 0; 639 var y = Number.isFinite(clientY) ? clientY : 0; 640 var maxX = window.innerWidth - bubble.offsetWidth - 8; 641 var maxY = window.innerHeight - bubble.offsetHeight - 8; 642 var finalX = Math.max(8, Math.min(maxX, x + 12)); 643 var finalY = Math.max(8, Math.min(maxY, y - bubble.offsetHeight - 12)); 644 bubble.style.left = finalX + 'px'; 645 bubble.style.top = finalY + 'px'; 646 } 647 648 $(document).off('.canvalayertooltip_public'); 649 $(document).on('mouseenter.canvalayertooltip_public focusin.canvalayertooltip_public', layerSelector, function (e) { 650 var text = String($(this).attr('data-tooltip') || '').trim(); 651 if (!text) { 652 bubble.style.display = 'none'; 653 return; 654 } 655 bubble.textContent = text; 656 bubble.style.display = 'block'; 657 if (e && Number.isFinite(e.clientX) && Number.isFinite(e.clientY)) { 658 positionBubble(e.clientX, e.clientY); 659 } 660 }); 661 662 $(document).on('mousemove.canvalayertooltip_public', layerSelector, function (e) { 663 positionBubble(e.clientX, e.clientY); 664 }); 665 666 $(document).on('mouseleave.canvalayertooltip_public blur.canvalayertooltip_public', layerSelector, function () { 667 bubble.style.display = 'none'; 668 }); 669 } 670 671 $(document).ready(function () { 672 initCanvaLayerTooltipsPublic(); 673 }); 674})();
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.