1var wpAjaxUrl = 'https://luthervillelax.com/wp-admin/admin-ajax.php';var flBuilderUrl = 'https://luthervillelax.com/wp-content/plugins/bb-plugin/';var FLBuilderLayoutConfig = { 2 anchorLinkAnimations : { 3 duration : 1000, 4 easing : 'swing', 5 offset : 100 6 }, 7 paths : { 8 pluginUrl : 'https://luthervillelax.com/wp-content/plugins/bb-plugin/', 9 wpAjaxUrl : 'https://luthervillelax.com/wp-admin/admin-ajax.php' 10 }, 11 breakpoints : { 12 small : 768, 13 medium : 992, 14 large : 1200 }, 15 waypoint: { 16 offset: 80 17 }, 18 emptyColWidth: '0%' 19}; 20(function($){ 21 22 if(typeof FLBuilderLayout != 'undefined') { 23 return; 24 } 25 26 /** 27 * Helper class with generic logic for a builder layout. 28 * 29 * @class FLBuilderLayout 30 * @since 1.0 31 */ 32 FLBuilderLayout = { 33 34 /** 35 * Initializes a builder layout. 36 * 37 * @since 1.0 38 * @method init 39 */ 40 init: function() 41 { 42 // Destroy existing layout events. 43 FLBuilderLayout._destroy(); 44 45 // Init CSS classes. 46 FLBuilderLayout._initClasses(); 47 48 // Init backgrounds. 49 FLBuilderLayout._initBackgroun
49ds(); 50 51 // Init row shape layer height. 52 FLBuilderLayout._initRowShapeLayerHeight(); 53 54 // Only init if the builder isn't active. 55 if ( 0 === $('.fl-builder-edit').length ) { 56 57 // Init module animations. 58 FLBuilderLayout._initModuleAnimations(); 59 60 // Init anchor links. 61 FLBuilderLayout._initAnchorLinks(); 62 63 // Init the browser hash. 64 FLBuilderLayout._initHash(); 65 66 // Init forms. 67 FLBuilderLayout._initForms(); 68 69 FLBuilderLayout._reorderMenu(); 70 } 71 else { 72 FLBuilderLayout._initNestedColsWidth(); 73 } 74 }, 75 76 /** 77 * Public method for refreshing Wookmark or MosaicFlow galleries 78 * within an element. 79 * 80 * @since 1.7.4 81 * @method refreshGalleries 82 */ 83 refreshGalleries: function( element ) 84 { 85 var $element = 'undefined' == typeof element ? $( 'body' ) : $( element ), 86 mfContent = $element.find( '.fl-mosaicflow-content' ), 87 wmContent = $element.find( '.fl-gallery' ), 88 mfObject = null; 89 90 if ( mfContent ) { 91 92 mfObject = mfContent.data( 'mosaicflow' ); 93 94 if ( mfObject ) { 95 mfObject.columns = $( [] ); 96 mfObject.columnsHeights = []; 97 mfContent.data( 'mosaicflow', mfObject ); 98 mfContent.mosaicflow( 'refill' ); 99 } 100 } 101 if ( wmContent ) { 102 wmContent.trigger( 'refreshWookmark' ); 103 } 104 }, 105 106 /** 107 * Public method for refreshing Masonry within an element 108 * 109 * @since 1.8.1 110 * @method refreshGridLayout 111 */ 112 refreshGridLayout: function( element ) 113 { 114 var $element = 'undefined' == typeof element ? $( 'body' ) : $( element ), 115 msnryContent = $element.find('.masonry'); 116 117 if ( msnryContent.length ) { 118 msnryContent.masonry('layout'); 119 } 120 }, 121 122 /** 123 * Public method for reloading BxSlider within an element 124 * 125 * @since 1.8.1 126 * @method reloadSlider 127 */ 128 reloadSlider: function( content ) 129 { 130 var $content = 'undefined' == typeof content ? $('body') : $(content); 131 132 // reload sliders. 133 if ($content.find('.bx-viewport > div').length > 0) { 134 $.each($content.find('.bx-viewport > div'), function (key, slider) { 135 setTimeout(function () { 136 $(slider).data('bxSlider').reloadSlider(); 137 }, 100); 138 }); 139 } 140 }, 141 142 /** 143 * Public method for resizing WP audio player 144 * 145 * @since 1.8.2 146 * @method resizeAudio 147 */ 148 resizeAudio: function( element ) 149 { 150 var $element = 'undefined' == typeof element ? $( 'body' ) : $( element ), 151 audioPlayers = $element.find('.wp-audio-shortcode.mejs-audio'), 152 player = null, 153 mejsPlayer = null, 154 rail = null, 155 railWidth = 400; 156 157 if ( audioPlayers.length && typeof mejs !== 'undefined' ) { 158 audioPlayers.each(function(){ 159 player = $(this); 160 mejsPlayer = mejs.players[player.attr('id')]; 161 rail = player.find('.mejs-controls .mejs-time-rail'); 162 var innerMejs = player.find('.mejs-inner'), 163 total = player.find('.mejs-controls .mejs-time-total'); 164 165 if ( typeof mejsPlayer !== 'undefined' ) { 166 railWidth = Math.ceil(player.width() * 0.8); 167 168 if ( innerMejs.length ) { 169 170 rail.css('width', railWidth +'px!important'); 171 //total.width(rail.width() - 10); 172 173 mejsPlayer.options.autosizeProgress = true; 174 175 // webkit has trouble doing this without a delay 176 setTimeout(function () { 177 mejsPlayer.setControlsSize(); 178 }, 50); 179 180 player.find('.mejs-inner').css({ 181 visibility: 'visible', 182 height: 'inherit' 183 }); 184 } 185 } 186 }); 187 } 188 }, 189 190 /** 191 * Public method for preloading WP audio player when it's inside the hidden element 192 * 193 * @since 1.8.2 194 * @method preloadAudio 195 */ 196 preloadAudio: function(element) 197 { 198 var $element = 'undefined' == typeof element ? $( 'body' ) : $( element ), 199 contentWrap = $element.closest('.fl-accordion-item'), 200 audioPlayers = $element.find('.wp-audio-shortcode.mejs-audio'); 201 202 if ( ! contentWrap.hasClass('fl-accordion-item-active') && audioPlayers.find('.mejs-inner').length ) { 203 audioPlayers.find('.mejs-inner').css({ 204 visibility : 'hidden', 205 height: 0 206 }); 207 } 208 }, 209 210 /** 211 * Public method for resizing slideshow momdule within the tab 212 * 213 * @since 1.10.5 214 * @method resizeSlideshow 215 */ 216 resizeSlideshow: function(){ 217 if(typeof YUI !== 'undefined') { 218 YUI().use('node-event-simulate', function(Y) { 219 Y.one(window).simulate("resize"); 220 }); 221 } 222 }, 223 224 /** 225 * Public method for reloading an embedded Google Map within the tabs or hidden element. 226 * 227 * @since 2.2 228 * @method reloadGoogleMap 229 */ 230 reloadGoogleMap: function(element){ 231 var $element = 'undefined' == typeof element ? $( 'body' ) : $( element ),
232 googleMap = $element.find( 'iframe[src*="google.com/maps"]' ); 233 234 if ( googleMap.length ) { 235 googleMap.attr( 'src', function(i, val) { 236 return val; 237 }); 238 } 239 }, 240 241 /** 242 * Unbinds builder layout events. 243 * 244 * @since 1.0 245 * @access private 246 * @method _destroy 247 */ 248 _destroy: function() 249 { 250 var win = $(window); 251 252 win.off('scroll.fl-bg-parallax'); 253 win.off('resize.fl-bg-video'); 254 }, 255 256 /** 257 * Checks to see if the current device has touch enabled. 258 * 259 * @since 1.0 260 * @access private 261 * @method _isTouch 262 * @return {Boolean} 263 */ 264 _isTouch: function() 265 { 266 if(('ontouchstart' in window) || (window.DocumentTouch && document instanceof DocumentTouch)) { 267 return true; 268 } 269 270 return false; 271 }, 272 273 /** 274 * Checks to see if the current device is mobile. 275 * 276 * @since 1.7 277 * @access private 278 * @method _isMobile 279 * @return {Boolean} 280 */ 281 _isMobile: function() 282 { 283 return /Mobile|Android|Silk\/|Kindle|BlackBerry|Opera Mini|Opera Mobi|webOS/i.test( navigator.userAgent ); 284 }, 285 286 /** 287 * Initializes builder body classes. 288 * 289 * @since 1.0 290 * @access private 291 * @method _initClasses 292 */ 293 _initClasses: function() 294 { 295 var body = $( 'body' ), 296 ua = navigator.userAgent; 297 298 // Add the builder body class. 299 if ( ! body.hasClass( 'archive' ) && $( '.fl-builder-content-primary' ).length > 0 ) { 300 body.addClass('fl-builder'); 301 } 302 303 // Add the builder touch body class. 304 if(FLBuilderLayout._isTouch()) { 305 body.addClass('fl-builder-touch'); 306 } 307 308 // Add the builder mobile body class. 309 if(FLBuilderLayout._isMobile()) { 310 body.addClass('fl-builder-mobile'); 311 } 312 313 if ( $(window).width() < FLBuilderLayoutConfig.breakpoints.small ) { 314 body.addClass( 'fl-builder-breakpoint-small' ); 315 } 316 317 if ( $(window).width() > FLBuilderLayoutConfig.breakpoints.small && $(window).width() < FLBuilderLayoutConfig.breakpoints.medium ) { 318 body.addClass( 'fl-builder-breakpoint-medium' ); 319 } 320 321 if ( $(window).width() > FLBuilderLayoutConfig.breakpoints.medium && $(window).width() < FLBuilderLayoutConfig.breakpoints.large ) { 322 body.addClass( 'fl-builder-breakpoint-large' ); 323 } 324 325 if ( $(window).width() > FLBuilderLayoutConfig.breakpoints.large ) { 326 body.addClass( 'fl-builder-breakpoint-default' ); 327 } 328 329 // IE11 body class. 330 if ( ua.indexOf( 'Trident/7.0' ) > -1 && ua.indexOf( 'rv:11.0' ) > -1 ) { 331 body.addClass( 'fl-builder-ie-11' ); 332 } 333 }, 334 335 /** 336 * Initializes builder node backgrounds that require 337 * additional JavaScript logic such as parallax. 338 * 339 * @since 1.1.4 340 * @access private
341 * @method _initBackgrounds 342 */ 343 _initBackgrounds: function() 344 { 345 var win = $(window); 346 347 // Init parallax backgrounds. 348 if($('.fl-row-bg-parallax').length > 0 && !FLBuilderLayout._isMobile()) { 349 FLBuilderLayout._scrollParallaxBackgrounds(); 350 FLBuilderLayout._initParallaxBackgrounds(); 351 win.on('resize.fl-bg-parallax', FLBuilderLayout._initParallaxBackgrounds); 352 win.on('scroll.fl-bg-parallax', FLBuilderLayout._scrollParallaxBackgrounds); 353 } 354 355 // Init video backgrounds. 356 if($('.fl-bg-video').length > 0) { 357 FLBuilderLayout._initBgVideos(); 358 FLBuilderLayout._resizeBgVideos(); 359 360 // Ensure FLBuilderLayout._resizeBgVideos() is only called once on window resize. 361 var resizeBGTimer = null; 362 win.on('resize.fl-bg-video', function(e){ 363 clearTimeout( resizeBGTimer ); 364 resizeBGTimer = setTimeout(function() { 365 FLBuilderLayout._resizeBgVideos(e); 366 }, 100 ); 367 }); 368 } 369 }, 370 371 /** 372 * Initializes all parallax backgrounds in a layout. 373 * 374 * @since 1.1.4 375 * @access private 376 * @method _initParallaxBackgrounds 377 */ 378 _initParallaxBackgrounds: function() 379 { 380 $('.fl-row-bg-parallax').each(FLBuilderLayout._initParallaxBackground); 381 }, 382 383 /** 384 * Initializes a single parallax background. 385 * 386 * @since 1.1.4 387 * @access private 388 * @method _initParallaxBackgrounds 389 */ 390 _initParallaxBackground: function() 391 { 392 var row = $(this), 393 content = row.find('> .fl-row-content-wrap'), 394 winWidth = $(window).width(), 395 screenSize = '', 396 imageSrc = { 397 default: '', 398 medium: '', 399 responsive: '', 400 }; 401 402 imageSrc.default = row.data('parallax-image') || ''; 403 imageSrc.medium = row.data('parallax-image-medium') || imageSrc.default; 404 imageSrc.responsive = row.data('parallax-image-responsive') || imageSrc.medium; 405 406 if (winWidth > FLBuilderLayoutConfig.breakpoints.medium) { 407 screenSize = 'default'; 408 } else if (winWidth > FLBuilderLayoutConfig.breakpoints.small && winWidth <= FLBuilderLayoutConfig.breakpoints.medium ) { 409 screenSize = 'medium'; 410 } else if (winWidth <= FLBuilderLayoutConfig.breakpoints.small) { 411 screenSize = 'responsive'; 412 } 413 414 content.css('background-image', 'url(' + imageSrc[screenSize] + ')'); 415 row.data('current-image-loaded', screenSize ); 416 417 }, 418 419 /** 420 * Fires when the window is scrolled to adjust 421 * parallax backgrounds. 422 * 423 * @since 1.1.4 424 * @access private 425 * @method _scrollParallaxBackgrounds 426 */ 427 _scrollParallaxBackgrounds: function() 428 { 429 $('.fl-row-bg-parallax').each(FLBuilderLayout._scrollParallaxBackground); 430 }, 431 432 /** 433 * Fires when the window is scrolled to adjust 434 * a single parallax background. 435 * 436 * @since 1.1.4 437 * @access private 438 * @method _scrollParallaxBackground 439 */ 440 _scrollParallaxBackground: function() 441 { 442 var win = $(window), 443 row = $(this), 444 content = row.find('> .fl-row-content-wrap'), 445 speed = row.data('parallax-speed'), 446 offset = content.offset(), 447 yPos = -((win.scrollTop() - offset.top) / speed), 448 initialOffset = ( row.data('parallax-offset') != null ) ? row.data('parallax-offset') : 0, 449 totalOffset = yPos - initialOffset; 450 451 content.css('background-position', 'center ' + totalOffset + 'px'); 452 }, 453 454 /** 455 * Initializes all video backgrounds. 456 * 457 * @since 1.6.3.3 458 * @access private 459 * @method _initBgVideos 460 */ 461 _initBgVideos: function() 462 { 463 $('.fl-bg-video').each(FLBuilderLayout._initBgVideo); 464 }, 465 466 /** 467 * Initializes a video background. 468 * 469 * @since 1.6.3.3 470 * @access private 471 * @method _initBgVideo 472 */ 473 _initBgVideo: function() 474 { 475 var wrap = $( this ), 476 width = wrap.data( 'width' ), 477 height = wrap.data( 'height' ), 478 mp4 = wrap.data( 'mp4' ), 479 youtube = wrap.data( 'youtube'), 480 vimeo = wrap.data( 'vimeo'), 481 mp4Type = wrap.data( 'mp4-type' ), 482 webm = wrap.data( 'webm' ), 483 webmType = wrap.data( 'webm-type' ), 484 fallback = wrap.data( 'fallback' ), 485 loaded = wrap.data( 'loaded' ), 486 videoMobile = wrap.data( 'video-mobile' ), 487 fallbackTag = '', 488 videoTag = null, 489 mp4Tag = null, 490 webmTag = null; 491 492 // Return if the video has been loaded for this row. 493 if ( loaded ) { 494 return; 495 } 496
497 videoTag = $( '<video autoplay loop muted playsinline></video>' ); 498 499 /** 500 * Add poster image (fallback image) 501 */ 502 if( 'undefined' != typeof fallback && '' != fallback ) { 503 videoTag.attr( 'poster', 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7' ) 504 videoTag.css({ 505 backgroundImage: 'url("' + fallback + '")', 506 backgroundColor: 'transparent', 507 backgroundRepeat: 'no-repeat', 508 backgroundSize: 'cover', 509 backgroundPosition: 'center center', 510 }) 511 } 512 513 // MP4 Source Tag 514 if ( 'undefined' != typeof mp4 && '' != mp4 ) { 515 516 mp4Tag = $( '<source />' ); 517 mp4Tag.attr( 'src', mp4 ); 518 mp4Tag.attr( 'type', mp4Type ); 519 520 videoTag.append( mp4Tag ); 521 } 522 // WebM Source Tag 523 if ( 'undefined' != typeof webm && '' != webm ) { 524 525 webmTag = $( '<source />' ); 526 webmTag.attr( 'src', webm ); 527 webmTag.attr( 'type', webmType ); 528 529 videoTag.append( webmTag ); 530 } 531 532 // This is either desktop, or mobile is enabled. 533 if ( ! FLBuilderLayout._isMobile() || ( FLBuilderLayout._isMobile() && "yes" == videoMobile ) ) { 534 if ( 'undefined' != typeof youtube ) { 535 FLBuilderLayout._initYoutubeBgVideo.apply( this ); 536 } 537 else if ( 'undefined' != typeof vimeo ) { 538 FLBuilderLayout._initVimeoBgVideo.apply( this ); 539 } 540 else { 541 wrap.append( videoTag ); 542 } 543 } 544 else { 545 // if we are here, it means we are on mobile and NO is set so remove video src and use fallback 546 videoTag.attr('src', '') 547 wrap.append( videoTag ); 548 } 549 550 // Mark this video as loaded. 551 wrap.data('loaded', true); 552 }, 553 554 /** 555 * Initializes Youtube video background 556 * 557 * @since 1.9 558 * @access private 559 * @method _initYoutubeBgVideo 560 */ 561 _initYoutubeBgVideo: function() 562 { 563 var playerWrap = $(this), 564 videoId = playerWrap.data('video-id'), 565 videoPlayer = playerWrap.find('.fl-bg-video-player'), 566 enableAudio = playerWrap.data('enable-audio'), 567 audioButton = playerWrap.find('.fl-bg-video-audio'), 568 startTime = 'undefined' !== typeof playerWrap.data('start') ? playerWrap.data('start') : 0, 569 startTime = 'undefined' !== typeof playerWrap.data('t') && startTime === 0 ? playerWrap.data('t') : startTime, 570 endTime = 'undefined' !== typeof playerWrap.data('end') ? playerWrap.data('end') : 0, 571 loop = 'undefined' !== typeof playerWrap.data('loop') ? playerWrap.data('loop') : 1, 572 stateCount = 0, 573 player,fallback_showing; 574 575 if ( videoId ) { 576 fallback = playerWrap.data('fallback') || false 577 if( fallback ) { 578 playerWrap.find('iframe').remove() 579 fallbackTag = $( '<div></div>' ); 580 fallbackTag.addClass( 'fl-bg-video-fallback' ); 581 fallbackTag.css( 'background-image', 'url(' + playerWrap.data('fallback') + ')' ); 582 fallbackTag.css( 'background-size', 'cover' ); 583 fallbackTag.css( 'transition', 'background-image 1s') 584 playerWrap.append( fallbackTag ); 585 fallback_showing = true; 586 } 587 FLBuilderLayout._onYoutubeApiReady( function( YT ) { 588 setTimeout( function() { 589 590 player = new YT.Player( videoPlayer[0], { 591 videoId: videoId, 592 events: { 593 onReady: function(event) { 594 if ( "no" === enableAudio || FLBuilderLayout._isMobile() ) { 595 event.target.mute(); 596 } 597 else if ( "yes" === enableAudio && event.target.isMuted ) { 598 event.target.unMute(); 599 } 600 601 // Store an instance to a parent 602 playerWrap.data('YTPlayer', player); 603 FLBuilderLayout._resizeYoutubeBgVideo.apply(playerWrap); 604 605 // Queue the video. 606 event.target.playVideo(); 607 608 if ( audioButton.length > 0 && ! FLBuilderLayout._isMobile() ) { 609 audioButton.on( 'click', {button: audioButton, player: player}, FLBuilderLayout._toggleBgVideoAudio ); 610 } 611 }, 612 onStateChange: function( event ) { 613 614 if ( event.data === 1 ) { 615 if ( fallback_showing ) { 616 $( '.fl-bg-video-fallback' ).css( 'background-image', 'url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)' ) 617 } 618 } 619 // Manual check if video is not playable in some browsers. 620 // StateChange order: [-1, 3, -1] 621 if ( stateCount < 4 ) { 622 stateCount++; 623 } 624 625 // Comply with the audio policy in some browsers like Chrome and Safari. 626 if ( stateCount > 1 && (-1 === event.data || 2 === event.data) && "yes" === enableAudio ) { 627 player.mute(); 628 player.playVideo(); 629 audioButton.show(); 630 } 631 632 if ( event.data === YT.PlayerState.ENDED && 1 === loop ) { 633 if ( startTime > 0 ) { 634 player.seekTo( startTime ); 635 } 636 else { 637 player.playVideo(); 638 } 639 } 640 }, 641 onError: function(event) { 642 console.info('YT Error: ' + event.data) 643 FLBuilderLayout._onErrorYoutubeVimeo(playerWrap) 644 } 645 }, 646 playerVars: { 647 playsinline: FLBuilderLayout._isMobile() ? 1 : 0, 648 controls: 0, 649 showinfo: 0, 650 rel : 0, 651 start: startTime, 652 end: endTime, 653 } 654 } ); 655 }, 1 ); 656 } ); 657 } 658 }, 659 660 /** 661 * On youtube or vimeo error show the fallback image if available. 662 * @since 2.0.7 663 */ 664 _onErrorYoutubeVimeo: function(playerWrap) { 665 666 fallback = playerWrap.data('fallback') || false 667 if( ! fallback ) { 668 return false;
669 } 670 playerWrap.find('iframe').remove() 671 fallbackTag = $( '<div></div>' ); 672 fallbackTag.addClass( 'fl-bg-video-fallback' ); 673 fallbackTag.css( 'background-image', 'url(' + playerWrap.data('fallback') + ')' ); 674 playerWrap.append( fallbackTag ); 675 }, 676 677 /** 678 * Check if Youtube API has been downloaded 679 * 680 * @since 1.9 681 * @access private 682 * @method _onYoutubeApiReady 683 * @param {Function} callback Method to call when YT API has been loaded 684 */ 685 _onYoutubeApiReady: function( callback ) { 686 if ( window.YT && YT.loaded ) { 687 callback( YT ); 688 } else { 689 // If not ready check again by timeout.. 690 setTimeout( function() { 691 FLBuilderLayout._onYoutubeApiReady( callback ); 692 }, 350 ); 693 } 694 }, 695 696 /** 697 * Initializes Vimeo video background 698 * 699 * @since 1.9 700 * @access private 701 * @method _initVimeoBgVideo 702 */ 703 _initVimeoBgVideo: function() 704 { 705 var playerWrap = $(this), 706 videoId = playerWrap.data('video-id'), 707 videoPlayer = playerWrap.find('.fl-bg-video-player'), 708 enableAudio = playerWrap.data('enable-audio'), 709 audioButton = playerWrap.find('.fl-bg-video-audio'), 710 player, 711 width = playerWrap.outerWidth(), 712 ua = navigator.userAgent; 713 714 if ( typeof Vimeo !== 'undefined' && videoId ) { 715 player = new Vimeo.Player(videoPlayer[0], { 716 id : videoId, 717 loop : true, 718 title : false, 719 portrait : false, 720 background : true, 721 autopause : false, 722 muted : true 723 }); 724 725 playerWrap.data('VMPlayer', player); 726 if ( "no" === enableAudio ) { 727 player.setVolume(0); 728 } 729 else if ("yes" === enableAudio ) { 730 // Chrome, Safari, Firefox have audio policy restrictions for autoplay videos. 731 if ( ua.indexOf("Safari") > -1 || ua.indexOf("Chrome") > -1 || ua.indexOf("Firefox") > -1 ) { 732 player.setVolume(0); 733 audioButton.show(); 734 } 735 else { 736 player.setVolume(1); 737 } 738 } 739 740 player.play().catch(function(error) { 741 FLBuilderLayout._onErrorYoutubeVimeo(playerWrap) 742 }); 743 744 if ( audioButton.length > 0 ) { 745 audioButton.on( 'click', {button: audioButton, player: player}, FLBuilderLayout._toggleBgVideoAudio ); 746 } 747 } 748 }, 749 750 /** 751 * Mute / unmute audio on row's video background. 752 * It works for both Youtube and Vimeo. 753 * 754 * @since 2.1.3 755 * @access private 756 * @method _toggleBgVideoAudio 757 * @param {Object} e Method arguments 758 */ 759 _toggleBgVideoAudio: function( e ) { 760 var player = e.data.player, 761 control = e.data.button.find('.fl-audio-control'); 762 763 if ( control.hasClass( 'fa-volume-off' ) ) { 764 // Unmute 765 control 766 .removeClass( 'fa-volume-off' ) 767 .addClass( 'fa-volume-up' ); 768 e.data.button.find( '.fa-times' ).hide(); 769 770 if ( 'function' === typeof player.unMute ) { 771 player.unMute(); 772 } 773 else { 774 player.setVolume( 1 ); 775 } 776 } 777 else { 778 // Mute 779 control 780 .removeClass( 'fa-volume-up' ) 781 .addClass( 'fa-volume-off' ); 782 e.data.button.find( '.fa-times' ).show(); 783 784 if ( 'function' === typeof player.unMute ) { 785 player.mute(); 786 } 787 else { 788 player.setVolume( 0 ); 789 } 790 } 791 }, 792 793 /** 794 * Fires when there is an error loading a video 795 * background source and shows the fallback. 796 * 797 * @since 1.6.3.3 798 * @access private 799 * @method _videoBgSourceError 800 * @param {Object} e An event object 801 * @deprecated 2.0.3 802 */ 803 _videoBgSourceError: function( e ) 804 { 805 var source = $( e.target ), 806 wrap = source.closest( '.fl-bg-video' ), 807 vid = wrap.find( 'video' ), 808 fallback = wrap.data( 'fallback' ), 809 fallbackTag = ''; 810 source.remove(); 811 812 if ( vid.find( 'source' ).length ) { 813 // Don't show the fallback if we still have other sources to check. 814 return; 815 } else if ( '' !== fallback ) { 816 fallbackTag = $( '<div></div>' ); 817 fallbackTag.addClass( 'fl-bg-video-fallback' ); 818 fallbackTag.css( 'background-image', 'url(' + fallback + ')' ); 819 wrap.append( fallbackTag ); 820 vid.remove(); 821 } 822 }, 823 824 /** 825 * Fires when the window is resized to resize 826 * all video backgrounds. 827 * 828 * @since 1.1.4 829 * @access private 830 * @method _resizeBgVideos 831 */ 832 _resizeBgVideos: function() 833 { 834 $('.fl-bg-video').each( function() { 835 836 FLBuilderLayout._resizeBgVideo.apply( this ); 837 838 if ( $( this ).parent().find( 'img' ).length > 0 ) { 839 $( this ).parent().imagesLoaded( $.proxy( FLBuilderLayout._resizeBgVideo, this ) ); 840 } 841 } ); 842 }, 843 844 /** 845 * Fires when the window is resized to resize 846 * a single video background. 847 * 848 * @since 1.1.4 849 * @access private 850 * @method _resizeBgVideo 851 */ 852 _resizeBgVideo: function() 853 { 854 if ( 0 === $( this ).find( 'video' ).length && 0 === $( this ).find( 'iframe' ).length ) { 855 return; 856 } 857 858 var wrap = $(this), 859 wrapHeight = wrap.outerHeight(), 860 wrapWidth = wrap.outerWidth(), 861 vid = wrap.find('video'), 862 vidHeight = wrap.data('height'), 863 vidWidth = wrap.data('width'), 864 newWidth = wrapWidth, 865 newHeight = Math.round(vidHeight * wrapWidth/vidWidth), 866 newLeft = 0, 867 newTop = 0, 868 iframe = wrap.find('iframe'), 869 isRowFullHeight = $(this).closest('.fl-row-bg-video').hasClass('fl-row-full-height'), 870 vidCSS = { 871 top: '50%', 872 left: '50%', 873 transform: 'translate(-50%,-50%)', 874 }; 875 876 if ( vid.length ) { 877 if(vidHeight === '' || typeof vidHeight === 'undefined' || vidWidth === '' || typeof vidWidth === 'undefined') { 878 vid.css({ 879 'left' : '0px', 880 'top' : '0px', 881 'width' : newWidth + 'px' 882 }); 883 884 // Try to set the actual video dimension on 'loadedmetadata' when using URL as video source 885 vid.on('loadedmetadata', FLBuilderLayout._resizeOnLoadedMeta); 886 887 return; 888 } 889 890 if ( ! isRowFullHeight ) { 891 if ( newHeight < wrapHeight ) { 892 newHeight = wrapHeight; 893 newLeft = -((newWidth - wrapWidth) / 2); 894 newWidth = vidHeight ? Math.round(vidWidth * wrapHeight/vidHeight) : newWidth; 895 } 896 else { 897 newTop = -((newHeight - wrapHeight)/2); 898 } 899 vidCSS = { 900 left : newLeft + 'px', 901 top : newTop + 'px', 902 height : newHeight + 'px', 903 width : newWidth + 'px', 904 } 905 } 906 907 vid.css( vidCSS ); 908 909 } 910 else if ( iframe.length ) { 911 912 // Resize Youtube video player within iframe tag 913 if ( typeof wrap.data('youtube') !== 'undefined' ) { 914 FLBuilderLayout._resizeYoutubeBgVideo.apply(this); 915 } 916 } 917 }, 918 919 /** 920 * Fires when video meta has been loaded. 921 * This will be Triggered when width/height attributes were not specified during video background resizing. 922 * 923 * @since 1.8.5 924 * @access private 925 * @method _resizeOnLoadedMeta 926 */ 927 _resizeOnLoadedMeta: function(){ 928 var video = $(this), 929 wrapHeight = video.parent().outerHeight(), 930 wrapWidth = video.parent().outerWidth(), 931 vidWidth = video[0].videoWidth, 932 vidHeight = video[0].videoHeight, 933 newHeight = Math.round(vidHeight * wrapWidth/vidWidth), 934 newWidth = wrapWidth, 935 newLeft = 0, 936 newTop = 0; 937 938 if(newHeight < wrapHeight) { 939 newHeight = wrapHeight; 940 newWidth = Math.round(vidWidth * wrapHeight/vidHeight); 941 newLeft = -((newWidth - wrapWidth)/2); 942 } 943 else { 944 newTop = -((newHeight - wrapHeight)/2); 945 } 946 947 video.parent().data('width', vidWidth); 948 video.parent().data('height', vidHeight); 949 950 video.css({ 951 'left' : newLeft + 'px', 952 'top' : newTop + 'px', 953 'width' : newWidth + 'px', 954 'height' : newHeight + 'px' 955 }); 956 }, 957 958 /** 959 * Fires when the window is resized to resize 960 * a single Youtube video background. 961 * 962 * @since 1.9 963 * @access private 964 * @method _resizeYoutubeBgVideo 965 */ 966 _resizeYoutubeBgVideo: function() 967 { 968 var wrap = $(this), 969 wrapWidth = wrap.outerWidth(), 970 wrapHeight = wrap.outerHeight(), 971 player = wrap.data('YTPlayer'), 972 video = player ? player.getIframe() : null, 973 aspectRatioSetting = '16:9', // Medium 974 aspectRatioArray = aspectRatioSetting.split( ':' ),
975 aspectRatio = aspectRatioArray[0] / aspectRatioArray[1], 976 ratioWidth = wrapWidth / aspectRatio, 977 ratioHeight = wrapHeight * aspectRatio, 978 isWidthFixed = wrapWidth / wrapHeight > aspectRatio, 979 width = isWidthFixed ? wrapWidth : ratioHeight, 980 height = isWidthFixed ? ratioWidth : wrapHeight; 981 982 if ( video ) { 983 $(video).width( width ).height( height ); 984 } 985 }, 986 987 /** 988 * Initializes module animations. 989 * 990 * @since 1.1.9 991 * @access private 992 * @method _initModuleAnimations 993 */ 994 _initModuleAnimations: function() 995 { 996 if(typeof jQuery.fn.waypoint !== 'undefined') { 997 $('.fl-animation').each( function() { 998 var node = $( this ), 999 nodeTop = node.offset().top, 1000 winHeight = $( window ).height(), 1001 bodyHeight = $( 'body' ).height(), 1002 waypoint = FLBuilderLayoutConfig.waypoint, 1003 offset = '80%'; 1004 1005 if ( typeof waypoint.offset !== undefined ) { 1006 offset = FLBuilderLayoutConfig.waypoint.offset + '%'; 1007 } 1008 1009 if ( bodyHeight - nodeTop < winHeight * 0.2 ) { 1010 offset = '100%'; 1011 } 1012 1013 node.waypoint({ 1014 offset: offset, 1015 handler: FLBuilderLayout._doModuleAnimation 1016 }); 1017 } ); 1018 } 1019 }, 1020 1021 /** 1022 * Runs a module animation. 1023 * 1024 * @since 1.1.9 1025 * @access private 1026 * @method _doModuleAnimation 1027 */ 1028 _doModuleAnimation: function() 1029 { 1030 var module = 'undefined' == typeof this.element ? $(this) : $(this.element), 1031 delay = parseFloat(module.data('animation-delay')), 1032 duration = parseFloat(module.data('animation-duration')); 1033 1034 if ( ! isNaN( duration ) ) { 1035 module.css( 'animation-duration', duration + 's' ); 1036 } 1037 1038 if(!isNaN(delay) && delay > 0) { 1039 setTimeout(function(){ 1040 module.addClass('fl-animated'); 1041 }, delay * 1000); 1042 } else { 1043 setTimeout(function(){ 1044 module.addClass('fl-animated'); 1045 }, 1); 1046 } 1047 }, 1048 1049 /** 1050 * Opens a tab or accordion item if the browser hash is set 1051 * to the ID of one on the page. 1052 * 1053 * @since 1.6.0 1054 * @access private 1055 * @method _initHash 1056 */ 1057 _initHash: function() 1058 { 1059 var hash = window.location.hash.replace( '#', '' ).split( '/' ).shift(), 1060 element = null, 1061 tabs = null, 1062 responsiveLabel = null, 1063 tabIndex = null, 1064 label = null; 1065 1066 if ( '' !== hash ) { 1067 1068 try { 1069 1070 element = $( '#' + hash ); 1071 1072 if ( element.length > 0 ) { 1073 1074 if ( element.hasClass( 'fl-accordion-item' ) ) { 1075 setTimeout( function() { 1076 element.find( '.fl-accordion-button' ).trigger( 'click' ); 1077 }, 100 ); 1078 } 1079 if ( element.hasClass( 'fl-tabs-panel' ) ) { 1080 setTimeout( function() { 1081 tabs = element.closest( '.fl-tabs' ); 1082 responsiveLabel = element.find( '.fl-tabs-panel-label' ); 1083 tabIndex = responsiveLabel.data( 'index' ); 1084 label = tabs.find( '.fl-tabs-labels .fl-tabs-label[data-index=' + tabIndex + ']' ); 1085 1086 label[0].click(); 1087 FLBuilderLayout._scrollToElement(element); 1088 }, 100 ); 1089 } 1090 } 1091 } 1092 catch( e ) {} 1093 } 1094 }, 1095 1096 /** 1097 * Initializes all anchor links on the page for smooth scrolling. 1098 * 1099 * @since 1.4.9 1100 * @access private 1101 * @method _initAnchorLinks 1102 */ 1103 _initAnchorLinks: function() 1104 { 1105 $( 'a' ).each( FLBuilderLayout._initAnchorLink ); 1106 }, 1107 1108 /** 1109 * Initializes a single anchor link for smooth scrolling. 1110 * 1111 * @since 1.4.9 1112 * @access private 1113 * @method _initAnchorLink 1114 */ 1115 _initAnchorLink: function() 1116 { 1117 var link = $( this ), 1118 href = link.attr( 'href' ), 1119 loc = window.location, 1120 id = null, 1121 element = null, 1122 flNode = false; 1123 1124 if ( 'undefined' != typeof href && href.indexOf( '#' ) > -1 && link.closest('svg').length < 1 ) { 1125 1126 if ( loc.pathname.replace( /^\//, '' ) == this.pathname.replace( /^\//, '' ) && loc.hostname == this.hostname ) { 1127 1128 try { 1129 1130 id = href.split( '#' ).pop(); 1131 // If there is no ID then we have nowhere to look 1132 // Fixes a quirk in jQuery and FireFox 1133 if( ! id ) { 1134 return; 1135 } 1136 element = $( '#' + id ); 1137 1138 if ( element.length > 0 ) { 1139 flNode = element.hasClass( 'fl-row' ) || element.hasClass( 'fl-col' ) || element.hasClass( 'fl-module' ); 1140 if ( !element.hasClass( 'fl-no-scroll' ) && ( link.hasClass( 'fl-scroll-link' ) || flNode ) ) { 1141 $( link ).on( 'click', FLBuilderLayout._scrollToElementOnLinkClick ); 1142 } 1143 if ( element.hasClass( 'fl-accordion-item' ) ) { 1144 $( link ).on( 'click', FLBuilderLayout._scrollToAccordionOnLinkClick ); 1145 } 1146 if ( element.hasClass( 'fl-tabs-panel' ) ) { 1147 $( link ).on( 'click', FLBuilderLayout._scrollToTabOnLinkClick ); 1148 } 1149 } 1150 } 1151 catch( e ) {} 1152 } 1153 } 1154 }, 1155 1156 /** 1157 * Scrolls to an element when an anchor link is clicked. 1158 * 1159 * @since 1.4.9 1160 * @access private 1161 * @method _scrollToElementOnLinkClick 1162 * @param {Object} e An event object. 1163 * @param {Function} callback A function to call when the scroll is complete. 1164 */ 1165 _scrollToElementOnLinkClick: function( e, callback ) 1166 { 1167 var element = $( '#' + $( this ).attr( 'href' ).split( '#' ).pop() ); 1168 1169 FLBuilderLayout._scrollToElement( element, callback ); 1170 1171 e.preventDefault(); 1172 }, 1173 1174 /** 1175 * Scrolls to an element. 1176 * 1177 * @since 1.6.4.5 1178 * @access private 1179 * @method _scrollToElement 1180 * @param {Object} element The element to scroll to. 1181 * @param {Function} callback A function to call when the scroll is complete. 1182 */ 1183 _scrollToElement: function( element, callback ) 1184 { 1185 var config = FLBuilderLayoutConfig.anchorLinkAnimations, 1186 dest = 0, 1187 win = $( window ), 1188 doc = $( document ); 1189 1190 if ( element.length > 0 ) { 1191 1192 if ( 'fixed' === element.css('position') || 'fixed' === element.parent().css('position') ) { 1193 dest = element.position().top; 1194 } 1195 else if ( element.offset().top > doc.height() - win.height() ) { 1196 dest = doc.height() - win.height(); 1197 } 1198 else { 1199 dest = element.offset().top - config.offset; 1200 } 1201 1202 $( 'html, body' ).animate( { scrollTop: dest }, config.duration, config.easing, function() { 1203 1204 if ( 'undefined' != typeof callback ) { 1205 callback(); 1206 } 1207 1208 if ( undefined != element.attr( 'id' ) ) { 1209 1210 if ( history.pushState ) { 1211 history.pushState( null, null, '#' + element.attr( 'id' ) ); 1212 } 1213 else { 1214 window.location.hash = element.attr( 'id' ); 1215 } 1216 } 1217 } ); 1218 } 1219 }, 1220 1221 /** 1222 * Scrolls to an accordion item when a link is clicked. 1223 * 1224 * @since 1.5.9 1225 * @access private 1226 * @method _scrollToAccordionOnLinkClick 1227 * @param {Object} e An event object. 1228 */ 1229 _scrollToAccordionOnLinkClick: function( e ) 1230 { 1231 var element = $( '#' + $( this ).attr( 'href' ).split( '#' ).pop() ); 1232 1233 if ( element.length > 0 ) { 1234 1235 var callback = function() { 1236 if ( element ) { 1237 element.find( '.fl-accordion-button' ).trigger( 'click' ); 1238 element = false;
1239 } 1240 }; 1241 1242 FLBuilderLayout._scrollToElementOnLinkClick.call( this, e, callback ); 1243 } 1244 }, 1245 1246 /** 1247 * Scrolls to a tab panel when a link is clicked. 1248 * 1249 * @since 1.5.9 1250 * @access private 1251 * @method _scrollToTabOnLinkClick 1252 * @param {Object} e An event object. 1253 */ 1254 _scrollToTabOnLinkClick: function( e ) 1255 { 1256 var element = $( '#' + $( this ).attr( 'href' ).split( '#' ).pop() ), 1257 tabs = null, 1258 label = null, 1259 responsiveLabel = null; 1260 1261 if ( element.length > 0 ) { 1262 1263 tabs = element.closest( '.fl-tabs' ); 1264 responsiveLabel = element.find( '.fl-tabs-panel-label' ); 1265 tabIndex = responsiveLabel.data( 'index' ); 1266 label = tabs.find( '.fl-tabs-labels .fl-tabs-label[data-index=' + tabIndex + ']' ); 1267 1268 if ( responsiveLabel.is( ':visible' ) ) { 1269 1270 var callback = function() { 1271 if ( element ) { 1272 responsiveLabel.trigger( $.Event( 'click', { which: 1 } ) ); 1273 } 1274 }; 1275 1276 FLBuilderLayout._scrollToElementOnLinkClick.call( this, e, callback ); 1277 } 1278 else { 1279 label[0].click(); 1280 FLBuilderLayout._scrollToElement( element ); 1281 } 1282 1283 e.preventDefault(); 1284 } 1285 }, 1286 1287 /** 1288 * Initializes all builder forms on a page. 1289 * 1290 * @since 1.5.4 1291 * @access private 1292 * @method _initForms 1293 */ 1294 _initForms: function() 1295 { 1296 if ( ! FLBuilderLayout._hasPlaceholderSupport ) { 1297 $( '.fl-form-field input' ).each( FLBuilderLayout._initFormFieldPlaceholderFallback ); 1298 } 1299 1300 $( '.fl-form-field input' ).on( 'focus', FLBuilderLayout._clearFormFieldError ); 1301 }, 1302 1303 /** 1304 * Checks to see if the current device has HTML5 1305 * placeholder support. 1306 * 1307 * @since 1.5.4 1308 * @access private 1309 * @method _hasPlaceholderSupport 1310 * @return {Boolean} 1311 */ 1312 _hasPlaceholderSupport: function() 1313 { 1314 var input = document.createElement( 'input' ); 1315 1316 return 'undefined' != input.placeholder; 1317 }, 1318 1319 /** 1320 * Initializes the fallback for when placeholders aren't supported. 1321 * 1322 * @since 1.5.4 1323 * @access private 1324 * @method _initFormFieldPlaceholderFallback 1325 */ 1326 _initFormFieldPlaceholderFallback: function() 1327 { 1328 var field = $( this ), 1329 val = field.val(), 1330 placeholder = field.attr( 'placeholder' ); 1331 1332 if ( 'undefined' != placeholder && '' === val ) { 1333 field.val( placeholder ); 1334 field.on( 'focus', FLBuilderLayout._hideFormFieldPlaceholderFallback ); 1335 field.on( 'blur', FLBuilderLayout._showFormFieldPlaceholderFallback ); 1336 } 1337 }, 1338 1339 /** 1340 * Hides a fallback placeholder on focus. 1341 * 1342 * @since 1.5.4 1343 * @access private 1344 * @method _hideFormFieldPlaceholderFallback 1345 */ 1346 _hideFormFieldPlaceholderFallback: function() 1347 { 1348 var field = $( this ), 1349 val = field.val(), 1350 placeholder = field.attr( 'placeholder' ); 1351 1352 if ( val == placeholder ) { 1353 field.val( '' ); 1354 } 1355 }, 1356 1357 /** 1358 * Shows a fallback placeholder on blur. 1359 * 1360 * @since 1.5.4 1361 * @access private 1362 * @method _showFormFieldPlaceholderFallback 1363 */ 1364 _showFormFieldPlaceholderFallback: function() 1365 { 1366 var field = $( this ), 1367 val = field.val(), 1368 placeholder = field.attr( 'placeholder' ); 1369 1370 if ( '' === val ) { 1371 field.val( placeholder ); 1372 } 1373 }, 1374 1375 /** 1376 * Clears a form field error message. 1377 * 1378 * @since 1.5.4 1379 * @access private 1380 * @method _clearFormFieldError 1381 */ 1382 _clearFormFieldError: function() 1383 { 1384 var field = $( this ); 1385 1386 field.removeClass( 'fl-form-error' ); 1387 field.siblings( '.fl-form-error-message' ).hide(); 1388 }, 1389 1390 /** 1391 * Init Row Shape Layer's height. 1392 * 1393 * @since 2.5.3 1394 * @access private 1395 * @method _initRowShapeLayerHeight 1396 */ 1397 _initRowShapeLayerHeight: function () { 1398 FLBuilderLayout._adjustRowShapeLayerHeight(); 1399 $( window ).on( 'resize', FLBuilderLayout._adjustRowShapeLayerHeight ); 1400 }, 1401 1402 /** 1403 * Set parent column width of nested columns when it's zero or blank. 1404 * 1405 * @since 2.7.4 1406 * @access private 1407 * @method _initNestedColsWidth 1408 */ 1409 _initNestedColsWidth: function() 1410 { 1411 var nestedCols = $( '.fl-col-has-cols' ); 1412 1413 if ( nestedCols.length <= 0 ) { 1414 return; 1415 } 1416 1417 $( nestedCols ).each( function(index, col ){ 1418 if ( $( col ).width() <= 0 ) { 1419 $( col ).css( 'width', FLBuilderLayoutConfig.emptyColWidth ); 1420 } 1421 }); 1422 }, 1423 1424 /** 1425 * Adjust Row Shape Layer's height to fix to remove the fine line that appears on certain screen sizes. 1426 * 1427 * @since 2.5.3 1428 * @access private 1429 * @method _adjustRowShapeLayerHeight 1430 */
1431 _adjustRowShapeLayerHeight: function() { 1432 var rowShapeLayers = $('.fl-builder-shape-layer'); 1433 1434 $( rowShapeLayers ).each(function (index) { 1435 var rowShapeLayer = $(this), 1436 shape = $(rowShapeLayer).find('svg'), 1437 height = shape.height(), 1438 excludeShapes = '.fl-builder-shape-circle, .fl-builder-shape-dot-cluster, .fl-builder-shape-topography, .fl-builder-shape-rect'; 1439 1440 if ( ! rowShapeLayer.is( excludeShapes ) ) { 1441 $(shape).css('height', Math.ceil( height ) ); 1442 } 1443 }); 1444 }, 1445 _string_to_slug: function( str ) { 1446 str = str.replace(/^\s+|\s+$/g, ''); // trim 1447 if ( 'undefined' == typeof window._fl_string_to_slug_regex ) { 1448 regex = new RegExp('[^a-zA-Z0-9\'":() !.,-_|]', 'g'); 1449 } else { 1450 regex = new RegExp('[^' + window._fl_string_to_slug_regex + '\'":\(\) !.,-_|\\\p{Letter}]', 'ug'); 1451 } 1452 str = str.replace(regex, '') // remove invalid chars 1453 .replace(/\s+/g, ' '); // collapse whitespace and replace by a space 1454 return str; 1455 }, 1456 _reorderMenu: function() { 1457 if ( $('#wp-admin-bar-fl-builder-frontend-edit-link-default li').length > 1 ) { 1458 $( '#wp-admin-bar-fl-builder-frontend-duplicate-link' ) 1459 .appendTo('#wp-admin-bar-fl-builder-frontend-edit-link-default') 1460 .css( 'padding-top', '5px' ) 1461 .css( 'border-top', '2px solid #1D2125' ) 1462 .css( 'margin-top', '5px' ) 1463 } 1464 } 1465 }; 1466 1467 /* Initializes the builder layout. */ 1468 $(function(){ 1469 FLBuilderLayout.init(); 1470 }); 1471 1472})(jQuery); 1473 1474/* Start Global JS */ 1475 1476/* End Global JS */ 1477 1478 1479/** 1480 * This file should contain frontend logic for 1481 * all module instances. 1482 */ 1483(function($) { 1484 1485 function equalheight() { 1486 1487 if( window.navigator.userAgent.indexOf( 'MSIE ' ) > 0 ) { 1488 return; 1489 } 1490 1491 var maxHeight = 0; 1492 $('.fl-node-zxd924ua5ohq .pp-logos-wrapper .pp-logo').each(function(index) { 1493 if(($(this).find('.logo-image').outerHeight() + 0) > maxHeight) { 1494 maxHeight = $(this).find('.logo-image').outerHeight() + 0; 1495 } 1496 }); 1497 $('.fl-node-zxd924ua5ohq .pp-logos-wrapper .pp-logo').css('height', maxHeight + 'px'); 1498 1499 return maxHeight; 1500 } 1501 1502 $('.fl-node-zxd924ua5ohq .pp-logos-wrapper').imagesLoaded(function() { 1503 // Clear the controls in case they were already created. 1504 //$('.fl-node-zxd924ua5ohq .logo-slider-next').empty(); 1505 //$('.fl-node-zxd924ua5ohq .logo-slider-prev').empty(); 1506 1507 var getMinSlides = function() { 1508 var minSlides = ( $( window ).width() <= 768 ) ? parseInt( $( '.fl-node-zxd924ua5ohq' ).width() / 325) : 4; 1509 1510 if ( window.innerWidth <= 1200 ) { 1511 minSlides = 4; 1512 } 1513 if ( window.innerWidth <= 992 ) { 1514 minSlides = 4; 1515 } 1516 if ( window.innerWidth <= 768 ) { 1517 minSlides = 4; 1518 } 1519 1520 minSlides = (minSlides === 0) ? 1 : minSlides; 1521 1522 return minSlides; 1523 } 1524 1525 var minSlides = getMinSlides(); 1526 1527 var maxSlides = minSlides; 1528 var moveSlides = maxSlides; 1529 1530 1531 var totalSlides = minSlides - 1; 1532 1533 $(window).on('resize', function() { 1534 minSlides = getMinSlides(); 1535 maxSlides = minSlides; 1536 moveSlides = maxSlides; 1537 1538 1539 totalSlides = minSlides - 1; 1540 }); 1541 1542 1543 //equalheight(); 1544 1545 var totalSlides = $('.fl-node-zxd924ua5ohq .pp-logo:not(.bx-clone)').length; 1546 1547 var options = { 1548 slideWidth: 250, 1549 moveSlides: moveSlides, 1550 slideMargin: 25, 1551 minSlides: minSlides, 1552 maxSlides: maxSlides, 1553 autoStart : 1, 1554 auto : true, 1555 autoHover: false, 1556 adaptiveHeight: false, 1557 pause : 4000, 1558 mode : 'horizontal', 1559 speed : 500, 1560 pager : 0, 1561 controls: false, 1562 ariaLive: false, 1563 onSliderLoad: function() { 1564 $('.fl-node-zxd924ua5ohq .pp-logos-wrapper').addClass('pp-logos-wrapper-loaded'); 1565 $('.fl-node-zxd924ua5ohq .pp-logo').attr('role', 'group'); 1566 1567 var visibleCount = 0; 1568 $('.fl-node-zxd924ua5ohq .pp-logo').each(function() { 1569 if ( ! $(this).hasClass( 'bx-clone' ) ) { 1570 visibleCount++; 1571 $(this).attr('aria-label', 'Slide ' + visibleCount + ' of ' + totalSlides ); 1572 } 1573 }); 1574 1575 setTimeout( function() { 1576 $(window).trigger('resize'); 1577 }, 200 ); 1578 1579 $(document).trigger( 'pp_logos_on_slider_load', [ $('.fl-node-zxd924ua5ohq') ] ); 1580 }, 1581 onSlideBefore: function( ele, oldIndex, newIndex ) { 1582 this.stopAuto( true ); 1583 $('.fl-node-zxd924ua5ohq .logo-slider-nav').addClass('disabled'); 1584 $('.fl-node-zxd924ua5ohq .bx-controls .bx-pager-link').addClass('disabled'); 1585 this.startAuto( true ); 1586 1587 var visibleCount = 0; 1588 $('.fl-node-zxd924ua5ohq .pp-logo').each(function() { 1589 if ( ! $(this).hasClass( 'bx-clone' ) ) { 1590 visibleCount++; 1591 $(this).attr('aria-label', 'Slide ' + visibleCount + ' of ' + totalSlides ); 1592 } 1593 }); 1594 }, 1595 onSlideAfter: function( ele, oldIndex, newIndex ) { 1596 $('.fl-node-zxd924ua5ohq .logo-slider-nav').removeClass('disabled'); 1597 $('.fl-node-zxd924ua5ohq .bx-controls .bx-pager-link').removeClass('disabled'); 1598 } 1599 }; 1600 1601 options.onSliderResize = function(currentIndex) { 1602 options.working = false;
1603 options.minSlides = minSlides; 1604 options.maxSlides = maxSlides; 1605 options.moveSlides = moveSlides; 1606 1607 this.reloadSlider( options ); 1608 }; 1609 1610 // Create the slider. 1611 var slider = $('.fl-node-zxd924ua5ohq .pp-logos-wrapper').bxSlider( options ); 1612 1613 // Store a reference to the slider. 1614 slider.data('bxSlider', slider); 1615 1616 1617 1618 1619 1620 }); 1621 1622})(jQuery); 1623jQuery(function($) { 1624 1625 $(function() { 1626 $( '.fl-node-64e7ceb8d8404 .fl-photo-img' ) 1627 .on( 'mouseenter', function( e ) { 1628 $( this ).data( 'title', $( this ).attr( 'title' ) ).removeAttr( 'title' ); 1629 } ) 1630 .on( 'mouseleave', function( e ){ 1631 $( this ).attr( 'title', $( this ).data( 'title' ) ).data( 'title', null ); 1632 } ); 1633 }); 1634 window._fl_string_to_slug_regex = 'a-zA-Z0-9'; 1635}); 1636jQuery(function($) { 1637 1638 $(function() { 1639 $( '.fl-node-64e7ceb8d8403 .fl-photo-img' ) 1640 .on( 'mouseenter', function( e ) { 1641 $( this ).data( 'title', $( this ).attr( 'title' ) ).removeAttr( 'title' ); 1642 } ) 1643 .on( 'mouseleave', function( e ){ 1644 $( this ).attr( 'title', $( this ).data( 'title' ) ).data( 'title', null ); 1645 } ); 1646 }); 1647 window._fl_string_to_slug_regex = 'a-zA-Z0-9'; 1648}); 1649jQuery(function($) { 1650 1651 $(function() { 1652 $( '.fl-node-64e7ceb8d8402 .fl-photo-img' ) 1653 .on( 'mouseenter', function( e ) { 1654 $( this ).data( 'title', $( this ).attr( 'title' ) ).removeAttr( 'title' ); 1655 } ) 1656 .on( 'mouseleave', function( e ){ 1657 $( this ).attr( 'title', $( this ).data( 'title' ) ).data( 'title', null ); 1658 } ); 1659 }); 1660 window._fl_string_to_slug_regex = 'a-zA-Z0-9'; 1661}); 1662jQuery(function($) { 1663 1664 $(function() { 1665 $( '.fl-node-64e7ceb8d8401 .fl-photo-img' ) 1666 .on( 'mouseenter', function( e ) { 1667 $( this ).data( 'title', $( this ).attr( 'title' ) ).removeAttr( 'title' ); 1668 } ) 1669 .on( 'mouseleave', function( e ){ 1670 $( this ).attr( 'title', $( this ).data( 'title' ) ).data( 'title', null ); 1671 } ); 1672 }); 1673 window._fl_string_to_slug_regex = 'a-zA-Z0-9'; 1674}); 1675 1676(function($) { 1677 1678 /** 1679 * Class for Menu Module 1680 * 1681 * @since 1.6.1 1682 */ 1683 FLBuilderMenu = function( settings ){ 1684 1685 // set params 1686 this.nodeId = settings.id; 1687 this.nodeClass = '.fl-node-' + settings.id; 1688 this.wrapperClass = this.nodeClass + ' .fl-menu'; 1689 this.type = settings.type; 1690 this.mobileToggle = settings.mobile; 1691 this.mobileBelowRow = settings.mobileBelowRow; 1692 this.mobileFlyout = settings.mobileFlyout; 1693 this.breakPoints = settings.breakPoints; 1694 this.mobileBreakpoint = settings.mobileBreakpoint; 1695 this.currentBrowserWidth = $( window ).width(); 1696 this.postId = settings.postId; 1697 this.mobileStacked = settings.mobileStacked; 1698 1699 // initialize the menu 1700 this._initMenu(); 1701 1702 // check if viewport is resizing 1703 $( window ).on( 'resize', $.proxy( function( e ) { 1704 1705 var width = $( window ).width(); 1706 1707 // if screen width is resized, reload the menu 1708 if( width != this.currentBrowserWidth ){ 1709 1710 this.currentBrowserWidth = width; 1711 this._initMenu(); 1712 this._clickOrHover(); 1713 } 1714 1715 }, this ) ); 1716 1717 $( 'body' ).on( 'click', $.proxy( function( e ) { 1718 if ( 'undefined' !== typeof FLBuilderConfig ){ 1719 return; 1720 } 1721 1722 var activeMobileMenu = $(this.wrapperClass + ' .fl-menu-mobile-toggle.fl-active' ); 1723 if ( activeMobileMenu.length && ( 'expanded' !== this.mobileToggle ) ){ 1724 $( activeMobileMenu ).trigger('click'); 1725 } 1726 1727 $( this.wrapperClass ).find( '.fl-has-submenu' ).removeClass( 'focus' ); 1728 $( this.wrapperClass ).find( '.fl-has-submenu .sub-menu' ).removeClass( 'focus' ); 1729 1730 }, this ) ); 1731 1732 // Close Mobile menu when tabbing out from the last menu item. 1733 $( this.wrapperClass + ' ul.menu > li:last-child' ).on( 'focusout', $.proxy(function (e) { 1734 if ( $( this.wrapperClass ).find( '.fl-menu-mobile-toggle' ).hasClass( 'fl-active' ) && ( 'expanded' !== this.mobileToggle ) ) { 1735 if ( ! $( e.relatedTarget ).parent().hasClass( 'menu-item' ) ) { 1736 $( this.wrapperClass ).find( '.fl-menu-mobile-toggle' ).trigger( 'click' ); 1737 } 1738 } 1739 }, this ) ); 1740 1741 }; 1742 1743 FLBuilderMenu.prototype = { 1744 nodeClass : '', 1745 wrapperClass : '', 1746 type : '', 1747 breakPoints : {}, 1748 $submenus : null, 1749 1750 /** 1751 * Check if the screen size fits a mobile viewport. 1752 * 1753 * @since 1.6.1 1754 * @return bool 1755 */ 1756 _isMobile: function(){ 1757 return this.currentBrowserWidth <= this.breakPoints.small ? true : false;
1758 }, 1759 1760 /** 1761 * Check if the screen size fits a medium viewport. 1762 * 1763 * @since 1.10.5 1764 * @return bool 1765 */ 1766 _isMedium: function(){ 1767 return this.currentBrowserWidth <= this.breakPoints.medium ? true : false; 1768 }, 1769 1770 /** 1771 * Check if the screen size fits a large viewport. 1772 * 1773 * @since 1.10.5 1774 * @return bool 1775 */ 1776 _isLarge: function(){ 1777 return this.currentBrowserWidth <= this.breakPoints.large ? true : false; 1778 }, 1779 1780 /** 1781 * Check if the menu should toggle for the current viewport base on the selected breakpoint 1782 * 1783 * @see this._isMobile() 1784 * @see this._isMedium() 1785 * @since 1.10.5 1786 * @return bool 1787 */ 1788 _isMenuToggle: function(){ 1789 if ( ( 'always' == this.mobileBreakpoint 1790 || ( this._isMobile() && 'mobile' == this.mobileBreakpoint ) 1791 || ( this._isMedium() && 'medium-mobile' == this.mobileBreakpoint ) 1792 || ( this._isLarge() && 'large-mobile' == this.mobileBreakpoint ) 1793 ) && ( $( this.wrapperClass ).find( '.fl-menu-mobile-toggle' ).is(':visible') || 'expanded' == this.mobileToggle ) ) { 1794 return true; 1795 } 1796 1797 return false; 1798 }, 1799 1800 /** 1801 * Initialize the toggle logic for the menu. 1802 * 1803 * @see this._isMenuToggle() 1804 * @see this._menuOnCLick() 1805 * @see this._clickOrHover() 1806 * @see this._submenuOnRight() 1807 * @see this._submenuRowZindexFix() 1808 * @see this._toggleForMobile() 1809 * @since 1.6.1 1810 * @return void 1811 */ 1812 _initMenu: function(){ 1813 this._setupSubmenu(); 1814 this._menuOnFocus(); 1815 this._menuOnEscape(); 1816 this._submenuOnClick(); 1817 if ( $( this.nodeClass ).length && this.type == 'horizontal' ) { 1818 this._initMegaMenus(); 1819 } 1820 1821 if( this._isMenuToggle() || this.type == 'accordion' ){ 1822 1823 $( this.wrapperClass ).off( 'mouseenter mouseleave' ); 1824 this._menuOnClick(); 1825 this._clickOrHover(); 1826 1827 } else { 1828 $( this.wrapperClass ).off( 'click' ); 1829 this._submenuOnRight(); 1830 this._submenuRowZindexFix(); 1831 } 1832 1833 if( this.mobileToggle != 'expanded' ){ 1834 this._toggleForMobile(); 1835 } 1836 1837 if( $( this.wrapperClass ).find( '.fl-menu-search-item' ).length ){ 1838 this._toggleMenuSearch(); 1839 } 1840 1841 if( $( this.wrapperClass ).find( '.fl-menu-cart-item').length ){ 1842 this._wooUpdateParams(); 1843 } 1844 }, 1845 1846 /** 1847 * Initializes submenu dropdowns. 1848 * 1849 * @since 3.0 1850 * @return void 1851 */ 1852 _setupSubmenu: function() { 1853 $( this.wrapperClass + ' ul.sub-menu' ).each( function(){ 1854 $( this ).closest( 'li' ).attr( 'aria-haspopup', 'true' ); 1855 }); 1856 }, 1857 1858 /** 1859 * Adds a focus class to menu elements similar to be used similar to CSS :hover psuedo event 1860 * 1861 * @since 1.9.0 1862 * @return void 1863 */ 1864 _menuOnFocus: function(){ 1865 var cKey = 0, 1866 isShifted = false; 1867 1868 $( this.nodeClass ).off('keydown').on( 'keydown', 'a', function( e ){ 1869 cKey = e.which; 1870 isShifted = e.shiftKey; 1871 }); 1872 1873 $( this.nodeClass ).off('focus').on( 'focus', 'a', $.proxy( function( e ){ 1874 var $menuItem = $( e.target ).parents( '.menu-item' ).first(), 1875 $parents = $( e.target ).parentsUntil( this.wrapperClass ); 1876 1877 $('.fl-menu .focus').removeClass('focus'); 1878 1879 $parents.addClass('focus') 1880 1881 if ( ! $menuItem.closest('.fl-has-submenu').hasClass('escaped') ) { 1882 $menuItem.addClass('focus') 1883 } 1884 else { 1885 $menuItem.closest('.fl-has-submenu').removeClass('focus escaped') 1886 } 1887 }, this ) ).on( 'focusout', 'a', $.proxy( function( e ){ 1888 var el = $(e.target).parent(), 1889 $megaMenu = el.closest( '.mega-menu' ), 1890 $megaLastItem = $megaMenu.find('> .sub-menu > .menu-item:last-child'), 1891 $lastItem = el.parents('.fl-has-submenu:last').find('.menu-item:last'), 1892 isLastChild = ! $megaMenu.length && el.is( $lastItem ); 1893 1894 if( $megaMenu.length ) { 1895 isLastChild = el.is( $megaLastItem ) || el.is( $megaLastItem.find( '.menu-item:last-child' ) ); 1896 } 1897 1898 if ( isLastChild && cKey === 9 && isShifted ) { 1899 isLastChild = false; 1900 cKey = 0; 1901 isShifted = false; 1902 } 1903 else if ( cKey === 27 ) { 1904 isLastChild = false; 1905 } 1906 1907 if ( isLastChild ) { 1908 $( e.target ).parentsUntil( this.wrapperClass ).removeClass( 'focus' ); 1909 } 1910 1911 }, this ) ); 1912 }, 1913 1914 /** 1915 * Logic for submenu items when Escape key is pressed. 1916 * 1917 * @since 2.7.1 1918 * @return void 1919 */ 1920 _menuOnEscape: function(){ 1921 $( 'body' ).off('keydown').on( 'keydown', $.proxy( function( e ){ 1922 if ( e.which !== 27 ) { 1923 return; 1924 } 1925 1926 if ( $( e.target ).closest('.menu-item').length ) { 1927 var activeSubmenu = null, 1928 menuItem = $( e.target ).closest('.menu-item'), 1929 type = menuItem.closest('.fl-menu-accordion').length ? 'accordion' : 'horizontal'; 1930 1931 if ( 'horizontal' === type ) { 1932 if ( menuItem.hasClass( 'fl-has-submenu' ) && menuItem.hasClass( 'focus' ) ) { 1933 activeSubmenu = menuItem.find('> ul.sub-menu'); 1934 } 1935 else { 1936 activeSubmenu = menuItem.closest('ul.sub-menu'); 1937 } 1938 activeSubmenu.parent().addClass('escaped'); 1939 activeSubmenu.parent().find('a:first').focus(); 1940 } 1941 else { 1942 if ( menuItem.hasClass( 'fl-has-submenu' ) && 'accordion' === type && menuItem.hasClass( 'fl-active' ) ) { 1943 activeSubmenu = menuItem.find('> ul.sub-menu'); 1944 } 1945 else { 1946 activeSubmenu = menuItem.closest('ul.sub-menu'); 1947 } 1948 1949 activeSubmenu.slideUp(400, function(){ 1950 if ( menuItem.hasClass( 'fl-has-submenu' ) && menuItem.hasClass( 'fl-active' ) ) { 1951 activeSubmenu.parent().last().find('a:first').focus(); 1952 } 1953 else { 1954 menuItem.removeClass('focus'); 1955 menuItem.parents('.menu-item').first().find('a:first').focus(); 1956 } 1957 activeSubmenu.parent().last().removeClass( 'fl-active' ); 1958 }); 1959 1960 } 1961 } 1962 else { 1963 $('.fl-menu').find( 'li.menu-item.focus' ).last().removeClass('focus'); 1964 } 1965 }, this ) ); 1966 }, 1967 1968 /** 1969 * Logic for submenu toggling on accordions or mobile menus (vertical, horizontal) 1970 * 1971 * @since 1.6.1 1972 * @return void 1973 */ 1974 _menuOnClick: function(){ 1975 $( this.wrapperClass ).off().on( 'click', '.fl-has-submenu-container', $.proxy( function( e ){ 1976 1977 var $link = $( e.target ).parents( '.fl-has-submenu' ).first(), 1978 $subMenu = $link.children( '.sub-menu' ).first(), 1979 $href = $link.children('.fl-has-submenu-container').first().find('> a').attr('href'), 1980 $subMenuParents = $( e.target ).parents( '.sub-menu' ), 1981 $activeParents = $( e.target ).parents( '.fl-has-submenu.fl-active' ); 1982 1983 if( !$subMenu.is(':visible') || $(e.target).hasClass('fl-menu-toggle') 1984 || ($subMenu.is(':visible') && (typeof $href === 'undefined' || $href == '#')) ){ 1985 e.preventDefault(); 1986 } 1987 else { 1988 e.stopPropagation(); 1989 window.location.href = $href; 1990 return; 1991 } 1992 1993 if ($(this.wrapperClass).hasClass('fl-menu-accordion-collapse')) { 1994 1995 if ( !$link.parents('.menu-item').hasClass('fl-active') ) { 1996 $('.menu .fl-active', this.wrapperClass).not($link).removeClass('fl-active'); 1997 } 1998 else if ($link.parents('.menu-item').hasClass('fl-active') && $link.parent('.sub-menu').length) { 1999 $('.menu .fl-active', this.wrapperClass).not($link).not($activeParents).removeClass('fl-active'); 2000 } 2001 2002 $('.sub-menu', this.wrapperClass).not($subMenu).not($subMenuParents).slideUp('normal'); 2003 } 2004 2005 if ( ! this.mobileStacked && 'horizontal' == this.type && 'expanded' == this.mobileToggle ) { 2006 $( this.wrapperClass ).find( '.fl-active' ).not($link).not($activeParents).removeClass( 'fl-active' ); 2007 } 2008 else { 2009 $subMenu.slideToggle(); 2010 } 2011 2012 $link.toggleClass( 'fl-active' ); 2013 e.stopPropagation(); 2014 2015 }, this ) ); 2016 2017 }, 2018 2019 /** 2020 * Logic for submenu items click event 2021 * 2022 * @since 1.10.6 2023 * @return void 2024 */ 2025 _submenuOnClick: function(){ 2026 $( this.wrapperClass + ' .sub-menu' ).off().on( 'click', 'a', $.proxy( function( e ){ 2027 if ( $( e.target ).parent().hasClass('focus') ) { 2028 $( e.target ).parentsUntil( this.wrapperClass ).removeClass('focus'); 2029 } 2030 }, this ) ); 2031 }, 2032 2033 /** 2034 * Changes general styling and behavior of menus based on mobile / desktop viewport. 2035 * 2036 * @see this._isMenuToggle() 2037 * @since 1.6.1 2038 * @return void 2039 */ 2040 _clickOrHover: function(){ 2041 this.$submenus = this.$submenus || $( this.wrapperClass ).find( '.sub-menu' ); 2042 var $wrapper = $( this.wrapperClass ), 2043 $menu = $wrapper.find( '.menu' ); 2044 $li = $wrapper.find( '.fl-has-submenu' ); 2045 2046 if( this._isMenuToggle() ){ 2047 $li.each( function( el ){ 2048 if( !$(this).hasClass('fl-active') ){ 2049 $(this).find( '.sub-menu' ).fadeOut(); 2050 } 2051 } ); 2052 } else { 2053 $li.each( function( el ){ 2054 if( !$(this).hasClass('fl-active') ){ 2055 $(this).find( '.sub-menu' ).css( { 2056 'display' : '', 2057 'opacity' : '' 2058 } ); 2059 } 2060 } ); 2061 } 2062 }, 2063 2064 /** 2065 * Logic to prevent submenus to go outside viewport boundaries. 2066 * 2067 * @since 1.6.1 2068 * @return void 2069 */ 2070 _submenuOnRight: function(){ 2071 2072 $( this.wrapperClass ) 2073 .on( 'mouseenter focus', '.fl-has-submenu', $.proxy( function( e ){ 2074 2075 if( $ ( e.currentTarget ).find('.sub-menu').length === 0 ) { 2076 return; 2077 } 2078 2079 var $link = $( e.currentTarget ), 2080 $parent = $link.parent(), 2081 $subMenu = $link.find( '.sub-menu' ), 2082 subMenuWidth = $subMenu.width(), 2083 subMenuPos = 0, 2084 bodyWidth = $( 'body' ).width(); 2085 2086 if( $link.closest( '.fl-menu-submenu-right' ).length !== 0) { 2087 2088 $link.addClass( 'fl-menu-submenu-right' ); 2089 2090 } else if( $( 'body' ).hasClass( 'rtl' ) ) { 2091 2092 subMenuPos = $parent.is( '.sub-menu' ) ? 2093 $parent.offset().left - subMenuWidth: 2094 $link.offset().left - $link.width() - subMenuWidth; 2095 2096 if( subMenuPos <= 0 ) { 2097 $link.addClass( 'fl-menu-submenu-right' ); 2098 } 2099 2100 } else { 2101 2102 subMenuPos = $parent.is( '.sub-menu' ) ? 2103 $parent.offset().left + $parent.width() + subMenuWidth : 2104 $link.offset().left + $link.width() + subMenuWidth; 2105 2106 if( subMenuPos > bodyWidth ) { 2107 $link.addClass('fl-menu-submenu-right'); 2108 } 2109 } 2110 }, this ) ) 2111 .on( 'mouseleave', '.fl-has-submenu', $.proxy( function( e ){ 2112 $( e.currentTarget ).removeClass( 'fl-menu-submenu-right' ); 2113 }, this ) ); 2114 2115 }, 2116 2117 /** 2118 * Logic to prevent submenus to go behind the next overlay row. 2119 * 2120 * @since 1.10.9 2121 * @return void 2122 */ 2123 _submenuRowZindexFix: function( e ){ 2124 2125 $( this.wrapperClass ) 2126 .on( 'mouseenter', 'ul.menu > .fl-has-submenu', $.proxy( function( e ){ 2127 2128 if( $ ( e.currentTarget ).find('.sub-menu').length === 0 ) { 2129 return; 2130 } 2131 2132 $( this.nodeClass ) 2133 .closest( '.fl-row' ) 2134 .find( '.fl-row-content' ) 2135 .css( 'z-index', '10' ); 2136 2137 }, this ) ) 2138 .on( 'mouseleave', 'ul.menu > .fl-has-submenu', $.proxy( function( e ){ 2139 2140 $( this.nodeClass ) 2141 .closest( '.fl-row' ) 2142 .find( '.fl-row-content' ) 2143 .css( 'z-index', '' ); 2144 2145 }, this ) ); 2146 }, 2147 2148 /** 2149 * Logic for the mobile menu button. 2150 * 2151 * @since 1.6.1 2152 * @return void 2153 */ 2154 _toggleForMobile: function(){ 2155 2156 var $wrapper = null, 2157 $menu = null, 2158 self = this; 2159 2160 if( this._isMenuToggle() ){ 2161 2162 if ( this._isMobileBelowRowEnabled() ) { 2163 this._placeMobileMenuBelowRow(); 2164 $wrapper = $( this.wrapperClass ); 2165 $menu = $( this.nodeClass + '-clone' ); 2166 $menu.find( 'ul.menu' ).show(); 2167 } 2168 else { 2169 $wrapper = $( this.wrapperClass ); 2170 $menu = $wrapper.find( '.menu' ); 2171 } 2172 2173 if( !$wrapper.find( '.fl-menu-mobile-toggle' ).hasClass( 'fl-active' ) && ! self.mobileFlyout ){ 2174 $menu.css({ display: 'none' }); 2175 } 2176 2177 // Flayout Menu 2178 if ( self.mobileFlyout ) { 2179 this._initFlyoutMenu(); 2180 } 2181 2182 $wrapper.on( 'click', '.fl-menu-mobile-toggle', function( e ){ 2183 2184 $( this ).toggleClass( 'fl-active' ); 2185 2186 if ( self.mobileFlyout ) { 2187 self._toggleFlyoutMenu(); 2188 } 2189 else { 2190 var targetMenu = null; 2191 2192 if ( self.mobileBelowRow ) { 2193 targetMenu = $( this ).closest( '.fl-col' ).next( '.fl-menu-mobile-clone' ); 2194 } else { 2195 targetMenu = $( this ).closest( '.fl-menu' ).find( 'ul.menu' ); 2196 } 2197 2198 if ( targetMenu.length ) { 2199 $menu = $( targetMenu ); 2200 } 2201 2202 $menu.slideToggle(); 2203 } 2204 2205 e.stopPropagation(); 2206 } ); 2207 2208 // Hide active menu when click on anchor link ID that exists on a page. 2209 $menu.off().on( 'click', '.menu-item > a[href*="#"]:not([href="#"])', function(e){ 2210 var $href = $(this).attr('href'), 2211 $targetID = $href.split('#')[1], 2212 element = $('#' + $targetID); 2213 if ( $('body').find(element).length > 0 ) { 2214 $( this ).toggleClass( 'fl-active' ); 2215 FLBuilderLayout._scrollToElement( element ); 2216 if ( ! self._isMenuToggle() ) { 2217 $menu.slideToggle(); 2218 } 2219 } 2220 }); 2221 } 2222 else { 2223 2224 if ( this._isMobileBelowRowEnabled() ) { 2225 this._removeMenuFromBelowRow(); 2226 } 2227 2228 $wrapper = $( this.wrapperClass ), 2229 $menu = $wrapper.find( 'ul.menu' ); 2230 $wrapper.find( '.fl-menu-mobile-toggle' ).removeClass( 'fl-active' ); 2231 $menu.css({ display: '' }); 2232 2233 if ( ! this._isMobileBelowRowEnabled() ) { 2234 $menu.off( 'click', '.menu-item > a[href*="#"]:not([href="#"])' ); 2235 } 2236 2237 if ( this.mobileFlyout && $wrapper.find( '.fl-menu-mobile-flyout' ).length > 0 ) { 2238 $( 'body' ).css( 'margin', '' );
2239 $( '.fl-builder-ui-pinned-content-transform' ).css( 'transform', '' ); 2240 $menu.unwrap(); 2241 $wrapper.find( '.fl-menu-mobile-close' ).remove(); 2242 $wrapper.find( '.fl-menu-mobile-opacity' ).remove(); 2243 } 2244 } 2245 }, 2246 2247 /** 2248 * Init any mega menus that exist. 2249 * 2250 * @see this._isMenuToggle() 2251 * @since 1.10.4 2252 * @return void 2253 */ 2254 _initMegaMenus: function(){ 2255 2256 var module = $( this.nodeClass ), 2257 rowContent = module.closest( '.fl-row-content' ), 2258 rowWidth = rowContent.width(), 2259 megas = module.find( '.mega-menu' ), 2260 disabled = module.find( '.mega-menu-disabled' ), 2261 isToggle = this._isMenuToggle(); 2262 2263 if ( isToggle ) { 2264 megas.removeClass( 'mega-menu' ).addClass( 'mega-menu-disabled' ); 2265 module.find( 'li.mega-menu-disabled > ul.sub-menu' ).css( 'width', '' ); 2266 rowContent.css( 'position', '' ); 2267 } else { 2268 disabled.removeClass( 'mega-menu-disabled' ).addClass( 'mega-menu' ); 2269 module.find( 'li.mega-menu > ul.sub-menu' ).css( 'width', rowWidth + 'px' ); 2270 rowContent.css( 'position', 'relative' ); 2271 } 2272 }, 2273 2274 /** 2275 * Check to see if Below Row should be enabled. 2276 * 2277 * @since 1.11 2278 * @return boolean 2279 */ 2280 _isMobileBelowRowEnabled: function() { 2281 return this.mobileBelowRow && $( this.nodeClass ).closest( '.fl-col' ).length; 2282 }, 2283 2284 /** 2285 * Logic for putting the mobile menu below the menu's 2286 * column so it spans the full width of the page. 2287 * 2288 * @since 1.10 2289 * @return void 2290 */ 2291 _placeMobileMenuBelowRow: function(){ 2292 2293 if ( $( this.nodeClass + '-clone' ).length ) { 2294 return; 2295 } 2296 2297 var module = $( this.nodeClass ), 2298 clone = null, 2299 col = module.closest( '.fl-col' ); 2300 2301 if ( module.length < 1 ) { 2302 return; 2303 } 2304 2305 clone = ( module.length > 1 ) ? $( module[0] ).clone() : module.clone(); 2306 module.find( 'ul.menu' ).remove(); 2307 clone.addClass( ( this.nodeClass + '-clone' ).replace( '.', '' ) ); 2308 clone.addClass( 'fl-menu-mobile-clone' ); 2309 clone.find( '.fl-menu-mobile-toggle' ).remove(); 2310 col.after( clone ); 2311 2312 // Removes animation when enabled. 2313 if ( module.hasClass( 'fl-animation' ) ) { 2314 clone.removeClass( 'fl-animation' ); 2315 } 2316 2317 this._menuOnClick(); 2318 }, 2319 2320 /** 2321 * Logic for removing the mobile menu from below the menu's 2322 * column and putting it back in the main wrapper. 2323 * 2324 * @since 1.10 2325 * @return void 2326 */ 2327 _removeMenuFromBelowRow: function(){ 2328 2329 if ( ! $( this.nodeClass + '-clone' ).length ) { 2330 return; 2331 } 2332 2333 var module = $( this.nodeClass ), 2334 clone = $( this.nodeClass + '-clone' ), 2335 menu = clone.find( 'ul.menu' ); 2336 2337 module.find( '.fl-menu-mobile-toggle' ).after( menu ); 2338 clone.remove(); 2339 menu.find( 'a' ).each( FLBuilderLayout._initAnchorLink ); 2340 }, 2341 2342 /** 2343 * Logic for Flyout responsive menu. 2344 * 2345 * @since 2.2 2346 * @return void 2347 */ 2348 _initFlyoutMenu: function(){ 2349 var win = $( window ), 2350 wrapper = $( this.wrapperClass ), 2351 menu = wrapper.find( 'ul.menu' ), 2352 button = wrapper.find( '.fl-menu-mobile-toggle' ); 2353 2354 if ( 0 === wrapper.find( '.fl-menu-mobile-flyout' ).length ) { 2355 menu.wrap( '<div class="fl-menu-mobile-flyout"></div>' ); 2356 } 2357 2358 if ( 0 === wrapper.find( '.fl-menu-mobile-close' ).length ) { 2359 close = window.fl_responsive_close || 'Close' 2360 wrapper.find( '.fl-menu-mobile-flyout' ) 2361 .prepend( '<button class="fl-menu-mobile-close" aria-label="' + close + '"><i class="fas fa-times" aria-hidden="true"></i></button>' ); 2362 } 2363 2364 // Push with opacity 2365 if ( wrapper.hasClass( 'fl-menu-responsive-flyout-push-opacity' ) && 0 === wrapper.find( '.fl-menu-mobile-opacity' ).length ) { 2366 wrapper.append( '<div class="fl-menu-mobile-opacity"></div>' ); 2367 } 2368 2369 wrapper.on( 'click', '.fl-menu-mobile-opacity, .fl-menu-mobile-close', function(e){ 2370 button.trigger( 'click' ); 2371 e.stopPropagation(); 2372 }); 2373 2374 if ( 'undefined' !== typeof FLBuilder ) { 2375 FLBuilder.addHook('restartEditingSession', function(){ 2376 $( '.fl-builder-ui-pinned-content-transform' ).css( 'transform', '' ); 2377 2378 // Toggle active menu. 2379 if ( button.hasClass( 'fl-active' ) ) { 2380 button.trigger( 'click' ); 2381 } 2382 }); 2383 } 2384 }, 2385 2386 /** 2387 * Logic to enable/disable the Flyout menu on button click. 2388 * 2389 * @since 2.2 2390 * @return void 2391 */ 2392 _toggleFlyoutMenu: function(){ 2393 var wrapper = $( this.wrapperClass ), 2394 button = wrapper.find( '.fl-menu-mobile-toggle' ), 2395 wrapFlyout = wrapper.find( '.fl-menu-mobile-flyout' ), 2396 position = wrapper.hasClass( 'fl-flyout-right' ) ? 'right' : 'left', 2397 pushMenu = wrapper.hasClass( 'fl-menu-responsive-flyout-push' ) || wrapper.hasClass( 'fl-menu-responsive-flyout-push-opacity' ), 2398 opacity = wrapper.find( '.fl-menu-mobile-opacity' ),
2399 marginPos = {}, 2400 posAttr = {}, 2401 fixedPos = {}, 2402 winHeight = $(window).height(), 2403 fixedHeader = $('header, header > div'); 2404 2405 if ( button.hasClass( 'fl-active' ) ) { 2406 posAttr[ position ] = '0px'; 2407 posAttr[ 'height' ] = winHeight + 'px'; 2408 } else { 2409 posAttr[ position ] = '-267px'; 2410 } 2411 2412 wrapFlyout.css( posAttr ); 2413 2414 // Fix the push menu when builder ui panel is pinned. 2415 if ( $( '.fl-builder-ui-pinned-content-transform' ).length > 0 && ! $( 'body' ).hasClass( 'fl-builder-edit' ) ) { 2416 $( '.fl-builder-ui-pinned-content-transform' ).css( 'transform', 'none' ); 2417 } 2418 2419 if ( pushMenu ) { 2420 marginPos[ 'margin-' + position ] = button.hasClass( 'fl-active' ) ? '250px' : '0px'; 2421 $( 'body' ).animate( marginPos, 200); 2422 2423 // Fixed header 2424 if ( fixedHeader.length > 0 ) { 2425 fixedPos[ position] = button.hasClass( 'fl-active' ) ? '250px' : '0px'; 2426 fixedHeader.each(function(){ 2427 if ( 'fixed' == $( this ).css( 'position' ) ) { 2428 $( this ).css({ 2429 '-webkit-transition': 'none', 2430 '-o-transition' : 'none', 2431 'transition' : 'none' 2432 }); 2433 $( this ).animate( fixedPos, 200 ); 2434 } 2435 }); 2436 } 2437 } 2438 2439 if ( opacity.length > 0 && button.hasClass( 'fl-active' ) ) { 2440 opacity.show(); 2441 } 2442 else { 2443 opacity.hide(); 2444 } 2445 }, 2446 2447 /** 2448 * Shows or hides the nav search form. 2449 * 2450 * @since 2.5 2451 * @method _toggleMenuSearch 2452 */ 2453 _toggleMenuSearch: function(){ 2454 var wrapper = $( this.wrapperClass ).find('.fl-menu-search-item'), 2455 button = wrapper.find('a.fl-button'), 2456 form = wrapper.find('.fl-search-form-input-wrap'), 2457 self = this; 2458 2459 button.on('click', function(e){ 2460 e.preventDefault(); 2461 2462 if(form.is(':visible')) { 2463 form.stop().fadeOut(200); 2464 } 2465 else { 2466 form.stop().fadeIn(200); 2467 $('body').on('click.fl-menu-search', $.proxy(self._hideMenuSearch, self)); 2468 form.find('.fl-search-text').focus(); 2469 } 2470 }); 2471 }, 2472 2473 /** 2474 * Hides the nav search form. 2475 * 2476 * @since 2.5 2477 * @method _hideMenuSearch 2478 */ 2479 _hideMenuSearch: function(e){ 2480 var form = $( this.wrapperClass ).find('.fl-search-form-input-wrap'); 2481 2482 if(e !== undefined) { 2483 if($(e.target).closest('.fl-menu-search-item').length > 0) { 2484 return; 2485 } 2486 } 2487 2488 form.stop().fadeOut(200); 2489 $('body').off('click.fl-menu-search'); 2490 }, 2491 2492 /** 2493 * Adds menu node and post ID to WooCommerce ajax URL requests. 2494 * 2495 * @since 3.0 2496 * @return void 2497 */ 2498 _wooUpdateParams: function() { 2499 if ( 'undefined' !== typeof wc_cart_fragments_params ) { 2500 wc_cart_fragments_params.wc_ajax_url += '&fl-menu-node='+ this.nodeId +'&post-id='+ this.postId; 2501 } 2502 if ( 'undefined' !== typeof wc_add_to_cart_params ) { 2503 wc_add_to_cart_params.wc_ajax_url += '&fl-menu-node='+ this.nodeId +'&post-id='+ this.postId; 2504 } 2505 }, 2506 }; 2507 2508})(jQuery); 2509 2510(function($) { 2511 2512 $(function() { 2513 2514 new FLBuilderMenu({ 2515 id: '6390024adc4a9', 2516 type: 'horizontal', 2517 mobile: 'hamburger', 2518 mobileBelowRow: false, 2519 mobileFlyout: false, 2520 breakPoints: { 2521 large: 1200, 2522 medium: 992, 2523 small: 768 }, 2524 mobileBreakpoint: 'mobile', 2525 postId : '400', 2526 mobileStacked: true, 2527 }); 2528 2529 }); 2530 2531})(jQuery); 2532jQuery(function($) { 2533 2534 $(function() { 2535 $( '.fl-node-63744d7f7a670 .fl-photo-img' ) 2536 .on( 'mouseenter', function( e ) { 2537 $( this ).data( 'title', $( this ).attr( 'title' ) ).removeAttr( 'title' ); 2538 } ) 2539 .on( 'mouseleave', function( e ){ 2540 $( this ).attr( 'title', $( this ).data( 'title' ) ).data( 'title', null ); 2541 } ); 2542 }); 2543 window._fl_string_to_slug_regex = 'a-zA-Z0-9'; 2544}); 2545 2546/** 2547 * This file should contain frontend logic for 2548 * all module instances. 2549 */jQuery(function($) { 2550 2551 $(function() { 2552 $( '.fl-node-5a3bf56067287 .fl-photo-img' ) 2553 .on( 'mouseenter', function( e ) { 2554 $( this ).data( 'title', $( this ).attr( 'title' ) ).removeAttr( 'title' ); 2555 } ) 2556 .on( 'mouseleave', function( e ){ 2557 $( this ).attr( 'title', $( this ).data( 'title' ) ).data( 'title', null ); 2558 } ); 2559 }); 2560 window._fl_string_to_slug_regex = 'a-zA-Z0-9'; 2561}); 2562 2563/* Start Global Node Custom JS */ 2564 2565/* End Global Node Custom JS */ 2566 2567 2568/* Start Layout Custom JS */ 2569 2570/* End Layout Custom JS */ 2571
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.