PageSourceSearch

https://praschberger.com/wp-content/uploads/bb-plugin/cache/716fbc…c9d144687-layout-bundle.js?ver=2.11.1-1.6.1

js praschberger.com collected 2026-10-02 20:16:44 UTC 126,066 bytes, 4,194 lines download raw bytes

vendor: 14,874 bytes, lines 1-513
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});
622
623;(function($) {
624
625	PPAdvancedMenu = function( settings ) {
626
627		// set params
628		this.settingsId 		 = settings.id;
629		this.nodeClass           = '.fl-node-' + settings.id;
630		this.wrapperClass        = this.nodeClass + ' .pp-advanced-menu';
631		this.type				 = settings.type;
632		this.mobileToggle		 = settings.mobile;
633		this.mobileBelowRow		 = 'below' === settings.menuPosition;
634		this.breakpoints         = settings.breakpoints;
635		this.mobileBreakpoint	 = settings.mobileBreakpoint;
636		this.mediaBreakpoint	 = settings.mediaBreakpoint;
637		this.mobileMenuType	 	 = settings.mobileMenuType;
638		this.offCanvasDirection	 = settings.offCanvasDirection;
639		this.postId 			 = bb_powerpack.post_id;
640		this.isBuilderActive	 = settings.isBuilderActive;
641		this.currentBrowserWidth = window.innerWidth;
642		this.fullScreenMenu 	= null;
643		this.offCanvasMenu 		= null;
644		this.$submenus 			= null;
645
646		// initialize the menu
647		$( this._initMenu.bind( this ) );
648
649		// check if viewport is resizing
650		$( window ).on( 'resize', function( e ) {
651
652			var width = window.innerWidth;
653
654			// if screen width is resized, reload the menu
655		    if( width != this.currentBrowserWidth ) {
656
657				this._initMenu();
658 				this._clickOrHover();
659		    	this.currentBrowserWidth = width;
660			}
661
662		}.bind( this ) );
663
664		$( 'body' ).on( 'click', function( e ) {
665			if ( 'undefined' !== typeof FLBuilderConfig ){
666				return;
667			}
668
669			if ( $( this.wrapperClass ).find( '.pp-advanced-menu-mobile-toggle' ).hasClass( 'pp-active' ) && ( 'expanded' !== this.mobileToggle ) ) {
670				if ( $( e.target ).parents('.fl-module-pp-advanced-menu').length > 0 ) {
671					return;
672				}
673				if ( $( e.target ).is( 'input' ) && $( e.target ).parents('.pp-advanced-menu').length > 0 ) {
674					return;
675				}
676				if ( $( e.target ).hasClass( 'pp-menu-close-btn' ) ) {
677					return;
678				}
679				$( this.wrapperClass ).find( '.pp-advanced-menu-mobile-toggle' ).trigger( 'click' );
680			}
681
682			$( this.wrapperClass ).find( '.pp-has-submenu' ).each( function() {
683				if ( ! $( this ).find( '> .sub-menu' ).is( ':visible' ) ) {
684					$( this ).removeClass( 'pp-active' );
685				}
686			} );
687			$( this.wrapperClass ).find( '.pp-has-submenu' ).removeClass( 'focus' );
688			$( this.wrapperClass ).find( '.pp-has-submenu .sub-menu' ).removeClass( 'focus' );
689			$( this.wrapperClass ).find( '.pp-has-submenu-container' ).removeClass( 'focus' );
690			$( this.wrapperClass ).find( '.pp-menu-toggle' ).attr( 'aria-expanded', false );
691
692		}.bind( this ) );
693
694		// Esc key to close the submenu.
695		$( document ).on( 'keyup', function( e ) {
696			if ( 27 == e.which ) {
697				$( this.wrapperClass ).find( '.pp-has-submenu' ).each( function() {
698					if ( ! $( this ).find( '> .sub-menu' ).is( ':visible' ) ) {
699						$( this ).removeClass( 'pp-active' );
700					}
701				} );
702				$( this.wrapperClass ).find( '.pp-has-submenu' ).removeClass( 'focus' );
703				$( this.wrapperClass ).find( '.pp-has-submenu .sub-menu' ).removeClass( 'focus' );
704				$( this.wrapperClass ).find( '.pp-has-submenu-container' ).removeClass( 'focus' );
705				$( this.wrapperClass ).find( '.pp-menu-toggle' ).attr( 'aria-expanded', false );
706				if ( $( this.wrapperClass ).find( '.pp-menu-toggle.focus' ).is( ':visible' ) ) {
707					$( this.wrapperClass ).find( '.pp-menu-toggle.focus' ).delay(100).trigger( 'focus' );
708				}
709			}
710		}.bind( this ) );
711
712	};
713
714	PPAdvancedMenu.prototype = {
715		nodeClass               : '',
716		wrapperClass            : '',
717		type 	                : '',
718		breakpoints 			: {},
719		$submenus				: null,
720		fullScreenMenu			: null,
721		offCanvasMenu			: null,
722
723		/**
724		 * Check if the screen size fits a mobile viewport.
725		 *
726		 * @since  1.6.1
727		 * @return bool
728		 */
729		_isMobile: function() {
730			return window.innerWidth <= this.breakpoints.small ? true : false;
731		},
732
733		/**
734		 * Check if the screen size fits a medium viewport.
735		 *
736		 * @since  1.10.5
737		 * @return bool
738		 */
739		_isMedium: function() {
740			return window.innerWidth <= this.breakpoints.medium ? true : false;
741		},
742
743		/**
744		 * Check if the screen size fits a large viewport.
745		 *
746		 * @since  1.10.5
747		 * @return bool
748		 */
749		_isLarge: function() {
750			return window.innerWidth <= this.breakpoints.large ? true : false;
751		},
752
753		/**
754		 * Check if the screen size fits a custom viewport.
755		 *
756		 * @since  1.10.5
757		 * @return bool
758		 */
759		_isCustom: function() {
760			return window.innerWidth <= this.breakpoints.custom ? true : false;
761		},
762
763		_isTouch: function() {
764			var prefixes = ' -webkit- -moz- -o- -ms- '.split(' ');
765			var mq = function(query) {
766			  return window.matchMedia(query).matches;
767			}
768		  
769			if (('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch) {
770			  return true;
771			}
772		  
773			// include the 'heartz' as a way to have a non matching MQ to help terminate the join
774			// https://git.io/vznFH
775			var query = ['(', prefixes.join('touch-enabled),('), 'heartz', ')'].join('');
776			return mq(query);
777		},
778
779		_isIOS: function() {
780			return [
781				'iPad Simulator',
782				'iPhone Simulator',
783				'iPod Simulator',
784				'iPad',
785				'iPhone',
786				'iPod'
787			].includes(navigator.platform) 
788			// This explicitly catches modern iPads mimicking desktop Macs:
789			|| (navigator.userAgent.includes("Mac") && navigator.maxTouchPoints > 1);
790		},
791
792		/**
793		 * Check if the menu should toggle for the current viewport base on the selected breakpoint
794		 *
795		 * @see 	this._isMobile()
796		 * @see 	this._isMedium()
797		 * @since  	1.10.5
798		 * @return bool
799		 */
800		_isMenuToggle: function() {
801			if ( ( 'always' == this.mobileBreakpoint
802				|| ( this._isMobile() && 'mobile' == this.mobileBreakpoint )
803				|| ( this._isMedium() && 'medium-mobile' == this.mobileBreakpoint )
804				|| ( this._isCustom() && 'custom' == this.mobileBreakpoint )
805				) && ( $( this.nodeClass ).find( '.pp-advanced-menu-mobile-toggle' ).is(':visible') || 'expanded' == this.mobileToggle ) ) {
806				return true;
807			}
808
809			return false;
810		},
811
812		_bindSettingsFormEvents: function()
813		{
814			// $('body').on( 'change', '.fl-builder-settings select[name="offcanvas_direction"]', function() {
815			// 	$('html').removeClass('pp-off-canvas-menu-open');
816			// } );
817		},
818
819		/**
820		 * Initialize the toggle logic for the menu.
821		 *
822		 * @see    this._isMobile()
823		 * @see    this._menuOnCLick()
824		 * @see    this._clickOrHover()
825		 * @see    this._submenuOnRight()
826		 * @see    this._submenuRowZindexFix()
827		 * @see    this._toggleForMobile()
828		 * @since  1.6.1
829		 * @return void
830		 */
831		_initMenu: function() {
832			if ( this.mobileToggle != 'expanded' ) {
833				this._initOffCanvas();
834				this._initFullScreen();
835			}
836
837			this._setupSubmenu();
838			this._menuOnHover();
839			this._menuOnFocus();
840			this._submenuOnClick();
841
842			if ( $( this.nodeClass ).length && this.type == 'horizontal' ) {
843				this._initMegaMenus();
844			}
845
846			if ( this.type == 'horizontal' || this.type == 'vertical' ) {
847				var self = this;
848				$( this.wrapperClass ).find('.pp-has-submenu-container').on( 'click', function( e ) {
849					if ( self.mobileMenuType !== 'off-canvas' && self.mobileMenuType !== 'full-screen' ) {
850						if ( self._isTouch() ) {
851							if ( ! $(this).hasClass('first-click') ) {
852								e.preventDefault();
853								$(this).addClass('first-click');
854							}
855						}
856					}
857				} );
858
859				// Keyboard nav support for submenu toggle.
860				$( this.wrapperClass ).on( 'keydown.pp-menu', 'a, .pp-has-submenu-container > .pp-menu-toggle', function(e) {
861					var $current = $(e.target);
862
863					var key = e.key || e.which;
864
865					// Normalize keys
866					var KEYS = {
867						LEFT: 'ArrowLeft',
868						RIGHT: 'ArrowRight',
869						UP: 'ArrowUp',
870						DOWN: 'ArrowDown',
871						ENTER: 'Enter',
872						SPACE: ' ',
873					};
874
875					function isKey(match) {
876						return key === match || key === {
877							ArrowLeft: 37,
878							ArrowUp: 38,
879							ArrowRight: 39,
880							ArrowDown: 40,
881							Enter: 13,
882							' ': 32
883						}[match];
884					}
885
886					var $item = $current.closest('li');
887					var $parentItem = $current.closest('li.pp-has-submenu');
888					var $submenu = $current.closest('ul.sub-menu');
889					var isTopLevel = $current.closest('.sub-menu').length === 0;
890
891					/* =========================
892					TOGGLE HANDLING
893					========================= */
894
895					function toggleSubmenu($el) {
896						var $li = $el.closest('li.pp-has-submenu');
897						var $btn = $li.find('> .pp-has-submenu-container > .pp-menu-toggle');
898
899						$li.toggleClass('pp-active');
900
901						var isOpen = $li.hasClass('pp-active');
902
903						if ($btn.length) {
904							$btn.attr('aria-expanded', isOpen);
905						}
906					}
907
908					// Button toggle
909					if ($current.hasClass('pp-menu-toggle')) {
910						if (isKey(KEYS.ENTER) || isKey(KEYS.SPACE)) {
911							e.preventDefault();
912							e.stopPropagation();
913							toggleSubmenu($current);
914							return;
915						}
916					}
917
918					/* =========================
919					TOP LEVEL NAV (← →)
920					========================= */
921
922					if (isTopLevel && (isKey(KEYS.LEFT) || isKey(KEYS.RIGHT))) {
923						e.preventDefault();
924						e.stopPropagation();
925
926						if (isKey(KEYS.LEFT)) {
927							if ( $current.is( '.pp-menu-toggle' ) ) {
928								$current.prev('a').focus();
929							} else {
930								var $prev = $item.prev();
931								if ($prev.length) {
932									var $target = $prev.find('> .pp-has-submenu-container > .pp-menu-toggle:visible');
933									($target.length ? $target : $prev.find('a')).first().focus();
934								}
935							}
936						}
937
938						if (isKey(KEYS.RIGHT)) {
939							if ( $current.next().is( '.pp-menu-toggle:visible' ) ) {
940								$current.next().focus();
941							} else {
942								var $next = $item.next();
943								if ($next.length) {
944									$next.find('a').first().focus();
945								}
946							}
947						}
948
949						return;
950					}
951
952					// NESTED submenu navigation (LEFT / RIGHT)
953					if (!isTopLevel && (isKey(KEYS.RIGHT) || isKey(KEYS.LEFT))) {
954
955						var $parentItem = $current.closest('li.pp-has-submenu');
956
957						// RIGHT → go into child submenu
958						if (isKey(KEYS.RIGHT)) {
959							var $childSubmenu = $parentItem.children('.sub-menu');
960
961							if ($childSubmenu.length) {
962								e.preventDefault();
963								e.stopPropagation();
964
965								// Ensure open state
966								$parentItem.addClass('pp-active');
967
968								var $toggle = $parentItem.find('> .pp-has-submenu-container > .pp-menu-toggle:visible');
969								if ($toggle.length) {
970									$toggle.attr('aria-expanded', true);
971								} else {
972									$parentItem.find('> .pp-has-submenu-container > a').attr('aria-expanded', true);
973								}
974
975								// Focus first item in child submenu
976								$childSubmenu.find('a, .pp-menu-toggle:visible').first().focus();
977							}
978							return;
979						}
980
981						// LEFT ← go back to parent menu item
982						if (isKey(KEYS.LEFT)) {
983							var $currentSubmenu = $current.closest('ul.sub-menu');
984							var $parentItem = $currentSubmenu.parent('li');
985
986							if ($parentItem.length) {
987								e.preventDefault();
988								e.stopPropagation();
989
990								// CLOSE submenu
991								$parentItem.removeClass('pp-active');
992
993								var $toggle = $parentItem.find('> .pp-has-submenu-container > .pp-menu-toggle:visible');
994
995								if ($toggle.length) {
996									$toggle.attr('aria-expanded', false);
997									$toggle.focus();
998								} else {
999									$parentItem.find('> .pp-has-submenu-container > a').attr('aria-expanded', false).focus();
1000								}
1001							}
1002							return;
1003						}
1004					}
1005
1006					/* =========================
1007					SUBMENU NAV (↑ ↓)
1008					========================= */
1009
1010					// DOWN from toggle → first submenu item
1011					if (isKey(KEYS.DOWN) && isTopLevel && $parentItem.length) {
1012						e.preventDefault();
1013    					e.stopPropagation();
1014
1015						var $submenu = $parentItem.children('.sub-menu');
1016
1017						if ($submenu.length) {
1018							// ensure open state
1019							if (!$parentItem.hasClass('pp-active')) {
1020								$parentItem.addClass('pp-active');
1021
1022								var $toggle = $parentItem.find('> .pp-has-submenu-container > .pp-menu-toggle:visible');
1023								if ($toggle.length) {
1024									$toggle.attr('aria-expanded', true);
1025								} else {
1026									$parentItem.find('> .pp-has-submenu-container > a').attr('aria-expanded', true);
1027								}
1028							}
1029
1030							// move focus into submenu
1031							$submenu.find('a, .pp-menu-toggle:visible').first().focus();
1032						}
1033
1034						return;
1035					}
1036
1037					if (!$submenu.length) {
1038						return;
1039					}
1040
1041					var $items = $submenu.find('a, .pp-menu-toggle').filter(':visible');
1042					var index = $items.index($current);
1043
1044					if (index === -1) return;
1045
1046					// DOWN ↓
1047					if (isKey(KEYS.DOWN)) {
1048						e.preventDefault();
1049						e.stopPropagation();
1050
1051						var next = index + 1; 
1052						if (next < $items.length) {
1053							$items.eq(next).focus();
1054						}
1055						return;
1056					}
1057
1058					// UP ↑
1059					if (isKey(KEYS.UP)) {
1060						e.preventDefault();
1061						e.stopPropagation();
1062
1063						if (index === 0 && ! $current.closest('.sub-menu').parents('.sub-menu').length) {
1064							var $currentSubmenu = $current.closest('ul.sub-menu');
1065							var $parentItem = $currentSubmenu.parent('li');
1066							var $toggle = $parentItem.find('> .pp-has-submenu-container > .pp-menu-toggle:visible');
1067							if ($toggle.length) {
1068								$toggle.focus();
1069							} else {
1070								$parentItem.find('> .pp-has-submenu-container > a').focus();
1071							}
1072							return;
1073						}
1074
1075						// Don't loop back to the last item if we're on the first item of a submenu
1076						if ( index === 0 ) {
1077							$items.eq(index).focus();
1078							return;
1079						}
1080
1081						$items.eq(index - 1).focus();
1082						return;
1083					}
1084
1085				}.bind( this ) );
1086			}
1087
1088			if ( this._isMenuToggle() || this.type == 'accordion' ) {
1089				$( this.wrapperClass ).off( 'mouseenter mouseleave' );
1090				this._menuOnClick();
1091				this._clickOrHover();
1092			} else {
1093				$( this.wrapperClass ).off( 'click' );
1094				this._submenuOnRight();
1095				this._submenuRowZindexFix();
1096			}
1097
1098			if ( this.mobileToggle != 'expanded' ) {
1099				this._toggleForMobile();
1100			}
1101
1102			$(this.wrapperClass).find('li:not(.menu-item-has-children)').on('click', 'a', function (e) {
1103				if ( $(e.target).closest( '.pp-menu-search-item' ).length > 0 ) {
1104					return;
1105				}
1106
1107				$(this.nodeClass).find('.pp-advanced-menu').removeClass('menu-open');
1108				$(this.nodeClass).find('.pp-advanced-menu').addClass('menu-close');
1109				$('html').removeClass('pp-off-canvas-menu-open');
1110				$('html').removeClass('pp-full-screen-menu-open');
1111
1112			}.bind( this ) );
1113
1114			if ( $( this.wrapperClass ).find( '.pp-menu-search-item' ).length ) {
1115				this._toggleMenuSearch();
1116			}
1117
1118			if ( $( this.wrapperClass ).find( '.pp-menu-cart-item').length ) {
1119				this._wooUpdateParams();
1120			}
1121		},
1122
1123		/**
1124		 * Initializes submenu dropdowns.
1125		 *
1126		 * @since 2.33.x
1127		 * @return void
1128		 */
1129		_setupSubmenu: function() {
1130			// $( this.wrapperClass + ' ul.sub-menu' ).each( function(){
1131			// 	$( this ).closest( 'li' ).attr( 'aria-haspopup', 'true' );
1132			// });
1133		},
1134
1135		_menuOnHover: function() {
1136			$( this.wrapperClass ).on( 'mouseenter', 'li.menu-item', function() {
1137				$(this).addClass( 'hover' );
1138			} ).on( 'mouseleave', 'li.menu-item', function() {
1139				$(this).removeClass( 'hover' );
1140			} );
1141		},
1142
1143		/**
1144		 * Adds a focus class to menu elements similar to be used similar to CSS :hover psuedo event
1145		 *
1146		 * @since  1.9.0
1147		 * @return void
1148		 */
1149		_menuOnFocus: function() {
1150			$( this.nodeClass ).off('focus', 'a').on( 'focus', 'a', function( e ) {
1151				var $menuItem	= $( e.target ).parents( '.menu-item' ).first(),
1152					$parents	= $( e.target ).parentsUntil( this.wrapperClass );
1153
1154				$('.pp-advanced-menu .focus:not(.pp-menu-toggle)').removeClass('focus');
1155
1156				$menuItem.addClass('focus');
1157				$parents.addClass('focus');
1158
1159			}.bind( this ) ).on( 'focusout', 'a', function( e ) {
1160				if ( $('.pp-advanced-menu .focus').hasClass('pp-has-submenu') ) {
1161					$( e.target ).parentsUntil( this.wrapperClass ).find('.pp-has-submenu-container').removeClass('first-click');
1162				}
1163			}.bind( this ) );
1164
1165			$( this.nodeClass ).off('focus', '.pp-menu-toggle').on( 'focus', '.pp-menu-toggle', function( e ) {
1166				$(e.target).addClass( 'focus' );
1167			}.bind( this ) ).off('blur', '.pp-menu-toggle').on( 'blur', '.pp-menu-toggle', function( e ) {
1168				if ( $(e.target).parents( 'li.pp-has-submenu.pp-active' ).length === 0 || $(e.target).parents( 'li.pp-has-submenu.pp-active' ).parent( 'ul.menu' ).length === 0 ) {
1169					$(e.target).removeClass( 'focus' );
1170				}
1171			}.bind( this ) );
1172		},
1173
1174		/**
1175		 * Logic for submenu toggling on accordions or mobile menus (vertical, horizontal)
1176		 *
1177		 * @since  1.6.1
1178		 * @return void
1179		 */
1180		_menuOnClick: function() {
1181			var self = this;
1182			var $mainItem = '';
1183
1184			$( this.wrapperClass )
1185				.off( 'click.pp-advanced-menu keyup', '.pp-has-submenu-container' )
1186				.on( 'click.pp-advanced-menu keyup', '.pp-has-submenu-container', function( e ) {
1187				var isValidEvent = e.which == 1 || e.which == 13 || e.which == undefined; // click or enter key press.
1188				if ( ! isValidEvent ) {
1189					return;
1190				}
1191				if ( e.which == 13 && ! $(e.target).hasClass( 'pp-menu-toggle' ) ) { // prevent event bubbling.
1192					return;
1193				}
1194				if ( self._isTouch() ) {
1195					if ( ! $(this).hasClass('first-click') ) {
1196						e.preventDefault();
1197						$(this).addClass('first-click');
1198					}
1199				}
1200
1201				e.stopPropagation();
1202
1203				var isMainEl = $(e.target).parents('.menu-item').parent().parent().hasClass('pp-advanced-menu');
1204
1205				if (isMainEl && $mainItem === '') {
1206					$mainItem = $(e.target).parents('.menu-item');
1207				}
1208
1209				var $link			= $( e.target ).parents( '.pp-has-submenu' ).first(),
1210					$subMenu 		= $link.children( '.sub-menu' ).first(),
1211					$href	 		= $link.children('.pp-has-submenu-container').first().find('> a').attr('href'),
1212					$subMenuParents = $( e.target ).parents( '.sub-menu' ),
1213					$activeParent 	= $( e.target ).closest( '.pp-has-submenu.pp-active' );
1214
1215					if ( $activeParent.length > 0 ) {
1216						$activeParent.find( '.pp-menu-toggle' ).first().attr('aria-expanded', true);
1217					} else {
1218						$activeParent.find( '.pp-menu-toggle' ).first().attr('aria-expanded', false);
1219					}
1220
1221				if( !$subMenu.is(':visible') || $(e.target).hasClass('pp-menu-toggle')
1222					|| ($subMenu.is(':visible') && (typeof $href === 'undefined' || $href == '#')) ) {
1223					if ( ! $(this.wrapperClass).hasClass('pp-advanced-menu-accordion-collapse') ) {
1224						e.preventDefault();
1225					}
1226					if ( $(e.target).hasClass('pp-menu-toggle') ) {
1227						e.stopPropagation();
1228						e.preventDefault();
1229					}
1230				}
1231				else {
1232					e.stopPropagation();
1233					window.location.href = $href;
1234					return;
1235				}
1236
1237				if ($(this.wrapperClass).hasClass('pp-advanced-menu-accordion-collapse')) {
1238
1239					if ( $link.parents('.menu-item').length && !$link.parents('.menu-item').hasClass('pp-active') ) {
1240						$('.menu .pp-active', this.wrapperClass).not($link).removeClass('pp-active');
1241					}
1242					else if ($link.parents('.menu-item').hasClass('pp-active') && $link.parent('.sub-menu').length) {
1243						$('.menu .pp-active', this.wrapperClass).not($link).not($activeParent).removeClass('pp-active');
1244					}
1245
1246					$('.sub-menu', this.wrapperClass).not($subMenu).not($subMenuParents).slideUp('normal');
1247				}
1248
1249				// Parent menu toggle icon was being reversed on collapsing its submenu,
1250				// so here is the workaround to fix this behavior.
1251				if ($(self.wrapperClass).find('.sub-menu:visible').length > 0) {
1252					$(self.wrapperClass).find('.sub-menu:visible').parent().addClass('pp-active');
1253				}
1254				$subMenu.slideToggle(400, function() {
1255					// Reset previously opened sub-menu toggle icon.
1256					$(e.target).parents('.pp-has-submenu-container').parent().parent().find('> .menu-item.pp-active').removeClass('pp-active');
1257					
1258					if ($mainItem !== '') {
1259						$mainItem.parent().find('.menu-item.pp-active').removeClass('pp-active');
1260						$(self.wrapperClass).find('.sub-menu').parent().removeClass('pp-active');
1261
1262						if ($(self.wrapperClass).find('.sub-menu:visible').length > 0) {
1263							$(self.wrapperClass).find('.sub-menu:visible').parent().addClass('pp-active');
1264						} else {
1265							$link.toggleClass('pp-active');
1266							$mainItem.removeClass('pp-active');
1267						}
1268					} else {
1269						$link.toggleClass('pp-active');
1270					}
1271					if (!$subMenu.is(':visible')) {
1272						$subMenu.parent().removeClass('pp-active');
1273						$subMenu.parent().find('> .p
1273p-has-submenu-container .pp-menu-toggle').attr('aria-expanded', false);
1274					} else {
1275						$subMenu.parent().find('> .pp-has-submenu-container .pp-menu-toggle').attr('aria-expanded', true);
1276					}
1277				});
1278
1279			}.bind( this ) );
1280
1281		},
1282
1283		/**
1284		 * Logic for submenu items click event
1285		 *
1286		 * @since  1.3.1
1287		 * @return void
1288		 */
1289		_submenuOnClick: function(){
1290			$( 'body' ).off( 'click', this.wrapperClass + ' .sub-menu a' ).on( 'click', this.wrapperClass + ' .sub-menu a', function( e ){
1291				if ( $( e.target ).parent().hasClass('focus') ) {
1292					$( e.target ).parentsUntil( this.wrapperClass ).removeClass( 'focus' );
1293				}
1294			}.bind( this ) );
1295		},
1296
1297		/**
1298		 * Changes general styling and behavior of menus based on mobile / desktop viewport.
1299		 *
1300		 * @see    this._isMobile()
1301		 * @since  1.6.1
1302		 * @return void
1303		 */
1304		_clickOrHover: function() {
1305			this.$submenus = this.$submenus || $( this.wrapperClass ).find( '.sub-menu' );
1306			var $wrapper   = $( this.wrapperClass ),
1307				$menu      = $wrapper.find( '.menu' );
1308				$li        = $wrapper.find( '.pp-has-submenu' );
1309
1310			if( this._isMenuToggle() ) {
1311				$li.each( function() {
1312					if( !$(this).hasClass('pp-active') ) {
1313						$(this).find( '.sub-menu' ).fadeOut();
1314					}
1315				} );
1316			} else {
1317				$li.each( function() {
1318					if( !$(this).hasClass('pp-active') ) {
1319						$(this).find( '.sub-menu' ).css( {
1320							'display' : '',
1321							'opacity' : ''
1322						} );
1323					}
1324				} );
1325			}
1326		},
1327
1328		/**
1329		 * Logic to prevent submenus to go outside viewport boundaries.
1330		 *
1331		 * @since  1.6.1
1332		 * @return void
1333		 */
1334		_submenuOnRight: function() {
1335
1336			$( this.wrapperClass )
1337				.on( 'mouseenter focus', '.pp-has-submenu', function( e ) {
1338
1339					if( $ ( e.currentTarget ).find('.sub-menu').length === 0 ) {
1340						return;
1341					}
1342
1343					var $link           = $( e.currentTarget ),
1344						$parent         = $link.parent(),
1345						$subMenu        = $link.find( '.sub-menu' ),
1346						subMenuWidth    = $subMenu.width(),
1347						subMenuPos      = 0,
1348						winWidth        = window.innerWidth;
1349
1350					if( $link.closest( '.pp-menu-submenu-right' ).length !== 0) {
1351
1352						$link.addClass( 'pp-menu-submenu-right' );
1353
1354					} else if( $( 'body' ).hasClass( 'rtl' ) ) {
1355
1356						subMenuPos = $parent.is( '.sub-menu' ) ?
1357									 $parent.offset().left - subMenuWidth:
1358									 $link.offset().left - subMenuWidth;
1359
1360						if( subMenuPos <= 0 ) {
1361							$link.addClass( 'pp-menu-submenu-right' );
1362						}
1363
1364					} else {
1365
1366						subMenuPos = $parent.is( '.sub-menu' ) ?
1367									 $parent.offset().left + $parent.width() + subMenuWidth :
1368									 $link.offset().left + subMenuWidth;
1369
1370						if( subMenuPos > winWidth ) {
1371							$link.addClass('pp-menu-submenu-right');
1372						}
1373					}
1374				}.bind( this ) )
1375				.on( 'mouseleave', '.pp-has-submenu', function( e ) {
1376					$( e.currentTarget ).removeClass( 'pp-menu-submenu-right' );
1377				}.bind( this ) );
1378
1379		},
1380
1381		/**
1382		 * Logic to prevent submenus to go behind the next overlay row.
1383		 *
1384		 * @since  2.2
1385		 * @return void
1386		 */
1387		_submenuRowZindexFix: function (e) {
1388
1389			$(this.wrapperClass)
1390				.on('mouseenter', 'ul.menu > .pp-has-submenu', function (e) {
1391
1392					if ($(e.currentTarget).find('.sub-menu').length === 0) {
1393						return;
1394					}
1395
1396					$(this.nodeClass)
1397						.closest('.fl-row')
1398						.find('.fl-row-content')
1399						.css('z-index', '10');
1400
1401				}.bind( this ) )
1402				.on('mouseleave', 'ul.menu > .pp-has-submenu', function (e) {
1403
1404					$(this.nodeClass)
1405						.closest('.fl-row')
1406						.find('.fl-row-content')
1407						.css('z-index', '');
1408
1409				}.bind( this ) );
1410		},
1411
1412		/**
1413		 * Logic for the mobile menu button.
1414		 *
1415		 * @since  1.6.1
1416		 * @return void
1417		 */
1418		_toggleForMobile: function() {
1419
1420			var $wrapper = null,
1421				$menu    = null,
1422				self 	 = this;
1423
1424			if ( this._isMenuToggle() ) {
1425				$wrapper = $(this.wrapperClass);
1426				if ( this._isMobileBelowRowEnabled() ) {
1427					this._placeMobileMenuBelowRow();
1428					$menu = $(this.nodeClass + '-clone');
1429					$menu.find('ul.menu').show();
1430				} else {
1431					$menu = $wrapper.find('.menu');
1432				}
1433
1434				if( !$wrapper.find( '.pp-advanced-menu-mobile-toggle' ).hasClass( 'pp-active' ) && this.mobileMenuType === 'default' ) {
1435					$menu.css({ display: 'none' });
1436				}
1437
1438				$wrapper
1439					.off( 'click.pp-mobile-menu-toggle', '.pp-advanced-menu-mobile-toggle' )
1440					.on( 'click.pp-mobile-menu-toggle', '.pp-advanced-menu-mobile-toggle', function( e ) {
1441						e.stopPropagation();
1442						$(this).toggleClass( 'pp-active' );
1443						if ( $(this).hasClass('pp-active') ) {
1444							$(this).attr('aria-expanded', 'true');
1445							$menu.addClass( 'pp-menu-visible' );
1446						} else {
1447							$(this).attr('aria-expanded', 'false');
1448							$menu.removeClass( 'pp-menu-visible' );
1449						}
1450						$menu.slideToggle();
1451				} );
1452
1453				$menu.on( 'click', '.menu-item > a[href*="#"]', function(e) {
1454					var $href = $(this).attr('href'),
1455						$targetID = '';
1456
1457					if ( $href !== '#' ) {
1458						$targetID = $href.split('#')[1];
1459
1460						if ( $('body').find('#'+  $targetID).length > 0 ) {
1461							e.preventDefault();
1462							$( this ).toggleClass( 'pp-active' );
1463							setTimeout(function() {
1464								$('html, body').animate({
1465									scrollTop: $('#'+ $targetID).offset().top
1466								}, 1000, function() {
1467									window.location.hash = $targetID;
1468								});
1469							}, 500);
1470
1471							if ( ! self._isMenuToggle() ) {
1472								$menu.slideToggle();
1473							}
1474						}
1475					}
1476				});
1477			}
1478			else {
1479
1480				if ( this._isMobileBelowRowEnabled() ) {
1481					this._removeMenuFromBelowRow();
1482				}
1483
1484				$wrapper = $( this.wrapperClass ),
1485				$menu    = $wrapper.children( '.menu' );
1486				$wrapper.find( '.pp-advanced-menu-mobile-toggle' ).removeClass( 'pp-active' );
1487				$menu.css({ display: '' });
1488			}
1489		},
1490
1491		/**
1492		 * Init any mega menus that exist.
1493		 *
1494		 * @see 	this._isMenuToggle()
1495		 * @since  	1.10.4
1496		 * @return void
1497		 */
1498		_initMegaMenus: function() {
1499
1500			var module     = $( this.nodeClass ),
1501				rowContent = module.closest( '.fl-row-content' ),
1502				rowWidth   = rowContent.width(),
1503				megas      = module.find( '.mega-menu' ),
1504				disabled   = module.find( '.mega-menu-disabled' ),
1505				isToggle   = this._isMenuToggle();
1506
1507			if ( isToggle ) {
1508				megas.removeClass( 'mega-menu' ).addClass( 'mega-menu-disabled' );
1509				module.find( 'li.mega-menu-disabled > ul.sub-menu' ).css( 'width', '' );
1510				rowContent.css( 'position', '' );
1511			} else {
1512				disabled.removeClass( 'mega-menu-disabled' ).addClass( 'mega-menu' );
1513				module.find( 'li.mega-menu > ul.sub-menu' ).css( 'width', rowWidth + 'px' );
1514				rowContent.css( 'position', 'relative' );
1515			}
1516		},
1517
1518		/**
1519		 * Init off-canvas menu.
1520		 *
1521		 * @since  	1.2.8
1522		 * @return void
1523		 */
1524		_initOffCanvas: function() {
1525			if ( this.mobileMenuType !== 'off-canvas' ) {
1526				return;
1527			}
1528			$('html').addClass('pp-off-canvas-menu-module');
1529			$('html').addClass('pp-off-canvas-menu-' + this.offCanvasDirection);
1530
1531			if ( $(this.nodeClass).find( '#pp-menu-' + this.settingsId ).length === 0 ) {
1532				return;
1533			}
1534
1535			var menuHTML = $(this.nodeClass).find( '#pp-menu-' + this.settingsId ).html();
1536
1537			if ( null === this.offCanvasMenu ) {
1538				this.offCanvasMenu = $('<div id="pp-advanced-menu-off-canvas-'+this.settingsId+'" class="fl-node-'+this.settingsId+' pp-menu-off-canvas" />').html( menuHTML );
1539			}
1540			if ( $('#pp-advanced-menu-off-canvas-'+this.settingsId).length === 0 && null !== this.offCanvasMenu && ! this.isBuilderActive ) {
1541				this.offCanvasMenu.appendTo( 'body' );
1542			}
1543
1544			$(this.nodeClass).trigger('pp-advanced-menu-off-canvas-init', [this.offCanvasMenu]);
1545
1546			this._toggleMenu();
1547		},
1548
1549		/**
1550		 * Init full-screen overlay menu.
1551		 *
1552		 * @since  	1.2.8
1553		 * @return void
1554		 */
1555		_initFullScreen: function() {
1556			if ( this.mobileMenuType !== 'full-screen' ) {
1557				return;
1558			}
1559
1560			$('html').addClass('pp-full-screen-menu-module');
1561
1562			if ( $(this.nodeClass).find( '#pp-menu-' + this.settingsId ).length === 0 ) {
1563				return;
1564			}
1565
1566			var menuHTML = $(this.nodeClass).find( '#pp-menu-' + this.settingsId ).html();
1567
1568			if ( null === this.fullScreenMenu ) {
1569				this.fullScreenMenu = $('<div id="pp-advanced-menu-full-screen-'+this.settingsId+'" class="fl-node-'+this.settingsId+' pp-menu-full-screen" />').html( menuHTML );
1570			}
1571			if ( $('#pp-advanced-menu-full-screen-'+this.settingsId).length === 0 && null !== this.fullScreenMenu && ! this.isBuilderActive ) {
1572				this.fullScreenMenu.appendTo( 'body' );
1573			}
1574
1575			$(this.nodeClass).trigger('pp-advanced-menu-full-screen-init', [this.fullScreenMenu]);
1576
1577			this._toggleMenu();
1578		},
1579
1580		/**
1581		 * Trigger the toggle event for off-canvas
1582		 * and full-screen overlay menus.
1583		 *
1584		 * @since  	1.2.8
1585		 * @return void
1586		 */
1587		_toggleMenu: function() {
1588			var self = this;
1589			var singleInstance = true;
1590			if( self.mobileMenuType === 'full-screen' ) {
1591				var winHeight = window.innerHeight;
1592				$(self.nodeClass).find('.pp-menu-overlay').css('height', winHeight + 'px');
1593				$(window).on('resize', function() {
1594					winHeight = window.innerHeight;
1595					$(self.nodeClass).find('.pp-menu-overlay').css('height', winHeight + 'px');
1596				});
1597			}
1598
1599			// Toggle Click
1600			var toggleEvent = ('ontouchend' in window) && this._isIOS() ? 'touchend' : 'click';
1601			$(self.nodeClass).find('.pp-advanced-menu-mobile-toggle' ).off(toggleEvent).on( toggleEvent, function() {
1602				if ( singleInstance ) {
1603					if ( $('.pp-advanced-menu.menu-open').length > 0 ) {
1604						$('.pp-advanced-menu').removeClass('menu-open');
1605						$('html').removeClass('pp-full-screen-menu-open');
1606					}
1607				}
1608				if( $(self.nodeClass).find('.pp-advanced-menu').hasClass('menu-open') ) {
1609					$(self.nodeClass).find('.pp-advanced-menu').removeClass('menu-open');
1610					$(self.nodeClass).find('.pp-advanced-menu').addClass('menu-close');
1611					$('html').removeClass('pp-off-canvas-menu-open');
1612					$('html').removeClass('pp-full-screen-menu-open');
1613				} else {
1614					$(self.nodeClass).find('.pp-advanced-menu').addClass('menu-open');
1615					if( self.mobileMenuType === 'off-canvas' ) {
1616						$('html').addClass('pp-off-canvas-menu-open');
1617						self.offCanvasMenu.find('nav').attr('tabindex', '0').trigger( 'focus' );
1618						$(this).attr( 'tabindex', '-1' ).trigger( 'blur' );
1619					}
1620					if( self.mobileMenuType === 'full-screen' ) {
1621						$('html').addClass('pp-full-screen-menu-open');
1622						self.fullScreenMenu.find('nav').attr('tabindex', '0').trigger( 'focus' );
1623						$(this).attr( 'tabindex', '-1' ).trigger( 'blur' );
1624					}
1625				}
1626
1627				if ( '0' == $(this).attr('tabindex') ) {
1628					$(this).attr('aria-expanded', 'false');
1629				} else {
1630					$(this).attr('aria-expanded', 'true');
1631				}
1632			} );
1633
1634			// iOS Safari "hover" fix.
1635			// This is needed to ensure the click event works properly on iOS devices since they treat the first tap as a hover event,
1636			// which can interfere with the intended toggle behavior of the menu.
1637			// $(self.nodeClass).find('.pp-advanced-menu-mobile-toggle' ).on( 'touchstart', function(e) {
1638			// 	e.preventDefault();
1639			// 	e.stopPropagation();
1640			// 	$(this).trigger('click');
1641			// } );
1642
1643			// Keyboard navigation.
1644			$(self.nodeClass).find('.pp-advanced-menu-mobile-toggle').on('keyup', function(e) {
1645				if ( 13 === e.keyCode || 13 === e.which ) {
1646					$(this).trigger('click');
1647				}
1648			});
1649
1650			// Close button click
1651			$(self.nodeClass).find('.pp-advanced-menu .pp-menu-close-btn, .pp-clear').on( 'click', function() {
1652				$(self.nodeClass).find('.pp-advanced-menu').removeClass('menu-open');
1653				$(self.nodeClass).find('.pp-advanced-menu').addClass('menu-close');
1654				$('html').removeClass('pp-off-canvas-menu-open');
1655				$('html').removeClass('pp-full-screen-menu-open');
1656
1657				if ( $(self.nodeClass).find('.pp-advanced-menu-mobile-toggle' ).is( ':visible' ) ) {
1658					setTimeout(function() {
1659						$(self.nodeClass).find('.pp-advanced-menu-mobile-toggle' )
1660							.attr( 'tabindex', 0 )
1661							.attr( 'aria-expanded', 'false' )
1662							.trigger( 'focus' );
1663					}, 120);
1664				}
1665
1666				if ( self.offCanvasMenu && self.offCanvasMenu.length > 0 ) {
1667					self.offCanvasMenu.find('nav').attr('tabindex', '-1').trigger( 'blur' );
1668				}
1669				if ( self.fullScreenMenu && self.fullScreenMenu.length > 0 ) {
1670					self.fullScreenMenu.find('nav').attr('tabindex', '-1').trigger( 'blur' );
1671				}
1672			} );
1673
1674			if ( this.isBuilderActive ) {
1675				setTimeout(function() {
1676					if ( $('.fl-builder-settings[data-node="'+self.settingsId+'"]').length > 0 ) {
1677						$('.pp-advanced-menu').removeClass('menu-open');
1678						$(self.nodeClass).find('.pp-advanced-menu-mobile-toggle').trigger('click');
1679					}
1680				}, 600);
1681
1682				FLBuilder.addHook('settings-form-init', function() {
1683					if ( ! $('.fl-builder-settings[data-node="'+self.settingsId+'"]').length > 0 ) {
1684						return;
1685					}
1686					if ( ! $(self.nodeClass).find('.pp-advanced-menu').hasClass('menu-open') ) {
1687						$('.pp-advanced-menu').removeClass('menu-open');
1688						$(self.nodeClass).find('.pp-advanced-menu-mobile-toggle').trigger('click');
1689					}
1690				});
1691
1692				if ( $('html').hasClass('pp-full-screen-menu-open') && ! $(self.nodeClass).find('.pp-advanced-menu').hasClass('menu-open') ) {
1693					$('html').removeClass('pp-full-screen-menu-open');
1694				}
1695				if ( $('html').hasClass('pp-off-canvas-menu-open') && ! $(self.nodeClass).find('.pp-advanced-menu').hasClass('menu-open') ) {
1696					$('html').removeClass('pp-off-canvas-menu-open');
1697				}
1698			}
1699		},
1700
1701		/**
1702		 * Check to see if Below Row should be enabled.
1703		 *
1704		 * @since  	2.8.0
1705		 * @return boolean
1706		 */
1707		_isMobileBelowRowEnabled: function() {
1708			if (this.mobileMenuType === 'default') {
1709				return this.mobileBelowRow && $( this.nodeClass ).closest( '.fl-col' ).length;
1710			}
1711			return false;
1712		},
1713
1714		/**
1715		 * Logic for putting the mobile menu below the menu's
1716		 * column so it spans the full width of the page.
1717		 *
1718		 * @since  2.2
1719		 * @return void
1720		 */
1721		_placeMobileMenuBelowRow: function () {
1722
1723			if ($(this.nodeClass + '-clone').length) {
1724				return;
1725			}
1726			// if ( $('html').hasClass( 'fl-builder-edit' ) ) {
1727			// 	return;
1728			// }
1729
1730			var module = $(this.nodeClass),
1731				clone = null,
1732				row = module.closest('.fl-row-content');
1733
1734			if ( module.length < 1 ) {
1735				return;
1736			}
1737
1738			clone = ( module.length > 1 ) ? $( module[0] ).clone() : module.clone();
1739			module.find('.pp-menu-nav').remove();
1740			clone.addClass((this.nodeClass + '-clone').replace('.', ''));
1741			clone.addClass('pp-menu-mobile-clone');
1742			clone.find('.pp-advanced-menu-mobile').remove();
1743			row.append(clone);
1744
1745			// Removes animation when enabled.
1746			if ( module.hasClass( 'fl-animation' ) ) {
1747				clone.removeClass( 'fl-animation' );
1748			}
1749
1750			this._menuOnClick();
1751		},
1752
1753		/**
1754		 * Logic for removing the mobile menu from below the menu's
1755		 * column and putting it back in the main wrapper.
1756		 *
1757		 * @since  2.2
1758		 * @return void
1759		 */
1760		_removeMenuFromBelowRow: function () {
1761
1762			if (!$(this.nodeClass + '-clone').length) {
1763				return;
1764			}
1765
1766			var module = $(this.nodeClass),
1767				clone = $(this.nodeClass + '-clone'),
1768				menu = clone.find('.pp-menu-nav');
1769
1770			module.find('.pp-advanced-menu-mobile').after(menu);
1771			module.find('.pp-advanced-menu-mobile-toggle').attr( 'aria-expanded', false );
1772			clone.remove();
1773		},
1774
1775		_toggleMenuSearch: function() {
1776			var items =  $( this.wrapperClass ).find( '.pp-menu-search-item' ),
1777				self  = this;
1778
1779			items.each( function() {
1780				var item = $(this);
1781				var button = item.find( '> a' ),
1782					form = item.find( '.pp-search-form' ),
1783					input = item.find('.pp-search-form__input');
1784
1785				button.on( 'click', function(e) {
1786					e.preventDefault();
1787					item.toggleClass( 'pp-search-active' );
1788					if ( item.hasClass( 'pp-search-active' ) ) {
1789						setTimeout( function() {
1790							input.focus();
1791							self._focusMenuSearch( input );
1792						}, 100 );
1793					}
1794
1795					$('body').on( 'click.pp-menu-search', self._hideMenuSearch.bind( self ) );
1796				} );
1797
1798				input.on( 'focus', function() {
1799					form.addClass( 'pp-search-form--focus' );
1800				} ).on( 'blur', function() {
1801					form.removeClass( 'pp-search-form--focus' );
1802				} );
1803
1804				// Close search form on ESC key press.
1805				input.on( 'keyup', function(e) {
1806					if ( e.key === 'Escape' || e.keyCode === 27 ) {
1807						item.removeClass( 'pp-search-active' );
1808						$('body').off('click.pp-menu-search');
1809						button.delay(100).focus();
1810					}
1811				} );
1812			} );
1813		},
1814
1815		_hideMenuSearch: function(e) {
1816			if (e !== undefined) {
1817				if ($(e.target).closest('.pp-menu-search-item').length > 0) {
1818					return;
1819				}
1820			}
1821
1822			$( this.wrapperClass ).find( '.pp-menu-search-item' ).removeClass( 'pp-search-active' );
1823			$('body').off('click.pp-menu-search');
1824		},
1825
1826		_focusMenuSearch: function( $el ) {
1827			// If this function exists... (IE 9+)
1828			if ( $el[0].setSelectionRange ) {
1829				// Double the length because Opera is inconsistent about whether a carriage return is one character or tw
1829o.
1830				var len = $el.val().length * 2;
1831
1832				// Timeout seems to be required for Blink
1833				setTimeout(function() {
1834					$el[0].setSelectionRange( len, len );
1835				}, 1);
1836			} else {
1837				// As a fallback, replace the contents with itself
1838				// Doesn't work in Chrome, but Chrome supports setSelectionRange
1839				$el.val( $el.val() );
1840			}
1841		},
1842
1843		/**
1844		 * Adds menu node and post ID to WooCommerce ajax URL requests.
1845		 *
1846		 * @since  2.20
1847		 * @return void
1848		 */
1849		 _wooUpdateParams: function() {
1850			if ( 'undefined' !== typeof wc_cart_fragments_params ) {
1851				wc_cart_fragments_params.wc_ajax_url += '&pp-advanced-menu-node='+ this.settingsId +'&post-id='+ this.postId;
1852			}
1853			if ( 'undefined' !== typeof wc_add_to_cart_params ) {
1854				wc_add_to_cart_params.wc_ajax_url += '&pp-advanced-menu-node='+ this.settingsId +'&post-id='+ this.postId;
1855			}
1856		},
1857
1858		_validClick: function(e) {
1859			return (e.which == 1 || e.which == 13 || e.which == 32 || e.which == undefined) ? true : false;
1860		}
1861
1862	};
1863
1864})(jQuery);
1865
1866var pp_menu_5c5816cad1308;
1867(function($) {
1868
1869    pp_menu_5c5816cad1308 = new PPAdvancedMenu({
1870    	id: '5c5816cad1308',
1871    	type: 'horizontal',
1872		mobile: 'hamburger',
1873		menuPosition: 'below',
1874		breakpoints: {
1875			large: 1200,
1876			medium: 1024,
1877			small: 750,
1878			custom: 768		},
1879		mobileBreakpoint: 'medium-mobile',
1880		mediaBreakpoint: '1024',
1881		mobileMenuType: 'off-canvas',
1882		offCanvasDirection: 'left',
1883		fullScreenAnimation: '',
1884		isBuilderActive: false    });
1885
1886})(jQuery);
1887jQuery(function($) {
1888	
1889		$(function() {
1890		$( '.fl-node-5c5816d338e2a .fl-photo-img' )
1891			.on( 'mouseenter', function( e ) {
1892				$( this ).data( 'title', $( this ).attr( 'title' ) ).removeAttr( 'title' );
1893			} )
1894			.on( 'mouseleave', function( e ){
1895				$( this ).attr( 'title', $( this ).data( 'title' ) ).data( 'title', null );
1896			} );
1897	});
1898		window._fl_string_to_slug_regex = 'a-zA-Z0-9';
1899});
1900
1901;/**
1902 * This file should contain frontend logic for 
1903 * all module instances.
1904 */
1905/* Start Layout Custom JS */
1906
1907/* End Layout Custom JS */
1908
1909(function($){
1910
1911	/**
1912	 * Helper class for header layout logic.
1913	 *
1914	 * @since 1.0
1915	 * @class FLThemeBuilderHeaderLayout
1916	 */
1917	FLThemeBuilderHeaderLayout = {
1918
1919		/**
1920		 * A reference to the window object for this page.
1921		 *
1922		 * @since 1.0
1923		 * @property {Object} win
1924		 */
1925		win : null,
1926
1927		/**
1928		 * A reference to the body object for this page.
1929		 *
1930		 * @since 1.0
1931		 * @property {Object} body
1932		 */
1933		body : null,
1934
1935		/**
1936		 * A reference to the header object for this page.
1937		 *
1938		 * @since 1.0
1939		 * @property {Object} header
1940		 */
1941		header : null,
1942
1943		/**
1944		 * Whether this header overlays the content or not.
1945		 *
1946		 * @since 1.0
1947		 * @property {Boolean} overlay
1948		 */
1949		overlay : false,
1950
1951		/**
1952		 * Whether the page has the WP admin bar or not.
1953		 *
1954		 * @since 1.0
1955		 * @property {Boolean} hasAdminBar
1956		 */
1957		hasAdminBar : false,
1958
1959		/**
1960		 * Breakpoint for when the sticky header should apply.
1961		 *
1962		 * @since 1.4
1963		 * @property {String} stickyOn
1964		 */
1965		stickyOn: '',
1966
1967		/**
1968		 * A reference of the sticky and shrink header breakpoint.
1969		 *
1970		 * @since 1.2.5
1971		 * @property {Number} breakpointWidth
1972		 */
1973		breakpointWidth: 0,
1974
1975		/**
1976		 * Whether this header can be pinned from page load.
1977		 *
1978		 * @since 1.6.1
1979		 * @property {Boolean} pinnable
1980		 */
1981		pinnable : false,
1982
1983		/**
1984		 * Initializes header layout logic.
1985		 *
1986		 * @since 1.0
1987		 * @method init
1988		 */
1989		init: function()
1990		{
1991			var editing          = $( 'html.fl-builder-edit' ).length,
1992				header           = $( '.fl-builder-content[data-type=header]' ),
1993				menuModule       = header.find( '.fl-module-menu' ),
1994				breakpoint       = null,
1995				adminBarHeight   = 0;
1996
1997			if ( ! editing && header.length ) {
1998
1999				header.imagesLoaded( $.proxy( function() {
2000
2001					this.win         = $( window );
2002					this.body        = $( 'body' );
2003					this.header      = header.eq( 0 );
2004					this.overlay     = !! Number( header.attr( 'data-overlay' ) );
2005					this.hasAdminBar = !! $( 'body.admin-bar' ).length;
2006					this.stickyOn    = this.header.data( 'sticky-on' );
2007					breakpoint       = this.header.data( 'sticky-breakpoint' );
2008
2009					if ( '' == this.stickyOn ) {
2010						if ( typeof FLBuilderLayoutConfig.breakpoints[ breakpoint ] !== undefined ) {
2011							this.breakpointWidth = FLBuilderLayoutConfig.breakpoints[ breakpoint ];
2012						}
2013						else {
2014							this.breakpointWidth = FLBuilderLayoutConfig.breakpoints.medium;
2015						}
2016					}
2017
2018					if ( Number( header.attr( 'data-sticky' ) ) ) {
2019
2020						this.header.data( 'original-top', this.header.offset().top );
2021
2022						// The pin decision is made once here, while the header offset and the admin bar height are read from the same layout.
2023						adminBarHeight = $( '#wpadminbar' ).length ? $( '#wpadminbar' ).outerHeight() : 0;
2024						this.pinnable  = this.overlay && this.header.data( 'original-top' ) <= adminBarHeight;
2025
2026						this.win.on( 'resize', $.throttle( 500, $.proxy( this._initSticky, this ) ) );
2027						this._initSticky();
2028
2029					}
2030
2031				}, this ) );
2032			}
2033		},
2034
2035		/**
2036		 * Initializes sticky logic for a header.
2037		 *
2038		 * @since 1.0
2039		 * @access private
2040		 * @method _initSticky
2041		 */
2042		_initSticky: function( e )
2043		{
2044			var header     = $('.fl-builder-content[data-type=header]'),
2045				windowSize = this.win.width(),
2046				makeSticky = false;
2047
2048			makeSticky = this._makeWindowSticky( windowSize );
2049			if ( makeSticky || ( this.breakpointWidth > 0 && windowSize >= this.breakpointWidth ) ) {
2050				this.win.on( 'scroll.fl-theme-builder-header-sticky', $.proxy( this._doSticky, this ) );
2051				this._initPin();
2052
2053				// Apply the sticky state on initial load when the page is
2054				// already scrolled past the header — e.g. when the browser
2055				// restores the scroll position on refresh. Overlay headers are
2056				// out of scope here; this mirrors the shrink-on-load behavior
2057				// in _initShrink().
2058				if ( ! e && ! this.overlay && ! this.header.hasClass( 'fl-theme-builder-header-sticky' ) ) {
2059					var loadWinTop    = this.win.scrollTop(),
2060						loadHeaderTop = Math.floor( this.header.data( 'original-top' ) );
2061
2062					if ( this.hasAdminBar && windowSize > 600 ) {
2063						loadWinTop += Math.floor( $( '#wpadminbar' ).outerHeight() );
2064					}
2065
2066					if ( loadWinTop > loadHeaderTop ) {
2067						this.header.addClass( 'fl-theme-builder-header-sticky' );
2068						this.header.addClass( 'fl-theme-builder-header-scrolled' );
2069						this._adjustHeaderHeight();
2070						this._adjustStickyHeaderWidth();
2071					}
2072				}
2073
2074				//
2075				// Check if Event Type is 'resize' then invoke this._doSticky()
2076				// only if the 'fl-theme-builder-header-sticky' class is already present.
2077				//
2078				if ( e && 'resize' === e.type ) {
2079					if ( this.header.hasClass( 'fl-theme-builder-header-sticky' ) ) {
2080						this._doSticky( e );
2081					}
2082					this._adjustStickyHeaderWidth();
2083				}
2084
2085				if ( Number( header.attr( 'data-shrink' ) ) ) {
2086					this.header.data( 'original-height', this.header.outerHeight() );
2087					this.win.on( 'resize', $.throttle( 500, $.proxy( this._initShrink, this ) ) );
2088					this._initShrink();
2089				}
2090
2091				this._initFlyoutMenuFix( e );
2092			} else {
2093				this.win.off( 'scroll.fl-theme-builder-header-sticky' );
2094				this.win.off( 'resize.fl-theme-builder-header-sticky' );
2095
2096				this.header.removeClass( 'fl-theme-builder-header-sticky' );
2097				this.header.removeClass( 'fl-theme-builder-header-pinned' );
2098				this.header.removeAttr( 'style' );
2099				this.header.parent().css( 'padding-top', '0' );
2100			}
2101		},
2102
2103		/**
2104		 * Pins an overlay header with fixed positioning from page load, avoiding a position change that a scroll handler cannot apply before the compositor paints.
2105		 *
2106		 * @since 1.6.1
2107		 * @access private
2108		 * @method _initPin
2109		 */
2110		_initPin: function()
2111		{
2112			this.header.toggleClass( 'fl-theme-builder-header-pinned', this.pinnable );
2113
2114			if ( ! this.pinnable ) {
2115				return;
2116			}
2117
2118			// Fixed positioning resolves the width against the viewport, so boxed layouts require their maximum width immediately.
2119			this._adjustStickyHeaderWidth();
2120
2121			// The header is visible from the first paint, so the scrolled state must reflect any restored scroll position.
2122			if ( this.win.scrollTop() > Math.floor( this.header.data( 'original-top' ) ) ) {
2123				this.header.addClass( 'fl-theme-builder-header-scrolled' );
2124			}
2125		},
2126
2127		/**
2128		 * Check if Header should be sticky at a particular Window size.
2129		 *
2130		 * @since 1.4
2131		 * @access private
2132		 * @param  widowSize
2133		 * @method _makeWindowSticky
2134		 */
2135		_makeWindowSticky: function ( windowSize )
2136		{
2137			var makeSticky = false;
2138
2139			switch (this.stickyOn) {
2140				case 'xl':
2141					makeSticky = windowSize > FLBuilderLayoutConfig.breakpoints['large'];
2142					break;
2143				case '': // Default
2144				case 'desktop':
2145					makeSticky = windowSize >= FLBuilderLayoutConfig.breakpoints['medium'];
2146					break;
2147				case 'desktop-medium':
2148					makeSticky = windowSize > FLBuilderLayoutConfig.breakpoints['small'];
2149					break;
2150				case 'large':
2151					makeSticky = windowSize > FLBuilderLayoutConfig.breakpoints['medium'] && windowSize <= FLBuilderLayoutConfig.breakpoints['large'];
2152					break;
2153				case 'large-medium':
2154					makeSticky = windowSize > FLBuilderLayoutConfig.breakpoints['small'] && windowSize <= FLBuilderLayoutConfig.breakpoints['large'];
2155					break;
2156				case 'medium':
2157					makeSticky = ( windowSize <= FLBuilderLayoutConfig.breakpoints['medium'] && windowSize > FLBuilderLayoutConfig.breakpoints['small'] );
2158					break;
2159				case 'medium-mobile':
2160					makeSticky = (windowSize <= FLBuilderLayoutConfig.breakpoints['medium']);
2161					break;
2162				case 'mobile':
2163					makeSticky = (windowSize <= FLBuilderLayoutConfig.breakpoints['small']);
2164					break;
2165				case 'all':
2166					makeSticky = true;
2167					break;
2168			}
2169
2170			return makeSticky;
2171		},
2172
2173		/**
2174		 * Sticks the header when the page is scrolled.
2175		 *
2176		 * @since 1.0
2177		 * @access private
2178		 * @method _doSticky
2179		 */
2180		_doSticky: function( e )
2181		{
2182			var winTop    		  = Math.floor( this.win.scrollTop() ),
2183				headerTop 		  = Math.floor( this.header.data( 'original-top' ) ),
2184				hasStickyClass    = this.header.hasClass( 'fl-theme-builder-header-sticky' ),
2185				hasScrolledClass  = this.header.hasClass( 'fl-theme-builder-header-scrolled' ),
2186				beforeHeader      = this.header.prevAll( '.fl-builder-content' ),
2187				bodyTopPadding    = parseInt( jQuery('body').css('padding-top') ),
2188				winBarHeight      = $('#wpadminbar').length ? $('#wpadminbar').outerHeight() : 0,
2189				headerHeight      = 0;
2190
2191			if ( isNaN( bodyTopPadding ) ) {
2192				bodyTopPadding = 0;
2193			}
2194
2195			if ( this.hasAdminBar && this.win.width() > 600 ) {
2196				winTop += Math.floor( winBarHeight );
2197			}
2198
2199			if ( winTop > headerTop ) {
2200				if ( ! hasStickyClass ) {
2201					if ( e && ( 'scroll' === e.type || 'smartscroll' === e.type ) ) {
2202					 	this.header.addClass( 'fl-theme-builder-header-sticky' );
2203						if ( this.overlay && beforeHeader.length ) {
2204							this.header.css( 'top', winBarHeight);
2205						}
2206					}
2207
2208					if ( ! this.overlay ) {
2209						this._adjustHeaderHeight();
2210					}
2211				}
2212			}
2213			else if ( hasStickyClass ) {
2214				this.header.removeClass( 'fl-theme-builder-header-sticky' );
2215				this.header.removeAttr( 'style' );
2216				this.header.parent().css( 'padding-top', '0' );
2217			}
2218
2219			this._adjustStickyHeaderWidth();
2220
2221			if ( winTop > headerTop ) {
2222				if ( ! hasScrolledClass ) {
2223					this.header.addClass( 'fl-theme-builder-header-scrolled' );
2224				}
2225			} else if ( hasScrolledClass ) {
2226				this.header.removeClass( 'fl-theme-builder-header-scrolled' );
2227			}
2228
2229			this._flyoutMenuFix( e );
2230		},
2231
2232		/**
2233		 * Initializes flyout menu fixes on sticky header.
2234		 *
2235		 * @since 1.4.1
2236		 * @method _initFlyoutMenuFix
2237		 */
2238		_initFlyoutMenuFix: function( e ) {
2239			var header       = this.header,
2240				menuModule   = header.closest( '.fl-menu' ),
2241				flyoutMenu   = menuModule.find( '.fl-menu-mobile-flyout' ),
2242				isPushMenu   = menuModule.hasClass( 'fl-menu-responsive-flyout-push' ) || menuModule.hasClass( 'fl-menu-responsive-flyout-push-opacity' ),
2243				isOverlay    = menuModule.hasClass( 'fl-menu-responsive-flyout-overlay' ),
2244				flyoutPos    = menuModule.hasClass( 'fl-flyout-right' ) ? 'right' : 'left',
2245				flyoutParent = header.parent().is( 'header' ) ? header.parent().parent() : header.parent();
2246				isFullWidth  = this.win.width() === header.width(),
2247				flyoutLayout = '',
2248				activePos    = 250,
2249				headerPos    = 0;
2250
2251			if ( ! flyoutMenu.length ) {
2252				return;
2253			}
2254
2255			if ( this.win.width() > header.parent().width() ) {
2256				headerPos = ( this.win.width() - header.width() ) / 2;
2257			}
2258
2259			if ( isOverlay ) {
2260				activePos = headerPos;
2261			}
2262			else if ( isPushMenu ) {
2263				activePos = activePos + headerPos;
2264			}
2265			flyoutMenu.data( 'activePos', activePos );
2266
2267			if ( isPushMenu ) {
2268				flyoutLayout = 'push-' + flyoutPos;
2269			}
2270			else if ( isOverlay ) {
2271				flyoutLayout = 'overlay-' + flyoutPos;
2272			}
2273
2274			if ( isPushMenu && ! $( 'html' ).hasClass( 'fl-theme-builder-has-flyout-menu' ) ) {
2275				$( 'html' ).addClass( 'fl-theme-builder-has-flyout-menu' );
2276			}
2277
2278			if ( ! flyoutParent.hasClass( 'fl-theme-builder-flyout-menu-' + flyoutLayout ) ) {
2279				flyoutParent.addClass( 'fl-theme-builder-flyout-menu-' + flyoutLayout );
2280			}
2281
2282			if ( ! header.hasClass( 'fl-theme-builder-flyout-menu-overlay' ) && isOverlay ) {
2283				header.addClass( 'fl-theme-builder-flyout-menu-overlay' );
2284			}
2285
2286			if ( ! header.hasClass( 'fl-theme-builder-header-full-width' ) && isFullWidth ) {
2287			   header.addClass( 'fl-theme-builder-header-full-width' );
2288		    }
2289			else if ( ! isFullWidth ) {
2290				header.removeClass( 'fl-theme-builder-header-full-width' );
2291			}
2292
2293			menuModule.on( 'click', '.fl-menu-mobile-toggle', $.proxy( function( event ){
2294				if ( menuModule.find( '.fl-menu-mobile-toggle.fl-active' ).length ) {
2295					$( 'html' ).addClass( 'fl-theme-builder-flyout-menu-active' );
2296					event.stopImmediatePropagation();
2297				}
2298				else {
2299					$( 'html' ).removeClass( 'fl-theme-builder-flyout-menu-active' );
2300				}
2301
2302				this._flyoutMenuFix( event );
2303			}, this ) );
2304		},
2305
2306		/**
2307		 * Fix flyout menu inside the sticky header.
2308		 *
2309		 * @since 1.4.1
2310		 * @method _flyoutMenuFix
2311		 */
2312		_flyoutMenuFix: function( e ){
2313			var header      = this.header,
2314			    menuModule  = $( e.target ).closest( '.fl-menu' ),
2315				flyoutMenu  = menuModule.find( '.fl-menu-mobile-flyout' ),
2316				flyoutPos   = menuModule.hasClass( 'fl-flyout-right' ) ? 'right' : 'left',
2317				menuOpacity = menuModule.find( '.fl-menu-mobile-opacity' ),
2318				isScroll    = 'undefined' !== typeof e && 'scroll' === e.handleObj.type,
2319				activePos   = 'undefined' !== typeof flyoutMenu.data( 'activePos' ) ? flyoutMenu.data( 'activePos' ) : 0,
2320				headerPos   = ( this.win.width() - header.width() ) / 2,
2321				inactivePos = headerPos > 0 ? activePos + 4 : 254;
2322
2323			if ( ! flyoutMenu.length ) {
2324				return;
2325			}
2326
2327			if ( this.overlay ) {
2328				return;
2329			}
2330
2331			if( $( '.fl-theme-builder-flyout-menu-active' ).length ) {
2332
2333				if ( isScroll && ! flyoutMenu.hasClass( 'fl-menu-disable-transition' ) ) {
2334					flyoutMenu.addClass( 'fl-menu-disable-transition' );
2335				}
2336
2337				if ( header.hasClass( 'fl-theme-builder-header-sticky' ) ) {
2338					if ( ! isScroll ) {
2339						setTimeout( $.proxy( function(){
2340							flyoutMenu.css( flyoutPos, '-' + activePos + 'px' );
2341						}, this ), 1 );
2342					}
2343					else {
2344						flyoutMenu.css( flyoutPos, '-' + activePos + 'px' );
2345					}
2346				}
2347				else {
2348					flyoutMenu.css( flyoutPos, '0px' );
2349				}
2350			}
2351			else {
2352				if ( flyoutMenu.hasClass( 'fl-menu-disable-transition' ) ) {
2353					flyoutMenu.removeClass( 'fl-menu-disable-transition' );
2354				}
2355
2356				if ( header.hasClass( 'fl-theme-builder-flyout-menu-overlay' ) && headerPos > 0 && headerPos < 250 ) {
2357					if ( header.hasClass( 'fl-theme-builder-header-sticky' ) ) {
2358						inactivePos = headerPos + 254;
2359					}
2360					else {
2361						inactivePos = 254;
2362					}
2363				}
2364
2365				if ( e && e.type === 'resize' ) {
2366					inactivePos = headerPos + 254;
2367				}
2368
2369				flyoutMenu.css( flyoutPos, '-' + inactivePos + 'px' );
2370			}
2371
2372			if ( e && menuModule.is('.fl-menu-responsive-flyout-overlay') && $.infinitescroll ) {
2373				e.stopImmediatePropagation();
2374			}
2375
2376			if( menuOpacity.length ) {
2377				if ( header.hasClass( 'fl-theme-builder-header-sticky' ) ) {
2378					if ( '0px' === menuOpacity.css( 'left' ) ) {
2379						menuOpacity.css( 'left', '-' + headerPos + 'px' );
2380					}
2381				}
2382				else {
2383					menuOpacity.css( 'left', '' );
2384				}
2385			}
2386		},
2387
2388		/**
2389		 * Adjust sticky header width if BB Theme Boxed Layout is used.
2390		 *
2391		 * @since 1.4
2392		 * @access private
2393		 * @method _adjustStickyHeaderWidth
2394		 */
2395		_adjustStickyHeaderWidth: function () {
2396			if ( $('body').hasClass( 'fl-fixed-width' ) ) {
2397				var parentWidth = this.header.parent().width();
2398
2399				// Better if this is set in the stylesheet file.
2400				if ( this.win.width() >= 992 ) {
2401					this.header.css({
2402						'margin': '0 auto',
2403						'max-width': parentWidth,
2404					});
2405				}
2406				else {
2407					this.header.css({
2408						'margin': '',
2409						'max-width': '',
2410					});
2411				}
2412			}
2413		},
2414
2415		/**
2416		 * Adjust Sticky Header Height
2417		 *
2418		 * @since 1.4
2419		 * @access private
2420		 * @method _adjustHeaderHeight
2421		 */
2422		_adjustHeaderHeight: function () {
2423			var beforeHeader = this.header.prevAll('.fl-builder-content'),
2424				beforeHeaderHeight = 0,
2425				beforeHeaderFix = 0,
2426				headerHeight = Math.floor( this.header.outerHeight() ),
2427				bodyTopPadding = parseInt( $( 'body' ).css( 'padding-top' ) ),
2428				wpAdminBarHeight = 0,
2429				totalHeaderHeight = 0;
2430
2431			if ( isNaN( bodyTopPadding ) ) {
2432				bodyTopPadding = 0;
2433			}
2434
2435			if ( beforeHeader.length ) {
2436				$.each( beforeHeader, function() {
2437					beforeHeaderHeight += Math.floor( $(this).outerHeight() );
2438				});
2439				// Subtract this value from the header parent's top padding.
2440				beforeHeaderFix = 2;
2441			}
2442
2443			if ( this.hasAdminBar && this.win.width() <= 600 ) {
2444				wpAdminBarHeight = Math.floor( $('#wpadminbar').outerHeight() );
2445			}
2446
2447			totalHeaderHeight = Math.floor( beforeHeaderHeight + headerHeight);
2448
2449			if ( headerHeight > 0 ) {
2450				var headerParent = this.header.parent(),
2451					headerParentTopPadding = 0;
2452
2453				// If the header's parent container is the BODY tag ignore its top padding.
2454				if ( $( headerParent ).is('body') ) {
2455					headerParentTopPadding = Math.floor( headerHeight - wpAdminBarHeight );
2456				} else {
2457					headerParentTopPadding = Math.floor( headerHeight - bodyTopPadding - wpAdminBarHeight );
2458				}
2459
2460				$( headerParent ).css( 'padding-top',  ( headerParentTopPadding - beforeHeaderFix ) + 'px' );
2461
2462				this.header.css({
2463					'-webkit-transform': 'translate(0px, -' + totalHeaderHeight + 'px)',
2464					'-ms-transform': 'translate(0px, -' + totalHeaderHeight + 'px)',
2465					'transform': 'translate(0px, -' + totalHeaderHeight + 'px)'
2466				});
2467
2468			}
2469
2470		},
2471
2472		/**
2473		 * Initializes shrink logic for a header.
2474		 *
2475		 * @since 1.0
2476		 * @access private
2477		 * @method _initShrink
2478		 */
2479		_initShrink: function( e )
2480		{
2481			if ( this.win.width() >= this.breakpointWidth ) {
2482				this.win.on( 'scroll.fl-theme-builder-header-shrink', $.proxy( this._doShrink, this ) );
2483				this._setImageMaxHeight();
2484
2485				if ( this.win.scrollTop() > 0 ){
2486					this._doShrink();
2487				}
2488
2489			} else {
2490				this.header.parent().css( 'padding-top', '0' );
2491				this.win.off( 'scroll.fl-theme-builder-header-shrink' );
2492				this._removeShrink();
2493				this._removeImageMaxHeight();
2494			}
2495		},
2496
2497		/**
2498		 * Shrinks the header when the page is scrolled.
2499		 *
2500		 * @since 1.0
2501		 * @access private
2502		 * @method _doShrink
2503		 */
2504		_doShrink: function( e )
2505		{
2506			var winTop 			  = this.win.scrollTop(),
2507				headerTop 		  = this.header.data('original-top'),
2508				headerHeight 	  = this.header.data('original-height'),
2509				shrinkImageHeight = this.header.data('shrink-image-height'),
2510				windowSize   	  = this.win.width(),
2511				makeSticky   	  = this._makeWindowSticky( windowSize ),
2512				hasClass     	  = this.header.hasClass( 'fl-theme-builder-header-shrink' );
2513
2514
2515			if ( this.hasAdminBar ) {
2516				winTop += 32;
2517			}
2518
2519			if ( makeSticky && ( winTop > headerTop + headerHeight ) ) {
2520				if ( ! hasClass ) {
2521
2522					this.header.addClass( 'fl-theme-builder-header-shrink' );
2523
2524					// Shrink images but don't include lightbox and menu images.
2525					this.header.find('img').each( function( i ) {
2526						var image           = $( this ),
2527							maxMegaMenu     = image.closest( '.max-mega-menu' ).length,
2528							imageInLightbox = image.closest( '.fl-button-lightbox-content' ).length,
2529							imageInNavMenu  = image.closest( 'li.menu-item' ).length;
2530
2531						if ( ! ( imageInLightbox || imageInNavMenu || maxMegaMenu ) ) {
2532							image.css( 'max-height', shrinkImageHeight );
2533						}
2534
2535					});
2536
2537					this.header.find( '.fl-row-content-wrap' ).each( function() {
2538
2539						var row = $( this );
2540
2541						if ( parseInt( row.css( 'padding-bottom' ) ) > 5 ) {
2542							row.addClass( 'fl-theme-builder-header-shrink-row-bottom' );
2543						}
2544
2545						if ( parseInt( row.css( 'padding-top' ) ) > 5 ) {
2546							row.addClass( 'fl-theme-builder-header-shrink-row-top' );
2547						}
2548					} );
2549
2550					this.header.find( '.fl-module' ).each( function() {
2551
2552						var module = $( this ).find( '.fl-module-content' ).length ? $( this ).find( '.fl-module-content' ) : $( this );
2553
2554						if ( parseInt( module.css( 'margin-bottom' ) ) > 5 ) {
2555							module.addClass( 'fl-theme-builder-header-shrink-module-bottom' );
2556						}
2557
2558						if ( parseInt( module.css( 'margin-top' ) ) > 5 ) {
2559							module.addClass( 'fl-theme-builder-header-shrink-module-top' );
2560						}
2561					} );
2562				}
2563			} else if (hasClass) {
2564				this.header.find( 'img' ).css( 'max-height', '' );
2565				this._removeShrink();
2566			}
2567
2568			// Fixes Shrink header issue with BB Theme when window is scrolled then resized and back.
2569			if ( 'undefined' === typeof( e ) && $('body').hasClass( 'fl-fixed-width' ) ) {
2570				if ( ! this.overlay ) {
2571					this._adjustHeaderHeight();
2572				}
2573			}
2574
2575		},
2576
2577		/**
2578		 * Removes the header shrink effect.
2579		 *
2580		 * @since 1.0
2581		 * @access private
2582		 * @method _removeShrink
2583		 */
2584		_removeShrink: function()
2585		{
2586			var rows    = this.header.find( '.fl-row-content-wrap' ),
2587				modules = this.header.find('.fl-module, .fl-module-content');
2588
2589			rows.removeClass( 'fl-theme-builder-header-shrink-row-bottom' );
2590			rows.removeClass( 'fl-theme-builder-header-shrink-row-top' );
2591			modules.removeClass( 'fl-theme-builder-header-shrink-module-bottom' );
2592			modules.removeClass( 'fl-theme-builder-header-shrink-module-top' );
2593			this.header.removeClass( 'fl-theme-builder-header-shrink' );
2594		},
2595
2596		/**
2597		 * Adds max height to images in modules for smooth scrolling.
2598		 *
2599		 * @since 1.1.1
2600		 * @access private
2601		 * @method _setImageMaxHeight
2602		 */
2603		_setImageMaxHeight: function()
2604		{
2605			var head = $( 'head' ),
2606				stylesId = 'fl-header-styles-' + this.header.data( 'post-id' ),
2607				styles = '',
2608				images = this.header.find( '.fl-module img' );
2609
2610			if ( $( '#' + stylesId ).length ) {
2611				return;
2612			}
2613
2614			images.each( function( i ) {
2615				var image           = $( this ),
2616					height          = image.height(),
2617					node            = image.closest( '.fl-module' ).data( 'node' ),
2618					className       = 'fl-node-' + node + '-img-' + i,
2619					maxMegaMenu     = image.closest( '.max-mega-menu' ).length,
2620					imageInLightbox = image.closest( '.fl-button-lightbox-content' ).length,
2621					imageInNavMenu  = image.closest( 'li.menu-item' ).length;
2622
2623				if ( ! ( imageInLightbox || imageInNavMenu || maxMegaMenu  ) ) {
2624					image.addClass( className );
2625					styles += '.' + className + ' { max-height: ' + ( height ? height : image[0].height )  + 'px }';
2626				}
2627
2628			} );
2629
2630			if ( '' !== styles ) {
2631				head.append( '<style id="' + stylesId + '">' + styles + '</style>' );
2632			}
2633		},
2634
2635		/**
2636		 * Removes max height on images in modules for smooth scrolling.
2637		 *
2638		 * @since 1.1.1
2639		 * @access private
2640		 * @method _removeImageMaxHeight
2641		 */
2642		_removeImageMaxHeight: function()
2643		{
2644			$( '#fl-header-styles-' + this.header.data( 'post-id' ) ).remove();
2645		},
2646	};
2647
2648	$( function() { FLThemeBuilderHeaderLayout.init(); } );
2649
2650})(jQuery);
2651
2652/*!
2653 * Bowser - a browser detector
2654 * https://github.com/ded/bowser
2655 * MIT License | (c) Dustin Diaz 2015
2656 */
2657
2658!function (name, definition) {
2659  if (typeof module != 'undefined' && module.exports) module.exports = definition()
2660  else if (typeof define == 'function' && define.amd) define(name, definition)
2661  else this[name] = definition()
2662}('bowser', function () {
2663  /**
2664    * See useragents.js for examples of navigator.userAgent
2665    */
2666
2667  var t = true
2668
2669  function detect(ua) {
2670
2671    function getFirstMatch(regex) {
2672      var match = ua.match(regex);
2673      return (match && match.length > 1 && match[1]) || '';
2674    }
2675
2676    function getSecondMatch(regex) {
2677      var match = ua.match(regex);
2678      return (match && match.length > 1 && match[2]) || '';
2679    }
2680
2681    var iosdevice = getFirstMatch(/(ipod|iphone|ipad)/i).toLowerCase()
2682      , likeAndroid = /like android/i.test(ua)
2683      , android = !likeAndroid && /android/i.test(ua)
2684      , nexusMobile = /nexus\s*[0-6]\s*/i.test(ua)
2685      , nexusTablet = !nexusMobile && /nexus\s*[0-9]+/i.test(ua)
2686      , chromeos = /CrOS/.test(ua)
2687      , silk = /silk/i.test(ua)
2688      , sailfish = /sailfish/i.test(ua)
2689      , tizen = /tizen/i.test(ua)
2690      , webos = /(web|hpw)os/i.test(ua)
2691      , windowsphone = /windows phone/i.test(ua)
2692      , windows = !windowsphone && /windows/i.test(ua)
2693      , mac = !iosdevice && !silk && /macintosh/i.test(ua)
2694      , linux = !android && !sailfish && !tizen && !webos && /linux/i.test(ua)
2695      , edgeVersion = getFirstMatch(/edge\/(\d+(\.\d+)?)/i)
2696      , versionIdentifier = getFirstMatch(/version\/(\d+(\.\d+)?)/i)
2697      , tablet = /tablet/i.test(ua)
2698      , mobile = !tablet && /[^-]mobi/i.test(ua)
2699      , xbox = /xbox/i.test(ua)
2700      , result
2701
2702    if (/opera|opr|opios/i.test(ua)) {
2703      result = {
2704        name: 'Opera'
2705      , opera: t
2706      , version: versionIdentifier || getFirstMatch(/(?:opera|opr|opios)[\s\/](\d+(\.\d+)?)/i)
2707      }
2708    }
2709    else if (/coast/i.test(ua)) {
2710      result = {
2711        name: 'Opera Coast'
2712        , coast: t
2713        , version: versionIdentifier || getFirstMatch(/(?:coast)[\s\/](\d+(\.\d+)?)/i)
2714      }
2715    }
2716    else if (/yabrowser/i.test(ua)) {
2717      result = {
2718        name: 'Yandex Browser'
2719      , yandexbrowser: t
2720      , version: versionIdentifier || getFirstMatch(/(?:yabrowser)[\s\/](\d+(\.\d+)?)/i)
2721      }
2722    }
2723    else if (/ucbrowser/i.test(ua)) {
2724      result = {
2725          name: 'UC Browser'
2726        , ucbrowser: t
2727        , version: getFirstMatch(/(?:ucbrowser)[\s\/](\d+(?:\.\d+)+)/i)
2728      }
2729    }
2730    else if (/mxios/i.test(ua)) {
2731      result = {
2732        name: 'Maxthon'
2733        , maxthon: t
2734        , version: getFirstMatch(/(?:mxios)[\s\/](\d+(?:\.\d+)+)/i)
2735      }
2736    }
2737    else if (/epiphany/i.test(ua)) {
2738      result = {
2739        name: 'Epiphany'
2740        , epiphany: t
2741        , version: getFirstMatch(/(?:epiphany)[\s\/](\d+(?:\.\d+)+)/i)
2742      }
2743    }
2744    else if (/puffin/i.test(ua)) {
2745      result = {
2746        name: 'Puffin'
2747        , puffin: t
2748        , version: getFirstMatch(/(?:puffin)[\s\/](\d+(?:\.\d+)?)/i)
2749      }
2750    }
2751    else if (/sleipnir/i.test(ua)) {
2752      result = {
2753        name: 'Sleipnir'
2754        , sleipnir: t
2755        , version: getFirstMatch(/(?:sleipnir)[\s\/](\d+(?:\.\d+)+)/i)
2756      }
2757    }
2758    else if (/k-meleon/i.test(ua)) {
2759      result = {
2760        name: 'K-Meleon'
2761        , kMeleon: t
2762        , version: getFirstMatch(/(?:k-meleon)[\s\/](\d+(?:\.\d+)+)/i)
2763      }
2764    }
2765    else if (windowsphone) {
2766      result = {
2767        name: 'Windows Phone'
2768      , windowsphone: t
2769      }
2770      if (edgeVersion) {
2771        result.msedge = t
2772        result.version = edgeVersion
2773      }
2774      else {
2775        result.msie = t
2776        result.version = getFirstMatch(/iemobile\/(\d+(\.\d+)?)/i)
2777      }
2778    }
2779    else if (/msie|trident/i.test(ua)) {
2780      result = {
2781        name: 'Internet Explorer'
2782      , msie: t
2783      , version: getFirstMatch(/(?:msie |rv:)(\d+(\.\d+)?)/i)
2784      }
2785    } else if (chromeos) {
2786      result = {
2787        name: 'Chrome'
2788      , chromeos: t
2789      , chromeBook: t
2790      , chrome: t
2791      , version: getFirstMatch(/(?:chrome|crios|crmo)\/(\d+(\.\d+)?)/i)
2792      }
2793    } else if (/chrome.+? edge/i.test(ua)) {
2794      result = {
2795        name: 'Microsoft Edge'
2796      , msedge: t
2797      , version: edgeVersion
2798      }
2799    }
2800    else if (/vivaldi/i.test(ua)) {
2801      result = {
2802        name: 'Vivaldi'
2803        , vivaldi: t
2804        , version: getFirstMatch(/vivaldi\/(\d+(\.\d+)?)/i) || versionIdentifier
2805      }
2806    }
2807    else if (sailfish) {
2808      result = {
2809        name: 'Sailfish'
2810      , sailfish: t
2811      , version: getFirstMatch(/sailfish\s?browser\/(\d+(\.\d+)?)/i)
2812      }
2813    }
2814    else if (/seamonkey\//i.test(ua)) {
2815      result = {
2816        name: 'SeaMonkey'
2817      , seamonkey: t
2818      , version: getFirstMatch(/seamonkey\/(\d+(\.\d+)?)/i)
2819      }
2820    }
2821    else if (/firefox|iceweasel|fxios/i.test(ua)) {
2822      result = {
2823        name: 'Firefox'
2824      , firefox: t
2825      , version: getFirstMatch(/(?:firefox|iceweasel|fxios)[ \/](\d+(\.\d+)?)/i)
2826      }
2827      if (/\((mobile|tablet);[^\)]*rv:[\d\.]+\)/i.test(ua)) {
2828        result.firefoxos = t
2829      }
2830    }
2831    else if (silk) {
2832      result =  {
2833        name: 'Amazon Silk'
2834      , silk: t
2835      , version : getFirstMatch(/silk\/(\d+(\.\d+)?)/i)
2836      }
2837    }
2838    else if (/phantom/i.test(ua)) {
2839      result = {
2840        name: 'PhantomJS'
2841      , phantom: t
2842      , version: getFirstMatch(/phantomjs\/(\d+(\.\d+)?)/i)
2843      }
2844    }
2845    else if (/slimerjs/i.test(ua)) {
2846      result = {
2847        name: 'SlimerJS'
2848        , slimer: t
2849        , version: getFirstMatch(/slimerjs\/(\d+(\.\d+)?)/i)
2850      }
2851    }
2852    else if (/blackberry|\bbb\d+/i.test(ua) || /rim\stablet/i.test(ua)) {
2853      result = {
2854        name: 'BlackBerry'
2855      , blackberry: t
2856      , version: versionIdentifier || getFirstMatch(/blackberry[\d]+\/(\d+(\.\d+)?)/i)
2857      }
2858    }
2859    else if (webos) {
2860      result = {
2861        name: 'WebOS'
2862      , webos: t
2863      , version: versionIdentifier || getFirstMatch(/w(?:eb)?osbrowser\/(\d+(\.\d+)?)/i)
2864      };
2865      if( /touchpad\//i.test(ua) ){
2866        result.touchpad = t;
2867      }
2868    }
2869    else if (/bada/i.test(ua)) {
2870      result = {
2871        name: 'Bada'
2872      , bada: t
2873      , version: getFirstMatch(/dolfin\/(\d+(\.\d+)?)/i)
2874      };
2875    }
2876    else if (tizen) {
2877      result = {
2878        name: 'Tizen'
2879      , tizen: t
2880      , version: getFirstMatch(/(?:tizen\s?)?browser\/(\d+(\.\d+)?)/i) || versionIdentifier
2881      };
2882    }
2883    else if (/qupzilla/i.test(ua)) {
2884      result = {
2885        name: 'QupZilla'
2886        , qupzilla: t
2887        , version: getFirstMatch(/(?:qupzilla)[\s\/](\d+(?:\.\d+)+)/i) || versionIdentifier
2888      }
2889    }
2890    else if (/chromium/i.test(ua)) {
2891      result = {
2892        name: 'Chromium'
2893        , chromium: t
2894        , version: getFirstMatch(/(?:chromium)[\s\/](\d+(?:\.\d+)?)/i) || versionIdentifier
2895      }
2896    }
2897    else if (/chrome|crios|crmo/i.test(ua)) {
2898      result = {
2899        name: 'Chrome'
2900        , chrome: t
2901        , version: getFirstMatch(/(?:chrome|crios|crmo)\/(\d+(\.\d+)?)/i)
2902      }
2903    }
2904    else if (android) {
2905      result = {
2906        name: 'Android'
2907        , version: versionIdentifier
2908      }
2909    }
2910    else if (/safari|applewebkit/i.test(ua)) {
2911      result = {
2912        name: 'Safari'
2913      , safari: t
2914      }
2915      if (versionIdentifier) {
2916        result.version = versionIdentifier
2917      }
2918    }
2919    else if (iosdevice) {
2920      result = {
2921        name : iosdevice == 'iphone' ? 'iPhone' : iosdevice == 'ipad' ? 'iPad' : 'iPod'
2922      }
2923      // WTF: version is not part of user agent in web apps
2924      if (versionIdentifier) {
2925        result.version = versionIdentifier
2926      }
2927    }
2928    else if(/googlebot/i.test(ua)) {
2929      result = {
2930        name: 'Googlebot'
2931      , googlebot: t
2932      , version: getFirstMatch(/googlebot\/(\d+(\.\d+))/i) || versionIdentifier
2933      }
2934    }
2935    else {
2936      result = {
2937        name: getFirstMatch(/^(.*)\/(.*) /),
2938        version: getSecondMatch(/^(.*)\/(.*) /)
2939     };
2940   }
2941
2942    // set webkit or gecko flag for browsers based on these engines
2943    if (!result.msedge && /(apple)?webkit/i.test(ua)) {
2944      if (/(apple)?webkit\/537\.36/i.test(ua)) {
2945        result.name = result.name || "Blink"
2946        result.blink = t
2947      } else {
2948        result.name = result.name || "Webkit"
2949        result.webkit = t
2950      }
2951      if (!result.version && versionIdentifier) {
2952        result.version = versionIdentifier
2953      }
2954    } else if (!result.opera && /gecko\//i.test(ua)) {
2955      result.name = result.name || "Gecko"
2956      result.gecko = t
2957      result.version = result.version || getFirstMatch(/gecko\/(\d+(\.\d+)?)/i)
2958    }
2959
2960    // set OS flags for platforms that have multiple browsers
2961    if (!result.msedge && (android || result.silk)) {
2962      result.android = t
2963    } else if (iosdevice) {
2964      result[iosdevice] = t
2965      result.ios = t
2966    } else if (mac) {
2967      result.mac = t
2968    } else if (xbox) {
2969      result.xbox = t
2970    } else if (windows) {
2971      result.windows = t
2972    } else if (linux) {
2973      result.linux = t
2974    }
2975
2976    // OS version extraction
2977    var osVersion = '';
2978    if (result.windowsphone) {
2979      osVersion = getFirstMatch(/windows phone (?:os)?\s?(\d+(\.\d+)*)/i);
2980    } else if (iosdevice) {
2981      osVersion = getFirstMatch(/os (\d+([_\s]\d+)*) like mac os x/i);
2982      osVersion = osVersion.replace(/[_\s]/g, '.');
2983    } else if (android) {
2984      osVersion = getFirstMatch(/android[ \/-](\d+(\.\d+)*)/i);
2985    } else if (result.webos) {
2986      osVersion = getFirstMatch(/(?:web|hpw)os\/(\d+(\.\d+)*)/i);
2987    } else if (result.blackberry) {
2988      osVersion = getFirstMatch(/rim\stablet\sos\s(\d+(\.\d+)*)/i);
2989    } else if (result.bada) {
2990      osVersion = getFirstMatch(/bada\/(\d+(\.\d+)*)/i);
2991    } else if (result.tizen) {
2992      osVersion = getFirstMatch(/tizen[\/\s](\d+(\.\d+)*)/i);
2993    }
2994    if (osVersion) {
2995      result.osversion = osVersion;
2996    }
2997
2998    // device type extraction
2999    var osMajorVersion = osVersion.split('.')[0];
3000    if (
3001         tablet
3002      || nexusTablet
3003      || iosdevice == 'ipad'
3004      || (android && (osMajorVersion == 3 || (osMajorVersion >= 4 && !mobile)))
3005      || result.silk
3006    ) {
3007      result.tablet = t
3008    } else if (
3009         mobile
3010      || iosdevice == 'iphone'
3011      || iosdevice == 'ipod'
3012      || android
3013      || nexusMobile
3014      || result.blackberry
3015      || result.webos
3016      || result.bada
3017    ) {
3018      result.mobile = t
3019    }
3020
3021    // Graded Browser Support
vendor: 4,367 bytes, lines 3022-3164
3022    // http://developer.yahoo.com/yui/articles/gbs
3023    if (result.msedge ||
3024        (result.msie && result.version >= 10) ||
3025        (result.yandexbrowser && result.version >= 15) ||
3026		    (result.vivaldi && result.version >= 1.0) ||
3027        (result.chrome && result.version >= 20) ||
3028        (result.firefox && result.version >= 20.0) ||
3029        (result.safari && result.version >= 6) ||
3030        (result.opera && result.version >= 10.0) ||
3031        (result.ios && result.osversion && result.osversion.split(".")[0] >= 6) ||
3032        (result.blackberry && result.version >= 10.1)
3033        || (result.chromium && result.version >= 20)
3034        ) {
3035      result.a = t;
3036    }
3037    else if ((result.msie && result.version < 10) ||
3038        (result.chrome && result.version < 20) ||
3039        (result.firefox && result.version < 20.0) ||
3040        (result.safari && result.version < 6) ||
3041        (result.opera && result.version < 10.0) ||
3042        (result.ios && result.osversion && result.osversion.split(".")[0] < 6)
3043        || (result.chromium && result.version < 20)
3044        ) {
3045      result.c = t
3046    } else result.x = t
3047
3048    return result
3049  }
3050
3051  var bowser = detect(typeof navigator !== 'undefined' ? navigator.userAgent : '')
3052
3053  bowser.test = function (browserList) {
3054    for (var i = 0; i < browserList.length; ++i) {
3055      var browserItem = browserList[i];
3056      if (typeof browserItem=== 'string') {
3057        if (browserItem in bowser) {
3058          return true;
3059        }
3060      }
3061    }
3062    return false;
3063  }
3064
3065  /**
3066   * Get version precisions count
3067   *
3068   * @example
3069   *   getVersionPrecision("1.10.3") // 3
3070   *
3071   * @param  {string} version
3072   * @return {number}
3073   */
3074  function getVersionPrecision(version) {
3075    return version.split(".").length;
3076  }
3077
3078  /**
3079   * Array::map polyfill
3080   *
3081   * @param  {Array} arr
3082   * @param  {Function} iterator
3083   * @return {Array}
3084   */
3085  function map(arr, iterator) {
3086    var result = [], i;
3087    if (Array.prototype.map) {
3088      return Array.prototype.map.call(arr, iterator);
3089    }
3090    for (i = 0; i < arr.length; i++) {
3091      result.push(iterator(arr[i]));
3092    }
3093    return result;
3094  }
3095
3096  /**
3097   * Calculate browser version weight
3098   *
3099   * @example
3100   *   compareVersions(['1.10.2.1',  '1.8.2.1.90'])    // 1
3101   *   compareVersions(['1.010.2.1', '1.09.2.1.90']);  // 1
3102   *   compareVersions(['1.10.2.1',  '1.10.2.1']);     // 0
3103   *   compareVersions(['1.10.2.1',  '1.0800.2']);     // -1
3104   *
3105   * @param  {Array<String>} versions versions to compare
3106   * @return {Number} comparison result
3107   */
3108  function compareVersions(versions) {
3109    // 1) get common precision for both versions, for example for "10.0" and "9" it should be 2
3110    var precision = Math.max(getVersionPrecision(versions[0]), getVersionPrecision(versions[1]));
3111    var chunks = map(versions, function (version) {
3112      var delta = precision - getVersionPrecision(version);
3113
3114      // 2) "9" -> "9.0" (for precision = 2)
3115      version = version + new Array(delta + 1).join(".0");
3116
3117      // 3) "9.0" -> ["000000000"", "000000009"]
3118      return map(version.split("."), function (chunk) {
3119        return new Array(20 - chunk.length).join("0") + chunk;
3120      }).reverse();
3121    });
3122
3123    // iterate in reverse order by reversed chunks array
3124    while (--precision >= 0) {
3125      // 4) compare: "000000009" > "000000010" = false (but "9" > "10" = true)
3126      if (chunks[0][precision] > chunks[1][precision]) {
3127        return 1;
3128      }
3129      else if (chunks[0][precision] === chunks[1][precision]) {
3130        if (precision === 0) {
3131          // all version chunks are same
3132          return 0;
3133        }
3134      }
3135      else {
3136        return -1;
3137      }
3138    }
3139  }
3140
3141  /**
3142   * Check if browser is unsupported
3143   *
3144   * @example
3145   *   bowser.isUnsupportedBrowser({
3146   *     msie: "10",
3147   *     firefox: "23",
3148   *     chrome: "29",
3149   *     safari: "5.1",
3150   *     opera: "16",
3151   *     phantom: "534"
3152   *   });
3153   *
3154   * @param  {Object}  minVersions map of minimal version to browser
3155   * @param  {Boolean} [strictMode = false] flag to return false if browser wasn't found in map
3156   * @param  {String}  [ua] user agent string
3157   * @return {Boolean}
3158   */
3159  function isUnsupportedBrowser(minVersions, strictMode, ua) {
3160    var _bowser = bowser;
3161
3162    // make strictMode param optional with ua param usage
3163    if (typeof strictMode === 'string') {
3164      ua = strictMode;
3165      strictMode = void(0);
3166    }
3167
3168    if (strictMode === void(0)) {
3169      strictMode = false;
3170    }
3171    if (ua) {
3172      _bowser = detect(ua);
3173    }
3174
3175    var version = "" + _bowser.version;
3176    for (var browser in minVersions) {
3177      if (minVersions.hasOwnProperty(browser)) {
3178        if (_bowser[browser]) {
3179          // browser version and min supported version.
3180          return compareVersions([version, minVersions[browser]]) < 0;
3181        }
3182      }
3183    }
3184
3185    return strictMode; // not found
3186  }
3187
3188  /**
3189   * Check if browser is supported
3190   *
3191   * @param  {Object} minVersions map of minimal version to browser
3192   * @param  {Boolean} [strictMode = false] flag to return false if browser wasn't found in map
3193   * @param  {String}  [ua] user agent string
3194   * @return {Boolean}
3195   */
3196  function check(minVersions, strictMode, ua) {
3197    return !isUnsupportedBrowser(minVersions, strictMode, ua);
3198  }
3199
3200  bowser.isUnsupportedBrowser = isUnsupportedBrowser;
3201  bowser.compareVersions = compareVersions;
3202  bowser.check = check;
3203
3204  /*
3205   * Set our detect method to the main bowser object so we can
3206   * reuse it to test other user agents.
3207   * This is needed to implement future tests.
3208   */
3209  bowser._detect = detect;
3210
3211  return bowser
3212});
3213
3214(function($){
3215  UABBTrigger = {
3216
3217      /**
3218       * Trigger a hook.
3219       *
3220       * @since 1.1.0.3
3221       * @method triggerHook
3222       * @param {String} hook The hook to trigger.
3223       * @param {Array} args An array of args to pass to the hook.
3224       */
3225      triggerHook: function( hook, args )
3226      {
3227        $( 'body' ).trigger( 'uabb-trigger.' + hook, args );
3228      },
3229    
3230      /**
3231       * Add a hook.
3232       *
3233       * @since 1.1.0.3
3234       * @method addHook
3235       * @param {String} hook The hook to add.
3236       * @param {Function} callback A function to call when the hook is triggered.
3237       */
3238      addHook: function( hook, callback )
3239      {
3240        $( 'body' ).on( 'uabb-trigger.' + hook, callback );
3241      },
3242    
3243      /**
3244       * Remove a hook.
3245       *
3246       * @since 1.1.0.3
3247       * @method removeHook
3248       * @param {String} hook The hook to remove.
3249       * @param {Function} callback The callback function to remove.
3250       */
3251      removeHook: function( hook, callback )
3252      {
3253        $( 'body' ).off( 'uabb-trigger.' + hook, callback );
3254      },
3255  };
3256})(jQuery);
3257
3258jQuery(document).ready(function( $ ) {
3259
3260    if( typeof bowser !== 'undefined' && bowser !== null ) {
3261
3262      var uabb_browser   = bowser.name,
3263          uabb_browser_v = bowser.version,
3264          uabb_browser_class = uabb_browser.replace(/\s+/g, '-').toLowerCase(),
3265          uabb_browser_v_class = uabb_browser_class + parseInt( uabb_browser_v );
3266      
3267      $('html').addClass(uabb_browser_class).addClass(uabb_browser_v_class);
3268      
3269    }
3270
3271    $('.uabb-row-separator').parents('html').css('overflow-x', 'hidden');
3272});
3273jQuery(function($) {
3274	
3275		$(function() {
3276		$( '.fl-node-5c5aca54d6db4 .fl-photo-img' )
3277			.on( 'mouseenter', function( e ) {
3278				$( this ).data( 'title', $( this ).attr( 'title' ) ).removeAttr( 'title' );
3279			} )
3280			.on( 'mouseleave', function( e ){
3281				$( this ).attr( 'title', $( this ).data( 'title' ) ).data( 'title', null );
3282			} );
3283	});
3284		window._fl_string_to_slug_regex = 'a-zA-Z0-9';
3285});
3286
3287;/* eslint-disable no-undef */
3288(function($) {
3289
3290	/**
3291	 * Class for Menu Module
3292	 *
3293	 * @since 1.6.1
3294	 */
3295	FLBuilderMenu = function( settings ){
3296
3297		// set params
3298		this.nodeId              = settings.id;
3299		this.nodeClass           = '.fl-node-' + settings.id;
3300		this.wrapperClass        = this.nodeClass + ' .fl-menu';
3301		this.type				 				 = settings.type;
3302		this.mobileToggle		     = settings.mobile;
3303		this.mobileBelowRow		   = settings.mobileBelowRow;
3304		this.mobileFlyout		     = settings.mobileFlyout;
3305		this.breakPoints         = settings.breakPoints;
3306		this.mobileBreakpoint	 	 = settings.mobileBreakpoint;
3307		this.currentBrowserWidth = $( window ).width();
3308		this.postId              = settings.postId;
3309		this.mobileStacked       = settings.mobileStacked;
3310		this.submenuIcon         = settings.submenuIcon;
3311		this.flyoutWidth         = settings.flyoutWidth;
3312
3313		// initialize the menu
3314		this._initMenu();
3315
3316		// check if viewport is resizing
3317		$( window ).on( 'resize', $.proxy( function() {
3318
3319			var width = $( window ).width();
3320
3321			// if screen width is resized, reload the menu
3322		    if( width != this.currentBrowserWidth ){
3323
3324				this.currentBrowserWidth = width;
3325				this._initMenu( true );
3326 				this._clickOrHover( true );
3327			}
3328
3329			this._resizeFlyoutMenuPanel();
3330		}, this ) );
3331
3332		$( window ).on( 'scroll', $.proxy( function() {
3333			this._resizeFlyoutMenuPanel();
3334		}, this ) );
3335
3336		// Move focus to the first menu item if the layout is set to BelowRow
3337		$( this.wrapperClass ).on( 'keydown', '.fl-menu-mobile-toggle, .menu-item:first a:first', $.proxy( function ( event ) {
3338			// Make sure it is a tab key with both the menu toggle enabled & below row layout set
3339			if ( event.key !== 'Tab' || ! this._isMenuToggle() || ! this._isMobileBelowRowEnabled() ) {
3340				return;
3341			}
3342			// Trigger focus on the mobile toggle button if the user is shift tabbing from the first menu item
3343			if ( event.shiftKey && $( event.currentTarget ).is( 'a' ) ) {
3344				event.preventDefault();
3345				$( this.wrapperClass ).find( '.fl-menu-mobile-toggle' ).trigger( 'focus' );
3346			}
3347			// Trigger focus on the first menu item if the user is tabbing from the mobile toggle button
3348			else if ( ! event.shiftKey && $( event.currentTarget ).hasClass( 'fl-menu-mobile-toggle' ) && $( event.currentTarget ).hasClass( 'fl-active' )  ) {
3349				event.preventDefault();
3350				$( this.wrapperClass ).find( '.menu-item' ).first().find( 'a' ).first().trigger( 'focus' );
3351			}
3352		}, this ) );
3353
3354		// Close mobile menu or accordion when tabbing out from the first or last menu item
3355		$( this.wrapperClass ).on( 'focusout', $.proxy( function ( event ) {
3356			if ( $( this.wrapperClass + ' nav' ).has( $( event.relatedTarget ) ).length === 0 ) {
3357				if ( this.type === 'accordion' ) {
3358					this._toggleSubmenu( $( event.target ).parents( '.fl-has-submenu' ).last(), false );
3359				}
3360				else {
3361					this._clickOrHover( true );
3362				}
3363				const mobileToggle = $( this.wrapperClass ).find( '.fl-menu-mobile-toggle' );
3364				if ( this._isMenuToggle() && mobileToggle.hasClass( 'fl-active' ) && ! $( event.relatedTarget ).is( mobileToggle ) && 'expanded' !== this.mobileToggle ) {
3365					mobileToggle.trigger( 'click' );
3366				}
3367			}
3368		}, this ) );
3369
3370	};
3371
3372	FLBuilderMenu.prototype = {
3373		nodeClass		: '',
3374		wrapperClass: '',
3375		type				: '',
3376		breakPoints	: {},
3377		$submenus		: null,
3378
3379		/**
3380		 * Check if the screen size fits a mobile viewport.
3381		 *
3382		 * @since  1.6.1
3383		 * @return bool
3384		 */
3385		_isMobile: function(){
3386			return this.currentBrowserWidth <= this.breakPoints.small ? true : false;
3387		},
3388
3389		/**
3390		 * Check if the device is connected to a mouse.
3391		 * 
3392		 * @since  2.9.0
3393		 * @return bool
3394		 */
3395		_isMouseAvailable: function(){
3396			return window.matchMedia("(pointer: fine) and (hover: hover)").matches;
3397		},
3398
3399		/**
3400		 * Check if the screen size fits a medium viewport.
3401		 *
3402		 * @since  1.10.5
3403		 * @return bool
3404		 */
3405		_isMedium: function(){
3406			return this.currentBrowserWidth <= this.breakPoints.medium ? true : false;
3407		},
3408
3409		/**
3410		 * Check if the screen size fits a large viewport.
3411		 *
3412		 * @since  1.10.5
3413		 * @return bool
3414		 */
3415		_isLarge: function(){
3416			return this.currentBrowserWidth <= this.breakPoints.large ? true : false;
3417		},
3418
3419		/**
3420		 * Check if the menu should toggle for the current viewport base on the selected breakpoint.
3421		 *
3422		 * @see 	 this._isMobile()
3423		 * @see 	 this._isMedium()
3424		 * @since  1.10.5
3425		 * @return bool
3426		 */
3427		_isMenuToggle: function(){
3428			if ( ( 'always' == this.mobileBreakpoint
3429				|| ( this._isMobile() && 'mobile' == this.mobileBreakpoint )
3430				|| ( this._isMedium() && 'medium-mobile' == this.mobileBreakpoint )
3431				|| ( this._isLarge() && 'large-mobile' == this.mobileBreakpoint )
3432			) && ( $( this.wrapperClass ).find( '.fl-menu-mobile-toggle' ).is(':visible') || 'expanded' == this.mobileToggle ) ) {
3433				return true;
3434			}
3435
3436			return false;
3437		},
3438
3439		/**
3440		 * Initialize the toggle logic for the menu.
3441		 *
3442		 * @see    this._isMenuToggle()
3443		 * @see    this._menuOnCLick()
3444		 * @see    this._clickOrHover()
3445		 * @see    this._submenuOnRight()
3446		 * @see    this._submenuRowZindexFix()
3447		 * @see    this._toggleForMobile()
3448		 * @since  1.6.1
3449		 * @return void
3450		 */
3451		_initMenu: function( resized = false ){
3452			this._setupSubmenu();
3453			if ( ! resized ) {
3454				this._menuOnFocus();
3455				this._menuOnClick();
3456				this._menuOnEscape();
3457			}
3458			if ( $( this.nodeClass ).length && this.type == 'horizontal' ) {
3459				this._initMegaMenus();
3460			}
3461
3462			if( this._isMenuToggle() || this.type == 'accordion' ){
3463
3464				$( this.wrapperClass ).off( 'mouseenter mouseleave' );
3465				this._clickOrHover();
3466
3467			} else {
3468				this._submenuOnRight();
3469				this._submenuRowZindexFix();
3470			}
3471
3472			if( this.mobileToggle != 'expanded' ){
3473				this._toggleForMobile();
3474			}
3475
3476			if( $( this.wrapperClass ).find( '.fl-menu-search-item' ).length ){
3477				this._toggleMenuSearch();
3478			}
3479
3480			if( $( this.wrapperClass ).find( '.fl-menu-cart-item').length ){
3481				this._wooUpdateParams();
3482			}
3483		},
3484
3485		/**
3486		 * Whether the toggle behavior for submenus is through hovering or not.
3487		 *
3488		 * @since  2.5
3489		 * @return void
3490		 */
3491		_setupSubmenu: function() {
3492			if ( ! this._isMouseAvailable() || this._isMenuToggle() || this.type === 'accordion' ) {
3493				$( this.wrapperClass ).addClass( 'no-hover' );
3494			}
3495			else {
3496				$( this.wrapperClass ).removeClass( 'no-hover' );
3497			}
3498		},
3499
3500		/**
3501		 * Logic for menu items when focused.
3502		 *
3503		 * @since  1.9.0
3504		 * @return void
3505		 */
3506		_menuOnFocus: function(){
3507			$( this.wrapperClass ).on( 'focus', 'a:not(.fl-button), .fl-menu-toggle', $.proxy( function( event ) {
3508				const focusedMenuItem = $( event.currentTarget ).closest( '.menu-item' );
3509				const blurredMenuItem = $( event.relatedTarget ).closest( '.menu-item' );
3510				// In case the blurred & focused items are siblings
3511				if ( focusedMenuItem.closest( 'ul' ).is( blurredMenuItem.closest( 'ul' ) ) )	{
3512					// Check if the focus event is not between the link & submenu icon of the same menu item
3513					if ( ! focusedMenuItem.is( blurredMenuItem ) ) {
3514						this._toggleSubmenu( blurredMenuItem, false );
3515					}
3516				}
3517				// In case neither items are child & parent nor vice versa
3518				else if ( focusedMenuItem.has( blurredMenuItem ).length === blurredMenuItem.has( focusedMenuItem ).length ) {
3519					// Get the blurred item parent & is the sibling of the focused item
3520					blurredMenuItem.parents( '.fl-has-submenu' ).each( ( _, parent ) => {
3521						if ( focusedMenuItem.closest( 'ul' ).is( $( parent ).closest( 'ul' ) ) ) {
3522							this._toggleSubmenu( $( parent ), false );
3523							return false;
3524						}
3525					} );
3526				}
3527				// In case the blurred item is a child of the focused item
3528				else if ( focusedMenuItem.has( blurredMenuItem ).length ) {
3529					if ( this.type !== 'accordion' && this.submenuIcon === 'none' ) {
3530						this._toggleSubmenu( blurredMenuItem, false );
3531					}
3532				}
3533			}, this ) );
3534		},
3535
3536		/**
3537		 * Logic for menu items when Escape key is pressed.
3538		 *
3539		 * @since  2.7.1
3540		 * @return void
3541		 */
3542		_menuOnEscape: function(){
3543			$( this.wrapperClass ).on( 'keydown', $.proxy( function( event ){
3544				if ( event.key !== 'Escape' ) return;
3545				const menuItem = $( event.target ).closest( '.menu-item' );
3546				const mobileToggle = $( this.wrapperClass ).find( '.fl-menu-mobile-toggle' );
3547				// In case there is a focused menu item
3548				if ( menuItem.length || $( event.target ).hasClass( 'fl-menu-mobile-close' ) ) {
3549					// Close the search form if it is open
3550					if ( menuItem.hasClass( 'fl-menu-search-item' ) && $( this.wrapperClass ).find('.fl-search-form-input-wrap').is( ':visible' ) ) {
3551						$( this.wrapperClass ).find('.fl-menu-search-item .fl-button:is(a, button:not([type="submit"]))').trigger( 'focus' );
3552					}
3553					// Close all the submenus of the focused menu item
3554					else if ( menuItem.hasClass( 'fl-has-submenu' ) && menuItem.find( '.sub-menu' ).first().is( ':visible' ) ) {
3555						this._toggleSubmenu( menuItem, false );
3556					}
3557					else {
3558						// Shift focus to the parent while closing all its submenus
3559						const parentMenuItem = menuItem.parents( '.fl-has-submenu' ).not( '.mega-menu.hide-heading, .mega-menu-disabled.hide-heading' ).first();
3560						// Close the mobile menu if there is no parent menu item and the mobile toggle is active
3561						if ( parentMenuItem.length === 0 && this._isMenuToggle() && mobileToggle.hasClass( 'fl-active' ) ) {
3562							// Blur to trigger the focus-out event for closing the menu
3563							mobileToggle.trigger( 'blur' ).trigger( 'focus' );
3564						}
3565						// Close the parent submenu and shift focus to its link
3566						else if ( parentMenuItem.length !== 0 ) {
3567							this._toggleSubmenu( parentMenuItem, false );
3568							parentMenuItem.find( 'a' ).first().trigger( 'focus' );
3569						}
3570					}
3571				}
3572				// Close the mobile menu if the mobile toggle is active
3573				else if ( $( event.target ).hasClass( 'fl-menu-mobile-toggle' ) && mobileToggle.hasClass( 'fl-active' ) ) {
3574					// Blur to trigger the focus-out event for closing the menu
3575					mobileToggle.trigger( 'blur' ).trigger( 'focus' );
3576				}
3577			}, this ) );
3578		},
3579
3580		/**
3581		 * Logic for menu items when clicked.
3582		 *
3583		 * @since  1.6.1
3584		 * @return void
3585		 */
3586		_menuOnClick: function(){
3587			// Fallback for span elements and fake links to interact with the keyboard
3588			$( this.wrapperClass ).on( 'keydown', 'a:not(.fl-button, [href]), span.fl-menu-toggle', $.proxy( function( event ) {
3589				if ( event.key === 'Enter' || event.key === ' ' ) {
3590					event.preventDefault();
3591					$( event.currentTarget ).trigger( 'click' );
3592				}
3593			}, this ) );
3594			$( this.wrapperClass ).on( 'click', 'a, .fl-menu-toggle', $.proxy( function( event ) {
3595				// Only allow mouse clicks with accordion & mobile menus
3596				if ( this._isMouseAvailable() && ! this._isMenuToggle() && event.detail && this.type !== 'accordion' ) return;
3597				// Links only open & do not toggle submenus if there is either a submenu icon or an accordion layout
3598				if ( $( event.currentTarget ).is( 'a' ) && ( this.submenuIcon !== 'none' || this.type === 'accordion' ) ) return;
3599				const menuItem = $( event.currentTarget ).closest( '.menu-item, .fl-menu-logo' );
3600				const menuLink = menuItem.find( 'a' ).first().attr( 'href' );
3601				const submenuHidden = menuItem.find( '.sub-menu' ).first().is( ':hidden' );
3602				if ( typeof menuLink === 'undefined' || menuLink === '#' || submenuHidden ) {
3603					event.preventDefault();
3604				}
3605				if ( $( event.currentTarget ).hasClass( 'fl-menu-toggle' ) || submenuHidden ) {
3606					this._toggleSubmenu( menuItem, submenuHidden );
3607				}
3608			}, this ) );
3609		},
3610
3611		/**
3612		 * Controls toggling the visibility of all submenu items for desktop & mobile.
3613		 *
3614		 * @since  2.10
3615		 * @return void
3616		 */
3617		_toggleSubmenu: function ( menuItem, opened ) {
3618			const togglingClass = this._isMenuToggle() || this.type === 'accordion' ? 'fl-active' : 'focus';
3619			const toggleElement = this.submenuIcon === 'none' ? 'a' : '.fl-menu-toggle';
3620			const hiddenMenu = '.mega-menu.hide-heading, .mega-menu-disabled.hide-heading';
3621			if ( opened && menuItem.hasClass( 'fl-has-submenu' ) && ! menuItem.is( hiddenMenu ) ) {
3622				menuItem.addClass( togglingClass );
3623				menuItem.find( toggleElement ).first().attr( 'aria-expanded', true );
3624				if ( this._isMenuToggle() || this.type === 'accordion' ) {
3625					menuItem.find( '.sub-menu' ).first().filter( ':hidden' ).slideDown();
3626				}
3627			}
3628			else {
3629				menuItem.parent().find( '.menu-item' ).removeClass( togglingClass );
3630				menuItem.parent().find( '.fl-has-submenu' ).not( hiddenMenu ).find( toggleElement ).attr( 'aria-expanded', false );
3631				if ( this._isMenuToggle() || this.type === 'accordion' ) {
3632					menuItem.find( '.sub-menu' ).filter( ':visible' ).slideUp();
3633				}
3634			}
3635		},
3636
3637		/**
3638		 * Changes general styling and behavior of menus based on mobile / desktop viewport.
3639		 *
3640		 * @see    this._isMenuToggle()
3641		 * @since  1.6.1
3642		 * @return void
3643		 */
3644		_clickOrHover: function( clear = false ){
3645			const selector = this._isMobileBelowRowEnabled() ? this.nodeClass + '-clone' : this.nodeClass;
3646			this.$submenus = this.$submenus || $( selector ).find( '.sub-menu' );
3647
3648			const className = this._isMenuToggle() || this.type === 'accordion' ? 'fl-active' : 'focus';
3649			const toggleElement = this.submenuIcon === 'none' ? 'a' : '.fl-menu-toggle';
3650			const hiddenMenu = '.mega-menu.hide-heading, .mega-menu-disabled.hide-heading';
3651			$( selector ).find( '.fl-has-submenu' ).not( hiddenMenu ).each( function() {
3652				if( clear || ! $ ( this ).hasClass( className ) ){
3653					if ( clear ) $( this ).removeClass( className );
3654					$( this ).find( toggleElement ).first().attr( 'aria-expanded', false );
3655					if ( className === 'fl-active' ) {
3656						$( this ).find( '.sub-menu' ).fadeOut();
3657					} else if ( className === 'focus' ) {
3658						$( this ).find( '.sub-menu' ).css( {
3659							'display' : '',
3660							'opacity' : ''
3661						} );
3662					}
3663				}
3664			} );
3665		},
3666
3667		/**
3668		 * Logic to prevent submenus to go outside viewport boundaries.
3669		 *
3670		 * @since  1.6.1
3671		 * @return void
3672		 */
3673		_submenuOnRight: function(){
3674
3675			$( this.wrapperClass )
3676				.on( 'mouseenter focus', '.fl-has-submenu', $.proxy( function( e ){
3677
3678					if( $ ( e.currentTarget ).find('.sub-menu').length === 0 ) {
3679						return;
3680					}
3681
3682					var $link           = $( e.currentTarget ),
3683						$parent         = $link.parent(),
3684						$subMenu        = $link.find( '.sub-menu' ),
3685						subMenuWidth    = $subMenu.width(),
3686						subMenuPos      = 0,
3687						bodyWidth       = $( 'body' ).width();
3688
3689					if( $link.closest( '.fl-menu-submenu-right' ).length !== 0) {
3690
3691						$link.addClass( 'fl-menu-submenu-right' );
3692
3693					} else if( $( 'body' ).hasClass( 'rtl' ) ) {
3694
3695						subMenuPos = $parent.is( '.sub-menu' ) ?
3696									 $parent.offset().left - subMenuWidth:
3697									 $link.offset().left - $link.width() - subMenuWidth;
3698
3699						if( subMenuPos <= 0 ) {
3700							$link.addClass( 'fl-menu-submenu-right' );
3701						}
3702
3703					} else {
3704
3705						subMenuPos = $parent.is( '.sub-menu' ) ?
3706									 $parent.offset().left + $parent.width() + subMenuWidth :
3707									 $link.offset().left + $link.width() + subMenuWidth;
3708
3709						if( subMenuPos > bodyWidth ) {
3710							$link.addClass('fl-menu-submenu-right');
3711						}
3712					}
3713				}, this ) )
3714				.on( 'mouseleave', '.fl-has-submenu', $.proxy( function( e ){
3715					$( e.currentTarget ).removeClass( 'fl-menu-submenu-right' );
3716				}, this ) );
3717
3718		},
3719
3720		/**
3721		 * Logic to prevent submenus to go behind the next overlay row.
3722		 *
3723		 * @since  1.10.9
3724		 * @return void
3725		 */
3726		_submenuRowZindexFix: function(){
3727
3728			$( this.wrapperClass )
3729				.on( 'mouseenter', 'ul.menu > .fl-has-submenu', $.proxy( function( e ){
3730
3731					if( $ ( e.currentTarget ).find('.sub-menu').length === 0 ) {
3732						return;
3733					}
3734
3735					$( this.nodeClass )
3736						.closest( '.fl-row' )
3737						.find( '.fl-row-content' )
3738						.css( 'z-index', '10' );
3739
3740				}, this ) )
3741				.on( 'mouseleave', 'ul.menu > .fl-has-submenu', $.proxy( function(){
3742
3743					$( this.nodeClass )
3744						.closest( '.fl-row' )
3745						.find( '.fl-row-content' )
3746						.css( 'z-index', '' );
3747
3748				}, this ) );
3749		},
3750
3751		/**
3752		 * Logic for the mobile menu button.
3753		 *
3754		 * @since  1.6.1
3755		 * @return void
3756		 */
3757		_toggleForMobile: function(){
3758
3759			var $wrapper = null,
3760				$menu    = null,
3761				self     = this;
3762
3763			$( this.wrapperClass ).find( '.fl-menu-mobile-toggle' ).attr('aria-controls', $( this.wrapperClass ).find( 'ul.menu' ).attr('id'));
3764
3765			if( this._isMenuToggle() ){
3766
3767				if ( this._isMobileBelowRowEnabled() ) {
3768					this._placeMobileMenuBelowRow();
3769					$wrapper = $( this.wrapperClass );
3770					$menu    = $( this.nodeClass + '-clone' );
3771					$menu.find( 'ul.menu' ).show();
3772				}
3773				else {
3774					$wrapper = $( this.wrapperClass );
3775					$menu    = $wrapper.find( '.menu' );
3776				}
3777
3778				if( !$wrapper.find( '.fl-menu-mobile-toggle' ).hasClass( 'fl-active' ) && ! self.mobileFlyout ){
3779					$menu.css({ display: 'none' });
3780				}
3781
3782				// Flayout Menu
3783				if ( self.mobileFlyout ) {
3784					this._initFlyoutMenu();
3785				}
3786
3787				$wrapper.on( 'click', '.fl-menu-mobile-toggle', function( e ){
3788					e.stopImmediatePropagation();
3789
3790					$( this ).toggleClass( 'fl-active' );
3791
3792					if ( self.mobileFlyout ) {
3793						self._toggleFlyoutMenu();
3794						const flyoutWrapper = $( '.fl-menu-mobile-flyout' );
3795						if ( $( this ).hasClass( 'fl-active' ) ) {
3796							flyoutWrapper.attr( 'aria-hidden', false );
3797							flyoutWrapper.find( 'a[href], button, input, select, textarea, span.fl-menu-toggle, [tabindex="-1"]' ).attr( 'tabindex', 0 );
3798						}
3799						else {
3800							flyoutWrapper.attr( 'aria-hidden', true );
3801							flyoutWrapper.find( 'a[href], button, input, select, textarea, span.fl-menu-toggle, [tabindex]:not
3801([tabindex="-1"])' ).attr( 'tabindex', -1 );
3802						}
3803					}
3804					else {
3805						var targetMenu = null;
3806
3807						if ( self.mobileBelowRow ) {
3808							var $closestCol = $( this ).parents( '.fl-col, .fl-module-box' ),
3809								$closestColGroup = $closestCol.length ? $closestCol.parent( '.fl-col-group' ) : null;
3810								targetMenu  = $closestCol.length ? $closestCol.last().next( '.fl-menu-mobile-clone' ) : null;
3811
3812							if ( $closestColGroup.length ) {
3813								if ( $closestColGroup.hasClass( 'fl-col-group-responsive-reversed' ) ) {
3814									$closestColGroup.find( '.fl-menu-mobile-clone' ).css( 'order', -1 );
3815								} else if ( $closestColGroup ) {
3816									$closestColGroup.find( '.fl-menu-mobile-clone' ).css( 'order', 2 );
3817								}
3818							}
3819						} else {
3820							targetMenu = $( this ).closest( '.fl-menu' ).find( 'ul.menu' );
3821						}
3822						
3823						if ( targetMenu.length ) {
3824							$menu = $( targetMenu );
3825						}
3826
3827						$menu.slideToggle();
3828					}
3829
3830					e.stopPropagation();
3831				} );
3832
3833				// Hide active menu when click on anchor link ID that exists on a page
3834				$menu.off().on( 'click', '.menu-item > a[href*="#"]:not([href="#"])', function(){
3835					var $href = $(this).attr('href'),
3836						$targetID = $href.split('#')[1],
3837						element = $('#' + $targetID);
3838					if ( $('body').find(element).length > 0 ) {
3839						$( this ).toggleClass( 'fl-active' );
3840						FLBuilderLayout._scrollToElement( element );
3841						if ( ! self._isMenuToggle() ) {
3842							$menu.slideToggle();
3843						}
3844					}
3845				});
3846			}
3847			else {
3848
3849				if ( this._isMobileBelowRowEnabled() ) {
3850					this._removeMenuFromBelowRow();
3851				}
3852
3853				$wrapper = $( this.wrapperClass ),
3854				$menu    = $wrapper.find( 'ul.menu' );
3855				$wrapper.find( '.fl-menu-mobile-toggle' ).removeClass( 'fl-active' );
3856				$menu.css({ display: '' });
3857
3858				if ( ! this._isMobileBelowRowEnabled() ) {
3859					$menu.off( 'click', '.menu-item > a[href*="#"]:not([href="#"])' );
3860				}
3861
3862				if ( this.mobileFlyout && $wrapper.find( '.fl-menu-mobile-flyout' ).length > 0 ) {
3863					$( 'body' ).css( 'margin', '' );
3864					$( '.fl-builder-ui-pinned-content-transform' ).css( 'transform', '' );
3865					$menu.unwrap();
3866					$wrapper.find( '.fl-menu-mobile-close' ).remove();
3867					$wrapper.find( '.fl-menu-mobile-opacity' ).remove();
3868				}
3869			}
3870		},
3871
3872		/**
3873		 * Init any mega menus that exist.
3874		 *
3875		 * @see 	 this._isMenuToggle()
3876		 * @since  1.10.4
3877		 * @return void
3878		 */
3879		_initMegaMenus: function(){
3880
3881			var module     = $( this.nodeClass ),
3882				rowContent = module.closest( '.fl-row-content' ),
3883				rowWidth   = rowContent.width(),
3884				megas      = module.find( '.mega-menu' ),
3885				disabled   = module.find( '.mega-menu-disabled' ),
3886				isToggle   = this._isMenuToggle();
3887
3888			if ( isToggle ) {
3889				megas.removeClass( 'mega-menu' ).addClass( 'mega-menu-disabled' );
3890				module.find( 'li.mega-menu-disabled > ul.sub-menu' ).css( 'width', '' );
3891				rowContent.css( 'position', '' );
3892			} else {
3893				disabled.removeClass( 'mega-menu-disabled' ).addClass( 'mega-menu' );
3894				module.find( 'li.mega-menu > ul.sub-menu' ).css( 'width', rowWidth + 'px' );
3895				rowContent.css( 'position', 'relative' );
3896			}
3897		},
3898
3899		/**
3900		 * Check to see if Below Row should be enabled.
3901		 *
3902		 * @since  1.11
3903		 * @return boolean
3904		 */
3905		_isMobileBelowRowEnabled: function() {
3906			return this.mobileBelowRow && ( $( this.nodeClass ).parents( '.fl-col, .fl-module-box' ).length );
3907		},
3908
3909		/**
3910		 * Logic for putting the mobile menu below the menu's
3911		 * column so it spans the full width of the page.
3912		 *
3913		 * @since  1.10
3914		 * @return void
3915		 */
3916		_placeMobileMenuBelowRow: function(){
3917
3918			if ( $( this.nodeClass + '-clone' ).length ) {
3919				return;
3920			}
3921
3922			var module = $( this.nodeClass ),
3923				clone  = null,
3924				col    = module.parents( '.fl-col, .fl-module-box' ).last();
3925
3926			if ( module.length < 1 ) {
3927				return;
3928			}
3929
3930			clone = ( module.length > 1 ) ? $( module[0] ).clone() : module.clone();
3931			module.find( 'ul.menu' ).remove();
3932			clone.addClass( ( this.nodeClass + '-clone' ).replace( '.', '' ) );
3933			clone.addClass( 'fl-menu-mobile-clone' );
3934			clone.find( '.fl-menu-mobile-toggle' ).remove();
3935			col.after( clone );
3936
3937			// Removes animation when enabled
3938			if ( module.hasClass( 'fl-animation' ) ) {
3939				clone.removeClass( 'fl-animation' );
3940			}
3941
3942			this._menuOnFocus();
3943			this._menuOnClick();
3944			this._menuOnEscape();
3945		},
3946
3947		/**
3948		 * Logic for removing the mobile menu from below the menu's
3949		 * column and putting it back in the main wrapper.
3950		 *
3951		 * @since  1.10
3952		 * @return void
3953		 */
3954		_removeMenuFromBelowRow: function(){
3955
3956			if ( ! $( this.nodeClass + '-clone' ).length ) {
3957				return;
3958			}
3959
3960			var module = $( this.nodeClass ),
3961				clone  = $( this.nodeClass + '-clone' ),
3962				menu   = clone.find( 'ul.menu' ),
3963				nav    = module.find( 'nav' );
3964
3965			if ( nav.length ) {
3966				nav.append( menu );
3967			} else {
3968				module.find( '.fl-menu-mobile-toggle' ).after( menu );
3969			}
3970			clone.remove();
3971			menu.find( 'a' ).each( FLBuilderLayout._initAnchorLink );
3972		},
3973
3974		/**
3975		 * Logic for Flyout responsive menu.
3976		 *
3977		 * @since  2.2
3978		 * @return void
3979		 */
3980		_initFlyoutMenu: function(){
3981			var wrapper = $( this.wrapperClass ),
3982				menu  	= wrapper.find( 'ul.menu' ),
3983				button	= wrapper.find( '.fl-menu-mobile-toggle' );
3984
3985			if ( 0 === wrapper.find( '.fl-menu-mobile-flyout' ).length ) {
3986				menu.wrap( '<div class="fl-menu-mobile-flyout" aria-hidden="true"></div>' );
3987			}
3988
3989			if ( 0 === wrapper.find( '.fl-menu-mobile-close' ).length ) {
3990				var close = window.fl_responsive_close || 'Close'
3991				wrapper.find( '.fl-menu-mobile-flyout' ).prepend( '<button class="fl-menu-mobile-close fl-content-ui-button" aria-label="' + close + '"><i class="fas fa-times"></i></button>' );
3992			}
3993
3994			// Push with opacity
3995			if ( wrapper.hasClass( 'fl-menu-responsive-flyout-push-opacity' ) && 0 === wrapper.find( '.fl-menu-mobile-opacity' ).length ) {
3996				wrapper.append( '<div class="fl-menu-mobile-opacity"></div>' );
3997			}
3998
3999			wrapper.off( 'click', '.fl-menu-mobile-opacity, .fl-menu-mobile-close' ).on( 'click', '.fl-menu-mobile-opacity, .fl-menu-mobile-close', function(e){
4000				button.trigger('focus').trigger( 'click' );
4001				e.stopPropagation();
4002			});
4003
4004			if ( 'undefined' !== typeof FLBuilder ) {
4005				FLBuilder.addHook('restartEditingSession', function(){
4006					$( '.fl-builder-ui-pinned-content-transform' ).css( 'transform', '' );
4007
4008					// Toggle active menu
4009					if ( button.hasClass( 'fl-active' ) ) {
4010						button.trigger( 'click' );
4011					}
4012				});
4013			}
4014			$( '.fl-menu-mobile-flyout' ).find( 'a[href], button, input, select, textarea, span.fl-menu-toggle, [tabindex]:not([tabindex="-1"])' ).attr( 'tabindex', -1 );
4015		},
4016
4017		/**
4018		 * Logic to enable/disable the Flyout menu on button click.
4019		 *
4020		 * @since  2.2
4021		 * @return void
4022		 */
4023		_toggleFlyoutMenu: function(){
4024			var wrapper		= $( this.wrapperClass ),
4025				button		= wrapper.find( '.fl-menu-mobile-toggle' ),
4026				position 	= wrapper.hasClass( 'fl-flyout-right' ) ? 'right' : 'left',
4027				pushMenu 	= wrapper.hasClass( 'fl-menu-responsive-flyout-push' ) || wrapper.hasClass( 'fl-menu-responsive-flyout-push-opacity' ),
4028				opacity		= wrapper.find( '.fl-menu-mobile-opacity' ),
4029				marginPos	= {},
4030				fixedPos 	= {},
4031				fixedHeader	= $('header, header > div');
4032
4033			this._resizeFlyoutMenuPanel();
4034
4035			// Fix the push menu when builder ui panel is pinned
4036			if ( $( '.fl-builder-ui-pinned-content-transform' ).length > 0 && ! $( 'body' ).hasClass( 'fl-builder-edit' ) ) {
4037				$( '.fl-builder-ui-pinned-content-transform' ).css( 'transform', 'none' );
4038			}
4039
4040			if ( pushMenu ) {
4041				marginPos[ 'margin-' + position ] = button.hasClass( 'fl-active' ) ? this.flyoutWidth + 'px' : '0px';
4042				$( 'body' ).animate( marginPos, 200);
4043
4044				// Fixed header
4045				if ( fixedHeader.length > 0 ) {
4046					fixedPos[ position] = button.hasClass( 'fl-active' ) ? this.flyoutWidth + 'px' : '0px';
4047					fixedHeader.each(function(){
4048						if ( 'fixed' == $( this ).css( 'position' ) ) {
4049							$( this ).css({ 'transition' : 'none' });
4050							$( this ).animate( fixedPos, 200 );
4051						}
4052					});
4053				}
4054			}
4055
4056			if ( opacity.length > 0 && button.hasClass( 'fl-active' ) ) {
4057				opacity.show();
4058			}
4059			else {
4060				opacity.hide();
4061			}
4062		},
4063
4064		/**
4065		 * Resize or reposition the Flyout Menu Panel.
4066		 * 
4067		 * @since  2.8.1
4068		 * @return void
4069		 */
4070		_resizeFlyoutMenuPanel: function(){
4071			const wrapper    = $( this.wrapperClass );
4072			const wrapFlyout = wrapper.find( '.fl-menu-mobile-flyout' );
4073				
4074			if ( wrapFlyout.length > 0 ) {
4075				wrapFlyout.css( this._getFlyoutMenuPanelPosition() );
4076			}
4077		},
4078
4079		/**
4080		 * Compute the Flyout Menu Panel's position on the screen.
4081		 * 
4082		 * @since  2.8.1
4083		 * @return object
4084		 */
4085		_getFlyoutMenuPanelPosition: function() {
4086			var wrapper        = $( this.wrapperClass ),
4087				button         = wrapper.find( '.fl-menu-mobile-toggle' ),
4088				side           = wrapper.hasClass( 'fl-flyout-right' ) ? 'right' : 'left',
4089				winHeight      = $(window).outerHeight(),
4090				winTop         = $(window).scrollTop(),
4091				adminBarHeight = $( '#wpadminbar' ).length ? $( '#wpadminbar' ).height() : 0,
4092				flyoutPosition = {};
4093
4094			flyoutPosition[ side ]  = '-' + ( parseInt( this.flyoutWidth ) + 15 ) + 'px';
4095			if ( ! button.hasClass( 'fl-active' ) ) {
4096				return flyoutPosition;
4097			}
4098
4099			flyoutPosition[ side ]  = '0px';
4100			flyoutPosition[ 'height' ]  = winHeight + 'px';
4101			flyoutPosition[ 'top' ] = '0px';
4102			
4103			if ( adminBarHeight > 0 ) {
4104				const diff = adminBarHeight - winTop;
4105				flyoutPosition[ 'top' ] = diff <= 0 ? '0px' : (diff) + 'px';
4106			}
4107
4108			return flyoutPosition;
4109		},
4110
4111		/**
4112		 * Shows or hides the nav search form.
4113		 *
4114		 * @since  2.5
4115		 * @method _toggleMenuSearch
4116		 */
4117		_toggleMenuSearch: function(){
4118			const form   = $( this.wrapperClass ).find('.fl-menu-search-item .fl-search-form-input-wrap'); 
4119			const button = $( this.wrapperClass ).find('.fl-menu-search-item .fl-button:is(a, button:not([type="submit"]))');
4120			form.on('submit', () => form.stop().fadeToggle('fast'));
4121			// Close the search form when focus is lost
4122			form.on('focusout', (event) => {
4123				if (form.is(':visible') && form.has($(event.relatedTarget)).length === 0) {
4124					button.trigger('click');
4125				}
4126			});
4127			button.attr('aria-expanded', false);
4128			// Close other open submenus when focusing on the search button
4129			button.on('focus', (event) => {
4130				const parentMenus = $(event.relatedTarget).parents('.menu-item.fl-has-submenu');
4131				if (event.relatedTarget && parentMenus.length) {
4132					this._toggleSubmenu(parentMenus, false);
4133				}
4134			});
4135			button.on('click', (event) => {
4136				// Prevent toggling when clicking with mouse while the form is already open
4137				if (event.detail && event.type === 'click' && form.is(':visible')) return;
4138				form.stop().fadeToggle('fast', () => {
4139					button.attr('aria-expanded', form.is(':visible'));
4140					if(form.is(':visible')) {
4141						form.find('.fl-search-text').focus();
4142					}
4143				});
4144			});
4145		},
4146
4147		/**
4148		 * Adds menu node and post ID to WooCommerce ajax URL requests.
4149		 *
4150		 * @since  2.5
4151		 * @return void
4152		 */
4153		_wooUpdateParams: function() {
4154			if ( 'undefined' !== typeof wc_cart_fragments_params ) {
4155				wc_cart_fragments_params.wc_ajax_url += '&fl-menu-node='+ this.nodeId +'&post-id='+ this.postId;
4156			}
4157			if ( 'undefined' !== typeof wc_add_to_cart_params ) {
4158				wc_add_to_cart_params.wc_ajax_url += '&fl-menu-node='+ this.nodeId +'&post-id='+ this.postId;
4159			}
4160		},
4161	};
4162
4163})(jQuery);
4164
4165(function($) {
4166
4167	$(function() {
4168
4169		new FLBuilderMenu({
4170			id: '5cbecd6eb2e4a',
4171			type: 'vertical',
4172			mobile: 'expanded',
4173			mobileBelowRow: false,
4174			mobileFlyout: false,
4175			breakPoints: {
4176				large: 1200,
4177				medium: 1024,
4178				small: 750			},
4179			mobileBreakpoint: 'mobile',
4180			postId : '75',
4181			mobileStacked: true,
4182			submenuIcon: 'none',
4183			flyoutWidth: '250',
4184		});
4185
4186	});
4187
4188})(jQuery);
4189
4190/* Start Layout Custom JS */
4191
4192/* End Layout Custom JS */
4193
4194

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.