1var wpAjaxUrl = 'https://shepherdess.co.nz/wp-admin/admin-ajax.php';var flBuilderUrl = 'https://shepherdess.co.nz/wp-content/plugins/bb-plugin/';var FLBuilderLayoutConfig = { 2 anchorLinkAnimations : { 3 duration : 1000, 4 easing : 'swing', 5 offset : 100 6 }, 7 paths : { 8 pluginUrl : 'https://shepherdess.co.nz/wp-content/plugins/bb-plugin/', 9 wpAjaxUrl : 'https://shepherdess.co.nz/wp-admin/admin-ajax.php' 10 }, 11 breakpoints : { 12 small : 768, 13 medium : 1024, 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 buttons. 52 FLBuilderLayout._initButtons(); 53 54 // Init row shape layer height. 55 FLBuilderLayout._initRowShapeLayerHeight(); 56 57 // Only init if the builder isn't active. 58 if ( 0 === $('.fl-builder-edit').length ) { 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 $('body').removeClass( 'fl-no-js' ); 75 }, 76 77 /** 78 * Public method for refreshing Wookmark or MosaicFlow galleries 79 * within an element. 80 * 81 * @since 1.7.4 82 * @method refreshGalleries 83 */ 84 refreshGalleries: function( element ) 85 { 86 var $element = 'undefined' == typeof element ? $( 'body' ) : $( element ), 87 mfContent = $element.find( '.fl-mosaicflow-content' ), 88 wmContent = $element.find( '.fl-gallery' ), 89 mfObject = null; 90 91 if ( mfContent ) { 92 93 mfObject = mfContent.data( 'mosaicflow' ); 94 95 if ( mfObject ) { 96 mfObject.columns = $( [] ); 97 mfObject.columnsHeights = []; 98 mfContent.data( 'mosaicflow', mfObject ); 99 mfContent.mosaicflow( 'refill' ); 100 } 101 } 102 if ( wmContent ) { 103 wmContent.trigger( 'refreshWookmark' ); 104 } 105 }, 106 107 /** 108 * Public method for refreshing Masonry within an element 109 * 110 * @since 1.8.1 111 * @method refreshGridLayout 112 */ 113 refreshGridLayout: function( element ) 114 { 115 var $element = 'undefined' == typeof element ? $( 'body' ) : $( element ), 116 msnryContent = $element.find('.masonry'); 117 118 if ( msnryContent.length ) { 119 msnryContent.masonry('layout'); 120 } 121 }, 122 123 /** 124 * Public method for reloading BxSlider within an element 125 * 126 * @since 1.8.1 127 * @method reloadSlider 128 */ 129 reloadSlider: function( content ) 130 { 131 var $content = 'undefined' == typeof content ? $('body') : $(content); 132 133 // reload sliders. 134 if ($content.find('.bx-viewport > div').length > 0) { 135 $.each($content.find('.bx-viewport > div'), function (key, slider) { 136 setTimeout(function () { 137 $(slider).data('bxSlider').reloadSlider(); 138 }, 100); 139 }); 140 } 141 }, 142 143 /** 144 * Public method for resizing WP audio player 145 * 146 * @since 1.8.2 147 * @method resizeAudio 148 */ 149 resizeAudio: function( element ) 150 { 151 var $element = 'undefined' == typeof element ? $( 'body' ) : $( element ), 152 audioPlayers = $element.find('.wp-audio-shortcode.mejs-audio'), 153 player = null, 154 mejsPlayer = null, 155 rail = null, 156 railWidth = 400; 157 158 if ( audioPlayers.length && typeof mejs !== 'undefined' ) { 159 audioPlayers.each(function(){ 160 player = $(this); 161 mejsPlayer = mejs.players[player.attr('id')]; 162 rail = player.find('.mejs-controls .mejs-time-rail'); 163 var innerMejs = player.find('.mejs-inner'), 164 total = player.find('.mejs-controls .mejs-time-total'); 165 166 if ( typeof mejsPlayer !== 'undefined' ) { 167 railWidth = Math.ceil(player.width() * 0.8); 168 169 if ( innerMejs.length ) { 170 171 rail.css('width', railWidth +'px!important'); 172 //total.width(rail.width() - 10); 173 174 mejsPlayer.options.autosizeProgress = true; 175 176 // webkit has trouble doing this without a delay 177 setTimeout(function () { 178 mejsPlayer.setControlsSize(); 179 }, 50); 180 181 player.find('.mejs-inner').css({ 182 visibility: 'visible', 183 height: 'inherit' 184 }); 185 } 186 } 187 }); 188 } 189 }, 190 191 /** 192 * Public method for preloading WP audio player when it's inside the hidden element 193 * 194 * @since 1.8.2 195 * @method preloadAudio 196 */ 197 preloadAudio: function(element) 198 { 199 var $element = 'undefined' == typeof element ? $( 'body' ) : $( element ), 200 contentWrap = $element.closest('.fl-accordion-item'), 201 audioPlayers = $element.find('.wp-audio-shortcode.mejs-audio'); 202 203 if ( ! contentWrap.hasClass('fl-accordion-item-active') && audioPlayers.find('.mejs-inner').length ) { 204 audioPlayers.find('.mejs-inner').css({ 205 visibility : 'hidden', 206 height: 0 207 }); 208 } 209 }, 210 211 /** 212 * Public method for resizing slideshow momdule within the tab 213 * 214 * @since 1.10.5 215 * @method resizeSlideshow 216 */ 217 resizeSlideshow: function(){ 218 if(typeof YUI !== 'undefined') { 219 YUI().use('node-event-simulate', function(Y) { 220 Y.one(window).simulate("resize"); 221 }); 222 } 223 }, 224 225 /** 226 * Public method for reloading an embedded Google Map within the tabs or hidden element. 227 * 228 * @since 2.2 229 * @method reloadGoogleMap 230 */ 231 reloadGoogleMap: function(element){ 232 var $element = 'undefined' == typeof element ? $( 'body' ) : $( element ),
233 googleMap = $element.find( 'iframe[src*="google.com/maps"]' ); 234 235 if ( googleMap.length ) { 236 googleMap.attr( 'src', function(i, val) { 237 return val; 238 }); 239 } 240 }, 241 242 /** 243 * Unbinds builder layout events. 244 * 245 * @since 1.0 246 * @access private 247 * @method _destroy 248 */ 249 _destroy: function() 250 { 251 var win = $(window); 252 253 win.off('scroll.fl-bg-parallax'); 254 win.off('resize.fl-bg-video'); 255 }, 256 257 /** 258 * Checks to see if the current device has touch enabled. 259 * 260 * @since 1.0 261 * @access private 262 * @method _isTouch 263 * @return {Boolean} 264 */ 265 _isTouch: function() 266 { 267 if(('ontouchstart' in window) || (window.DocumentTouch && document instanceof DocumentTouch)) { 268 return true; 269 } 270 271 return false; 272 }, 273 274 /** 275 * Checks to see if the current device is mobile. 276 * 277 * @since 1.7 278 * @access private 279 * @method _isMobile 280 * @return {Boolean} 281 */ 282 _isMobile: function() 283 { 284 return /Mobile|Android|Silk\/|Kindle|BlackBerry|Opera Mini|Opera Mobi|webOS/i.test( navigator.userAgent ); 285 }, 286 287 /** 288 * Initializes builder body classes. 289 * 290 * @since 1.0 291 * @access private 292 * @method _initClasses 293 */ 294 _initClasses: function() 295 { 296 var body = $( 'body' ), 297 ua = navigator.userAgent; 298 299 // Add the builder body class. 300 if ( ! body.hasClass( 'archive' ) && $( '.fl-builder-content-primary' ).length > 0 ) { 301 body.addClass('fl-builder'); 302 } 303 304 // Add the builder touch body class. 305 if(FLBuilderLayout._isTouch()) { 306 body.addClass('fl-builder-touch'); 307 } 308 309 // Add the builder mobile body class. 310 if(FLBuilderLayout._isMobile()) { 311 body.addClass('fl-builder-mobile'); 312 } 313 314 if ( $(window).width() < FLBuilderLayoutConfig.breakpoints.small ) { 315 body.addClass( 'fl-builder-breakpoint-small' ); 316 } 317 318 if ( $(window).width() > FLBuilderLayoutConfig.breakpoints.small && $(window).width() < FLBuilderLayoutConfig.breakpoints.medium ) { 319 body.addClass( 'fl-builder-breakpoint-medium' ); 320 } 321 322 if ( $(window).width() > FLBuilderLayoutConfig.breakpoints.medium && $(window).width() < FLBuilderLayoutConfig.breakpoints.large ) { 323 body.addClass( 'fl-builder-breakpoint-large' ); 324 } 325 326 if ( $(window).width() > FLBuilderLayoutConfig.breakpoints.large ) { 327 body.addClass( 'fl-builder-breakpoint-default' ); 328 } 329 330 // IE11 body class. 331 if ( ua.indexOf( 'Trident/7.0' ) > -1 && ua.indexOf( 'rv:11.0' ) > -1 ) { 332 body.addClass( 'fl-builder-ie-11' ); 333 } 334 }, 335 336 /** 337 * Initializes builder node backgrounds that require 338 * additional JavaScript logic such as parallax. 339 * 340 * @since 1.1.4 341 * @access private
342 * @method _initBackgrounds 343 */ 344 _initBackgrounds: function() 345 { 346 var win = $(window); 347 348 // Init parallax backgrounds. 349 if($('.fl-row-bg-parallax').length > 0 && !FLBuilderLayout._isMobile()) { 350 FLBuilderLayout._scrollParallaxBackgrounds(); 351 FLBuilderLayout._initParallaxBackgrounds(); 352 win.on('resize.fl-bg-parallax', FLBuilderLayout._initParallaxBackgrounds); 353 win.on('scroll.fl-bg-parallax', FLBuilderLayout._scrollParallaxBackgrounds); 354 } 355 356 // Init video backgrounds. 357 if($('.fl-bg-video').length > 0) { 358 FLBuilderLayout._initBgVideos(); 359 FLBuilderLayout._resizeBgVideos(); 360 361 // Ensure FLBuilderLayout._resizeBgVideos() is only called once on window resize. 362 var resizeBGTimer = null; 363 win.on('resize.fl-bg-video', function(e){ 364 clearTimeout( resizeBGTimer ); 365 resizeBGTimer = setTimeout(function() { 366 FLBuilderLayout._resizeBgVideos(e); 367 }, 100 ); 368 }); 369 } 370 }, 371 372 /** 373 * Initializes all buttons in a layout. 374 * 375 * @since 2.10 376 * @access private 377 * @method _initButtons 378 */ 379 _initButtons: function() 380 { 381 // Trigger click event on Enter or Space key press for deprecated button markup. 382 $('a.fl-button[role="button"]').on('keydown', function(event) { 383 if (event.key === 'Enter' || event.key === ' ') { 384 // Necessary to prevent the default behavior of the space key from scrolling the page 385 event.preventDefault(); 386 $(this).trigger('click'); 387 } 388 }); 389 }, 390 391 /** 392 * Initializes all parallax backgrounds in a layout. 393 * 394 * @since 1.1.4 395 * @access private 396 * @method _initParallaxBackgrounds 397 */ 398 _initParallaxBackgrounds: function() 399 { 400 $('.fl-row-bg-parallax').each(FLBuilderLayout._initParallaxBackground); 401 }, 402 403 /** 404 * Initializes a single parallax background. 405 * 406 * @since 1.1.4 407 * @access private 408 * @method _initParallaxBackgrounds 409 */ 410 _initParallaxBackground: function() 411 { 412 var row = $(this), 413 content = row.find('> .fl-row-content-wrap'), 414 winWidth = $(window).width(), 415 screenSize = '', 416 imageSrc = { 417 default: '', 418 medium: '', 419 responsive: '', 420 }; 421 422 imageSrc.default = row.data('parallax-image') || ''; 423 imageSrc.medium = row.data('parallax-image-medium') || imageSrc.default; 424 imageSrc.responsive = row.data('parallax-image-responsive') || imageSrc.medium; 425 426 if (winWidth > FLBuilderLayoutConfig.breakpoints.medium) { 427 screenSize = 'default'; 428 } else if (winWidth > FLBuilderLayoutConfig.breakpoints.small && winWidth <= FLBuilderLayoutConfig.breakpoints.medium ) { 429 screenSize = 'medium'; 430 } else if (winWidth <= FLBuilderLayoutConfig.breakpoints.small) { 431 screenSize = 'responsive'; 432 } 433 434 content.css('background-image', 'url(' + imageSrc[screenSize] + ')'); 435 row.data('current-image-loaded', screenSize ); 436 437 }, 438 439 /** 440 * Fires when the window is scrolled to adjust 441 * parallax backgrounds. 442 * 443 * @since 1.1.4 444 * @access private 445 * @method _scrollParallaxBackgrounds 446 */ 447 _scrollParallaxBackgrounds: function() 448 { 449 $('.fl-row-bg-parallax').each(FLBuilderLayout._scrollParallaxBackground); 450 }, 451 452 /** 453 * Fires when the window is scrolled to adjust 454 * a single parallax background. 455 * 456 * @since 1.1.4 457 * @access private 458 * @method _scrollParallaxBackground 459 */ 460 _scrollParallaxBackground: function() 461 { 462 var win = $(window), 463 row = $(this), 464 content = row.find('> .fl-row-content-wrap'), 465 speed = row.data('parallax-speed'), 466 offset = content.offset(), 467 yPos = -((win.scrollTop() - offset.top) / speed), 468 initialOffset = ( row.data('parallax-offset') != null ) ? row.data('parallax-offset') : 0, 469 totalOffset = yPos - initialOffset; 470 471 content.css('background-position', 'center ' + totalOffset + 'px'); 472 }, 473 474 /** 475 * Initializes all video backgrounds. 476 * 477 * @since 1.6.3.3 478 * @access private 479 * @method _initBgVideos 480 */ 481 _initBgVideos: function() 482 { 483 $('.fl-bg-video').each(FLBuilderLayout._initBgVideo); 484 }, 485 486 /** 487 * Initializes a video background. 488 * 489 * @since 1.6.3.3 490 * @access private 491 * @method _initBgVideo 492 */ 493 _initBgVideo: function() 494 { 495 var wrap = $( this ), 496 width = wrap.data( 'width' ), 497 height = wrap.data( 'height' ), 498 mp4 = wrap.data( 'mp4' ), 499 youtube = wrap.data( 'youtube'), 500 vimeo = wrap.data( 'vimeo'), 501 mp4Type = wrap.data( 'mp4-type' ), 502 webm = wrap.data( 'webm' ), 503 webmType = wrap.data( 'webm-type' ), 504 fallback = wrap.data( 'fallback' ), 505 loaded = wrap.data( 'loaded' ), 506 videoMobile = wrap.data( 'video-mobile' ), 507 playPauseButton = wrap.find('.fl-bg-video-play-pause-control'), 508 fallbackTag = '', 509 videoTag = null, 510 mp4Tag = null, 511 webmTag = null; 512 513 // Return if the video has been loaded for this row. 514 if ( loaded ) { 515 return; 516 } 517
518 videoTag = $( '<video autoplay loop muted playsinline></video>' ); 519 520 /** 521 * Add poster image (fallback image) 522 */ 523 if( 'undefined' != typeof fallback && '' != fallback ) { 524 videoTag.attr( 'poster', 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7' ) 525 videoTag.css({ 526 backgroundImage: 'url("' + fallback + '")', 527 backgroundColor: 'transparent', 528 backgroundRepeat: 'no-repeat', 529 backgroundSize: 'cover', 530 backgroundPosition: 'center center', 531 }) 532 } 533 534 // MP4 Source Tag 535 if ( 'undefined' != typeof mp4 && '' != mp4 ) { 536 537 mp4Tag = $( '<source />' ); 538 mp4Tag.attr( 'src', mp4 ); 539 mp4Tag.attr( 'type', mp4Type ); 540 541 videoTag.append( mp4Tag ); 542 } 543 // WebM Source Tag 544 if ( 'undefined' != typeof webm && '' != webm ) { 545 546 webmTag = $( '<source />' ); 547 webmTag.attr( 'src', webm ); 548 webmTag.attr( 'type', webmType ); 549 550 videoTag.append( webmTag ); 551 } 552 553 // This is either desktop, or mobile is enabled. 554 if ( ! FLBuilderLayout._isMobile() || ( FLBuilderLayout._isMobile() && "yes" == videoMobile ) ) { 555 if ( 'undefined' != typeof youtube ) { 556 FLBuilderLayout._initYoutubeBgVideo.apply( this ); 557 } 558 else if ( 'undefined' != typeof vimeo ) { 559 FLBuilderLayout._initVimeoBgVideo.apply( this ); 560 } 561 else { 562 wrap.append( videoTag ); 563 564 if ( playPauseButton.length > 0 ) { 565 var video = videoTag[0]; 566 567 playPauseButton.on( 'click', { video: video }, function(e) { 568 var video = e.data.video; 569 570 if ( video.paused ) { 571 video.play(); 572 } else { 573 video.pause(); 574 } 575 } ); 576 577 $( video ).on( 'play playing', function () { 578 playPauseButton.removeClass( 'fa-play' ).addClass( 'fa-pause' ); 579 } ); 580 581 $( video ).on( 'pause ended waiting', function () { 582 playPauseButton.removeClass( 'fa-pause' ).addClass( 'fa-play' ); 583 } ); 584 } 585 } 586 } 587 else { 588 // if we are here, it means we are on mobile and NO is set so remove video src and use fallback 589 videoTag.attr('src', '') 590 wrap.append( videoTag ); 591 } 592 593 // Mark this video as loaded. 594 wrap.data('loaded', true); 595 }, 596 597 /** 598 * Initializes Youtube video background 599 * 600 * @since 1.9 601 * @access private 602 * @method _initYoutubeBgVideo 603 */ 604 _initYoutubeBgVideo: function() 605 { 606 var playerWrap = $(this), 607 videoId = playerWrap.data('video-id'), 608 videoPlayer = playerWrap.find('.fl-bg-video-player'), 609 enableAudio = playerWrap.data('enable-audio'), 610 audioButton = playerWrap.find('.fl-bg-video-audio'), 611 playPauseButton = playerWrap.find('.fl-bg-video-play-pause-control'), 612 startTime = 'undefined' !== typeof playerWrap.data('start') ? playerWrap.data('start') : 0, 613 startTime = 'undefined' !== typeof playerWrap.data('t') && startTime === 0 ? playerWrap.data('t') : startTime, 614 endTime = 'undefined' !== typeof playerWrap.data('end') ? playerWrap.data('end') : 0, 615 loop = 'undefined' !== typeof playerWrap.data('loop') ? playerWrap.data('loop') : 1, 616 stateCount = 0, 617 player,fallback_showing; 618 619 if ( videoId ) { 620 fallback = playerWrap.data('fallback') || false 621 if( fallback ) { 622 playerWrap.find('iframe').remove() 623 fallbackTag = $( '<div></div>' ); 624 fallbackTag.addClass( 'fl-bg-video-fallback' ); 625 fallbackTag.css( 'background-image', 'url(' + playerWrap.data('fallback') + ')' ); 626 fallbackTag.css( 'background-size', 'cover' ); 627 fallbackTag.css( 'transition', 'background-image 1s') 628 playerWrap.append( fallbackTag ); 629 fallback_showing = true; 630 } 631 FLBuilderLayout._onYoutubeApiReady( function( YT ) { 632 setTimeout( function() { 633 634 player = new YT.Player( videoPlayer[0], { 635 videoId: videoId, 636 events: { 637 onReady: function(event) { 638 if ( "no" === enableAudio || FLBuilderLayout._isMobile() ) { 639 event.target.mute(); 640 } 641 else if ( "yes" === enableAudio && event.target.isMuted ) { 642 event.target.unMute(); 643 } 644 645 // Store an instance to a parent 646 playerWrap.data('YTPlayer', player); 647 FLBuilderLayout._resizeYoutubeBgVideo.apply(playerWrap); 648 649 // Queue the video. 650 event.target.playVideo(); 651 652 if ( audioButton.length > 0 && ! FLBuilderLayout._isMobile() ) {
653 audioButton.on( 'click', {button: audioButton, player: player}, FLBuilderLayout._toggleBgVideoAudio ); 654 } 655 656 if ( playPauseButton.length > 0 ) { 657 playPauseButton.on( 'click', {player: player}, function(e) { 658 var player = e.data.player; 659 660 if ( 1 === player.getPlayerState() ) { 661 player.pauseVideo(); 662 } else { 663 player.playVideo(); 664 } 665 }); 666 } 667 }, 668 onStateChange: function( event ) { 669 670 if ( event.data === 1 ) { 671 if ( fallback_showing ) { 672 $( '.fl-bg-video-fallback' ).css( 'background-image', 'url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)' ) 673 } 674 } 675 // Manual check if video is not playable in some browsers. 676 // StateChange order: [-1, 3, -1] 677 if ( stateCount < 4 ) { 678 stateCount++; 679 } 680 681 // Comply with the audio policy in some browsers like Chrome and Safari. 682 if ( stateCount > 1 && -1 === event.data && "yes" === enableAudio ) { 683 player.mute(); 684 player.playVideo(); 685 audioButton.show(); 686 } 687 688 if ( event.data === YT.PlayerState.ENDED && 1 === loop ) { 689 if ( startTime > 0 ) { 690 player.seekTo( startTime ); 691 } 692 else { 693 player.playVideo(); 694 } 695 } 696 697 if ( event.data === YT.PlayerState.PLAYING ) { 698 playPauseButton.removeClass( 'fa-play' ).addClass( 'fa-pause' ); 699 } else if ( event.data === YT.PlayerState.PAUSED ) { 700 playPauseButton.removeClass( 'fa-pause' ).addClass( 'fa-play' ); 701 } else if ( event.data === YT.PlayerState.BUFFERING ) { 702 playPauseButton.removeClass( 'fa-play' ).addClass( 'fa-pause' ); 703 } else if ( event.data === YT.PlayerState.CUED ) { 704 playPauseButton.removeClass( 'fa-pause' ).addClass( 'fa-play' ); 705 } else if ( event.data === YT.PlayerState.ENDED ) { 706 playPauseButton.removeClass( 'fa-pause' ).addClass( 'fa-play' ); 707 } 708 }, 709 onError: function(event) { 710 console.info('YT Error: ' + event.data) 711 FLBuilderLayout._onErrorYoutubeVimeo(playerWrap) 712 } 713 }, 714 playerVars: { 715 playsinline: FLBuilderLayout._isMobile() ? 1 : 0, 716 controls: 0, 717 showinfo: 0, 718 rel : 0, 719 start: startTime, 720 end: endTime, 721 } 722 } ); 723 }, 1 ); 724 } ); 725 } 726 }, 727 728 /** 729 * On youtube or vimeo error show the fallback image if available. 730 * @since 2.0.7 731 */ 732 _onErrorYoutubeVimeo: function(playerWrap) { 733 734 fallback = playerWrap.data('fallback') || false 735 if( ! fallback ) { 736 return false; 737 } 738 playerWrap.find('iframe').remove() 739 fallbackTag = $( '<div></div>' ); 740 fallbackTag.addClass( 'fl-bg-video-fallback' ); 741 fallbackTag.css( 'background-image', 'url(' + playerWrap.data('fallback') + ')' ); 742 playerWrap.append( fallbackTag ); 743 }, 744 745 /** 746 * Check if Youtube API has been downloaded 747 * 748 * @since 1.9 749 * @access private 750 * @method _onYoutubeApiReady 751 * @param {Function} callback Method to call when YT API has been loaded 752 */ 753 _onYoutubeApiReady: function( callback ) { 754 if ( window.YT && YT.loaded ) { 755 callback( YT ); 756 } else { 757 // If not ready check again by timeout.. 758 setTimeout( function() { 759 FLBuilderLayout._onYoutubeApiReady( callback ); 760 }, 350 ); 761 } 762 }, 763 764 /** 765 * Initializes Vimeo video background 766 * 767 * @since 1.9 768 * @access private 769 * @method _initVimeoBgVideo 770 */ 771 _initVimeoBgVideo: function() 772 { 773 var playerWrap = $(this), 774 videoId = playerWrap.data('video-id'), 775 videoHash = playerWrap.data('video-hash'), 776 videoPlayer = playerWrap.find('.fl-bg-video-player'), 777 enableAudio = playerWrap.data('enable-audio'), 778 audioButton = playerWrap.find('.fl-bg-video-audio'), 779 playPauseButton = playerWrap.find('.fl-bg-video-play-pause-control'), 780 playerState = '', 781 player, 782 width = playerWrap.outerWidth(), 783 ua = navigator.userAgent; 784 785 if ( typeof Vimeo !== 'undefined' && videoId ) { 786 787 const vimOptions = { 788 loop : true, 789 title : false, 790 portrait : false, 791 background : true, 792 autopause : false, 793 muted : true, 794 }; 795 796 if ( videoHash.length ) { 797 vimOptions.url = `https://player.vimeo.com/video/${ videoId }?h=${ videoHash }`; 798 } else { 799 vimOptions.id = videoId; 800 } 801 802 player = new Vimeo.Player(videoPlayer[0], vimOptions ); 803 playerWrap.data('VMPlayer', player); 804 if ( "no" === enableAudio ) { 805 player.setVolume(0); 806 } 807 else if ("yes" === enableAudio ) { 808 // Chrome, Safari, Firefox have audio policy restrictions for autoplay videos. 809 if ( ua.indexOf("Safari") > -1 || ua.indexOf("Chrome") > -1 || ua.indexOf("Firefox") > -1 ) { 810 player.setVolume(0); 811 audioButton.show(); 812 } 813 else { 814 player.setVolume(1); 815 } 816 } 817 818 player.play().catch(function(error) { 819 FLBuilderLayout._onErrorYoutubeVimeo(playerWrap) 820 }); 821 822 if ( audioButton.length > 0 ) {
823 audioButton.on( 'click', {button: audioButton, player: player}, FLBuilderLayout._toggleBgVideoAudio ); 824 } 825 826 player.on( 'play', function() { 827 playerState = 'play'; 828 playPauseButton.removeClass( 'fa-play' ).addClass( 'fa-pause' ); 829 } ); 830 player.on( 'pause', function() { 831 playerState = 'pause'; 832 playPauseButton.removeClass( 'fa-pause' ).addClass( 'fa-play' ); 833 } ); 834 player.on( 'ended', function() { 835 playerState = 'ended'; 836 playPauseButton.removeClass( 'fa-pause' ).addClass( 'fa-play' ); 837 } ); 838 player.on( 'bufferstart', function() { 839 playerState = 'bufferstart'; 840 playPauseButton.removeClass( 'fa-play' ).addClass( 'fa-pause' ); 841 } ); 842 843 if ( playPauseButton.length > 0 ) { 844 playPauseButton.on( 'click', { player: player }, function( e ) { 845 var player = e.data.player; 846 847 if ( playerState === 'play' ) { 848 player.pause(); 849 } else { 850 player.play(); 851 } 852 } ); 853 } 854 } 855 }, 856 857 /** 858 * Mute / unmute audio on row's video background. 859 * It works for both Youtube and Vimeo. 860 * 861 * @since 2.1.3 862 * @access private 863 * @method _toggleBgVideoAudio 864 * @param {Object} e Method arguments 865 */ 866 _toggleBgVideoAudio: function( e ) { 867 var player = e.data.player, 868 control = e.data.button.find('.fl-audio-control'); 869 870 if ( control.hasClass( 'fa-volume-off' ) ) { 871 // Unmute 872 control 873 .removeClass( 'fa-volume-off' ) 874 .addClass( 'fa-volume-up' ); 875 e.data.button.find( '.fa-times' ).hide(); 876 877 if ( 'function' === typeof player.unMute ) { 878 player.unMute(); 879 } 880 else { 881 player.setVolume( 1 ); 882 } 883 } 884 else { 885 // Mute 886 control 887 .removeClass( 'fa-volume-up' ) 888 .addClass( 'fa-volume-off' ); 889 e.data.button.find( '.fa-times' ).show(); 890 891 if ( 'function' === typeof player.unMute ) { 892 player.mute(); 893 } 894 else { 895 player.setVolume( 0 ); 896 } 897 } 898 }, 899 900 /** 901 * Fires when there is an error loading a video 902 * background source and shows the fallback. 903 * 904 * @since 1.6.3.3 905 * @access private 906 * @method _videoBgSourceError 907 * @param {Object} e An event object 908 * @deprecated 2.0.3 909 */ 910 _videoBgSourceError: function( e ) 911 { 912 var source = $( e.target ), 913 wrap = source.closest( '.fl-bg-video' ), 914 vid = wrap.find( 'video' ), 915 fallback = wrap.data( 'fallback' ), 916 fallbackTag = ''; 917 source.remove(); 918 919 if ( vid.find( 'source' ).length ) { 920 // Don't show the fallback if we still have other sources to check. 921 return; 922 } else if ( '' !== fallback ) { 923 fallbackTag = $( '<div></div>' ); 924 fallbackTag.addClass( 'fl-bg-video-fallback' ); 925 fallbackTag.css( 'background-image', 'url(' + fallback + ')' ); 926 wrap.append( fallbackTag ); 927 vid.remove(); 928 } 929 }, 930 931 /** 932 * Fires when the window is resized to resize 933 * all video backgrounds. 934 * 935 * @since 1.1.4 936 * @access private 937 * @method _resizeBgVideos 938 */ 939 _resizeBgVideos: function() 940 { 941 $('.fl-bg-video').each( function() { 942 943 FLBuilderLayout._resizeBgVideo.apply( this ); 944 945 if ( $( this ).parent().find( 'img' ).length > 0 ) { 946 $( this ).parent().imagesLoaded( $.proxy( FLBuilderLayout._resizeBgVideo, this ) ); 947 } 948 } ); 949 }, 950 951 /** 952 * Fires when the window is resized to resize 953 * a single video background. 954 * 955 * @since 1.1.4 956 * @access private 957 * @method _resizeBgVideo 958 */ 959 _resizeBgVideo: function() 960 { 961 if ( 0 === $( this ).find( 'video' ).length && 0 === $( this ).find( 'iframe' ).length ) { 962 return; 963 } 964 965 var wrap = $(this), 966 wrapHeight = wrap.outerHeight(), 967 wrapWidth = wrap.outerWidth(), 968 vid = wrap.find('video'), 969 vidHeight = wrap.data('height'), 970 vidWidth = wrap.data('width'), 971 newWidth = wrapWidth, 972 newHeight = Math.round(vidHeight * wrapWidth/vidWidth), 973 newLeft = 0, 974 newTop = 0, 975 iframe = wrap.find('iframe'), 976 isRowFullHeight = $(this).closest('.fl-row-bg-video').hasClass('fl-row-full-height'), 977 vidCSS = { 978 top: '50%', 979 left: '50%', 980 transform: 'translate(-50%,-50%)', 981 }; 982 983 if ( vid.length ) { 984 if(vidHeight === '' || typeof vidHeight === 'undefined' || vidWidth === '' || typeof vidWidth === 'undefined') { 985 vid.css({ 986 'left' : '0px', 987 'top' : '0px', 988 'width' : newWidth + 'px' 989 }); 990 991 // Try to set the actual video dimension on 'loadedmetadata' when using URL as video source 992 vid.on('loadedmetadata', FLBuilderLayout._resizeOnLoadedMeta); 993 994 return; 995 } 996 997 if ( ! isRowFullHeight ) { 998 if ( newHeight < wrapHeight ) { 999 newHeight = wrapHeight; 1000 newLeft = -((newWidth - wrapWidth) / 2); 1001 newWidth = vidHeight ? Math.round(vidWidth * wrapHeight/vidHeight) : newWidth; 1002 } 1003 else { 1004 newTop = -((newHeight - wrapHeight)/2); 1005 } 1006 vidCSS = { 1007 left : newLeft + 'px', 1008 top : newTop + 'px', 1009 height : newHeight + 'px', 1010 width : newWidth + 'px', 1011 } 1012 } 1013 1014 vid.css( vidCSS ); 1015 1016 } 1017 else if ( iframe.length ) { 1018 1019 // Resize Youtube video player within iframe tag 1020 if ( typeof wrap.data('youtube') !== 'undefined' ) { 1021 FLBuilderLayout._resizeYoutubeBgVideo.apply(this); 1022 } 1023 } 1024 }, 1025 1026 /** 1027 * Fires when video meta has been loaded. 1028 * This will be Triggered when width/height attributes were not specified during video background resizing. 1029 * 1030 * @since 1.8.5 1031 * @access private 1032 * @method _resizeOnLoadedMeta 1033 */ 1034 _resizeOnLoadedMeta: function(){ 1035 var video = $(this), 1036 wrapHeight = video.parent().outerHeight(), 1037 wrapWidth = video.parent().outerWidth(), 1038 vidWidth = video[0].videoWidth, 1039 vidHeight = video[0].videoHeight, 1040 newHeight = Math.round(vidHeight * wrapWidth/vidWidth), 1041 newWidth = wrapWidth, 1042 newLeft = 0, 1043 newTop = 0; 1044 1045 if(newHeight < wrapHeight) { 1046 newHeight = wrapHeight; 1047 newWidth = Math.round(vidWidth * wrapHeight/vidHeight); 1048 newLeft = -((newWidth - wrapWidth)/2); 1049 } 1050 else { 1051 newTop = -((newHeight - wrapHeight)/2); 1052 } 1053 1054 video.parent().data('width', vidWidth); 1055 video.parent().data('height', vidHeight); 1056 1057 video.css({ 1058 'left' : newLeft + 'px', 1059 'top' : newTop + 'px', 1060 'width' : newWidth + 'px', 1061 'height' : newHeight + 'px' 1062 }); 1063 }, 1064 1065 /** 1066 * Fires when the window is resized to resize 1067 * a single Youtube video background. 1068 * 1069 * @since 1.9 1070 * @access private 1071 * @method _resizeYoutubeBgVideo 1072 */ 1073 _resizeYoutubeBgVideo: function() 1074 { 1075 var wrap = $(this), 1076 wrapWidth = wrap.outerWidth(), 1077 wrapHeight = wrap.outerHeight(), 1078 player = wrap.data('YTPlayer'), 1079 video = player ? player.getIframe() : null, 1080 aspectRatioSetting = '16:9', // Medium 1081 aspectRatioArray = aspectRatioSetting.split( ':' ),
1082 aspectRatio = aspectRatioArray[0] / aspectRatioArray[1], 1083 ratioWidth = wrapWidth / aspectRatio, 1084 ratioHeight = wrapHeight * aspectRatio, 1085 isWidthFixed = wrapWidth / wrapHeight > aspectRatio, 1086 width = isWidthFixed ? wrapWidth : ratioHeight, 1087 height = isWidthFixed ? ratioWidth : wrapHeight; 1088 1089 if ( video ) { 1090 $(video).width( width ).height( height ); 1091 } 1092 }, 1093 1094 /** 1095 * Opens a tab or accordion item if the browser hash is set 1096 * to the ID of one on the page. 1097 * 1098 * @since 1.6.0 1099 * @access private 1100 * @method _initHash 1101 */ 1102 _initHash: function() 1103 { 1104 var hash = window.location.hash.replace( '#', '' ).split( '/' ).shift(), 1105 element = null, 1106 tabs = null, 1107 responsiveLabel = null, 1108 tabIndex = null, 1109 label = null; 1110 1111 if ( '' !== hash ) { 1112 1113 try { 1114 1115 element = $( '#' + hash ); 1116 1117 if ( element.length > 0 ) { 1118 1119 if ( element.hasClass( 'fl-accordion-item' ) ) { 1120 setTimeout( function() { 1121 element.find( '.fl-accordion-button' ).trigger( 'click' ); 1122 }, 100 ); 1123 } 1124 if ( element.hasClass( 'fl-tabs-panel' ) ) { 1125 setTimeout( function() { 1126 tabs = element.closest( '.fl-tabs' ); 1127 responsiveLabel = element.find( '.fl-tabs-panel-label' ); 1128 tabIndex = responsiveLabel.data( 'index' ); 1129 label = tabs.find( '.fl-tabs-labels .fl-tabs-label[data-index=' + tabIndex + ']' ); 1130 1131 label[0].click(); 1132 FLBuilderLayout._scrollToElement(element); 1133 }, 100 ); 1134 } 1135 } 1136 } 1137 catch( e ) {} 1138 } 1139 }, 1140 1141 /** 1142 * Initializes all anchor links on the page for smooth scrolling. 1143 * 1144 * @since 1.4.9 1145 * @access private 1146 * @method _initAnchorLinks 1147 */ 1148 _initAnchorLinks: function() 1149 { 1150 $( 'a' ).each( FLBuilderLayout._initAnchorLink ); 1151 }, 1152 1153 /** 1154 * Initializes a single anchor link for smooth scrolling. 1155 * 1156 * @since 1.4.9 1157 * @access private 1158 * @method _initAnchorLink 1159 */ 1160 _initAnchorLink: function() 1161 { 1162 var link = $( this ), 1163 href = link.attr( 'href' ), 1164 loc = window.location, 1165 id = null, 1166 element = null, 1167 flNode = false; 1168 1169 if ( 'undefined' != typeof href && href.indexOf( '#' ) > -1 && link.closest('svg').length < 1 ) { 1170 1171 if ( loc.pathname.replace( /^\//, '' ) == this.pathname.replace( /^\//, '' ) && loc.hostname == this.hostname ) { 1172 1173 try { 1174 1175 id = href.split( '#' ).pop(); 1176 // If there is no ID then we have nowhere to look 1177 // Fixes a quirk in jQuery and FireFox 1178 if( ! id ) { 1179 return; 1180 } 1181 element = $( '#' + id ); 1182 1183 if ( element.length > 0 ) { 1184 flNode = element.hasClass( 'fl-row' ) || element.hasClass( 'fl-col' ) || element.hasClass( 'fl-module' ); 1185 if ( !element.hasClass( 'fl-no-scroll' ) && ( link.hasClass( 'fl-scroll-link' ) || flNode ) ) { 1186 $( link ).on( 'click', FLBuilderLayout._scrollToElementOnLinkClick ); 1187 } 1188 if ( element.hasClass( 'fl-accordion-item' ) ) { 1189 $( link ).on( 'click', FLBuilderLayout._scrollToAccordionOnLinkClick ); 1190 } 1191 if ( element.hasClass( 'fl-tabs-panel' ) ) { 1192 $( link ).on( 'click', FLBuilderLayout._scrollToTabOnLinkClick ); 1193 } 1194 } 1195 } 1196 catch( e ) {} 1197 } 1198 } 1199 }, 1200 1201 /** 1202 * Scrolls to an element when an anchor link is clicked. 1203 * 1204 * @since 1.4.9 1205 * @access private 1206 * @method _scrollToElementOnLinkClick 1207 * @param {Object} e An event object. 1208 * @param {Function} callback A function to call when the scroll is complete. 1209 */ 1210 _scrollToElementOnLinkClick: function( e, callback ) 1211 { 1212 var element = $( '#' + $( this ).attr( 'href' ).split( '#' ).pop() ); 1213 1214 FLBuilderLayout._scrollToElement( element, callback ); 1215 1216 e.preventDefault(); 1217 }, 1218 1219 /** 1220 * Scrolls to an element. 1221 * 1222 * @since 1.6.4.5 1223 * @access private 1224 * @method _scrollToElement 1225 * @param {Object} element The element to scroll to. 1226 * @param {Function} callback A function to call when the scroll is complete. 1227 */ 1228 _scrollToElement: function( element, callback ) 1229 { 1230 var config = FLBuilderLayoutConfig.anchorLinkAnimations, 1231 dest = 0, 1232 win = $( window ), 1233 doc = $( document ); 1234 1235 if ( element.length > 0 ) { 1236 1237 if ( 'fixed' === element.css('position') || 'fixed' === element.parent().css('position') ) { 1238 dest = element.position().top; 1239 } 1240 else if ( element.offset().top > doc.height() - win.height() ) { 1241 dest = doc.height() - win.height(); 1242 } 1243 else { 1244 dest = element.offset().top - config.offset; 1245 } 1246 1247 $( 'html, body' ).stop( true ).animate( { scrollTop: dest }, config.duration, config.easing, function() { 1248 1249 if ( 'undefined' != typeof callback ) { 1250 callback(); 1251 } 1252 1253 if ( undefined != element.attr( 'id' ) && window.location.hash !== '#' + element.attr( 'id' ) ) { 1254 1255 var firefox_version = window.navigator.userAgent.match( /Firefox\/(\d+)\./ ), 1256 firefox_version = firefox_version ? parseInt( firefox_version[1], 10 ) : null; 1257 1258 if ( firefox_version !== null && firefox_version < 135 ) { 1259 window.location.hash = element.attr( 'id' ); 1260 } else { 1261 if ( history.pushState ) { 1262 history.pushState( null, null, '#' + element.attr( 'id' ) ); 1263 } else { 1264 window.location.hash = element.attr( 'id' ); 1265 } 1266 } 1267 } 1268 } ); 1269 } 1270 }, 1271 1272 /** 1273 * Scrolls to an accordion item when a link is clicked. 1274 * 1275 * @since 1.5.9 1276 * @access private 1277 * @method _scrollToAccordionOnLinkClick 1278 * @param {Object} e An event object. 1279 */ 1280 _scrollToAccordionOnLinkClick: function( e ) 1281 { 1282 var element = $( '#' + $( this ).attr( 'href' ).split( '#' ).pop() ); 1283 1284 if ( element.length > 0 ) { 1285 1286 var callback = function() { 1287 if ( element ) { 1288 element.find( '.fl-accordion-button' ).trigger( 'click' ); 1289 element = false;
1290 } 1291 }; 1292 1293 FLBuilderLayout._scrollToElementOnLinkClick.call( this, e, callback ); 1294 } 1295 }, 1296 1297 /** 1298 * Scrolls to a tab panel when a link is clicked. 1299 * 1300 * @since 1.5.9 1301 * @access private 1302 * @method _scrollToTabOnLinkClick 1303 * @param {Object} e An event object. 1304 */ 1305 _scrollToTabOnLinkClick: function( e ) 1306 { 1307 var element = $( '#' + $( this ).attr( 'href' ).split( '#' ).pop() ), 1308 tabs = null, 1309 label = null, 1310 responsiveLabel = null; 1311 1312 if ( element.length > 0 ) { 1313 1314 tabs = element.closest( '.fl-tabs' ); 1315 responsiveLabel = element.find( '.fl-tabs-panel-label' ); 1316 tabIndex = responsiveLabel.data( 'index' ); 1317 label = tabs.find( '.fl-tabs-labels .fl-tabs-label[data-index=' + tabIndex + ']' ); 1318 1319 if ( responsiveLabel.is( ':visible' ) ) { 1320 1321 var callback = function() { 1322 if ( element ) { 1323 responsiveLabel.trigger( $.Event( 'click', { which: 1 } ) ); 1324 } 1325 }; 1326 1327 FLBuilderLayout._scrollToElementOnLinkClick.call( this, e, callback ); 1328 } 1329 else { 1330 label[0].click(); 1331 FLBuilderLayout._scrollToElement( element ); 1332 } 1333 1334 e.preventDefault(); 1335 } 1336 }, 1337 1338 /** 1339 * Initializes all builder forms on a page. 1340 * 1341 * @since 1.5.4 1342 * @access private 1343 * @method _initForms 1344 */ 1345 _initForms: function() 1346 { 1347 if ( ! FLBuilderLayout._hasPlaceholderSupport ) { 1348 $( '.fl-form-field input' ).each( FLBuilderLayout._initFormFieldPlaceholderFallback ); 1349 } 1350 1351 $( '.fl-form-field input' ).on( 'focus', FLBuilderLayout._clearFormFieldError ); 1352 }, 1353 1354 /** 1355 * Checks to see if the current device has HTML5 1356 * placeholder support. 1357 * 1358 * @since 1.5.4 1359 * @access private 1360 * @method _hasPlaceholderSupport 1361 * @return {Boolean} 1362 */ 1363 _hasPlaceholderSupport: function() 1364 { 1365 var input = document.createElement( 'input' ); 1366 1367 return 'undefined' != input.placeholder; 1368 }, 1369 1370 /** 1371 * Initializes the fallback for when placeholders aren't supported. 1372 * 1373 * @since 1.5.4 1374 * @access private 1375 * @method _initFormFieldPlaceholderFallback 1376 */ 1377 _initFormFieldPlaceholderFallback: function() 1378 { 1379 var field = $( this ), 1380 val = field.val(), 1381 placeholder = field.attr( 'placeholder' ); 1382 1383 if ( 'undefined' != placeholder && '' === val ) { 1384 field.val( placeholder ); 1385 field.on( 'focus', FLBuilderLayout._hideFormFieldPlaceholderFallback ); 1386 field.on( 'blur', FLBuilderLayout._showFormFieldPlaceholderFallback ); 1387 } 1388 }, 1389 1390 /** 1391 * Hides a fallback placeholder on focus. 1392 * 1393 * @since 1.5.4 1394 * @access private 1395 * @method _hideFormFieldPlaceholderFallback 1396 */ 1397 _hideFormFieldPlaceholderFallback: function() 1398 { 1399 var field = $( this ), 1400 val = field.val(), 1401 placeholder = field.attr( 'placeholder' ); 1402 1403 if ( val == placeholder ) { 1404 field.val( '' ); 1405 } 1406 }, 1407 1408 /** 1409 * Shows a fallback placeholder on blur. 1410 * 1411 * @since 1.5.4 1412 * @access private 1413 * @method _showFormFieldPlaceholderFallback 1414 */ 1415 _showFormFieldPlaceholderFallback: function() 1416 { 1417 var field = $( this ), 1418 val = field.val(), 1419 placeholder = field.attr( 'placeholder' ); 1420 1421 if ( '' === val ) { 1422 field.val( placeholder ); 1423 } 1424 }, 1425 1426 /** 1427 * Clears a form field error message. 1428 * 1429 * @since 1.5.4 1430 * @access private 1431 * @method _clearFormFieldError 1432 */ 1433 _clearFormFieldError: function() 1434 { 1435 var field = $( this ); 1436 1437 field.removeAttr( 'aria-invalid' ); 1438 field.removeClass( 'fl-form-error' ); 1439 const message = field.attr('aria-describedby'); 1440 message ? $( '#' + message ).hide() : field.siblings( '.fl-form-error-message' ).hide(); 1441 }, 1442 1443 /** 1444 * Init Row Shape Layer's height. 1445 * 1446 * @since 2.5.3 1447 * @access private 1448 * @method _initRowShapeLayerHeight 1449 */ 1450 _initRowShapeLayerHeight: function () { 1451 FLBuilderLayout._adjustRowShapeLayerHeight(); 1452 $( window ).on( 'resize', FLBuilderLayout._adjustRowShapeLayerHeight ); 1453 }, 1454 1455 /** 1456 * Set parent column width of nested columns when it's zero or blank. 1457 * 1458 * @since 2.7.4 1459 * @access private 1460 * @method _initNestedColsWidth 1461 */ 1462 _initNestedColsWidth: function() 1463 { 1464 var nestedCols = $( '.fl-col-has-cols' ); 1465 1466 if ( nestedCols.length <= 0 ) { 1467 return; 1468 } 1469 1470 $( nestedCols ).each( function(index, col ){ 1471 if ( $( col ).width() <= 0 ) { 1472 $( col ).css( 'width', FLBuilderLayoutConfig.emptyColWidth ); 1473 } 1474 }); 1475 }, 1476 1477 /** 1478 * Adjust Row Shape Layer's height to fix to remove the fine line that appears on certain screen sizes. 1479 * 1480 * @since 2.5.3 1481 * @access private 1482 * @method _adjustRowShapeLayerHeight 1483 */
1484 _adjustRowShapeLayerHeight: function() { 1485 var rowShapeLayers = $('.fl-builder-shape-layer'); 1486 1487 $( rowShapeLayers ).each(function (index) { 1488 var rowShapeLayer = $(this), 1489 shape = $(rowShapeLayer).find('svg'), 1490 height = shape.height(), 1491 excludeShapes = '.fl-builder-shape-circle, .fl-builder-shape-dot-cluster, .fl-builder-shape-topography, .fl-builder-shape-rect'; 1492 1493 if ( ! rowShapeLayer.is( excludeShapes ) ) { 1494 $(shape).css('height', Math.ceil( height ) ); 1495 } 1496 }); 1497 }, 1498 _string_to_slug: function( str ) { 1499 str = str.replace(/^\s+|\s+$/g, ''); // trim 1500 if ( 'undefined' == typeof window._fl_string_to_slug_regex ) { 1501 regex = new RegExp('[^a-zA-Z0-9\'":() !.,-_|]', 'g'); 1502 } else { 1503 regex = new RegExp('[^' + window._fl_string_to_slug_regex + '\'":\(\) !.,-_|\\\p{Letter}]', 'ug'); 1504 } 1505 str = str.replace(regex, '') // remove invalid chars 1506 .replace(/\s+/g, ' '); // collapse whitespace and replace by a space 1507 return str; 1508 }, 1509 _reorderMenu: function() { 1510 if ( $('#wp-admin-bar-fl-builder-frontend-edit-link-default li').length > 1 ) { 1511 $( '#wp-admin-bar-fl-builder-frontend-duplicate-link' ) 1512 .appendTo('#wp-admin-bar-fl-builder-frontend-edit-link-default') 1513 .css( 'padding-top', '5px' ) 1514 .css( 'border-top', '2px solid #1D2125' ) 1515 .css( 'margin-top', '5px' ) 1516 } 1517 } 1518 }; 1519 1520 /* Initializes the builder layout. */ 1521 $(function(){ 1522 FLBuilderLayout.init(); 1523 }); 1524 1525})(jQuery); 1526(function($){ 1527 1528 if(typeof FLBuilderLayoutModules !== 'undefined') { 1529 return; 1530 } 1531 1532 /** 1533 * Helper class with generic logic for builder modules. 1534 * If generic module code needs to work in both the block 1535 * editor and builder, it should go here. Otherwise, it 1536 * should go on FLBuilderLayout. 1537 * 1538 * @since 2.9 1539 */ 1540 FLBuilderLayoutModules = { 1541 1542 /** 1543 * Initializes builder module logic. 1544 * 1545 * @since 2.9 1546 * @method init 1547 */ 1548 init: function() 1549 { 1550 // Only init if the builder isn't active. 1551 if ( 0 === $('.fl-builder-edit').length ) { 1552 1553 // Init module animations. 1554 FLBuilderLayoutModules._initModuleAnimations(); 1555 } 1556 }, 1557 1558 /** 1559 * Initializes module animations. 1560 * 1561 * @since 1.1.9 1562 * @access private 1563 * @method _initModuleAnimations 1564 */ 1565 _initModuleAnimations: function() 1566 { 1567 if(typeof jQuery.fn.waypoint !== 'undefined') { 1568 $('.fl-animation').each( function() { 1569 var node = $( this ), 1570 nodeTop = node.offset().top, 1571 winHeight = $( window ).height(), 1572 bodyHeight = $( 'body' ).height(), 1573 waypoint = FLBuilderLayoutConfig.waypoint, 1574 offset = '80%'; 1575 1576 if ( typeof waypoint.offset !== undefined ) { 1577 offset = FLBuilderLayoutConfig.waypoint.offset + '%'; 1578 } 1579 1580 if ( bodyHeight - nodeTop < winHeight * 0.2 ) { 1581 offset = '100%'; 1582 } 1583 1584 node.waypoint({ 1585 offset: offset, 1586 handler: FLBuilderLayoutModules._doModuleAnimation 1587 }); 1588 } ); 1589 } 1590 }, 1591 1592 /** 1593 * Runs a module animation. 1594 * 1595 * @since 1.1.9 1596 * @access private 1597 * @method _doModuleAnimation 1598 */ 1599 _doModuleAnimation: function() 1600 { 1601 var module = 'undefined' == typeof this.element ? $(this) : $(this.element), 1602 delay = parseFloat(module.data('animation-delay')), 1603 duration = parseFloat(module.data('animation-duration')); 1604 1605 if ( ! isNaN( duration ) ) { 1606 module.css( 'animation-duration', duration + 's' ); 1607 } 1608 1609 if(!isNaN(delay) && delay > 0) { 1610 setTimeout(function(){ 1611 module.addClass('fl-animated'); 1612 }, delay * 1000); 1613 } else { 1614 setTimeout(function(){ 1615 module.addClass('fl-animated'); 1616 }, 1); 1617 } 1618 } 1619 }; 1620 1621 /* Initializes builder module logic. */ 1622 $(function(){ 1623 FLBuilderLayoutModules.init(); 1624 }); 1625 1626})(jQuery); 1627 1628/* Start Global JS */ 1629 1630/* End Global JS */ 1631 1632(function($) { 1633 if ( $('.fl-node-pvxmab49ne03 .pp-photo-rollover').length > 0 ) { 1634 $('body').on( 'mouseenter.pp-rollover', '.fl-node-pvxmab49ne03 .pp-photo-rollover .pp-photo-content', function() { 1635 $(this).addClass( 'is-hover' ); 1636 } ).on( 'mouseleave.pp-rollover', '.fl-node-pvxmab49ne03 .pp-photo-rollover .pp-photo-content', function() { 1637 $(this).removeClass( 'is-hover' ); 1638 } ); 1639 } 1640})(jQuery); 1641;/* eslint-disable no-undef */ 1642(function($) { 1643 1644 /** 1645 * Class for Menu Module 1646 * 1647 * @since 1.6.1 1648 */ 1649 FLBuilderMenu = function( settings ){ 1650 1651 // set params 1652 this.nodeId = settings.id; 1653 this.nodeClass = '.fl-node-' + settings.id; 1654 this.wrapperClass = this.nodeClass + ' .fl-menu'; 1655 this.type = settings.type; 1656 this.mobileToggle = settings.mobile; 1657 this.mobileBelowRow = settings.mobileBelowRow; 1658 this.mobileFlyout = settings.mobileFlyout; 1659 this.breakPoints = settings.breakPoints; 1660 this.mobileBreakpoint = settings.mobileBreakpoint; 1661 this.currentBrowserWidth = $( window ).width(); 1662 this.postId = settings.postId; 1663 this.mobileStacked = settings.mobileStacked; 1664 this.submenuIcon = settings.submenuIcon; 1665 this.flyoutWidth = settings.flyoutWidth; 1666 1667 // initialize the menu 1668 this._initMenu(); 1669 1670 // check if viewport is resizing 1671 $( window ).on( 'resize', $.proxy( function() { 1672 1673 var width = $( window ).width(); 1674 1675 // if screen width is resized, reload the menu 1676 if( width != this.currentBrowserWidth ){ 1677 1678 this.currentBrowserWidth = width; 1679 this._initMenu( true ); 1680 this._clickOrHover( true ); 1681 } 1682 1683 this._resizeFlyoutMenuPanel(); 1684 }, this ) ); 1685 1686 $( window ).on( 'scroll', $.proxy( function() { 1687 this._resizeFlyoutMenuPanel(); 1688 }, this ) ); 1689 1690 // Move focus to the first menu item if the layout is set to BelowRow 1691 $( this.wrapperClass ).on( 'keydown', '.fl-menu-mobile-toggle, .menu-item:first a:first', $.proxy( function ( event ) { 1692 // Make sure it is a tab key with both the menu toggle enabled & below row layout set 1693 if ( event.key !== 'Tab' || ! this._isMenuToggle() || ! this._isMobileBelowRowEnabled() ) { 1694 return; 1695 } 1696 // Trigger focus on the mobile toggle button if the user is shift tabbing from the first menu item 1697 if ( event.shiftKey && $( event.target ).is( 'a' ) ) { 1698 event.preventDefault(); 1699 $( this.wrapperClass ).find( '.fl-menu-mobile-toggle' ).trigger( 'focus' ); 1700 } 1701 // Trigger focus on the first menu item if the user is tabbing from the mobile toggle button 1702 else if ( ! event.shiftKey && $( event.target ).hasClass( 'fl-menu-mobile-toggle' ) && $( event.target ).hasClass( 'fl-active' ) ) { 1703 event.preventDefault(); 1704 $( this.wrapperClass ).find( '.menu-item:first a:first' ).trigger( 'focus' ); 1705 } 1706 }, this ) ); 1707 1708 // Close mobile menu or accordion when tabbing out from the first or last menu item 1709 $( this.wrapperClass ).on( 'focusout', $.proxy( function ( event ) { 1710 if ( $( this.wrapperClass + ' nav' ).has( $( event.relatedTarget ) ).length === 0 ) { 1711 if ( this.type === 'accordion' ) { 1712 this._toggleSubmenu( $( event.target ).parents( '.fl-has-submenu:last' ), false ); 1713 } 1714 else { 1715 this._clickOrHover( true ); 1716 } 1717 const mobileToggle = $( this.wrapperClass ).find( '.fl-menu-mobile-toggle' ); 1718 if ( this._isMenuToggle() && mobileToggle.hasClass( 'fl-active' ) && ! $( event.relatedTarget ).is( mobileToggle ) && 'expanded' !== this.mobileToggle ) { 1719 mobileToggle.trigger( 'click' ); 1720 } 1721 } 1722 }, this ) ); 1723 1724 }; 1725 1726 FLBuilderMenu.prototype = { 1727 nodeClass : '', 1728 wrapperClass: '', 1729 type : '', 1730 breakPoints : {}, 1731 $submenus : null, 1732 1733 /** 1734 * Check if the screen size fits a mobile viewport. 1735 * 1736 * @since 1.6.1 1737 * @return bool 1738 */ 1739 _isMobile: function(){ 1740 return this.currentBrowserWidth <= this.breakPoints.small ? true : false;
1741 }, 1742 1743 /** 1744 * Check if the device is connected to a mouse. 1745 * 1746 * @since 2.9.0 1747 * @return bool 1748 */ 1749 _isMouseAvailable: function(){ 1750 return window.matchMedia("(pointer: fine) and (hover: hover)").matches; 1751 }, 1752 1753 /** 1754 * Check if the screen size fits a medium viewport. 1755 * 1756 * @since 1.10.5 1757 * @return bool 1758 */ 1759 _isMedium: function(){ 1760 return this.currentBrowserWidth <= this.breakPoints.medium ? true : false; 1761 }, 1762 1763 /** 1764 * Check if the screen size fits a large viewport. 1765 * 1766 * @since 1.10.5 1767 * @return bool 1768 */ 1769 _isLarge: function(){ 1770 return this.currentBrowserWidth <= this.breakPoints.large ? true : false; 1771 }, 1772 1773 /** 1774 * Check if the menu should toggle for the current viewport base on the selected breakpoint. 1775 * 1776 * @see this._isMobile() 1777 * @see this._isMedium() 1778 * @since 1.10.5 1779 * @return bool 1780 */ 1781 _isMenuToggle: function(){ 1782 if ( ( 'always' == this.mobileBreakpoint 1783 || ( this._isMobile() && 'mobile' == this.mobileBreakpoint ) 1784 || ( this._isMedium() && 'medium-mobile' == this.mobileBreakpoint ) 1785 || ( this._isLarge() && 'large-mobile' == this.mobileBreakpoint ) 1786 ) && ( $( this.wrapperClass ).find( '.fl-menu-mobile-toggle' ).is(':visible') || 'expanded' == this.mobileToggle ) ) { 1787 return true; 1788 } 1789 1790 return false; 1791 }, 1792 1793 /** 1794 * Initialize the toggle logic for the menu. 1795 * 1796 * @see this._isMenuToggle() 1797 * @see this._menuOnCLick() 1798 * @see this._clickOrHover() 1799 * @see this._submenuOnRight() 1800 * @see this._submenuRowZindexFix() 1801 * @see this._toggleForMobile() 1802 * @since 1.6.1 1803 * @return void 1804 */ 1805 _initMenu: function( resized = false ){ 1806 this._setupSubmenu(); 1807 if ( ! resized ) { 1808 this._menuOnFocus(); 1809 this._menuOnClick(); 1810 this._menuOnEscape(); 1811 } 1812 if ( $( this.nodeClass ).length && this.type == 'horizontal' ) { 1813 this._initMegaMenus(); 1814 } 1815 1816 if( this._isMenuToggle() || this.type == 'accordion' ){ 1817 1818 $( this.wrapperClass ).off( 'mouseenter mouseleave' ); 1819 this._clickOrHover(); 1820 1821 } else { 1822 this._submenuOnRight(); 1823 this._submenuRowZindexFix(); 1824 } 1825 1826 if( this.mobileToggle != 'expanded' ){ 1827 this._toggleForMobile(); 1828 } 1829 1830 if( $( this.wrapperClass ).find( '.fl-menu-search-item' ).length ){ 1831 this._toggleMenuSearch(); 1832 } 1833 1834 if( $( this.wrapperClass ).find( '.fl-menu-cart-item').length ){ 1835 this._wooUpdateParams(); 1836 } 1837 }, 1838 1839 /** 1840 * Whether the toggle behavior for submenus is through hovering or not. 1841 * 1842 * @since 2.5 1843 * @return void 1844 */ 1845 _setupSubmenu: function() { 1846 if ( ! this._isMouseAvailable() || this._isMenuToggle() || this.type === 'accordion' ) { 1847 $( this.wrapperClass ).addClass( 'no-hover' ); 1848 } 1849 else { 1850 $( this.wrapperClass ).removeClass( 'no-hover' ); 1851 } 1852 }, 1853 1854 /** 1855 * Logic for menu items when focused. 1856 * 1857 * @since 1.9.0 1858 * @return void 1859 */ 1860 _menuOnFocus: function(){ 1861 $( this.wrapperClass ).on( 'focus', 'a, .fl-menu-toggle', $.proxy( function( event ) { 1862 const focusedMenuItem = $( event.target ).closest( '.menu-item' ); 1863 const blurredMenuItem = $( event.relatedTarget ).closest( '.menu-item' ); 1864 // In case the blurred & focused items are siblings 1865 if ( focusedMenuItem.closest( 'ul' ).is( blurredMenuItem.closest( 'ul' ) ) ) { 1866 // Check if the focus event is not between the link & submenu icon of the same menu item 1867 if ( ! focusedMenuItem.is( blurredMenuItem ) ) { 1868 this._toggleSubmenu( blurredMenuItem, false ); 1869 } 1870 } 1871 // In case neither items are child & parent nor vice versa 1872 else if ( focusedMenuItem.has( blurredMenuItem ).length === blurredMenuItem.has( focusedMenuItem ).length ) { 1873 // Get the blurred item parent & is the sibling of the focused item 1874 blurredMenuItem.parents( '.fl-has-submenu' ).each( ( _, parent ) => { 1875 if ( focusedMenuItem.closest( 'ul' ).is( $( parent ).closest( 'ul' ) ) ) { 1876 this._toggleSubmenu( $( parent ), false ); 1877 return false; 1878 } 1879 } ); 1880 } 1881 // In case the blurred item is a child of the focused item 1882 else if ( focusedMenuItem.has( blurredMenuItem ).length ) { 1883 if ( this.type !== 'accordion' && this.submenuIcon === 'none' ) { 1884 this._toggleSubmenu( blurredMenuItem, false ); 1885 } 1886 } 1887 }, this ) ); 1888 }, 1889 1890 /** 1891 * Logic for menu items when Escape key is pressed. 1892 * 1893 * @since 2.7.1 1894 * @return void 1895 */ 1896 _menuOnEscape: function(){ 1897 $( this.wrapperClass ).on( 'keydown', $.proxy( function( event ){ 1898 if ( event.key !== 'Escape' ) return; 1899 const menuItem = $( event.target ).closest( '.menu-item' ); 1900 const mobileToggle = $( this.wrapperClass ).find( '.fl-menu-mobile-toggle' ); 1901 // In case there is a focused menu item 1902 if ( menuItem.length || $( event.target ).hasClass( 'fl-menu-mobile-close' ) ) { 1903 // Close all the submenus of the focused menu item 1904 if ( menuItem.hasClass( 'fl-has-submenu' ) && menuItem.find( '.sub-menu:first' ).is( ':visible' ) ) { 1905 this._toggleSubmenu( menuItem, false ); 1906 } 1907 else { 1908 // Shift focus to the parent while closing all its submenus 1909 const parentMenuItem = menuItem.parents( '.fl-has-submenu' ).not( '.mega-menu.hide-heading, .mega-menu-disabled.hide-heading' ).first(); 1910 // Close the mobile menu if there is no parent menu item and the mobile toggle is active 1911 if ( parentMenuItem.length === 0 && this._isMenuToggle() && mobileToggle.hasClass( 'fl-active' ) ) { 1912 // Blur to trigger the focus-out event for closing the menu 1913 mobileToggle.trigger( 'blur' ).trigger( 'focus' ); 1914 } 1915 // Close the parent submenu and shift focus to its link 1916 else if ( parentMenuItem.length !== 0 ) { 1917 this._toggleSubmenu( parentMenuItem, false ); 1918 parentMenuItem.find( 'a:first' ).trigger( 'focus' ); 1919 } 1920 } 1921 } 1922 // Close the mobile menu if the mobile toggle is active 1923 else if ( $( event.target ).hasClass( 'fl-menu-mobile-toggle' ) && mobileToggle.hasClass( 'fl-active' ) ) { 1924 // Blur to trigger the focus-out event for closing the menu 1925 mobileToggle.trigger( 'blur' ).trigger( 'focus' ); 1926 } 1927 }, this ) ); 1928 }, 1929 1930 /** 1931 * Logic for menu items when clicked. 1932 * 1933 * @since 1.6.1 1934 * @return void 1935 */ 1936 _menuOnClick: function(){ 1937 // Fallback for span elements with role="button" to be clickable 1938 $( this.wrapperClass ).on( 'keydown', 'span.fl-menu-toggle', $.proxy( function( event ) { 1939 if ( event.key === 'Enter' || event.key === ' ' ) { 1940 event.preventDefault(); 1941 $( event.target ).trigger( 'click' ); 1942 } 1943 }, this ) ); 1944 $( this.wrapperClass ).on( 'click', 'a, .fl-menu-toggle', $.proxy( function( event ) { 1945 event.stopPropagation(); 1946 // Only allow mouse clicks with accordion & mobile menus 1947 if ( this._isMouseAvailable() && ! this._isMenuToggle() && event.detail && this.type !== 'accordion' ) return; 1948 // Links only open & do not toggle submenus if there is either a submenu icon or an accordion layout 1949 if ( $( event.target ).is( 'a' ) && ( this.submenuIcon !== 'none' || this.type === 'accordion' ) ) return; 1950 const menuItem = $( event.target ).closest( '.menu-item' ); 1951 const menuLink = menuItem.find( 'a:first' ).attr( 'href' ); 1952 const submenuHidden = menuItem.find( '.sub-menu:first' ).is( ':hidden' ); 1953 if ( typeof menuLink === 'undefined' || menuLink === '#' || submenuHidden ) { 1954 event.preventDefault(); 1955 } 1956 if ( $( event.target ).hasClass( 'fl-menu-toggle' ) || submenuHidden ) { 1957 this._toggleSubmenu( menuItem, submenuHidden ); 1958 } 1959 }, this ) ); 1960 }, 1961 1962 /** 1963 * Controls toggling the visibility of all submenu items for desktop & mobile. 1964 * 1965 * @since 2.10 1966 * @return void 1967 */ 1968 _toggleSubmenu: function ( menuItem, opened ) { 1969 const togglingClass = this._isMenuToggle() || this.type === 'accordion' ? 'fl-active' : 'focus'; 1970 const toggleElement = this.submenuIcon === 'none' ? 'a' : '.fl-menu-toggle'; 1971 const hiddenMenu = '.mega-menu.hide-heading, .mega-menu-disabled.hide-heading'; 1972 if ( opened && menuItem.hasClass( 'fl-has-submenu' ) && ! menuItem.is( hiddenMenu ) ) { 1973 menuItem.addClass( togglingClass ); 1974 menuItem.find( toggleElement ).first().attr( 'aria-expanded', true ); 1975 if ( this._isMenuToggle() || this.type === 'accordion' ) { 1976 menuItem.find( '.sub-menu:first:hidden' ).slideDown(); 1977 } 1978 } 1979 else { 1980 menuItem.parent().find( '.menu-item' ).removeClass( togglingClass ); 1981 menuItem.parent().find( '.fl-has-submenu' ).not( hiddenMenu ).find( toggleElement ).attr( 'aria-expanded', false ); 1982 if ( this._isMenuToggle() || this.type === 'accordion' ) {
1983 menuItem.find( '.sub-menu:visible' ).slideUp(); 1984 } 1985 } 1986 }, 1987 1988 /** 1989 * Changes general styling and behavior of menus based on mobile / desktop viewport. 1990 * 1991 * @see this._isMenuToggle() 1992 * @since 1.6.1 1993 * @return void 1994 */ 1995 _clickOrHover: function( clear = false ){ 1996 const selector = this._isMobileBelowRowEnabled() ? this.nodeClass + '-clone' : this.nodeClass; 1997 this.$submenus = this.$submenus || $( selector ).find( '.sub-menu' ); 1998 1999 const className = this._isMenuToggle() || this.type === 'accordion' ? 'fl-active' : 'focus'; 2000 const toggleElement = this.submenuIcon === 'none' ? 'a' : '.fl-menu-toggle'; 2001 const hiddenMenu = '.mega-menu.hide-heading, .mega-menu-disabled.hide-heading'; 2002 $( selector ).find( '.fl-has-submenu' ).not( hiddenMenu ).each( function() { 2003 if( clear || ! $ ( this ).hasClass( className ) ){ 2004 if ( clear ) $( this ).removeClass( className ); 2005 $( this ).find( toggleElement + ':first' ).attr( 'aria-expanded', false ); 2006 if ( className === 'fl-active' ) { 2007 $( this ).find( '.sub-menu' ).fadeOut(); 2008 } else if ( className === 'focus' ) { 2009 $( this ).find( '.sub-menu' ).css( { 2010 'display' : '', 2011 'opacity' : '' 2012 } ); 2013 } 2014 } 2015 } ); 2016 }, 2017 2018 /** 2019 * Logic to prevent submenus to go outside viewport boundaries. 2020 * 2021 * @since 1.6.1 2022 * @return void 2023 */ 2024 _submenuOnRight: function(){ 2025 2026 $( this.wrapperClass ) 2027 .on( 'mouseenter focus', '.fl-has-submenu', $.proxy( function( e ){ 2028 2029 if( $ ( e.currentTarget ).find('.sub-menu').length === 0 ) { 2030 return; 2031 } 2032 2033 var $link = $( e.currentTarget ), 2034 $parent = $link.parent(), 2035 $subMenu = $link.find( '.sub-menu' ), 2036 subMenuWidth = $subMenu.width(), 2037 subMenuPos = 0, 2038 bodyWidth = $( 'body' ).width(); 2039 2040 if( $link.closest( '.fl-menu-submenu-right' ).length !== 0) { 2041 2042 $link.addClass( 'fl-menu-submenu-right' ); 2043 2044 } else if( $( 'body' ).hasClass( 'rtl' ) ) { 2045 2046 subMenuPos = $parent.is( '.sub-menu' ) ? 2047 $parent.offset().left - subMenuWidth: 2048 $link.offset().left - $link.width() - subMenuWidth; 2049 2050 if( subMenuPos <= 0 ) { 2051 $link.addClass( 'fl-menu-submenu-right' ); 2052 } 2053 2054 } else { 2055 2056 subMenuPos = $parent.is( '.sub-menu' ) ? 2057 $parent.offset().left + $parent.width() + subMenuWidth : 2058 $link.offset().left + $link.width() + subMenuWidth; 2059 2060 if( subMenuPos > bodyWidth ) { 2061 $link.addClass('fl-menu-submenu-right'); 2062 } 2063 } 2064 }, this ) ) 2065 .on( 'mouseleave', '.fl-has-submenu', $.proxy( function( e ){ 2066 $( e.currentTarget ).removeClass( 'fl-menu-submenu-right' ); 2067 }, this ) ); 2068 2069 }, 2070 2071 /** 2072 * Logic to prevent submenus to go behind the next overlay row. 2073 * 2074 * @since 1.10.9 2075 * @return void 2076 */ 2077 _submenuRowZindexFix: function(){ 2078 2079 $( this.wrapperClass ) 2080 .on( 'mouseenter', 'ul.menu > .fl-has-submenu', $.proxy( function( e ){ 2081 2082 if( $ ( e.currentTarget ).find('.sub-menu').length === 0 ) { 2083 return; 2084 } 2085 2086 $( this.nodeClass ) 2087 .closest( '.fl-row' ) 2088 .find( '.fl-row-content' ) 2089 .css( 'z-index', '10' ); 2090 2091 }, this ) ) 2092 .on( 'mouseleave', 'ul.menu > .fl-has-submenu', $.proxy( function(){ 2093 2094 $( this.nodeClass ) 2095 .closest( '.fl-row' ) 2096 .find( '.fl-row-content' ) 2097 .css( 'z-index', '' ); 2098 2099 }, this ) ); 2100 }, 2101 2102 /** 2103 * Logic for the mobile menu button. 2104 * 2105 * @since 1.6.1 2106 * @return void 2107 */ 2108 _toggleForMobile: function(){ 2109 2110 var $wrapper = null, 2111 $menu = null, 2112 self = this; 2113 2114 $( this.wrapperClass ).find( 'ul.menu' ).attr( 'role', 'menu'); 2115 $( this.wrapperClass ).find( '.fl-menu-mobile-toggle' ).attr('aria-controls', $( this.wrapperClass ).find( 'ul.menu' ).attr('id')); 2116 2117 if( this._isMenuToggle() ){ 2118 2119 if ( this._isMobileBelowRowEnabled() ) { 2120 this._placeMobileMenuBelowRow(); 2121 $wrapper = $( this.wrapperClass ); 2122 $menu = $( this.nodeClass + '-clone' ); 2123 $menu.find( 'ul.menu' ).show(); 2124 } 2125 else { 2126 $wrapper = $( this.wrapperClass ); 2127 $menu = $wrapper.find( '.menu' ); 2128 } 2129 2130 if( !$wrapper.find( '.fl-menu-mobile-toggle' ).hasClass( 'fl-active' ) && ! self.mobileFlyout ){ 2131 $menu.css({ display: 'none' }); 2132 } 2133 2134 // Flayout Menu 2135 if ( self.mobileFlyout ) { 2136 this._initFlyoutMenu(); 2137 } 2138 2139 $wrapper.on( 'click', '.fl-menu-mobile-toggle', function( e ){ 2140 e.stopImmediatePropagation(); 2141 2142 $( this ).toggleClass( 'fl-active' ); 2143 2144 if ( self.mobileFlyout ) { 2145 self._toggleFlyoutMenu(); 2146 const flyoutWrapper = $( '.fl-menu-mobile-flyout' ); 2147 if ( $( this ).hasClass( 'fl-active' ) ) { 2148 flyoutWrapper.attr( 'aria-hidden', false ); 2149 flyoutWrapper.find( 'a[href], button, input, select, textarea, span.fl-menu-toggle, [tabindex="-1"]' ).attr( 'tabindex', 0 ); 2150 } 2151 else { 2152 flyoutWrapper.attr( 'aria-hidden', true ); 2153 flyoutWrapper.find( 'a[href], button, input, select, textarea, span.fl-menu-toggle, [tabindex]:not
2153([tabindex="-1"])' ).attr( 'tabindex', -1 ); 2154 } 2155 } 2156 else { 2157 var targetMenu = null; 2158 2159 if ( self.mobileBelowRow ) { 2160 var $closestCol = $( this ).parents( '.fl-col, .fl-module-box' ), 2161 $closestColGroup = $closestCol.length ? $closestCol.parent( '.fl-col-group' ) : null; 2162 targetMenu = $closestCol.length ? $closestCol.last().next( '.fl-menu-mobile-clone' ) : null; 2163 2164 if ( $closestColGroup.length ) { 2165 if ( $closestColGroup.hasClass( 'fl-col-group-responsive-reversed' ) ) { 2166 $closestColGroup.find( '.fl-menu-mobile-clone' ).css( 'order', -1 ); 2167 } else if ( $closestColGroup ) { 2168 $closestColGroup.find( '.fl-menu-mobile-clone' ).css( 'order', 2 ); 2169 } 2170 } 2171 } else { 2172 targetMenu = $( this ).closest( '.fl-menu' ).find( 'ul.menu' ); 2173 } 2174 2175 if ( targetMenu.length ) { 2176 $menu = $( targetMenu ); 2177 } 2178 2179 $menu.slideToggle(); 2180 } 2181 2182 e.stopPropagation(); 2183 } ); 2184 2185 // Hide active menu when click on anchor link ID that exists on a page 2186 $menu.off().on( 'click', '.menu-item > a[href*="#"]:not([href="#"])', function(){ 2187 var $href = $(this).attr('href'), 2188 $targetID = $href.split('#')[1], 2189 element = $('#' + $targetID); 2190 if ( $('body').find(element).length > 0 ) { 2191 $( this ).toggleClass( 'fl-active' ); 2192 FLBuilderLayout._scrollToElement( element ); 2193 if ( ! self._isMenuToggle() ) { 2194 $menu.slideToggle(); 2195 } 2196 } 2197 }); 2198 } 2199 else { 2200 2201 if ( this._isMobileBelowRowEnabled() ) { 2202 this._removeMenuFromBelowRow(); 2203 } 2204 2205 $wrapper = $( this.wrapperClass ), 2206 $menu = $wrapper.find( 'ul.menu' ); 2207 $wrapper.find( '.fl-menu-mobile-toggle' ).removeClass( 'fl-active' ); 2208 $menu.css({ display: '' }); 2209 2210 if ( ! this._isMobileBelowRowEnabled() ) { 2211 $menu.off( 'click', '.menu-item > a[href*="#"]:not([href="#"])' ); 2212 } 2213 2214 if ( this.mobileFlyout && $wrapper.find( '.fl-menu-mobile-flyout' ).length > 0 ) { 2215 $( 'body' ).css( 'margin', '' ); 2216 $( '.fl-builder-ui-pinned-content-transform' ).css( 'transform', '' ); 2217 $menu.unwrap(); 2218 $wrapper.find( '.fl-menu-mobile-close' ).remove(); 2219 $wrapper.find( '.fl-menu-mobile-opacity' ).remove(); 2220 } 2221 } 2222 }, 2223 2224 /** 2225 * Init any mega menus that exist. 2226 * 2227 * @see this._isMenuToggle() 2228 * @since 1.10.4 2229 * @return void 2230 */ 2231 _initMegaMenus: function(){ 2232 2233 var module = $( this.nodeClass ), 2234 rowContent = module.closest( '.fl-row-content' ), 2235 rowWidth = rowContent.width(), 2236 megas = module.find( '.mega-menu' ), 2237 disabled = module.find( '.mega-menu-disabled' ), 2238 isToggle = this._isMenuToggle(); 2239 2240 if ( isToggle ) { 2241 megas.removeClass( 'mega-menu' ).addClass( 'mega-menu-disabled' ); 2242 module.find( 'li.mega-menu-disabled > ul.sub-menu' ).css( 'width', '' ); 2243 rowContent.css( 'position', '' ); 2244 } else { 2245 disabled.removeClass( 'mega-menu-disabled' ).addClass( 'mega-menu' ); 2246 module.find( 'li.mega-menu > ul.sub-menu' ).css( 'width', rowWidth + 'px' ); 2247 rowContent.css( 'position', 'relative' ); 2248 } 2249 }, 2250 2251 /** 2252 * Check to see if Below Row should be enabled. 2253 * 2254 * @since 1.11 2255 * @return boolean 2256 */ 2257 _isMobileBelowRowEnabled: function() { 2258 return this.mobileBelowRow && ( $( this.nodeClass ).parents( '.fl-col, .fl-module-box' ).length ); 2259 }, 2260 2261 /** 2262 * Logic for putting the mobile menu below the menu's 2263 * column so it spans the full width of the page. 2264 * 2265 * @since 1.10 2266 * @return void 2267 */ 2268 _placeMobileMenuBelowRow: function(){ 2269 2270 if ( $( this.nodeClass + '-clone' ).length ) { 2271 return; 2272 } 2273 2274 var module = $( this.nodeClass ), 2275 clone = null, 2276 col = module.parents( '.fl-col, .fl-module-box' ).last(); 2277 2278 if ( module.length < 1 ) { 2279 return; 2280 } 2281 2282 clone = ( module.length > 1 ) ? $( module[0] ).clone() : module.clone(); 2283 module.find( 'ul.menu' ).remove(); 2284 clone.addClass( ( this.nodeClass + '-clone' ).replace( '.', '' ) ); 2285 clone.addClass( 'fl-menu-mobile-clone' ); 2286 clone.find( '.fl-menu-mobile-toggle' ).remove(); 2287 col.after( clone ); 2288 2289 // Removes animation when enabled 2290 if ( module.hasClass( 'fl-animation' ) ) { 2291 clone.removeClass( 'fl-animation' ); 2292 } 2293 2294 this._menuOnFocus(); 2295 this._menuOnClick(); 2296 this._menuOnEscape(); 2297 }, 2298 2299 /** 2300 * Logic for removing the mobile menu from below the menu's 2301 * column and putting it back in the main wrapper. 2302 * 2303 * @since 1.10 2304 * @return void 2305 */ 2306 _removeMenuFromBelowRow: function(){ 2307 2308 if ( ! $( this.nodeClass + '-clone' ).length ) { 2309 return; 2310 } 2311 2312 var module = $( this.nodeClass ), 2313 clone = $( this.nodeClass + '-clone' ), 2314 menu = clone.find( 'ul.menu' ); 2315 2316 module.find( '.fl-menu-mobile-toggle' ).after( menu ); 2317 clone.remove(); 2318 menu.find( 'a' ).each( FLBuilderLayout._initAnchorLink ); 2319 }, 2320 2321 /** 2322 * Logic for Flyout responsive menu. 2323 * 2324 * @since 2.2 2325 * @return void 2326 */ 2327 _initFlyoutMenu: function(){ 2328 var wrapper = $( this.wrapperClass ), 2329 menu = wrapper.find( 'ul.menu' ), 2330 button = wrapper.find( '.fl-menu-mobile-toggle' ); 2331 2332 if ( 0 === wrapper.find( '.fl-menu-mobile-flyout' ).length ) { 2333 menu.wrap( '<div class="fl-menu-mobile-flyout" aria-hidden="true"></div>' ); 2334 } 2335 2336 if ( 0 === wrapper.find( '.fl-menu-mobile-close' ).length ) { 2337 var close = window.fl_responsive_close || 'Close' 2338 wrapper.find( '.fl-menu-mobile-flyout' ).prepend( '<button class="fl-menu-mobile-close fl-content-ui-button" aria-label="' + close + '"><i class="fas fa-times"></i></button>' ); 2339 } 2340 2341 // Push with opacity 2342 if ( wrapper.hasClass( 'fl-menu-responsive-flyout-push-opacity' ) && 0 === wrapper.find( '.fl-menu-mobile-opacity' ).length ) { 2343 wrapper.append( '<div class="fl-menu-mobile-opacity"></div>' ); 2344 } 2345 2346 wrapper.off( 'click', '.fl-menu-mobile-opacity, .fl-menu-mobile-close' ).on( 'click', '.fl-menu-mobile-opacity, .fl-menu-mobile-close', function(e){ 2347 button.trigger('focus').trigger( 'click' ); 2348 e.stopPropagation(); 2349 }); 2350 2351 if ( 'undefined' !== typeof FLBuilder ) { 2352 FLBuilder.addHook('restartEditingSession', function(){
2353 $( '.fl-builder-ui-pinned-content-transform' ).css( 'transform', '' ); 2354 2355 // Toggle active menu 2356 if ( button.hasClass( 'fl-active' ) ) { 2357 button.trigger( 'click' ); 2358 } 2359 }); 2360 } 2361 $( '.fl-menu-mobile-flyout' ).find( 'a[href], button, input, select, textarea, span.fl-menu-toggle, [tabindex]:not([tabindex="-1"])' ).attr( 'tabindex', -1 ); 2362 }, 2363 2364 /** 2365 * Logic to enable/disable the Flyout menu on button click. 2366 * 2367 * @since 2.2 2368 * @return void 2369 */ 2370 _toggleFlyoutMenu: function(){ 2371 var wrapper = $( this.wrapperClass ), 2372 button = wrapper.find( '.fl-menu-mobile-toggle' ), 2373 position = wrapper.hasClass( 'fl-flyout-right' ) ? 'right' : 'left', 2374 pushMenu = wrapper.hasClass( 'fl-menu-responsive-flyout-push' ) || wrapper.hasClass( 'fl-menu-responsive-flyout-push-opacity' ), 2375 opacity = wrapper.find( '.fl-menu-mobile-opacity' ), 2376 marginPos = {}, 2377 fixedPos = {}, 2378 fixedHeader = $('header, header > div'); 2379 2380 this._resizeFlyoutMenuPanel(); 2381 2382 // Fix the push menu when builder ui panel is pinned 2383 if ( $( '.fl-builder-ui-pinned-content-transform' ).length > 0 && ! $( 'body' ).hasClass( 'fl-builder-edit' ) ) { 2384 $( '.fl-builder-ui-pinned-content-transform' ).css( 'transform', 'none' ); 2385 } 2386 2387 if ( pushMenu ) { 2388 marginPos[ 'margin-' + position ] = button.hasClass( 'fl-active' ) ? this.flyoutWidth + 'px' : '0px'; 2389 $( 'body' ).animate( marginPos, 200); 2390 2391 // Fixed header 2392 if ( fixedHeader.length > 0 ) { 2393 fixedPos[ position] = button.hasClass( 'fl-active' ) ? this.flyoutWidth + 'px' : '0px'; 2394 fixedHeader.each(function(){ 2395 if ( 'fixed' == $( this ).css( 'position' ) ) { 2396 $( this ).css({ 'transition' : 'none' }); 2397 $( this ).animate( fixedPos, 200 ); 2398 } 2399 }); 2400 } 2401 } 2402 2403 if ( opacity.length > 0 && button.hasClass( 'fl-active' ) ) { 2404 opacity.show(); 2405 } 2406 else { 2407 opacity.hide(); 2408 } 2409 }, 2410 2411 /** 2412 * Resize or reposition the Flyout Menu Panel. 2413 * 2414 * @since 2.8.1 2415 * @return void 2416 */ 2417 _resizeFlyoutMenuPanel: function(){ 2418 const wrapper = $( this.wrapperClass ); 2419 const wrapFlyout = wrapper.find( '.fl-menu-mobile-flyout' ); 2420 2421 if ( wrapFlyout.length > 0 ) { 2422 wrapFlyout.css( this._getFlyoutMenuPanelPosition() ); 2423 } 2424 }, 2425 2426 /** 2427 * Compute the Flyout Menu Panel's position on the screen. 2428 * 2429 * @since 2.8.1 2430 * @return object 2431 */ 2432 _getFlyoutMenuPanelPosition: function() { 2433 var wrapper = $( this.wrapperClass ), 2434 button = wrapper.find( '.fl-menu-mobile-toggle' ), 2435 side = wrapper.hasClass( 'fl-flyout-right' ) ? 'right' : 'left', 2436 winHeight = $(window).outerHeight(), 2437 winTop = $(window).scrollTop(), 2438 adminBarHeight = $( '#wpadminbar' ).length ? $( '#wpadminbar' ).height() : 0, 2439 flyoutPosition = {}; 2440 2441 flyoutPosition[ side ] = '-' + ( parseInt( this.flyoutWidth ) + 15 ) + 'px'; 2442 if ( ! button.hasClass( 'fl-active' ) ) { 2443 return flyoutPosition; 2444 } 2445 2446 flyoutPosition[ side ] = '0px'; 2447 flyoutPosition[ 'height' ] = winHeight + 'px'; 2448 flyoutPosition[ 'top' ] = '0px'; 2449 2450 if ( adminBarHeight > 0 ) { 2451 const diff = adminBarHeight - winTop; 2452 flyoutPosition[ 'top' ] = diff <= 0 ? '0px' : (diff) + 'px'; 2453 } 2454 2455 return flyoutPosition; 2456 }, 2457 2458 /** 2459 * Shows or hides the nav search form. 2460 * 2461 * @since 2.5 2462 * @method _toggleMenuSearch 2463 */ 2464 _toggleMenuSearch: function(){ 2465 var wrapper = $( this.wrapperClass ).find('.fl-menu-search-item'), 2466 button = wrapper.find('.fl-button:is(a, button)'), 2467 form = wrapper.find('.fl-search-form-input-wrap'), 2468 self = this; 2469 2470 button.attr( 'tabindex', 0 ); 2471 button.attr( 'aria-label', 'Search' ); 2472 button.on('click', function(e){ 2473 e.preventDefault(); 2474 2475 if(form.is(':visible')) { 2476 form.stop().fadeOut(200); 2477 } 2478 else { 2479 form.stop().fadeIn(200); 2480 $('body').on('click.fl-menu-search', $.proxy(self._hideMenuSearch, self)); 2481 form.find('.fl-search-text').focus(); 2482 } 2483 }); 2484 }, 2485 2486 /** 2487 * Hides the nav search form. 2488 * 2489 * @since 2.5 2490 * @method _hideMenuSearch 2491 */ 2492 _hideMenuSearch: function(e){ 2493 var form = $( this.wrapperClass ).find('.fl-search-form-input-wrap'); 2494 2495 if(e !== undefined) { 2496 if($(e.target).closest('.fl-menu-search-item').length > 0) { 2497 return; 2498 } 2499 } 2500 2501 form.stop().fadeOut(200); 2502 $('body').off('click.fl-menu-search'); 2503 }, 2504 2505 /** 2506 * Adds menu node and post ID to WooCommerce ajax URL requests. 2507 * 2508 * @since 2.5 2509 * @return void 2510 */ 2511 _wooUpdateParams: function() { 2512 if ( 'undefined' !== typeof wc_cart_fragments_params ) { 2513 wc_cart_fragments_params.wc_ajax_url += '&fl-menu-node='+ this.nodeId +'&post-id='+ this.postId; 2514 } 2515 if ( 'undefined' !== typeof wc_add_to_cart_params ) { 2516 wc_add_to_cart_params.wc_ajax_url += '&fl-menu-node='+ this.nodeId +'&post-id='+ this.postId; 2517 } 2518 }, 2519 }; 2520 2521})(jQuery); 2522 2523(function($) { 2524 2525 $(function() { 2526 2527 new FLBuilderMenu({ 2528 id: 'okf2zve5btrs', 2529 type: 'horizontal', 2530 mobile: 'expanded', 2531 mobileBelowRow: false, 2532 mobileFlyout: false, 2533 breakPoints: { 2534 large: 1200, 2535 medium: 1024, 2536 small: 768 }, 2537 mobileBreakpoint: 'mobile', 2538 postId : '44', 2539 mobileStacked: true, 2540 submenuIcon: 'none', 2541 flyoutWidth: '250', 2542 }); 2543 2544 }); 2545 2546})(jQuery); 2547(function($) { 2548 if ( $('.fl-node-w5bugk8427ny .pp-photo-rollover').length > 0 ) { 2549 $('body').on( 'mouseenter.pp-rollover', '.fl-node-w5bugk8427ny .pp-photo-rollover .pp-photo-content', function() { 2550 $(this).addClass( 'is-hover' ); 2551 } ).on( 'mouseleave.pp-rollover', '.fl-node-w5bugk8427ny .pp-photo-rollover .pp-photo-content', function() { 2552 $(this).removeClass( 'is-hover' ); 2553 } ); 2554 } 2555})(jQuery); 2556;(function($) { 2557 2558 PPSearchForm = function(settings) { 2559 this.id = settings.id; 2560 this.node = $('.fl-node-' + this.id); 2561 this.form = this.node.find('.pp-search-form'); 2562 this.selectors = {
2563 input: '.fl-node-' + this.id + ' .pp-search-form__input', 2564 toggle: '.fl-node-' + this.id + ' .pp-search-form__toggle', 2565 container: '.fl-node-' + this.id + ' .pp-search-form__container', 2566 }; 2567 2568 this._init(); 2569 }; 2570 2571 PPSearchForm.prototype = { 2572 id : '', 2573 node: '', 2574 form: '', 2575 2576 _init: function() { 2577 $( this.selectors.input ).on( 'focus', function() { 2578 this.form.addClass('pp-search-form--focus'); 2579 }.bind( this ) ).on( 'blur', function() { 2580 this.form.removeClass('pp-search-form--focus'); 2581 }.bind( this ) ); 2582 2583 $( this.selectors.toggle ).on( 'click', function() { 2584 $( this.selectors.container ).addClass('pp-search-form--lightbox').find('.pp-search-form__input').trigger( 'focus' ); 2585 this._focus( this.form ); 2586 }.bind( this ) ); 2587 2588 this.form.find('.pp-search-form--lightbox-close').on( 'click', function() { 2589 $( this.selectors.container ).removeClass('pp-search-form--lightbox'); 2590 }.bind( this ) ); 2591 2592 // close modal box on Esc key press. 2593 $(document).on( 'keyup', function(e) { 2594 if ( 27 == e.which && this.form.find('.pp-search-form--lightbox').length > 0 ) { 2595 $( this.selectors.container ).removeClass('pp-search-form--lightbox'); 2596 } 2597 }.bind( this ) ); 2598 }, 2599 2600 _focus: function( form ) { 2601 var $el = form.find('.pp-search-form__input'); 2602 2603 // If this function exists... (IE 9+) 2604 if ( $el[0].setSelectionRange ) { 2605 // Double the length because Opera is inconsistent about whether a carriage return is one character or two. 2606 var len = $el.val().length * 2; 2607 2608 // Timeout seems to be required for Blink 2609 setTimeout(function() { 2610 $el[0].setSelectionRange( len, len ); 2611 }, 1); 2612 } else { 2613 // As a fallback, replace the contents with itself 2614 // Doesn't work in Chrome, but Chrome supports setSelectionRange 2615 $el.val( $el.val() ); 2616 } 2617 } 2618 }; 2619 2620})(jQuery);(function($) { 2621 2622 new PPSearchForm({ 2623 id: 'uy4hvsaj8n93', 2624 }); 2625 2626})(jQuery);(function($) { 2627 if ( $('.fl-node-dnu7zsk4ehv1 .pp-photo-rollover').length > 0 ) { 2628 $('body').on( 'mouseenter.pp-rollover', '.fl-node-dnu7zsk4ehv1 .pp-photo-rollover .pp-photo-content', function() { 2629 $(this).addClass( 'is-hover' ); 2630 } ).on( 'mouseleave.pp-rollover', '.fl-node-dnu7zsk4ehv1 .pp-photo-rollover .pp-photo-content', function() { 2631 $(this).removeClass( 'is-hover' ); 2632 } ); 2633 } 2634})(jQuery);(function($) { 2635 if ( $('.fl-node-duo7a3160wip .pp-photo-rollover').length > 0 ) { 2636 $('body').on( 'mouseenter.pp-rollover', '.fl-node-duo7a3160wip .pp-photo-rollover .pp-photo-content', function() { 2637 $(this).addClass( 'is-hover' ); 2638 } ).on( 'mouseleave.pp-rollover', '.fl-node-duo7a3160wip .pp-photo-rollover .pp-photo-content', function() { 2639 $(this).removeClass( 'is-hover' ); 2640 } ); 2641 } 2642})(jQuery);(function($) { 2643 2644 new PPSearchForm({ 2645 id: 'nkofz5gsl76h', 2646 }); 2647 2648})(jQuery); 2649;(function($) { 2650 2651 PPModalBox = function(settings) { 2652 this.id = settings.id; 2653 this.settings = settings; 2654 this.type = settings.type; 2655 this.cookieKey = 'pp_modal_' + this.id; 2656 this.cookieTime = settings.display_after; 2657 this.cookieValue = settings.cookie_value ? settings.cookie_value : this.cookieTime; 2658 this.triggerType = settings.trigger_type; 2659 this.layout = settings.layout; 2660 this.wrap = $('#modal-' + this.id); 2661 this.container = this.wrap.find('.pp-modal-container'); 2662 this.element = this.wrap.find('.pp-modal'); 2663 this.isPreviewing = settings.previewing; 2664 this.isVisible = settings.visible; 2665 this.eventClose = false; 2666 2667 this.initCookieApi(); 2668 this.init(); 2669 }; 2670 2671 PPModalBox.prototype = { 2672 id : '', 2673 settings : {}, 2674 type : '', 2675 cookieKey : '', 2676 cookieTime : 0, 2677 triggerType : '', 2678 layout : '', 2679 wrap : '', 2680 element : '', 2681 prevFocusedEl: '', 2682 isActive : false, 2683 isPreviewing: false, 2684 isVisible : false, 2685 eventClose : false, 2686 2687 init: function() 2688 { 2689 if ( parseInt( this.cookieTime ) === 0 || this.cookieTime < 0 || this.cookieTime === '' ) { 2690 this.removeCookie(); 2691 } 2692 if ( ( 'exit_intent' === this.triggerType || 'auto' === this.triggerType ) && this.getCookie() && ! this.isPreviewing ) { 2693 return; 2694 } 2695 if ( ! this.isPreviewing && 'undefined' !== typeof this.isVisible && ! this.isVisible ) { 2696 return; 2697 } 2698 if ( this.isActive ) { 2699 return; 2700 } 2701 2702 this.setResponsive(); 2703 this.bindEvents(); 2704 this.show(); 2705 }, 2706 2707 setResponsive: function() 2708 { 2709 if ( window.innerWidth <= this.settings.breakpoint ) { 2710 this.element.removeClass('layout-standard').addClass('layout-fullscreen'); 2711 } 2712 if ( window.innerWidth < this.element.width() ) { 2713 this.element.css('width', window.innerWidth + 'px'); 2714 } 2715 }, 2716 2717 bindEvents: function() 2718 { 2719 var self = this; 2720 2721 $( this.element ).on( 'beforeload', this.beforeLoad.bind( this ) ); 2722 2723 $(document).on( 'keyup', function(e) { 2724 // close modal box on Esc key press. 2725 if ( self.settings.esc_exit && 27 == e.which && self.isActive && $('form[data-type="pp-modal-box"]').length === 0 ) { 2726 self.eventClose = true; 2727 self.hide(); 2728 } 2729 }).on( 'keydown', function(e) { 2730 // trap focus inside the modal element. 2731 if ( (e.key === 'Tab' || e.keyCode === 9) && self.isActive ) { 2732 if ( e.shiftKey && $(document.activeElement).is( self.element ) ) { 2733 e.preventDefault(); 2734 } 2735 if ( $(document.activeElement).closest( self.element ).length === 0 ) { 2736 self.element.trigger('focus'); 2737 e.preventDefault(); 2738 } 2739 } 2740 } ); 2741 2742 // close modal box by clicking on outside of modal box element in document. 2743 $(document).on( 'click', function(e) { 2744 if ( self.settings.click_exit && $(e.target).parents('.pp-modal').length === 0 && self.isActive && ! self.isPreviewing && ! self.element.is(e.target) && self.element.has(e.target).length === 0 && ! $(e.target).hasClass('modal-' + self.id) && $(e.target).parents('.modal
2744-' + self.id).length === 0 && e.which ) { 2745 self.eventClose = true; 2746 self.hide(); 2747 } 2748 }); 2749 2750 // close modal box by clicking on the close button. 2751 $(self.wrap).find('.pp-modal-close, .pp-modal-close-custom').on('keypress click', function(e) { 2752 e.preventDefault(); 2753 e.stopPropagation(); 2754 if (e.which == 1 || e.which == 13 || e.which == 32 || e.which == undefined) { 2755 self.eventClose = true; 2756 self.hide(); 2757 } 2758 }); 2759 2760 // close the modal box on clicking on inner links start with hash. 2761 $('body').on( 'click', '#modal-' + self.id + ' .pp-modal-content a[href*="#"]:not([href="#"])', function() { 2762 if ( $('.fl-node-' + self.id).hasClass('anchor-click-no-event') ) { 2763 return; 2764 } 2765 self.eventClose = true; 2766 self.hide(); 2767 } ); 2768 2769 $(window).on( 'resize', this.setResponsive.bind( this ) ); 2770 $(window).on( 'resize', this.setPosition.bind( this ) ); 2771 }, 2772 2773 setPosition: function() 2774 { 2775 if ( 'fullscreen' !== this.layout ) { 2776 if ( typeof this.settings.height === 'undefined' ) { 2777 2778 this.wrap.addClass('pp-modal-height-auto'); 2779 var modalHeight = this.element.outerHeight(); 2780 this.wrap.removeClass('pp-modal-height-auto'); 2781 2782 if ( 'photo' === this.type ) { 2783 this.element.find( '.pp-modal-content-inner img' ).css( 'max-width', '100%' ); 2784 } 2785 2786 var topPos = ( window.innerHeight - modalHeight ) / 2; 2787 if ( topPos < 0 ) { 2788 topPos = 0; 2789 } 2790 this.element.css( 'top', topPos + 'px' ); 2791 } else { 2792 var topPos = ( window.innerHeight - this.settings.height ) / 2; 2793 if ( topPos < 0 ) { 2794 topPos = 0; 2795 } 2796 this.element.css( 'top', topPos + 'px' ); 2797 } 2798 } 2799 }, 2800 2801 beforeLoad: function() { 2802 if ( this.settings.clickedElement ) { 2803 var clickedElement = this.settings.clickedElement; 2804 var postId = clickedElement.attr( 'data-pp-modal-post' ) || clickedElement.closest( '[data-pp-modal-post]' ).attr( 'data-pp-modal-post' ) || clickedElement.parents( '.pp-content-post' ).attr( 'data-id' ); 2805 var self = this; 2806 2807 if ( 'undefined' === typeof postId || '' === postId ) { 2808 return; 2809 } 2810 2811 if ( 'html' === self.settings.type && '' !== self.settings.content ) { 2812 self.element.find( '.pp-modal-content-inner' ).html('<div style="text-align: center;"><img src="' + self.settings.loaderImg + '" /></div>'); 2813 self.setPosition(); 2814 $.ajax({
2815 url: bb_powerpack.getAjaxUrl(), 2816 type: 'post', 2817 data: { 2818 action: 'pp_modal_dynamic_content', 2819 content: self.settings.content, 2820 postId: postId 2821 }, 2822 success: function( response ) { 2823 if ( ! response.success ) { 2824 return; 2825 } 2826 2827 self.element.find( '.pp-modal-content-inner' ).html( response.data ); 2828 self.setPosition(); 2829 } 2830 }); 2831 } 2832 } 2833 }, 2834 2835 show: function() 2836 { 2837 if ( this.element.length === 0 ) { 2838 return; 2839 } 2840 2841 this.setPosition(); 2842 2843 var self = this; 2844 2845 if ( 'photo' === this.type ) { 2846 this.element.find( '.pp-modal-content-inner img' ).css( 'max-width', '100%' ); 2847 } 2848 2849 this.prevFocusedEl = $( document.activeElement ); 2850 2851 //this.element.find( '.pp-modal-content' ).scrollTop(0); 2852 2853 setTimeout( function() { 2854 self.element.trigger('beforeload'); 2855 2856 if ( ! self.isPreviewing ) { 2857 setTimeout(function() { 2858 self.element.attr( 'tabindex', '0' ).trigger( 'focus' ); 2859 }, 100); 2860 } 2861 2862 $('html').addClass( 'pp-modal-active-' + self.id ); 2863 2864 self.wrap.addClass( 'pp-modal-active' ); 2865 2866 self.container 2867 .removeClass( self.settings.animation_load + ' animated' ) 2868 .addClass( 'modal-visible' ) 2869 .addClass( self.settings.animation_load + ' animated' ); 2870 2871 if ( ! $('body').hasClass('wp-admin') ) { 2872 self.container.one( 'webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend', function() { 2873 self.eventClose = false; 2874 $(this).removeClass( self.settings.animation_load + ' animated' ); 2875 self.setup(); 2876 } ); 2877 } else { 2878 self.setup(); 2879 } 2880 2881 self.isActive = true; 2882 2883 if ( 'exit_intent' === self.triggerType || 'auto' === self.triggerType ){ 2884 if ( ! self.isPreviewing ) { 2885 self.setCookie(); 2886 } 2887 } 2888 2889 self.restruct(); 2890 self.setPosition(); 2891 2892 self.element.trigger('afterload'); 2893 $(document).trigger( 'pp_modal_box_rendered', [self.element] ); 2894 2895 }, self.settings.auto_load ? parseFloat(self.settings.delay) * 1000 : 0); 2896 }, 2897 2898 setup: function() 2899 { 2900 if ( this.element.find('.pp-modal-iframe').length > 0 ) { 2901 var original_src = this.element.find('.pp-modal-iframe').attr('src'); 2902 var src = this.element.find('.pp-modal-iframe').data('url'); 2903 if ( original_src === undefined || original_src === '' ) { 2904 this.element.find('.pp-modal-iframe').attr( 'src', src ); 2905 } 2906 } 2907 2908 var iframeAndSource = this.element.find('iframe, source'); 2909 if ( iframeAndSource.length > 0 && iframeAndSource.closest( '.fl-module' ).length === 0 ) { 2910 var src = ''; 2911 var m_src = iframeAndSource.attr('src'); 2912 2913 if ( m_src === undefined || m_src === '' ) { 2914 src = iframeAndSource.data('url'); 2915 } else { 2916 src = iframeAndSource.attr('src'); 2917 } 2918 2919 if ( src ) { 2920 if ( ( src.search('youtube') !== -1 || src.search('vimeo') !== -1) && src.search('autoplay=1') == -1 ) { 2921 if ( typeof src.split('?')[1] === 'string' ) { 2922 src = src + '&autoplay=1&rel=0'; 2923 } else { 2924 src = src + '?autoplay=1&rel=0'; 2925 } 2926 } 2927 iframeAndSource.attr('src', src); 2928 } 2929 } 2930 2931 if ( this.element.find('video').length ) { 2932 this.element.find('video')[0].play(); 2933 } 2934 }, 2935 2936 reset: function() 2937 { 2938 var iframeAndSource = this.element.find('iframe, source'); 2939 if ( iframeAndSource.length > 0 && iframeAndSource.closest( '.fl-module' ).length === 0 ) { 2940 var src = iframeAndSource.attr('src'); 2941 if ( '' !== src ) { 2942 iframeAndSource.attr('data-url', src).attr('src', ''); 2943 } 2944 } 2945 if ( this.element.find('video').length > 0 ) { 2946 this.element.find('video')[0].pause(); 2947 } 2948 if ( this.element.find('mux-player').length > 0 ) { 2949 this.element.find('mux-player')[0].pause(); 2950 } 2951 2952 this.element.attr( 'tabindex', '-1' ); 2953 var self = this; 2954 2955 setTimeout(function() { 2956 if ( self.settings.clickedElement ) { 2957 var $clickedElement = self.settings.clickedElement; 2958 if ( $clickedElement.closest( '.modal-' + self.id ).length ) { 2959 $clickedElement.closest( '.modal-' + self.id ).trigger( 'focus' ); 2960 } else if ( $clickedElement.closest( '#trigger-' + self.id ).length ) { 2961 $clickedElement.closest( '#trigger-' + self.id ).trigger( 'focus' ); 2962 }
2962 else if ( '' !== self.settings.customTrigger ) { 2963 if ( $clickedElement.is( self.settings.customTrigger ) ) { 2964 $clickedElement.trigger( 'focus' ); 2965 } else if ( $clickedElement.closest( self.settings.customTrigger ).length ) { 2966 $clickedElement.closest( self.settings.customTrigger ).trigger( 'focus' ); 2967 } 2968 } 2969 } 2970 }, 100); 2971 }, 2972 2973 restruct: function() 2974 { 2975 var mH = 0, hH = 0, cH = 0, eq = 0; 2976 var self = this; 2977 2978 setTimeout( function() { 2979 if ( self.isActive ) { 2980 if ( 'fullscreen' === self.layout ) { 2981 var marginTop = parseInt( self.element.css('margin-top') ); 2982 var marginBottom = parseInt( self.element.css('margin-bottom') ); 2983 var modalHeight = $(window).height() - (marginTop + marginBottom); 2984 2985 self.element.css( 'height', modalHeight + 'px' ); 2986 } 2987 eq = 6; 2988 mH = self.element.outerHeight(); // Modal height. 2989 hH = self.element.find('.pp-modal-header').outerHeight(); // Header height. 2990 2991 if ( self.settings.auto_height && 'fullscreen' !== self.layout ) { 2992 return; 2993 } 2994 2995 var cP = parseInt( self.element.find('.pp-modal-content').css('padding') ); // Content padding. 2996 2997 self.element.find('.pp-modal-content').css( 'height', mH - (hH + eq) + 'px' ); 2998 2999 if ( ! self.settings.auto_height && self.element.find('.pp-modal-header').length === 0) { 3000 self.element.find('.pp-modal-content').css('height', mH + 'px'); 3001 } 3002 3003 // Adjust iframe height. 3004 if ( 'url' === self.type && self.element.find( '.pp-modal-video-embed' ).length === 0 ) { 3005 self.element.find('.pp-modal-iframe').css('height', self.element.find('.pp-modal-content-inner').outerHeight() + 'px'); 3006 } 3007 if ( 'video' === self.type ) { 3008 self.element.find('iframe').css({'height':'100%', 'width':'100%'}); 3009 } 3010 } 3011 }, self.settings.auto_load ? parseFloat(self.settings.delay) * 1000 : 1); 3012 }, 3013 3014 hide: function() 3015 { 3016 var self = this; 3017 3018 this.element.trigger('beforeclose'); 3019 3020 this.container 3021 .removeClass( self.settings.animation_exit + ' animated' ) 3022 .addClass( self.settings.animation_exit + ' animated' ); 3023 3024 if ( ! $('body').hasClass('wp-admin') ) { 3025 this.container.one( 'webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend', function() { 3026 if ( self.eventClose ) { 3027 self.close(); 3028 } 3029 }); 3030 } else { 3031 self.close(); 3032 } 3033 3034 if ( window.location.hash ) { 3035 var hashVal = window.location.hash.replace('/', ''); 3036 if ( '#modal-' + self.id === hashVal ) { 3037 var scrollTop = self.settings.scrollTop || $(window).scrollTop(); 3038 window.location.href = window.location.href.split('#')[0] + '#'; 3039 $(window).scrollTop(scrollTop); 3040 } 3041 } 3042 3043 if ( ! this.isPreviewing ) { 3044 this.element.attr( 'tabindex', '-1' ).trigger( 'blur' ); 3045 if ( this.prevFocusedEl && this.prevFocusedEl.length > 0 ) { 3046 this.prevFocusedEl.trigger( 'focus' ); 3047 } 3048 } 3049 3050 this.element.trigger('afterclose'); 3051 $(document).trigger( 'pp_modal_box_after_close', [this.element, this] ); 3052 }, 3053 3054 close: function() 3055 { 3056 this.container.removeClass( this.settings.animation_exit + ' animated' ).removeClass('modal-visible'); 3057 this.container.find('.pp-modal-content').removeAttr('style'); 3058 this.wrap.removeClass( 'pp-modal-active' ); 3059 3060 $('html').removeClass( 'pp-modal-active-' + this.id ); 3061 3062 this.isActive = false; 3063 this.eventClose = false; 3064 this.reset(); 3065 }, 3066 3067 initCookieApi: function() { 3068 if ( 'undefined' === typeof $.cookie ) { 3069 /*! 3070 * jQuery Cookie Plugin v1.4.1 3071 * https://github.com/carhartl/jquery-cookie 3072 * 3073 * Copyright 2013 Klaus Hartl 3074 * Released under the MIT license 3075 */ 3076 !function(a){"function"==typeof define&&define.amd?define(["jquery"],a):a("object"==typeof exports?require("jquery"):jQuery)}(function(a){function b(a){return h.raw?a:encodeURIComponent(a)}function c(a){return h.raw?a:decodeURIComponent(a)}function d(a){return b(h.json?JSON.stringify(a):String(a))}function e(a){0===a.indexOf('"')&&(a=a.slice(1,-1).replace(/\\"/g,'"').replace(/\\\\/g,"\\"));try{return a=decodeURIComponent(a.replace(g," ")),h.json?JSON.parse(a):a}catch(b){}}function f(b,c){var d=h.raw?b:e(b);return a.isFunction(c)?c(d):d}var g=/\+/g,h=a.cookie=function(e,g,i){if(void 0!==g&&!a.isFunction(g)){if(i=a.extend({},h.defaults,i),"number"==typeof i.expires){var j=i.expires,k=i.expires=new Date;k.setTime(+k+864e5*j)}return document.cookie=[b(e),"=",d(g),i.expires?"; expires="+i.expires.toUTCString():"",i.path?"; path="+i.path:"",i.domain?"; domain="+i.domain:"",i.secure?"; secure":""].join("")}for(var l=e?void 0:{},m=document.cookie?document.cookie.split("; "):[],n=0,o=m.length;o>n;n++){var p=m[n].split("="),q=c(p.shift()),r=p.join("=");if(e&&e===q){l=f(r,g);break}e||void 0===(r=f(r))||(l[q]=r)}return l};h.defaults={},a.removeCookie=function(b,c){return void 0===a.cookie(b)?!1:(a.cookie(b,"",a.extend({},c,{expires:-1})),!a.cookie(b))}}); 3077 } 3078 }, 3079 3080 setCookie: function() 3081 { 3082 if ( parseInt( this.cookieTime ) > 0 ) { 3083 return $.cookie( this.cookieKey, this.cookieValue, {expires: this.cookieTime, path: '/'} ); 3084 } else { 3085 this.removeCookie(); 3086 } 3087 }, 3088 3089 getCookie: function() 3090 { 3091 // Reset cookie when module settings change. 3092 if ( this.cookieValue != $.cookie( this.cookieKey ) ) { 3093 this.removeCookie(); 3094 } 3095 return $.cookie( this.cookieKey ); 3096 }, 3097 3098 removeCookie: function() 3099 { 3100 $.cookie( this.cookieKey, 0, {expires: 0, path: '/'} ); 3101 } 3102 }; 3103})(jQuery); 3104 3105var pp_modal_b0hytrzd9g6c = false;
3106var pp_modal_b0hytrzd9g6c_config = false; 3107 3108;(function($) { 3109 3110 pp_modal_b0hytrzd9g6c_config = { 3111 id: 'b0hytrzd9g6c', 3112 type: 'templates', 3113 trigger_type: 'onclick', 3114 auto_load: false, 3115 exit_intent: false, 3116 delay: 1, 3117 animation_load: 'fadeIn', 3118 animation_exit: 'fadeOut', 3119 overlay_animation: true, 3120 esc_exit: true, 3121 click_exit: true, 3122 layout: 'fullscreen', 3123 auto_height: true, 3124 width: 550, 3125 breakpoint: 0, 3126 loaderImg: 'https://shepherdess.co.nz/wp-content/plugins/bbpowerpack/assets/images/ajax-loader.gif', 3127 previewing: false }; 3128 3129 3130 $(document).on('click', function(e) { 3131 if ( e && e.target.tagName === 'A' && e.target.href.indexOf('#modal-b0hytrzd9g6c') !== -1 ) { 3132 pp_modal_b0hytrzd9g6c_config['scrollTop'] = $(window).scrollTop(); 3133 } 3134 }); 3135 3136 $(function() { 3137 $('#modal-b0hytrzd9g6c').appendTo(document.body); 3138 3139 var tabHash = window.location.hash ? window.location.hash.replace('/', '') : false; 3140 var modalId = window.location.hash.split('#modal-')[1]; 3141 3142 // If the URL contains a hash beginning with modal, trigger that modal box. 3143 if ( tabHash && tabHash.indexOf('modal-') >= 0 ) { 3144 if ( modalId === 'b0hytrzd9g6c' ) { 3145 pp_modal_b0hytrzd9g6c = new PPModalBox(pp_modal_b0hytrzd9g6c_config); 3146 } 3147 } 3148 3149 $(window).on('hashchange', function() { 3150 var tabHash = window.location.hash; 3151 var modalId = window.location.hash.split('#modal-')[1]; 3152 3153 // If the URL contains a hash beginning with modal, trigger that modal box. 3154 if ( tabHash && tabHash.indexOf('modal-') >= 0 ) { 3155 if ( modalId === 'b0hytrzd9g6c' ) { 3156 if ( pp_modal_b0hytrzd9g6c instanceof PPModalBox ) { 3157 pp_modal_b0hytrzd9g6c.show(); 3158 } else { 3159 pp_modal_b0hytrzd9g6c = new PPModalBox(pp_modal_b0hytrzd9g6c_config); 3160 } 3161 } 3162 } 3163 }); 3164 3165 }); 3166 3167 3168 3169 // Bind the click event to any element with the class. 3170 pp_modal_b0hytrzd9g6c_config.customTrigger = ''; 3171 $(document).on('click keydown', '.modal-b0hytrzd9g6c', function(e) { 3172 var valid = (e.which == 1 || e.which == 13 || e.which == 32 || e.which == undefined); 3173 if ( ! valid ) { 3174 return; 3175 } 3176 e.preventDefault(); 3177 if ( pp_modal_b0hytrzd9g6c instanceof PPModalBox ) { 3178 pp_modal_b0hytrzd9g6c.settings.clickedElement = $( e.target ); 3179 pp_modal_b0hytrzd9g6c.show(); 3180 } else { 3181 pp_modal_b0hytrzd9g6c_config.clickedElement = $( e.target ); 3182 pp_modal_b0hytrzd9g6c = new PPModalBox(pp_modal_b0hytrzd9g6c_config); 3183 } 3184 }); 3185 3186 3187})(jQuery); 3188 3189var pp_modal_dwtkhgenzj2p = false; 3190var pp_modal_dwtkhgenzj2p_config = false; 3191 3192;(function($) { 3193 3194 pp_modal_dwtkhgenzj2p_config = { 3195 id: 'dwtkhgenzj2p', 3196 type: 'templates', 3197 trigger_type: 'onclick', 3198 auto_load: false, 3199 exit_intent: false, 3200 delay: 1, 3201 animation_load: 'fadeIn', 3202 animation_exit: 'fadeOut', 3203 overlay_animation: true, 3204 esc_exit: true, 3205 click_exit: true, 3206 layout: 'fullscreen', 3207 auto_height: true, 3208 width: 550, 3209 breakpoint: 0, 3210 loaderImg: 'https://shepherdess.co.nz/wp-content/plugins/bbpowerpack/assets/images/ajax-loader.gif', 3211 previewing: false }; 3212 3213 3214 $(document).on('click', function(e) { 3215 if ( e && e.target.tagName === 'A' && e.target.href.indexOf('#modal-dwtkhgenzj2p') !== -1 ) { 3216 pp_modal_dwtkhgenzj2p_config['scrollTop'] = $(window).scrollTop(); 3217 } 3218 }); 3219 3220 $(function() { 3221 $('#modal-dwtkhgenzj2p').appendTo(document.body); 3222 3223 var tabHash = window.location.hash ? window.location.hash.replace('/', '') : false; 3224 var modalId = window.location.hash.split('#modal-')[1]; 3225 3226 // If the URL contains a hash beginning with modal, trigger that modal box. 3227 if ( tabHash && tabHash.indexOf('modal-') >= 0 ) { 3228 if ( modalId === 'dwtkhgenzj2p' ) { 3229 pp_modal_dwtkhgenzj2p = new PPModalBox(pp_modal_dwtkhgenzj2p_config); 3230 } 3231 } 3232 3233 $(window).on('hashchange', function() { 3234 var tabHash = window.location.hash; 3235 var modalId = window.location.hash.split('#modal
3235-')[1]; 3236 3237 // If the URL contains a hash beginning with modal, trigger that modal box. 3238 if ( tabHash && tabHash.indexOf('modal-') >= 0 ) { 3239 if ( modalId === 'dwtkhgenzj2p' ) { 3240 if ( pp_modal_dwtkhgenzj2p instanceof PPModalBox ) { 3241 pp_modal_dwtkhgenzj2p.show(); 3242 } else { 3243 pp_modal_dwtkhgenzj2p = new PPModalBox(pp_modal_dwtkhgenzj2p_config); 3244 } 3245 } 3246 } 3247 }); 3248 3249 }); 3250 3251 3252 3253 // Bind the click event to any element with the class. 3254 pp_modal_dwtkhgenzj2p_config.customTrigger = ''; 3255 $(document).on('click keydown', '.modal-dwtkhgenzj2p', function(e) { 3256 var valid = (e.which == 1 || e.which == 13 || e.which == 32 || e.which == undefined); 3257 if ( ! valid ) { 3258 return; 3259 } 3260 e.preventDefault(); 3261 if ( pp_modal_dwtkhgenzj2p instanceof PPModalBox ) { 3262 pp_modal_dwtkhgenzj2p.settings.clickedElement = $( e.target ); 3263 pp_modal_dwtkhgenzj2p.show(); 3264 } else { 3265 pp_modal_dwtkhgenzj2p_config.clickedElement = $( e.target ); 3266 pp_modal_dwtkhgenzj2p = new PPModalBox(pp_modal_dwtkhgenzj2p_config); 3267 } 3268 }); 3269 3270 3271})(jQuery); 3272 3273/* Start Global Node Custom JS */ 3274 3275/* End Global Node Custom JS */ 3276 3277 3278/* Start Layout Custom JS */ 3279jQuery('#fl-main-content').on('click', function(e){ 3280 jQuery('.search-bar').fadeOut('fast'); 3281}); 3282 3283const body = document.body; 3284const scrollUp = "nav-up"; 3285const scrollDown = "nav-down"; 3286let lastScroll = 0; 3287 3288 3289window.addEventListener("scroll", () => { 3290 const currentScroll = window.scrollY; 3291 if (currentScroll <= 0) { 3292 body.classList.remove(scrollUp); 3293 return; 3294 } 3295 3296 if (currentScroll > lastScroll && !body.classList.contains(scrollDown)) { 3297 // down 3298 body.classList.remove(scrollUp); 3299 body.classList.add(scrollDown); 3300 } else if ( currentScroll < lastScroll && body.classList.contains(scrollDown) ) { 3301 // up 3302 body.classList.remove(scrollDown); 3303 body.classList.add(scrollUp); 3304 } 3305 lastScroll = currentScroll; 3306}); 3307/* End Layout Custom JS */ 3308 3309(function($){ 3310 3311 /** 3312 * Helper class for header layout logic. 3313 * 3314 * @since 1.0 3315 * @class FLThemeBuilderHeaderLayout 3316 */ 3317 FLThemeBuilderHeaderLayout = { 3318 3319 /** 3320 * A reference to the window object for this page. 3321 * 3322 * @since 1.0 3323 * @property {Object} win 3324 */ 3325 win : null, 3326 3327 /** 3328 * A reference to the body object for this page. 3329 * 3330 * @since 1.0 3331 * @property {Object} body 3332 */ 3333 body : null, 3334 3335 /** 3336 * A reference to the header object for this page. 3337 * 3338 * @since 1.0 3339 * @property {Object} header 3340 */ 3341 header : null, 3342 3343 /** 3344 * Whether this header overlays the content or not. 3345 * 3346 * @since 1.0 3347 * @property {Boolean} overlay 3348 */ 3349 overlay : false, 3350 3351 /** 3352 * Whether the page has the WP admin bar or not. 3353 * 3354 * @since 1.0 3355 * @property {Boolean} hasAdminBar 3356 */ 3357 hasAdminBar : false, 3358 3359 /** 3360 * Breakpoint for when the sticky header should apply. 3361 * 3362 * @since 1.4 3363 * @property {String} stickyOn 3364 */ 3365 stickyOn: '', 3366 3367 /** 3368 * A reference of the sticky and shrink header breakpoint. 3369 * 3370 * @since 1.2.5 3371 * @property {Number} breakpointWidth 3372 */ 3373 breakpointWidth: 0, 3374 3375 /** 3376 * Initializes header layout logic. 3377 * 3378 * @since 1.0 3379 * @method init 3380 */ 3381 init: function() 3382 { 3383 var editing = $( 'html.fl-builder-edit' ).length, 3384 header = $( '.fl-builder-content[data-type=header]' ), 3385 menuModule = header.find( '.fl-module-menu' ), 3386 breakpoint = null; 3387 3388 if ( ! editing && header.length ) { 3389 3390 header.imagesLoaded( $.proxy( function() { 3391 3392 this.win = $( window ); 3393 this.body = $( 'body' ); 3394 this.header = header.eq( 0 ); 3395 this.overlay = !! Number( header.attr( 'data-overlay' ) ); 3396 this.hasAdminBar = !! $( 'body.admin-bar' ).length; 3397 this.stickyOn = this.header.data( 'sticky-on' ); 3398 breakpoint = this.header.data( 'sticky-breakpoint' ); 3399 3400 if ( '' == this.stickyOn ) { 3401 if ( typeof FLBuilderLayoutConfig.breakpoints[ breakpoint ] !== undefined ) { 3402 this.breakpointWidth = FLBuilderLayoutConfig.breakpoints[ breakpoint ]; 3403 } 3404 else { 3405 this.breakpointWidth = FLBuilderLayoutConfig.breakpoints.medium; 3406 } 3407 } 3408 3409 if ( Number( header.attr( 'data-sticky' ) ) ) { 3410 3411 this.header.data( 'original-top', this.header.offset().top ); 3412 this.win.on( 'resize', $.throttle( 500, $.proxy( this._initSticky, this ) ) ); 3413 this._initSticky(); 3414 3415 } 3416 3417 }, this ) ); 3418 } 3419 }, 3420 3421 /** 3422 * Initializes sticky logic for a header. 3423 * 3424 * @since 1.0 3425 * @access private 3426 * @method _initSticky 3427 */ 3428 _initSticky: function( e ) 3429 {
3430 var header = $('.fl-builder-content[data-type=header]'), 3431 windowSize = this.win.width(), 3432 makeSticky = false; 3433 3434 makeSticky = this._makeWindowSticky( windowSize ); 3435 if ( makeSticky || ( this.breakpointWidth > 0 && windowSize >= this.breakpointWidth ) ) { 3436 this.win.on( 'scroll.fl-theme-builder-header-sticky', $.proxy( this._doSticky, this ) ); 3437 // 3438 // Check if Event Type is 'resize' then invoke this._doSticky() 3439 // only if the 'fl-theme-builder-header-sticky' class is already present. 3440 // 3441 if ( e && 'resize' === e.type ) { 3442 if ( this.header.hasClass( 'fl-theme-builder-header-sticky' ) ) { 3443 this._doSticky( e ); 3444 } 3445 this._adjustStickyHeaderWidth(); 3446 } 3447 3448 if ( Number( header.attr( 'data-shrink' ) ) ) { 3449 this.header.data( 'original-height', this.header.outerHeight() ); 3450 this.win.on( 'resize', $.throttle( 500, $.proxy( this._initShrink, this ) ) ); 3451 this._initShrink(); 3452 } 3453 3454 this._initFlyoutMenuFix( e ); 3455 } else { 3456 this.win.off( 'scroll.fl-theme-builder-header-sticky' ); 3457 this.win.off( 'resize.fl-theme-builder-header-sticky' ); 3458 3459 this.header.removeClass( 'fl-theme-builder-header-sticky' ); 3460 this.header.removeAttr( 'style' ); 3461 this.header.parent().css( 'padding-top', '0' ); 3462 } 3463 }, 3464 3465 /** 3466 * Check if Header should be sticky at a particular Window size. 3467 * 3468 * @since 1.4 3469 * @access private 3470 * @param widowSize 3471 * @method _makeWindowSticky 3472 */ 3473 _makeWindowSticky: function ( windowSize ) 3474 { 3475 var makeSticky = false; 3476 3477 switch (this.stickyOn) { 3478 case 'xl': 3479 makeSticky = windowSize > FLBuilderLayoutConfig.breakpoints['large']; 3480 break; 3481 case '': // Default 3482 case 'desktop': 3483 makeSticky = windowSize >= FLBuilderLayoutConfig.breakpoints['medium']; 3484 break; 3485 case 'desktop-medium': 3486 makeSticky = windowSize > FLBuilderLayoutConfig.breakpoints['small']; 3487 break; 3488 case 'large': 3489 makeSticky = windowSize > FLBuilderLayoutConfig.breakpoints['medium'] && windowSize <= FLBuilderLayoutConfig.breakpoints['large']; 3490 break; 3491 case 'large-medium': 3492 makeSticky = windowSize > FLBuilderLayoutConfig.breakpoints['small'] && windowSize <= FLBuilderLayoutConfig.breakpoints['large']; 3493 break; 3494 case 'medium': 3495 makeSticky = ( windowSize <= FLBuilderLayoutConfig.breakpoints['medium'] && windowSize > FLBuilderLayoutConfig.breakpoints['small'] ); 3496 break; 3497 case 'medium-mobile': 3498 makeSticky = (windowSize <= FLBuilderLayoutConfig.breakpoints['medium']); 3499 break; 3500 case 'mobile': 3501 makeSticky = (windowSize <= FLBuilderLayoutConfig.breakpoints['small']); 3502 break; 3503 case 'all': 3504 makeSticky = true; 3505 break; 3506 } 3507 3508 return makeSticky; 3509 }, 3510 3511 /** 3512 * Sticks the header when the page is scrolled. 3513 * 3514 * @since 1.0 3515 * @access private 3516 * @method _doSticky 3517 */ 3518 _doSticky: function( e ) 3519 { 3520 var winTop = Math.floor( this.win.scrollTop() ), 3521 headerTop = Math.floor( this.header.data( 'original-top' ) ), 3522 hasStickyClass = this.header.hasClass( 'fl-theme-builder-header-sticky' ), 3523 hasScrolledClass = this.header.hasClass( 'fl-theme-builder-header-scrolled' ), 3524 beforeHeader = this.header.prevAll( '.fl-builder-content' ), 3525 bodyTopPadding = parseInt( jQuery('body').css('padding-top') ), 3526 winBarHeight = $('#wpadminbar').length ? $('#wpadminbar').outerHeight() : 0, 3527 headerHeight = 0; 3528 3529 if ( isNaN( bodyTopPadding ) ) { 3530 bodyTopPadding = 0; 3531 } 3532 3533 if ( this.hasAdminBar && this.win.width() > 600 ) { 3534 winTop += Math.floor( winBarHeight ); 3535 } 3536 3537 if ( winTop > headerTop ) { 3538 if ( ! hasStickyClass ) { 3539 if ( e && ( 'scroll' === e.type || 'smartscroll' === e.type ) ) { 3540 this.header.addClass( 'fl-theme-builder-header-sticky' ); 3541 if ( this.overlay && beforeHeader.length ) { 3542 this.header.css( 'top', winBarHeight); 3543 } 3544 } 3545 3546 if ( ! this.overlay ) { 3547 this._adjustHeaderHeight(); 3548 } 3549 } 3550 } 3551 else if ( hasStickyClass ) { 3552 this.header.removeClass( 'fl-theme-builder-header-sticky' ); 3553 this.header.removeAttr( 'style' ); 3554 this.header.parent().css( 'padding-top', '0' ); 3555 } 3556 3557 this._adjustStickyHeaderWidth(); 3558 3559 if ( winTop > headerTop ) { 3560 if ( ! hasScrolledClass ) {
3561 this.header.addClass( 'fl-theme-builder-header-scrolled' ); 3562 } 3563 } else if ( hasScrolledClass ) { 3564 this.header.removeClass( 'fl-theme-builder-header-scrolled' ); 3565 } 3566 3567 this._flyoutMenuFix( e ); 3568 }, 3569 3570 /** 3571 * Initializes flyout menu fixes on sticky header. 3572 * 3573 * @since 1.4.1 3574 * @method _initFlyoutMenuFix 3575 */ 3576 _initFlyoutMenuFix: function( e ) { 3577 var header = this.header, 3578 menuModule = header.closest( '.fl-menu' ), 3579 flyoutMenu = menuModule.find( '.fl-menu-mobile-flyout' ), 3580 isPushMenu = menuModule.hasClass( 'fl-menu-responsive-flyout-push' ) || menuModule.hasClass( 'fl-menu-responsive-flyout-push-opacity' ), 3581 isOverlay = menuModule.hasClass( 'fl-menu-responsive-flyout-overlay' ), 3582 flyoutPos = menuModule.hasClass( 'fl-flyout-right' ) ? 'right' : 'left', 3583 flyoutParent = header.parent().is( 'header' ) ? header.parent().parent() : header.parent(); 3584 isFullWidth = this.win.width() === header.width(), 3585 flyoutLayout = '', 3586 activePos = 250, 3587 headerPos = 0; 3588 3589 if ( ! flyoutMenu.length ) { 3590 return; 3591 } 3592 3593 if ( this.win.width() > header.parent().width() ) { 3594 headerPos = ( this.win.width() - header.width() ) / 2; 3595 } 3596 3597 if ( isOverlay ) { 3598 activePos = headerPos; 3599 } 3600 else if ( isPushMenu ) { 3601 activePos = activePos + headerPos; 3602 } 3603 flyoutMenu.data( 'activePos', activePos ); 3604 3605 if ( isPushMenu ) { 3606 flyoutLayout = 'push-' + flyoutPos; 3607 } 3608 else if ( isOverlay ) { 3609 flyoutLayout = 'overlay-' + flyoutPos; 3610 } 3611 3612 if ( isPushMenu && ! $( 'html' ).hasClass( 'fl-theme-builder-has-flyout-menu' ) ) { 3613 $( 'html' ).addClass( 'fl-theme-builder-has-flyout-menu' ); 3614 } 3615 3616 if ( ! flyoutParent.hasClass( 'fl-theme-builder-flyout-menu-' + flyoutLayout ) ) { 3617 flyoutParent.addClass( 'fl-theme-builder-flyout-menu-' + flyoutLayout ); 3618 } 3619 3620 if ( ! header.hasClass( 'fl-theme-builder-flyout-menu-overlay' ) && isOverlay ) { 3621 header.addClass( 'fl-theme-builder-flyout-menu-overlay' ); 3622 } 3623 3624 if ( ! header.hasClass( 'fl-theme-builder-header-full-width' ) && isFullWidth ) { 3625 header.addClass( 'fl-theme-builder-header-full-width' ); 3626 } 3627 else if ( ! isFullWidth ) { 3628 header.removeClass( 'fl-theme-builder-header-full-width' ); 3629 } 3630 3631 menuModule.on( 'click', '.fl-menu-mobile-toggle', $.proxy( function( event ){ 3632 if ( menuModule.find( '.fl-menu-mobile-toggle.fl-active' ).length ) { 3633 $( 'html' ).addClass( 'fl-theme-builder-flyout-menu-active' ); 3634 event.stopImmediatePropagation(); 3635 } 3636 else { 3637 $( 'html' ).removeClass( 'fl-theme-builder-flyout-menu-active' ); 3638 } 3639 3640 this._flyoutMenuFix( event ); 3641 }, this ) ); 3642 }, 3643 3644 /** 3645 * Fix flyout menu inside the sticky header. 3646 * 3647 * @since 1.4.1 3648 * @method _flyoutMenuFix 3649 */ 3650 _flyoutMenuFix: function( e ){ 3651 var header = this.header, 3652 menuModule = $( e.target ).closest( '.fl-menu' ), 3653 flyoutMenu = menuModule.find( '.fl-menu-mobile-flyout' ), 3654 flyoutPos = menuModule.hasClass( 'fl-flyout-right' ) ? 'right' : 'left', 3655 menuOpacity = menuModule.find( '.fl-menu-mobile-opacity' ), 3656 isScroll = 'undefined' !== typeof e && 'scroll' === e.handleObj.type, 3657 activePos = 'undefined' !== typeof flyoutMenu.data( 'activePos' ) ? flyoutMenu.data( 'activePos' ) : 0, 3658 headerPos = ( this.win.width() - header.width() ) / 2, 3659 inactivePos = headerPos > 0 ? activePos + 4 : 254; 3660 3661 if ( ! flyoutMenu.length ) { 3662 return; 3663 } 3664 3665 if ( this.overlay ) { 3666 return; 3667 } 3668 3669 if( $( '.fl-theme-builder-flyout-menu-active' ).length ) { 3670 3671 if ( isScroll && ! flyoutMenu.hasClass( 'fl-menu-disable-transition' ) ) { 3672 flyoutMenu.addClass( 'fl-menu-disable-transition' ); 3673 } 3674 3675 if ( header.hasClass( 'fl-theme-builder-header-sticky' ) ) { 3676 if ( ! isScroll ) { 3677 setTimeout( $.proxy( function(){ 3678 flyoutMenu.css( flyoutPos, '-' + activePos + 'px' ); 3679 }, this ), 1 ); 3680 } 3681 else { 3682 flyoutMenu.css( flyoutPos, '-' + activePos + 'px' ); 3683 } 3684 } 3685 else { 3686 flyoutMenu.css( flyoutPos, '0px' ); 3687 } 3688 } 3689 else { 3690 if ( flyoutMenu.hasClass( 'fl-menu-disable-transition' ) ) { 3691 flyoutMenu.removeClass( 'fl-menu-disable-transition' ); 3692 } 3693
3694 if ( header.hasClass( 'fl-theme-builder-flyout-menu-overlay' ) && headerPos > 0 && headerPos < 250 ) { 3695 if ( header.hasClass( 'fl-theme-builder-header-sticky' ) ) { 3696 inactivePos = headerPos + 254; 3697 } 3698 else { 3699 inactivePos = 254; 3700 } 3701 } 3702 3703 if ( e && e.type === 'resize' ) { 3704 inactivePos = headerPos + 254; 3705 } 3706 3707 flyoutMenu.css( flyoutPos, '-' + inactivePos + 'px' ); 3708 } 3709 3710 if ( e && menuModule.is('.fl-menu-responsive-flyout-overlay') && $.infinitescroll ) { 3711 e.stopImmediatePropagation(); 3712 } 3713 3714 if( menuOpacity.length ) { 3715 if ( header.hasClass( 'fl-theme-builder-header-sticky' ) ) { 3716 if ( '0px' === menuOpacity.css( 'left' ) ) { 3717 menuOpacity.css( 'left', '-' + headerPos + 'px' ); 3718 } 3719 } 3720 else { 3721 menuOpacity.css( 'left', '' ); 3722 } 3723 } 3724 }, 3725 3726 /** 3727 * Adjust sticky header width if BB Theme Boxed Layout is used. 3728 * 3729 * @since 1.4 3730 * @access private 3731 * @method _adjustStickyHeaderWidth 3732 */ 3733 _adjustStickyHeaderWidth: function () { 3734 if ( $('body').hasClass( 'fl-fixed-width' ) ) { 3735 var parentWidth = this.header.parent().width(); 3736 3737 // Better if this is set in the stylesheet file. 3738 if ( this.win.width() >= 992 ) { 3739 this.header.css({ 3740 'margin': '0 auto', 3741 'max-width': parentWidth, 3742 }); 3743 } 3744 else { 3745 this.header.css({ 3746 'margin': '', 3747 'max-width': '', 3748 }); 3749 } 3750 } 3751 }, 3752 3753 /** 3754 * Adjust Sticky Header Height 3755 * 3756 * @since 1.4 3757 * @access private 3758 * @method _adjustHeaderHeight 3759 */ 3760 _adjustHeaderHeight: function () { 3761 var beforeHeader = this.header.prevAll('.fl-builder-content'), 3762 beforeHeaderHeight = 0, 3763 beforeHeaderFix = 0, 3764 headerHeight = Math.floor( this.header.outerHeight() ), 3765 bodyTopPadding = parseInt( $( 'body' ).css( 'padding-top' ) ), 3766 wpAdminBarHeight = 0, 3767 totalHeaderHeight = 0; 3768 3769 if ( isNaN( bodyTopPadding ) ) { 3770 bodyTopPadding = 0; 3771 } 3772 3773 if ( beforeHeader.length ) { 3774 $.each( beforeHeader, function() { 3775 beforeHeaderHeight += Math.floor( $(this).outerHeight() ); 3776 }); 3777 // Subtract this value from the header parent's top padding. 3778 beforeHeaderFix = 2; 3779 } 3780 3781 if ( this.hasAdminBar && this.win.width() <= 600 ) { 3782 wpAdminBarHeight = Math.floor( $('#wpadminbar').outerHeight() ); 3783 } 3784 3785 totalHeaderHeight = Math.floor( beforeHeaderHeight + headerHeight); 3786 3787 if ( headerHeight > 0 ) { 3788 var headerParent = this.header.parent(), 3789 headerParentTopPadding = 0; 3790 3791 // If the header's parent container is the BODY tag ignore its top padding. 3792 if ( $( headerParent ).is('body') ) { 3793 headerParentTopPadding = Math.floor( headerHeight - wpAdminBarHeight ); 3794 } else { 3795 headerParentTopPadding = Math.floor( headerHeight - bodyTopPadding - wpAdminBarHeight ); 3796 } 3797 3798 $( headerParent ).css( 'padding-top', ( headerParentTopPadding - beforeHeaderFix ) + 'px' ); 3799 3800 this.header.css({ 3801 '-webkit-transform': 'translate(0px, -' + totalHeaderHeight + 'px)', 3802 '-ms-transform': 'translate(0px, -' + totalHeaderHeight + 'px)', 3803 'transform': 'translate(0px, -' + totalHeaderHeight + 'px)' 3804 }); 3805 3806 } 3807 3808 }, 3809 3810 /** 3811 * Initializes shrink logic for a header. 3812 * 3813 * @since 1.0 3814 * @access private 3815 * @method _initShrink 3816 */ 3817 _initShrink: function( e ) 3818 { 3819 if ( this.win.width() >= this.breakpointWidth ) { 3820 this.win.on( 'scroll.fl-theme-builder-header-shrink', $.proxy( this._doShrink, this ) ); 3821 this._setImageMaxHeight(); 3822 3823 if ( this.win.scrollTop() > 0 ){ 3824 this._doShrink(); 3825 } 3826 3827 } else { 3828 this.header.parent().css( 'padding-top', '0' ); 3829 this.win.off( 'scroll.fl-theme-builder-header-shrink' ); 3830 this._removeShrink(); 3831 this._removeImageMaxHeight(); 3832 } 3833 }, 3834 3835 /** 3836 * Shrinks the header when the page is scrolled. 3837 * 3838 * @since 1.0 3839 * @access private 3840 * @method _doShrink 3841 */ 3842 _doShrink: function( e ) 3843 { 3844 var winTop = this.win.scrollTop(), 3845 headerTop = this.header.data('original-top'), 3846 headerHeight = this.header.data('original-height'), 3847 shrinkImageHeight = this.header.data('shrink-image-height'), 3848 windowSize = this.win.width(), 3849 makeSticky = this._makeWindowSticky( windowSize ),
3850 hasClass = this.header.hasClass( 'fl-theme-builder-header-shrink' ); 3851 3852 3853 if ( this.hasAdminBar ) { 3854 winTop += 32; 3855 } 3856 3857 if ( makeSticky && ( winTop > headerTop + headerHeight ) ) { 3858 if ( ! hasClass ) { 3859 3860 this.header.addClass( 'fl-theme-builder-header-shrink' ); 3861 3862 // Shrink images but don't include lightbox and menu images. 3863 this.header.find('img').each( function( i ) { 3864 var image = $( this ), 3865 maxMegaMenu = image.closest( '.max-mega-menu' ).length, 3866 imageInLightbox = image.closest( '.fl-button-lightbox-content' ).length, 3867 imageInNavMenu = image.closest( 'li.menu-item' ).length; 3868 3869 if ( ! ( imageInLightbox || imageInNavMenu || maxMegaMenu ) ) { 3870 image.css( 'max-height', shrinkImageHeight ); 3871 } 3872 3873 }); 3874 3875 this.header.find( '.fl-row-content-wrap' ).each( function() { 3876 3877 var row = $( this ); 3878 3879 if ( parseInt( row.css( 'padding-bottom' ) ) > 5 ) { 3880 row.addClass( 'fl-theme-builder-header-shrink-row-bottom' ); 3881 } 3882 3883 if ( parseInt( row.css( 'padding-top' ) ) > 5 ) { 3884 row.addClass( 'fl-theme-builder-header-shrink-row-top' ); 3885 } 3886 } ); 3887 3888 this.header.find( '.fl-module' ).each( function() { 3889 3890 var module = $( this ).find( '.fl-module-content' ).length ? $( this ).find( '.fl-module-content' ) : $( this ); 3891 3892 if ( parseInt( module.css( 'margin-bottom' ) ) > 5 ) { 3893 module.addClass( 'fl-theme-builder-header-shrink-module-bottom' ); 3894 } 3895 3896 if ( parseInt( module.css( 'margin-top' ) ) > 5 ) { 3897 module.addClass( 'fl-theme-builder-header-shrink-module-top' ); 3898 } 3899 } ); 3900 } 3901 } else if (hasClass) { 3902 this.header.find( 'img' ).css( 'max-height', '' ); 3903 this._removeShrink(); 3904 } 3905 3906 // Fixes Shrink header issue with BB Theme when window is scrolled then resized and back. 3907 if ( 'undefined' === typeof( e ) && $('body').hasClass( 'fl-fixed-width' ) ) { 3908 if ( ! this.overlay ) { 3909 this._adjustHeaderHeight(); 3910 } 3911 } 3912 3913 }, 3914 3915 /** 3916 * Removes the header shrink effect. 3917 * 3918 * @since 1.0 3919 * @access private 3920 * @method _removeShrink 3921 */ 3922 _removeShrink: function() 3923 { 3924 var rows = this.header.find( '.fl-row-content-wrap' ), 3925 modules = this.header.find('.fl-module, .fl-module-content'); 3926 3927 rows.removeClass( 'fl-theme-builder-header-shrink-row-bottom' ); 3928 rows.removeClass( 'fl-theme-builder-header-shrink-row-top' ); 3929 modules.removeClass( 'fl-theme-builder-header-shrink-module-bottom' ); 3930 modules.removeClass( 'fl-theme-builder-header-shrink-module-top' ); 3931 this.header.removeClass( 'fl-theme-builder-header-shrink' ); 3932 }, 3933 3934 /** 3935 * Adds max height to images in modules for smooth scrolling. 3936 * 3937 * @since 1.1.1 3938 * @access private 3939 * @method _setImageMaxHeight 3940 */ 3941 _setImageMaxHeight: function() 3942 { 3943 var head = $( 'head' ), 3944 stylesId = 'fl-header-styles-' + this.header.data( 'post-id' ), 3945 styles = '', 3946 images = this.header.find( '.fl-module img' ); 3947 3948 if ( $( '#' + stylesId ).length ) { 3949 return; 3950 } 3951 3952 images.each( function( i ) { 3953 var image = $( this ), 3954 height = image.height(), 3955 node = image.closest( '.fl-module' ).data( 'node' ), 3956 className = 'fl-node-' + node + '-img-' + i, 3957 maxMegaMenu = image.closest( '.max-mega-menu' ).length, 3958 imageInLightbox = image.closest( '.fl-button-lightbox-content' ).length, 3959 imageInNavMenu = image.closest( 'li.menu-item' ).length; 3960 3961 if ( ! ( imageInLightbox || imageInNavMenu || maxMegaMenu ) ) { 3962 image.addClass( className ); 3963 styles += '.' + className + ' { max-height: ' + ( height ? height : image[0].height ) + 'px }'; 3964 } 3965 3966 } ); 3967 3968 if ( '' !== styles ) { 3969 head.append( '<style id="' + stylesId + '">' + styles + '</style>' ); 3970 } 3971 }, 3972 3973 /** 3974 * Removes max height on images in modules for smooth scrolling. 3975 * 3976 * @since 1.1.1 3977 * @access private 3978 * @method _removeImageMaxHeight 3979 */ 3980 _removeImageMaxHeight: function() 3981 { 3982 $( '#fl-header-styles-' + this.header.data( 'post-id' ) ).remove(); 3983 }, 3984 }; 3985 3986 $( function() { FLThemeBuilderHeaderLayout.init(); } ); 3987 3988})(jQuery); 3989 3990 3991(function($) { 3992 3993 $(function() { 3994 3995 new FLBuilderMenu({ 3996 id: 'wpl8on6d19qt', 3997 type: 'vertical', 3998 mobile: 'expanded', 3999 mobileBelowRow: false, 4000 mobileFlyout: false, 4001 breakPoints: { 4002 large: 1200, 4003 medium: 1024, 4004 small: 768 }, 4005 mobileBreakpoint: 'mobile', 4006 postId : '3032', 4007 mobileStacked: true, 4008 submenuIcon: 'none', 4009 flyoutWidth: '250', 4010 }); 4011 4012 }); 4013 4014})(jQuery); 4015 4016(function($) { 4017 4018 $(function() { 4019 4020 new FLBuilderMenu({ 4021 id: '1t9anvk2zfeu', 4022 type: 'vertical', 4023 mobile: 'expanded', 4024 mobileBelowRow: false, 4025 mobileFlyout: false, 4026 breakPoints: { 4027 large: 1200, 4028 medium: 1024, 4029 small: 768 }, 4030 mobileBreakpoint: 'mobile', 4031 postId : '3032', 4032 mobileStacked: true, 4033 submenuIcon: 'none', 4034 flyoutWidth: '250', 4035 }); 4036 4037 }); 4038 4039})(jQuery); 4040 4041(function($) { 4042 4043 $(function() { 4044 4045 new FLBuilderMenu({ 4046 id: 'zlj0yxmghadu', 4047 type: 'vertical', 4048 mobile: 'expanded', 4049 mobileBelowRow: false, 4050 mobileFlyout: false, 4051 breakPoints: { 4052 large: 1200, 4053 medium: 1024, 4054 small: 768 }, 4055 mobileBreakpoint: 'mobile', 4056 postId : '3032', 4057 mobileStacked: true, 4058 submenuIcon: 'none', 4059 flyoutWidth: '250', 4060 }); 4061 4062 }); 4063 4064})(jQuery); 4065 4066(function($) { 4067 4068 $(function() { 4069 4070 new FLBuilderMenu({ 4071 id: 'asxbu0zor596', 4072 type: 'vertical', 4073 mobile: 'expanded', 4074 mobileBelowRow: false, 4075 mobileFlyout: false, 4076 breakPoints: { 4077 large: 1200, 4078 medium: 1024, 4079 small: 768 }, 4080 mobileBreakpoint: 'mobile', 4081 postId : '3032', 4082 mobileStacked: true, 4083 submenuIcon: 'none', 4084 flyoutWidth: '250', 4085 }); 4086 4087 }); 4088 4089})(jQuery); 4090 4091(function($) { 4092 4093 $(function() { 4094 4095 new FLBuilderMenu({ 4096 id: 'myht20x41w8k', 4097 type: 'vertical', 4098 mobile: 'expanded', 4099 mobileBelowRow: false, 4100 mobileFlyout: false, 4101 breakPoints: { 4102 large: 1200, 4103 medium: 1024, 4104 small: 768 }, 4105 mobileBreakpoint: 'mobile', 4106 postId : '3032', 4107 mobileStacked: true, 4108 submenuIcon: 'none', 4109 flyoutWidth: '250', 4110 }); 4111 4112 }); 4113 4114})(jQuery); 4115 4116/* Start Layout Custom JS */ 4117 4118/* End Layout Custom JS */ 4119 4120 4121(function($) { 4122 if ( $('.fl-node-r52yxpbsnmwq .pp-photo-rollover').length > 0 ) { 4123 $('body').on( 'mouseenter.pp-rollover', '.fl-node-r52yxpbsnmwq .pp-photo-rollover .pp-photo-content', function() { 4124 $(this).addClass( 'is-hover' ); 4125 } ).on( 'mouseleave.pp-rollover', '.fl-node-r52yxpbsnmwq .pp-photo-rollover .pp-photo-content', function() { 4126 $(this).removeClass( 'is-hover' ); 4127 } ); 4128 } 4129})(jQuery);(function($) { 4130 if ( $('.fl-node-c6vu14kpsqyo .pp-photo-rollover').length > 0 ) { 4131 $('body').on( 'mouseenter.pp-rollover', '.fl-node-c6vu14kpsqyo .pp-photo-rollover .pp-photo-content', function() { 4132 $(this).addClass( 'is-hover' ); 4133 } ).on( 'mouseleave.pp-rollover', '.fl-node-c6vu14kpsqyo .pp-photo-rollover .pp-photo-content', function() { 4134 $(this).removeClass( 'is-hover' ); 4135 } ); 4136 } 4137})(jQuery);(function($) { 4138 if ( $('.fl-node-qw7pk3fmbjrz .pp-photo-rollover').length > 0 ) { 4139 $('body').on( 'mouseenter.pp-rollover', '.fl-node-qw7pk3fmbjrz .pp-photo-rollover .pp-photo-content', function() { 4140 $(this).addClass( 'is-hover' ); 4141 } ).on( 'mouseleave.pp-rollover', '.fl-node-qw7pk3fmbjrz .pp-photo-rollover .pp-photo-content', function() { 4142 $(this).removeClass( 'is-hover' ); 4143 } ); 4144 } 4145})(jQuery);(function($){ 4146 })(jQuery); 4147(function($){ 4148 })(jQuery); 4149(function($){ 4150 })(jQuery); 4151(function($) { 4152 if ( $('.fl-node-5jd8ukyeqvs4 .pp-photo-rollover').length > 0 ) { 4153 $('body').on( 'mouseenter.pp-rollover', '.fl-node-5jd8ukyeqvs4 .pp-photo-rollover .pp-photo-content', function() { 4154 $(this).addClass( 'is-hover' ); 4155 } ).on( 'mouseleave.pp-rollover', '.fl-node-5jd8ukyeqvs4 .pp-photo-rollover .pp-photo-content', function() { 4156 $(this).removeClass( 'is-hover' ); 4157 } ); 4158 } 4159})(jQuery);(function($) { 4160 if ( $('.fl-node-ka9b8nocuj2q .pp-photo-rollover').length > 0 ) { 4161 $('body').on( 'mouseenter.pp-rollover', '.fl-node-ka9b8nocuj2q .pp-photo-rollover .pp-photo-content', function() { 4162 $(this).addClass( 'is-hover' ); 4163 } ).on( 'mouseleave.pp-rollover', '.fl-node-ka9b8nocuj2q .pp-photo-rollover .pp-photo-content', function() { 4164 $(this).removeClass( 'is-hover' ); 4165 } ); 4166 } 4167})(jQuery); 4168;/** 4169 * This file should contain frontend logic for 4170 * all module instances. 4171 */(function($){ 4172 })(jQuery); 4173(function($){ 4174 })(jQuery); 4175(function($) { 4176 if ( $('.fl-node-nmdekqry3ul9 .pp-photo-rollover').length > 0 ) { 4177 $('body').on( 'mouseenter.pp-rollover', '.fl-node-nmdekqry3ul9 .pp-photo-rollover .pp-photo-content', function() { 4178 $(this).addClass( 'is-hover' ); 4179 } ).on( 'mouseleave.pp-rollover', '.fl-node-nmdekqry3ul9 .pp-photo-rollover .pp-photo-content', function() { 4180 $(this).removeClass( 'is-hover' ); 4181 } ); 4182 } 4183})(jQuery);(function($) { 4184 if ( $('.fl-node-41tybsmd6ila .pp-photo-rollover').length > 0 ) { 4185 $('body').on( 'mouseenter.pp-rollover', '.fl-node-41tybsmd6ila .pp-photo-rollover .pp-photo-content', function() { 4186 $(this).addClass( 'is-hover' ); 4187 } ).on( 'mouseleave.pp-rollover', '.fl-node-41tybsmd6ila .pp-photo-rollover .pp-photo-content', function() { 4188 $(this).removeClass( 'is-hover' ); 4189 } ); 4190 } 4191})(jQuery);(function($){ 4192 })(jQuery); 4193(function($){ 4194 })(jQuery); 4195(function($) { 4196 if ( $('.fl-node-h0olzwbt37ae .pp-photo-rollover').length > 0 ) { 4197 $('body').on( 'mouseenter.pp-rollover', '.fl-node-h0olzwbt37ae .pp-photo-rollover .pp-photo-content', function() { 4198 $(this).addClass( 'is-hover' ); 4199 } ).on( 'mouseleave.pp-rollover', '.fl-node-h0olzwbt37ae .pp-photo-rollover .pp-photo-content', function() { 4200 $(this).removeClass( 'is-hover' ); 4201 } ); 4202 } 4203})(jQuery);(function($) { 4204 if ( $('.fl-node-q2citxwlkg3f .pp-photo-rollover').length > 0 ) { 4205 $('body').on( 'mouseenter.pp-rollover', '.fl-node-q2citxwlkg3f .pp-photo-rollover .pp-photo-content', function() { 4206 $(this).addClass( 'is-hover' ); 4207 } ).on( 'mouseleave.pp-rollover', '.fl-node-q2citxwlkg3f .pp-photo-rollover .pp-photo-content', function() { 4208 $(this).removeClass( 'is-hover' ); 4209 } ); 4210 } 4211})(jQuery);(function($){ 4212 })(jQuery); 4213(function($){ 4214 })(jQuery); 4215 4216/* Start Layout Custom JS */ 4217 4218/* End Layout Custom JS */ 4219 4220
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.