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