1var wpAjaxUrl = 'https://starsapphire-oto.org/wp-admin/admin-ajax.php';var flBuilderUrl = 'https://starsapphire-oto.org/wp-content/plugins/bb-plugin/';var FLBuilderLayoutConfig = { 2 anchorLinkAnimations : { 3 duration : 1000, 4 easing : 'swing', 5 offset : 100 6 }, 7 paths : { 8 pluginUrl : 'https://starsapphire-oto.org/wp-content/plugins/bb-plugin/', 9 wpAjaxUrl : 'https://starsapphire-oto.org/wp-admin/admin-ajax.php' 10 }, 11 breakpoints : { 12 small : 768, 13 medium : 992 }, 14 waypoint: { 15 offset: 80 16 } 17};(function($){ 18 19 if(typeof FLBuilderLayout != 'undefined') { 20 return; 21 } 22 23 /** 24 * Helper class with generic logic for a builder layout. 25 * 26 * @class FLBuilderLayout 27 * @since 1.0 28 */ 29 FLBuilderLayout = { 30 31 /** 32 * Initializes a builder layout. 33 * 34 * @since 1.0 35 * @method init 36 */ 37 init: function() 38 { 39 // Destroy existing layout events. 40 FLBuilderLayout._destroy(); 41 42 // Init CSS classes. 43 FLBuilderLayout._initClasses(); 44 45 // Init backgrounds. 46 FLBuilderLayout._initBackgrounds(); 47 48 // Only init if the builder isn't active. 49 if ( 0 === $('.fl-builder-edit').length ) { 50 51 // Init anchor links. 52 FLBuilderLayout._initAnchorLinks(); 53 54 // Init the browser hash. 55 FLBuilderLayout._initHash(); 56 57 // Init module animations. 58 FLBuilderLayout._initModuleAnimations(); 59 60 // Init forms. 61 FLBuilderLayout._initForms(); 62 } 63 }, 64 65 /** 66 * Public method for refreshing Wookmark or MosaicFlow galleries 67 * within an element. 68 * 69 * @since 1.7.4 70 * @method refreshGalleries 71 */ 72 refreshGalleries: function( element ) 73 { 74 var $element = 'undefined' == typeof element ? $( 'body' ) : $( element ), 75 mfContent = $element.find( '.fl-mosaicflow-content' ), 76 wmContent = $element.find( '.fl-gallery' ), 77 mfObject = null; 78 79 if ( mfContent ) { 80 81 mfObject = mfContent.data( 'mosaicflow' ); 82 83 if ( mfObject ) { 84 mfObject.columns = $( [] ); 85 mfObject.columnsHeights = []; 86 mfContent.data( 'mosaicflow', mfObject ); 87 mfContent.mosaicflow( 'refill' ); 88 } 89 } 90 if ( wmContent ) { 91 wmContent.trigger( 'refreshWookmark' ); 92 } 93 }, 94 95 /** 96 * Public method for refreshing Masonry within an element 97 * 98 * @since 1.8.1 99 * @method refreshGridLayout 100 */ 101 refreshGridLayout: function( element ) 102 { 103 var $element = 'undefined' == typeof element ? $( 'body' ) : $( element ), 104 msnryContent = $element.find('.masonry'); 105 106 if ( msnryContent.length ) { 107 msnryContent.masonry('layout'); 108 } 109 }, 110 111 /** 112 * Public method for reloading BxSlider within an element 113 * 114 * @since 1.8.1 115 * @method reloadSlider 116 */ 117 reloadSlider: function( element ) 118 { 119 var $element = 'undefined' == typeof element ? $( 'body' ) : $( element ), 120 bxContent = $element.find('.bx-viewport .fl-post-carousel-wrapper'), 121 bxObject = null; 122 123 if ( bxContent.length ) { 124 bxContent.each(function(){ 125 bxObject = $(this).data( 'bxSlider'); 126 if ( bxObject ) { 127 bxObject.reloadSlider(); 128 } 129 }) 130 131 } 132 }, 133 134 /** 135 * Public method for resizing WP audio player 136 * 137 * @since 1.8.2 138 * @method resizeAudio 139 */ 140 resizeAudio: function( element ) 141 { 142 var $element = 'undefined' == typeof element ? $( 'body' ) : $( element ), 143 audioPlayers = $element.find('.wp-audio-shortcode.mejs-audio'), 144 player = null, 145 mejsPlayer = null, 146 rail = null, 147 railWidth = 400; 148 149 if ( audioPlayers.length && typeof mejs !== 'undefined' ) { 150 audioPlayers.each(function(){ 151 player = $(this); 152 mejsPlayer = mejs.players[player.attr('id')]; 153 rail = player.find('.mejs-controls .mejs-time-rail'); 154 var innerMejs = player.find('.mejs-inner'), 155 total = player.find('.mejs-controls .mejs-time-total'); 156 157 if ( typeof mejsPlayer !== 'undefined' ) { 158 railWidth = Math.ceil(player.width() * 0.8); 159 160 if ( innerMejs.length ) { 161
162 rail.css('width', railWidth +'px!important'); 163 //total.width(rail.width() - 10); 164 165 mejsPlayer.options.autosizeProgress = true; 166 167 // webkit has trouble doing this without a delay 168 setTimeout(function () { 169 mejsPlayer.setControlsSize(); 170 }, 50); 171 172 player.find('.mejs-inner').css({ 173 visibility: 'visible', 174 height: 'inherit' 175 }); 176 } 177 } 178 }); 179 } 180 }, 181 182 /** 183 * Public method for preloading WP audio player when it's inside the hidden element 184 * 185 * @since 1.8.2 186 * @method preloadAudio 187 */ 188 preloadAudio: function(element) 189 { 190 var $element = 'undefined' == typeof element ? $( 'body' ) : $( element ), 191 contentWrap = $element.closest('.fl-accordion-item'), 192 audioPlayers = $element.find('.wp-audio-shortcode.mejs-audio'); 193 194 if ( ! contentWrap.hasClass('fl-accordion-item-active') && audioPlayers.find('.mejs-inner').length ) { 195 audioPlayers.find('.mejs-inner').css({ 196 visibility : 'hidden', 197 height: 0 198 }); 199 } 200 }, 201 202 /** 203 * Unbinds builder layout events. 204 * 205 * @since 1.0 206 * @access private 207 * @method _destroy 208 */ 209 _destroy: function() 210 { 211 var win = $(window); 212 213 win.off('scroll.fl-bg-parallax'); 214 win.off('resize.fl-bg-video'); 215 }, 216 217 /** 218 * Checks to see if the current device has touch enabled. 219 * 220 * @since 1.0 221 * @access private 222 * @method _isTouch 223 * @return {Boolean} 224 */ 225 _isTouch: function() 226 { 227 if(('ontouchstart' in window) || (window.DocumentTouch && document instanceof DocumentTouch)) { 228 return true; 229 } 230 231 return false; 232 }, 233 234 /** 235 * Checks to see if the current device is mobile. 236 * 237 * @since 1.7 238 * @access private 239 * @method _isMobile 240 * @return {Boolean} 241 */ 242 _isMobile: function() 243 { 244 return /Mobile|Android|Silk\/|Kindle|BlackBerry|Opera Mini|Opera Mobi|webOS/i.test( navigator.userAgent ); 245 }, 246 247 /** 248 * Initializes builder body classes. 249 * 250 * @since 1.0 251 * @access private 252 * @method _initClasses 253 */ 254 _initClasses: function() 255 { 256 var body = $( 'body' ), 257 ua = navigator.userAgent; 258 259 // Add the builder body class. 260 if ( ! body.hasClass( 'archive' ) && $( '.fl-builder-content-primary' ).length > 0 ) { 261 body.addClass('fl-builder'); 262 } 263 264 // Add the builder touch body class. 265 if(FLBuilderLayout._isTouch()) { 266 body.addClass('fl-builder-touch'); 267 } 268 269 // Add the builder mobile body class. 270 if(FLBuilderLayout._isMobile()) { 271 body.addClass('fl-builder-mobile'); 272 } 273 274 // IE11 body class. 275 if ( ua.indexOf( 'Trident/7.0' ) > -1 && ua.indexOf( 'rv:11.0' ) > -1 ) { 276 body.addClass( 'fl-builder-ie-11' ); 277 } 278 }, 279 280 /** 281 * Initializes builder node backgrounds that require 282 * additional JavaScript logic such as parallax. 283 * 284 * @since 1.1.4 285 * @access private
286 * @method _initBackgrounds 287 */ 288 _initBackgrounds: function() 289 { 290 var win = $(window); 291 292 // Init parallax backgrounds. 293 if($('.fl-row-bg-parallax').length > 0 && !FLBuilderLayout._isMobile()) { 294 FLBuilderLayout._scrollParallaxBackgrounds(); 295 FLBuilderLayout._initParallaxBackgrounds(); 296 win.on('scroll.fl-bg-parallax', FLBuilderLayout._scrollParallaxBackgrounds); 297 } 298 299 // Init video backgrounds. 300 if($('.fl-bg-video').length > 0) { 301 FLBuilderLayout._initBgVideos(); 302 FLBuilderLayout._resizeBgVideos(); 303 win.on('resize.fl-bg-video', FLBuilderLayout._resizeBgVideos); 304 } 305 }, 306 307 /** 308 * Initializes all parallax backgrounds in a layout. 309 * 310 * @since 1.1.4 311 * @access private 312 * @method _initParallaxBackgrounds 313 */ 314 _initParallaxBackgrounds: function() 315 { 316 $('.fl-row-bg-parallax').each(FLBuilderLayout._initParallaxBackground); 317 }, 318 319 /** 320 * Initializes a single parallax background. 321 * 322 * @since 1.1.4 323 * @access private 324 * @method _initParallaxBackgrounds 325 */ 326 _initParallaxBackground: function() 327 { 328 var row = $(this), 329 content = row.find('> .fl-row-content-wrap'), 330 src = row.data('parallax-image'), 331 loaded = row.data('parallax-loaded'), 332 img = new Image(); 333 334 if(loaded) { 335 return; 336 } 337 else if(typeof src != 'undefined') { 338 339 $(img).on('load', function() { 340 content.css('background-image', 'url(' + src + ')'); 341 row.data('parallax-loaded', true); 342 }); 343 344 img.src = src; 345 } 346 }, 347 348 /** 349 * Fires when the window is scrolled to adjust 350 * parallax backgrounds. 351 * 352 * @since 1.1.4 353 * @access private 354 * @method _scrollParallaxBackgrounds 355 */ 356 _scrollParallaxBackgrounds: function() 357 { 358 $('.fl-row-bg-parallax').each(FLBuilderLayout._scrollParallaxBackground); 359 }, 360 361 /** 362 * Fires when the window is scrolled to adjust 363 * a single parallax background. 364 * 365 * @since 1.1.4 366 * @access private 367 * @method _scrollParallaxBackground 368 */ 369 _scrollParallaxBackground: function() 370 { 371 var win = $(window), 372 row = $(this), 373 content = row.find('> .fl-row-content-wrap'), 374 speed = row.data('parallax-speed'), 375 offset = content.offset(), 376 yPos = -((win.scrollTop() - offset.top) / speed); 377 378 content.css('background-position', 'center ' + yPos + 'px'); 379 }, 380 381 /** 382 * Initializes all video backgrounds. 383 * 384 * @since 1.6.3.3 385 * @access private 386 * @method _initBgVideos 387 */ 388 _initBgVideos: function() 389 { 390 $('.fl-bg-video').each(FLBuilderLayout._initBgVideo); 391 }, 392 393 /** 394 * Initializes a video background. 395 * 396 * @since 1.6.3.3 397 * @access private 398 * @method _initBgVideo 399 */ 400 _initBgVideo: function() 401 { 402 var wrap = $( this ), 403 width = wrap.data( 'width' ), 404 height = wrap.data( 'height' ), 405 mp4 = wrap.data( 'mp4' ), 406 youtube = wrap.data( 'youtube'), 407 vimeo = wrap.data( 'vimeo'), 408 mp4Type = wrap.data( 'mp4-type' ), 409 webm = wrap.data( 'webm' ), 410 webmType = wrap.data( 'webm-type' ), 411 fallback = wrap.data( 'fallback' ), 412 loaded = wrap.data( 'loaded' ), 413 fallbackTag = '', 414 videoTag = null, 415 mp4Tag = null, 416 webmTag = null; 417 418 // Return if the video has been loaded for this row. 419 if ( loaded ) { 420 return; 421 } 422 // Append the video tag for non-mobile. 423 else if ( ! FLBuilderLayout._isMobile() ) { 424 425 videoTag = $( '<video autoplay loop muted preload></video>' ); 426 427 // MP4 Source Tag 428 if ( 'undefined' != typeof mp4 ) { 429 430 mp4Tag = $( '<source />' ); 431 mp4Tag.attr( 'src', mp4 ); 432 mp4Tag.attr( 'type', mp4Type ); 433 434 if ( 'undefined' == typeof webm ) { 435 mp4Tag.on( 'error', FLBuilderLayout._videoBgSourceError ); 436 } 437 438 videoTag.append( mp4Tag ); 439 } 440 441 // WebM Source Tag 442 if ( 'undefined' != typeof webm ) { 443 444 webmTag = $( '<source />' ); 445 webmTag.attr( 'src', webm ); 446 webmTag.attr( 'type', webmType ); 447 448 if ( 'undefined' != typeof mp4 ) { 449 webmTag.on( 'error', FLBuilderLayout._videoBgSourceError ); 450 } 451 452 videoTag.append( webmTag ); 453 } 454 455 // Check what video player we are going to load in a row 456 if ( 'undefined' != typeof youtube ) { 457 FLBuilderLayout._initYoutubeBgVideo.apply( this ); 458 } 459 else if ( 'undefined' != typeof vimeo ) { 460 FLBuilderLayout._initVimeoBgVideo.apply( this ); 461 } 462 else { 463 wrap.append( videoTag ); 464 } 465 } 466 // Append the fallback tag for mobile.
467 else if ( '' !== fallback ) { 468 fallbackTag = $( '<div></div>' ); 469 fallbackTag.addClass( 'fl-bg-video-fallback' ); 470 fallbackTag.css( 'background-image', 'url(' + fallback + ')' ); 471 wrap.append( fallbackTag ); 472 } 473 474 // Mark this video as loaded. 475 wrap.data('loaded', true); 476 }, 477 478 /** 479 * Initializes Youtube video background 480 * 481 * @since 1.9 482 * @access private 483 * @method _initYoutubeBgVideo 484 */ 485 _initYoutubeBgVideo: function() 486 { 487 var playerWrap = $(this), 488 videoId = playerWrap.data('video-id'), 489 videoPlayer = playerWrap.find('.fl-bg-video-player'), 490 enableAudio = playerWrap.data('enable-audio'), 491 player; 492 493 if ( videoId ) { 494 495 FLBuilderLayout._onYoutubeApiReady( function( YT ) { 496 setTimeout( function() { 497 498 player = new YT.Player( videoPlayer[0], { 499 videoId: videoId, 500 events: { 501 onReady: function(event) { 502 if ( "no" === enableAudio ) { 503 event.target.mute(); 504 } 505 else if ("yes" === enableAudio && event.target.isMuted ) { 506 event.target.unMute(); 507 } 508 509 // Store an instance to a parent 510 playerWrap.data('YTPlayer', player); 511 FLBuilderLayout._resizeYoutubeBgVideo.apply(playerWrap); 512 513 event.target.playVideo(); 514 }, 515 onStateChange: function( event ) { 516 if ( event.data === YT.PlayerState.ENDED ) { 517 player.seekTo( 0 ); 518 } 519 } 520 }, 521 playerVars: { 522 controls: 0, 523 showinfo: 0 524 } 525 } ); 526 }, 1 ); 527 } ); 528 } 529 }, 530 531 /** 532 * Check if Youtube API has been downloaded 533 * 534 * @since 1.9 535 * @access private 536 * @method _onYoutubeApiReady 537 * @param {Function} callback Method to call when YT API has been loaded 538 */ 539 _onYoutubeApiReady: function( callback ) { 540 if ( window.YT && YT.loaded ) { 541 callback( YT ); 542 } else { 543 // If not ready check again by timeout.. 544 setTimeout( function() { 545 FLBuilderLayout._onYoutubeApiReady( callback ); 546 }, 350 ); 547 } 548 }, 549 550 /** 551 * Initializes Vimeo video background 552 * 553 * @since 1.9 554 * @access private 555 * @method _initVimeoBgVideo 556 */ 557 _initVimeoBgVideo: function() 558 { 559 var playerWrap = $(this), 560 videoId = playerWrap.data('video-id'), 561 videoPlayer = playerWrap.find('.fl-bg-video-player'), 562 enableAudio = playerWrap.data('enable-audio'), 563 player, 564 width = playerWrap.outerWidth(); 565 566 if ( typeof Vimeo !== 'undefined' && videoId ) { 567 player = new Vimeo.Player(videoPlayer[0], { 568 id: videoId, 569 loop: true, 570 title: false, 571 portrait: false 572 }); 573 574 playerWrap.data('VMPlayer', player); 575 if ( "no" === enableAudio ) { 576 player.setVolume(0); 577 } 578 else if ("yes" === enableAudio ) { 579 player.setVolume(1); 580 } 581 582 player.play(); 583 } 584 }, 585 586 /** 587 * Fires when there is an error loading a video 588 * background source and shows the fallback. 589 * 590 * @since 1.6.3.3 591 * @access private 592 * @method _videoBgSourceError 593 * @param {Object} e An event object. 594 */ 595 _videoBgSourceError: function( e ) 596 { 597 var source = $( e.target ), 598 wrap = source.closest( '.fl-bg-video' ), 599 vid = wrap.find( 'video' ), 600 fallback = wrap.data( 'fallback' ), 601 fallbackTag = ''; 602 603 if ( '' !== fallback ) { 604 fallbackTag = $( '<div></div>' ); 605 fallbackTag.addClass( 'fl-bg-video-fallback' ); 606 fallbackTag.css( 'background-image', 'url(' + fallback + ')' ); 607 wrap.append( fallbackTag ); 608 vid.remove(); 609 } 610 }, 611 612 /** 613 * Fires when the window is resized to resize 614 * all video backgrounds. 615 * 616 * @since 1.1.4 617 * @access private 618 * @method _resizeBgVideos 619 */ 620 _resizeBgVideos: function() 621 { 622 $('.fl-bg-video').each( function() { 623 624 FLBuilderLayout._resizeBgVideo.apply( this ); 625 626 if ( $( this ).parent().find( 'img' ).length > 0 ) { 627 $( this ).parent().imagesLoaded( $.proxy( FLBuilderLayout._resizeBgVideo, this ) ); 628 } 629 } ); 630 }, 631 632 /** 633 * Fires when the window is resized to resize 634 * a single video background. 635 * 636 * @since 1.1.4 637 * @access private 638 * @method _resizeBgVideo 639 */ 640 _resizeBgVideo: function() 641 { 642 if ( 0 === $( this ).find( 'video' ).length && 0 === $( this ).find( 'iframe' ).length ) { 643 return; 644 } 645 646 var wrap = $(this), 647 wrapHeight = wrap.outerHeight(), 648 wrapWidth = wrap.outerWidth(), 649 vid = wrap.find('video'), 650 vidHeight = wrap.data('height'), 651 vidWidth = wrap.data('width'), 652 newWidth = wrapWidth, 653 newHeight = Math.round(vidHeight * wrapWidth/vidWidth), 654 newLeft = 0, 655 newTop = 0, 656 iframe = wrap.find('iframe'); 657 658 if ( vid.length ) { 659 if(vidHeight === '' || typeof vidHeight === 'undefined' || vidWidth === '' || typeof vidWidth === 'undefined') { 660 vid.css({ 661 'left' : '0px', 662 'top' : '0px', 663 'width' : newWidth + 'px' 664 }); 665 666 // Try to set the actual video dimension on 'loadedmetadata' when using URL as video source 667 vid.on('loadedmetadata', FLBuilderLayout._resizeOnLoadedMeta); 668 669 } 670 else { 671 672 if(newHeight < wrapHeight) { 673 newHeight = wrapHeight; 674 newWidth = Math.round(vidWidth * wrapHeight/vidHeight); 675 newLeft = -((newWidth - wrapWidth)/2); 676 } 677 else { 678 newTop = -((newHeight - wrapHeight)/2); 679 } 680 681 vid.css({ 682 'left' : newLeft + 'px', 683 'top' : newTop + 'px', 684 'height' : newHeight + 'px', 685 'width' : newWidth + 'px' 686 }); 687 } 688 } 689 else if ( iframe.length ) { 690 691 // Resize Youtube video player within iframe tag 692 if ( typeof wrap.data('youtube') !== 'undefined' ) { 693 FLBuilderLayout._resizeYoutubeBgVideo.apply(this); 694 } 695 } 696 }, 697 698 /** 699 * Fires when video meta has been loaded. 700 * This will be Triggered when width/height attributes were not specified during video background resizing. 701 * 702 * @since 1.8.5 703 * @access private 704 * @method _resizeOnLoadedMeta 705 */ 706 _resizeOnLoadedMeta: function(){ 707 var video = $(this), 708 wrapHeight = video.parent().outerHeight(), 709 wrapWidth = video.parent().outerWidth(), 710 vidWidth = video[0].videoWidth, 711 vidHeight = video[0].videoHeight, 712 newHeight = Math.round(vidHeight * wrapWidth/vidWidth), 713 newTop = 0; 714 715 if(newHeight < wrapHeight) { 716 newHeight = wrapHeight; 717 newWidth = Math.round(vidWidth * wrapHeight/vidHeight); 718 newLeft = -((newWidth - wrapWidth)/2); 719 } 720 else { 721 newTop = -((newHeight - wrapHeight)/2); 722 } 723 724 video.parent().data('width', vidWidth); 725 video.parent().data('height', vidHeight); 726 727 video.css({ 728 'left' : newLeft + 'px', 729 'top' : newTop + 'px', 730 'width' : newWidth + 'px', 731 'height' : newHeight + 'px' 732 }); 733 }, 734 735 /** 736 * Fires when the window is resized to resize 737 * a single Youtube video background. 738 * 739 * @since 1.9 740 * @access private 741 * @method _resizeYoutubeBgVideo 742 */ 743 _resizeYoutubeBgVideo: function() 744 { 745 var wrap = $(this), 746 wrapWidth = wrap.outerWidth(), 747 wrapHeight = wrap.outerHeight(), 748 player = wrap.data('YTPlayer'), 749 video = player ? player.getIframe() : null, 750 aspectRatioSetting = '16:9', // Medium 751 aspectRatioArray = aspectRatioSetting.split( ':' ),
752 aspectRatio = aspectRatioArray[0] / aspectRatioArray[1], 753 ratioWidth = wrapWidth / aspectRatio, 754 ratioHeight = wrapHeight * aspectRatio, 755 isWidthFixed = wrapWidth / wrapHeight > aspectRatio, 756 width = isWidthFixed ? wrapWidth : ratioHeight, 757 height = isWidthFixed ? ratioWidth : wrapHeight; 758 759 if ( video ) { 760 $(video).width( width ).height( height ); 761 } 762 }, 763 764 /** 765 * Initializes module animations. 766 * 767 * @since 1.1.9 768 * @access private 769 * @method _initModuleAnimations 770 */ 771 _initModuleAnimations: function() 772 { 773 if(typeof jQuery.fn.waypoint !== 'undefined' && !FLBuilderLayout._isMobile()) { 774 $('.fl-animation').each( function() { 775 var node = $( this ), 776 nodeTop = node.offset().top, 777 winHeight = $( window ).height(), 778 bodyHeight = $( 'body' ).height(), 779 offset = '80%'; 780 781 if ( bodyHeight - nodeTop < winHeight * 0.2 ) { 782 offset = '100%'; 783 } 784 785 node.waypoint({ 786 offset: offset, 787 handler: FLBuilderLayout._doModuleAnimation 788 }); 789 } ); 790 } 791 }, 792 793 /** 794 * Runs a module animation. 795 * 796 * @since 1.1.9 797 * @access private 798 * @method _doModuleAnimation 799 */ 800 _doModuleAnimation: function() 801 { 802 var module = 'undefined' == typeof this.element ? $(this) : $(this.element), 803 delay = parseFloat(module.data('animation-delay')); 804 805 if(!isNaN(delay) && delay > 0) { 806 setTimeout(function(){ 807 module.addClass('fl-animated'); 808 }, delay * 1000); 809 } 810 else { 811 module.addClass('fl-animated'); 812 } 813 }, 814 815 /** 816 * Opens a tab or accordion item if the browser hash is set 817 * to the ID of one on the page. 818 * 819 * @since 1.6.0 820 * @access private 821 * @method _initHash 822 */ 823 _initHash: function() 824 { 825 var hash = window.location.hash.replace( '#', '' ).split( '/' ).shift(), 826 element = null, 827 tabs = null, 828 responsiveLabel = null, 829 tabIndex = null, 830 label = null; 831 832 if ( '' !== hash ) { 833 834 try { 835 836 element = $( '#' + hash ); 837 838 if ( element.length > 0 ) { 839 840 if ( element.hasClass( 'fl-accordion-item' ) ) { 841 setTimeout( function() { 842 element.find( '.fl-accordion-button' ).trigger( 'click' ); 843 }, 100 ); 844 } 845 if ( element.hasClass( 'fl-tabs-panel' ) ) { 846 847 setTimeout( function() { 848 849 tabs = element.closest( '.fl-tabs' ); 850 responsiveLabel = element.find( '.fl-tabs-panel-label' ); 851 tabIndex = responsiveLabel.data( 'index' ); 852 label = tabs.find( '.fl-tabs-labels .fl-tabs-label[data-index=' + tabIndex + ']' ); 853 854 if ( responsiveLabel.is( ':visible' ) ) { 855 responsiveLabel.trigger( 'click' ); 856 } 857 else { 858 label[0].click(); 859 FLBuilderLayout._scrollToElement( element ); 860 } 861 862 }, 100 ); 863 } 864 } 865 } 866 catch( e ) {} 867 } 868 }, 869 870 /** 871 * Initializes all anchor links on the page for smooth scrolling. 872 * 873 * @since 1.4.9 874 * @access private 875 * @method _doModuleAnimation 876 */ 877 _initAnchorLinks: function() 878 { 879 $( 'a' ).each( FLBuilderLayout._initAnchorLink ); 880 }, 881 882 /** 883 * Initializes a single anchor link for smooth scrolling. 884 * 885 * @since 1.4.9 886 * @access private 887 * @method _doModuleAnimation 888 */ 889 _initAnchorLink: function() 890 { 891 var link = $( this ), 892 href = link.attr( 'href' ), 893 loc = window.location, 894 id = null, 895 element = null; 896 897 if ( 'undefined' != typeof href && href.indexOf( '#' ) > -1 ) { 898 899 if ( loc.pathname.replace( /^\//, '' ) == this.pathname.replace( /^\//, '' ) && loc.hostname == this.hostname ) { 900 901 try { 902 903 id = href.split( '#' ).pop(); 904 // If there is no ID then we have nowhere to look 905 // Fixes a quirk in jQuery and FireFox 906 if( ! id ) { 907 return; 908 } 909 element = $( '#' + id ); 910 911 if ( element.length > 0 ) { 912 if ( link.hasClass( 'fl-scroll-link' ) || element.hasClass( 'fl-row' ) || element.hasClass( 'fl-col' ) || element.hasClass( 'fl-module' ) ) { 913 $( link ).on( 'click', FLBuilderLayout._scrollToElementOnLinkClick ); 914 } 915 if ( element.hasClass( 'fl-accordion-item' ) ) { 916 $( link ).on( 'click', FLBuilderLayout._scrollToAccordionOnLinkClick ); 917 } 918 if ( element.hasClass( 'fl-tabs-panel' ) ) { 919 $( link ).on( 'click', FLBuilderLayout._scrollToTabOnLinkClick ); 920 } 921 } 922 } 923 catch( e ) {} 924 } 925 } 926 }, 927 928 /** 929 * Scrolls to an element when an anchor link is clicked. 930 * 931 * @since 1.4.9 932 * @access private 933 * @method _scrollToElementOnLinkClick 934 * @param {Object} e An event object. 935 * @param {Function} callback A function to call when the scroll is complete. 936 */ 937 _scrollToElementOnLinkClick: function( e, callback ) 938 { 939 var element = $( '#' + $( this ).attr( 'href' ).split( '#' ).pop() ); 940 941 FLBuilderLayout._scrollToElement( element, callback ); 942 943 e.preventDefault(); 944 }, 945 946 /** 947 * Scrolls to an element. 948 * 949 * @since 1.6.4.5 950 * @access private 951 * @method _scrollToElement 952 * @param {Object} element The element to scroll to. 953 * @param {Function} callback A function to call when the scroll is complete. 954 */ 955 _scrollToElement: function( element, callback ) 956 { 957 var config = FLBuilderLayoutConfig.anchorLinkAnimations, 958 dest = 0, 959 win = $( window ), 960 doc = $( document ); 961 962 if ( element.length > 0 ) { 963 964 if ( element.offset().top > doc.height() - win.height() ) { 965 dest = doc.height() - win.height(); 966 } 967 else { 968 dest = element.offset().top - config.offset; 969 } 970 971 $( 'html, body' ).animate( { scrollTop: dest }, config.duration, config.easing, function() { 972 973 if ( 'undefined' != typeof callback ) { 974 callback(); 975 } 976 977 if ( undefined != element.attr( 'id' ) ) { 978 979 if ( history.pushState ) { 980 history.pushState( null, null, '#' + element.attr( 'id' ) ); 981 } 982 else { 983 window.location.hash = element.attr( 'id' ); 984 } 985 } 986 } ); 987 } 988 }, 989 990 /** 991 * Scrolls to an accordion item when a link is clicked. 992 * 993 * @since 1.5.9 994 * @access private 995 * @method _scrollToAccordionOnLinkClick 996 * @param {Object} e An event object. 997 */ 998 _scrollToAccordionOnLinkClick: function( e ) 999 { 1000 var element = $( '#' + $( this ).attr( 'href' ).split( '#' ).pop() ); 1001 1002 if ( element.length > 0 ) { 1003 1004 var callback = function() { 1005 if ( element ) { 1006 element.find( '.fl-accordion-button' ).trigger( 'click' ); 1007 element = false;
1008 } 1009 }; 1010 1011 FLBuilderLayout._scrollToElementOnLinkClick.call( this, e, callback ); 1012 } 1013 }, 1014 1015 /** 1016 * Scrolls to a tab panel when a link is clicked. 1017 * 1018 * @since 1.5.9 1019 * @access private 1020 * @method _scrollToTabOnLinkClick 1021 * @param {Object} e An event object. 1022 */ 1023 _scrollToTabOnLinkClick: function( e ) 1024 { 1025 var element = $( '#' + $( this ).attr( 'href' ).split( '#' ).pop() ), 1026 tabs = null, 1027 label = null, 1028 responsiveLabel = null; 1029 1030 if ( element.length > 0 ) { 1031 1032 tabs = element.closest( '.fl-tabs' ); 1033 responsiveLabel = element.find( '.fl-tabs-panel-label' ); 1034 tabIndex = responsiveLabel.data( 'index' ); 1035 label = tabs.find( '.fl-tabs-labels .fl-tabs-label[data-index=' + tabIndex + ']' ); 1036 1037 if ( responsiveLabel.is( ':visible' ) ) { 1038 1039 var callback = function() { 1040 if ( element ) { 1041 responsiveLabel.trigger( 'click' ); 1042 element = false; 1043 } 1044 }; 1045 1046 FLBuilderLayout._scrollToElementOnLinkClick.call( this, e, callback ); 1047 } 1048 else { 1049 label[0].click(); 1050 FLBuilderLayout._scrollToElement( element ); 1051 } 1052 1053 e.preventDefault(); 1054 } 1055 }, 1056 1057 /** 1058 * Initializes all builder forms on a page. 1059 * 1060 * @since 1.5.4 1061 * @access private 1062 * @method _initForms 1063 */ 1064 _initForms: function() 1065 { 1066 if ( ! FLBuilderLayout._hasPlaceholderSupport ) { 1067 $( '.fl-form-field input' ).each( FLBuilderLayout._initFormFieldPlaceholderFallback ); 1068 } 1069 1070 $( '.fl-form-field input' ).on( 'focus', FLBuilderLayout._clearFormFieldError ); 1071 }, 1072 1073 /** 1074 * Checks to see if the current device has HTML5 1075 * placeholder support. 1076 * 1077 * @since 1.5.4 1078 * @access private 1079 * @method _hasPlaceholderSupport 1080 * @return {Boolean} 1081 */ 1082 _hasPlaceholderSupport: function() 1083 { 1084 var input = document.createElement( 'input' ); 1085 1086 return 'undefined' != input.placeholder; 1087 }, 1088 1089 /** 1090 * Initializes the fallback for when placeholders aren't supported. 1091 * 1092 * @since 1.5.4 1093 * @access private 1094 * @method _initFormFieldPlaceholderFallback 1095 */ 1096 _initFormFieldPlaceholderFallback: function() 1097 { 1098 var field = $( this ), 1099 val = field.val(), 1100 placeholder = field.attr( 'placeholder' ); 1101 1102 if ( 'undefined' != placeholder && '' === val ) { 1103 field.val( placeholder ); 1104 field.on( 'focus', FLBuilderLayout._hideFormFieldPlaceholderFallback ); 1105 field.on( 'blur', FLBuilderLayout._showFormFieldPlaceholderFallback ); 1106 } 1107 }, 1108 1109 /** 1110 * Hides a fallback placeholder on focus. 1111 * 1112 * @since 1.5.4 1113 * @access private 1114 * @method _hideFormFieldPlaceholderFallback 1115 */ 1116 _hideFormFieldPlaceholderFallback: function() 1117 { 1118 var field = $( this ), 1119 val = field.val(), 1120 placeholder = field.attr( 'placeholder' ); 1121 1122 if ( val == placeholder ) { 1123 field.val( '' ); 1124 } 1125 }, 1126 1127 /** 1128 * Shows a fallback placeholder on blur. 1129 * 1130 * @since 1.5.4 1131 * @access private 1132 * @method _showFormFieldPlaceholderFallback 1133 */ 1134 _showFormFieldPlaceholderFallback: function() 1135 { 1136 var field = $( this ), 1137 val = field.val(), 1138 placeholder = field.attr( 'placeholder' ); 1139 1140 if ( '' === val ) { 1141 field.val( placeholder ); 1142 } 1143 }, 1144 1145 /** 1146 * Clears a form field error message. 1147 * 1148 * @since 1.5.4 1149 * @access private 1150 * @method _clearFormFieldError 1151 */ 1152 _clearFormFieldError: function() 1153 { 1154 var field = $( this ); 1155 1156 field.removeClass( 'fl-form-error' ); 1157 field.siblings( '.fl-form-error-message' ).hide(); 1158 } 1159 }; 1160 1161 /* Initializes the builder layout. */ 1162 $(function(){ 1163 FLBuilderLayout.init(); 1164 }); 1165 1166})(jQuery);
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.