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