PageSourceSearch

https://repolera.se/wp-content/themes/enfold/js/avia-snippet-hamburger-menu.js?ver=5.2.1

js repolera.se collected 2026-09-27 15:10:40 UTC 15,950 bytes, 560 lines download raw bytes

1/*
2 * Implements the hamburger menu behaviour
3 *
4 *
5 * @since 4.8		moved from avia.js to own file as some user request to customize this feature
6 */
7(function($)
8{
9    "use strict";
10
11    $(function()
12    {
13		$.avia_utilities = $.avia_utilities || {};
14
15		if( 'undefined' == typeof $.avia_utilities.isMobile )
16		{
17			if( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) && 'ontouchstart' in document.documentElement )
18			{
19				$.avia_utilities.isMobile = true;
20			}
21			else
22			{
23				$.avia_utilities.isMobile = false;
24			}
25		}
26
27		//activates the hamburger mobile menu
28		avia_hamburger_menu();
29
30		$(window).trigger( 'resize' );
31
32	});
33
34	$.avia_utilities = $.avia_utilities || {};
35
36	function avia_hamburger_menu()
37	{
38		var header		= $('#header'),
39			header_main	= $('#main .av-logo-container'), //check if we got a top menu that is above the header
40			menu		= $('#avia-menu'),
41			burger_wrap = $('.av-burger-menu-main a'),
42			htmlEL  	= $('html').eq(0),
43			overlay		= $('<div class="av-burger-overlay"></div>'),
44			overlay_scroll	= $('<div class="av-burger-overlay-scroll"></div>').appendTo(overlay),
45			inner_overlay 	= $('<div class="av-burger-overlay-inner"></div>').appendTo(overlay_scroll),
46			bgColor 	  	= $('<div class="av-burger-overlay-bg"></div>').appendTo(overlay),
47			animating 	  	= false,
48			first_level	  	= {},
49			logo_container	= $('.av-logo-container .inner-container'),
50			menu_in_logo_container = logo_container.find('.main_menu'),
51			cloneFirst		= htmlEL.is('.html_av-submenu-display-click.html_av-submenu-clone, .html_av-submenu-display-hover.html_av-submenu-clone'),
52			menu_generated 	= false,
53			cloned_menu_cnt = 0;
54
55		/**
56		 * Check for alternate mobile menu
57		 */
58		var alternate = $('#avia_alternate_menu');
59		if( alternate.length > 0 )
60		{
61			menu = alternate;
62		}
63
64		var	set_list_container_height = function()
65			{
66				//necessary for ios since the height is usually not 100% but 100% - menu bar which can be requested by window.innerHeight
67				if($.avia_utilities.isMobile)
68				{
69					overlay_scroll.outerHeight(window.innerHeight);
70				}
71			},
72			create_list = function( items , append_to )
73			{
74				if(!items) return;
75
76				var list, link, current, subitems, megacolumns, sub_current, sub_current_list, new_li, new_ul;
77
78				items.each(function()
79				{
80					current  = $(this);
81					subitems = current.find(' > .sub-menu > li'); //find sublists of a regular defined menu
82					if( subitems.length == 0 )
83					{
84						subitems = current.find(' > .children > li'); //find sublists of a fallback menu
85					}
86					megacolumns = current.find( '.avia_mega_div > .sub-menu > li.menu-item' );
87
88					//	href = '#': we have a custom link that should not link to something - is also in use by megamenu for titles
89					var cur_menu = current.find('>a');
90					var clone_events = true;
91
92					if( cur_menu.length )
93					{
94						if( cur_menu.get(0).hash == '#' || 'undefined' == typeof cur_menu.attr('href') || cur_menu.attr('href') == '#' )
95						{
96							// eventhandler conflict 'click' by megamenu (returns false) - ignore all handlers
97							if( subitems.length > 0 || megacolumns.length > 0 )
98							{
99								clone_events = false;
100							}
101						}
102					}
103
104					link   = cur_menu.clone(clone_events).attr('style','');
105
106						//	megamenus can have '' as url in top menu - allow click event in burger
107					if( 'undefined' == typeof cur_menu.attr('href') )
108					{
109						link.attr( 'href', '#' );
110					}
111
112					new_li = $('<li>').append( link );
113
114					//	Copy user set classes for menu items - these must not start with menu-item, page-item, page_item (used by default classes)
115					var cls = [];
116					if( 'undefined' != typeof current.attr('class') )
117					{
118						cls = current.attr('class').split(/\s+/);
119						$.each( cls, function( index, value ){
120										if( ( value.indexOf('menu-item') != 0 ) && ( value.indexOf('page-item') < 0 ) && ( value.indexOf('page_item') != 0 ) && ( value.indexOf('dropdown_ul') < 0 ) )
121										{
122											//	'current-menu-item' is also copied !!
123											new_li.addClass( value );
124										}
125										return true;
126									});
127					}
128
129					if( 'undefined' != typeof current.attr('id') && '' != current.attr('id') )
130					{
131						new_li.addClass(current.attr('id'));
132					}
133					else
134					{
135						//	fallback menu has no id -> try to find page id in class
136						$.each( cls, function( index, value ){
137										if( value.indexOf('page-item-') >= 0 )
138										{
139											new_li.addClass(value);
140											return false;
141										}
142								});
143					}
144
145					append_to.append(new_li);
146
147					if(subitems.length)
148					{
149						new_ul = $('<ul class="sub-menu">').appendTo(new_li);
150
151						if(cloneFirst && ( link.get(0).hash != '#' && link.attr('href') != '#' ))
152						{
153							new_li.clone(true).prependTo(new_ul);
154						}
155
156						new_li.addClass('av-width-submenu').find('>a').append('<span class="av-submenu-indicator">');
157
158						create_list( subitems , new_ul);
159					}
160					else if(megacolumns.length)	//if we got no normal sublists try megamenu columns and sublists
161					{
162						new_ul = $('<ul class="sub-menu">').appendTo(new_li);
163
164						if(cloneFirst && ( link.get(0).hash != '#' && link.attr('href') != '#' ))
165						{
166							new_li.clone(true).prependTo(new_ul);
167						}
168
169						megacolumns.each(function(iteration)
170						{
171							var megacolumn		= $(this),
172								mega_current  	= megacolumn.find( '> .sub-menu' ),		//	can be 0 if only a column is used without submenus
173								mega_title 		= megacolumn.find( '> .mega_menu_title' ),
174								mega_title_link = mega_title.find('a').attr('href') || "#",
175								current_megas 	= mega_current.length > 0 ? mega_current.find('>li') : null,
176								mega_title_set  = false,
177								mega_link 		= new_li.find('>a'),
178								hide_enty		= '';
179
180							//	ignore columns that have no actual link and no subitems
181							if( ( current_megas === null ) || ( current_megas.length == 0 ) )
182							{
183								if( mega_title_link == '#' )
184								{
185									hide_enty = ' style="display: none;"';
186								}
187							}
188
189							if(iteration == 0) new_li.addClass('av-width-submenu').find('>a').append('<span class="av-submenu-indicator">');
190
191							//if we got a title split up submenu items into multiple columns
192							if(mega_title.length && mega_title.text() != "")
193							{
194								mega_title_set  = true;
195
196								//if we are within the first iteration we got a new submenu, otherwise we start a new one
197								if(iteration > 0)
198								{
199									var check_li = new_li.parents('li').eq(0);
200
201									if(check_li.length) new_li = check_li;
202
203									new_ul = $('<ul class="sub-menu">').appendTo(new_li);
204								}
205
206
207								new_li = $('<li' + hide_enty + '>').appendTo(new_ul);
208								new_ul = $('<ul class="sub-menu">').appendTo(new_li);
209
210								$('<a href="'+mega_title_link+'"><span class="avia-bullet"></span><span class="avia-menu-text">' +mega_title.text()+ '</span></a>').insertBefore(new_ul);
211								mega_link = new_li.find('>a');
212
213								//	Clone if we have submenus
214								if(cloneFirst && ( mega_current.length > 0 ) && ( mega_link.length && mega_link.get(0).hash != '#' && mega_link.attr('href') != '#' ))
215								{
216									new_li.clone(true).addClass('av-cloned-title').prependTo(new_ul);
217								}
218
219							}
220
221								//	do not append av-submenu-indicator if no submenus (otherwise link action is blocked !!!)
222							if( mega_title_set && ( mega_current.length > 0 ) ) new_li.addClass('av-width-submenu').find('>a').append('<span class="av-submenu-indicator">');
223							create_list( current_megas , new_ul);
224						});
225
226					}
227
228				});
229
230				burger_wrap.trigger( 'avia_burger_list_created' );
231				return list;
232			};
233
234		var burger_ul, burger;
235
236		//prevent scrolling of outer window when scrolling inside
237		$('body').on( 'mousewheel DOMMouseScroll touchmove', '.av-burger-overlay-scroll', function (e)
238		{
239			var height = this.offsetHeight,
240				scrollHeight = this.scrollHeight,
241				direction = e.originalEvent.wheelDelta;
242
243			if(scrollHeight != this.clientHeight)
244			{
245				if( ( this.scrollTop >= (scrollHeight - height) && direction < 0) || (this.scrollTop <= 0 && direction > 0) )
246				{
247			      e.preventDefault();
248			    }
249		    }
250		    else
251		    {
252				e.preventDefault();
253		    }
254		});
255
256		//prevent scrolling for the rest of the screen
257		$(document).on( 'mousewheel DOMMouseScroll touchmove', '.av-burger-overlay-bg, .av-burger-overlay-active .av-burger-menu-main', function (e)
258		{
259				e.preventDefault();
260		});
261
262		//prevent scrolling on mobile devices
263		var touchPos = {};
264
265		$(document).on('touchstart', '.av-burger-overlay-scroll', function(e)
266		{
267			touchPos.Y = e.originalEvent.touches[0].clientY;
268		});
269
270		$(document).on('touchend', '.av-burger-overlay-scroll', function(e)
271		{
272			touchPos = {};
273		});
274
275		//prevent rubberband scrolling http://blog.christoffer.me/six-things-i-learnt-about-ios-safaris-rubber-band-scrolling/
276		$(document).on( 'touchmove', '.av-burger-overlay-scroll', function (e)
277		{
278			if(!touchPos.Y)
279			{
280				touchPos.Y = e.originalEvent.touches[0].clientY;
281			}
282
283			var	differenceY = e.originalEvent.touches[0].clientY - touchPos.Y,
284				element 	= this,
285				top 		= element.scrollTop,
286				totalScroll = element.scrollHeight,
287				currentScroll = top + element.offsetHeight,
288				direction	  = differenceY > 0 ? "up" : "down";
289
290			$('body').get(0).scrollTop = touchPos.body;
291
292	        if( top <= 0 )
293	        {
294	            if( direction == "up" )
295				{
296					e.preventDefault();
297				}
298
299	        }
300			else if( currentScroll >= totalScroll )
301	        {
302	            if( direction == "down" )
303				{
304					e.preventDefault();
305				}
306	        }
307		});
308
309		$(window).on( 'debouncedresize', function (e)
310		{
311			var close = true;
312
313			//	@since 4.8.3 we support portrait/landscape screens to switch mobile menu
314			if( $.avia_utilities.isMobile && htmlEL.hasClass( 'av-mobile-menu-switch-portrait' ) && htmlEL.hasClass( 'html_text_menu_active' ) )
315			{
316				var height = $( window ).height();
317				var width = $( window ).width();
318
319				if( width <= height )
320				{
321					//	in portrait mode we only need to remove added class
322					htmlEL.removeClass( 'html_burger_menu' );
323				}
324				else
325				{
326					//	in landscape mode
327					var switch_width = htmlEL.hasClass( 'html_mobile_menu_phone' ) ? 768 : 990;
328					if( height < switch_width )
329					{
330						htmlEL.addClass( 'html_burger_menu' );
331						close = false;
332					}
333					else
334					{
335						htmlEL.removeClass( 'html_burger_menu' );
336					}
337				}
338			}
339
340
341			//	close burger menu when returning to desktop
342			if( close && burger && burger.length )
343			{
344				if( ! burger_wrap.is(':visible') )
345				{
346					burger.filter(".is-active").parents('a').eq(0).trigger('click');
347				}
348			}
349
350			set_list_container_height();
351		});
352
353		//close overlay on overlay click
354		$('.html_av-overlay-side').on( 'click', '.av-burger-overlay-bg', function (e)
355		{
356			e.preventDefault();
357			burger.parents('a').eq(0).trigger('click');
358		});
359
360		 //close overlay when smooth scrollign begins
361		$(window).on('avia_smooth_scroll_start', function()
362		{
363			if(burger && burger.length)
364			{
365				burger.filter(".is-active").parents('a').eq(0).trigger('click');
366			}
367		});
368
369
370		//toogle hide/show for submenu items
371		$('.html_av-submenu-display-hover').on( 'mouseenter', '.av-width-submenu', function (e)
372		{
373			$(this).children("ul.sub-menu").slideDown('fast');
374		});
375
376		$('.html_av-submenu-display-hover').on( 'mouseleave', '.av-width-submenu', function (e)
377		{
378			$(this).children("ul.sub-menu").slideUp('fast');
379		});
380
381		$('.html_av-submenu-display-hover').on( 'click', '.av-width-submenu > a', function (e)
382		{
383			e.preventDefault();
384			e.stopImmediatePropagation();
385		});
386
387			//	for mobile we use same behaviour as submenu-display-click
388		$('.html_av-submenu-display-hover').on( 'touchstart', '.av-width-submenu > a', function (e)
389		{
390			var menu = $(this);
391			toggle_submenu( menu, e );
392		});
393
394
395		//toogle hide/show for submenu items
396		$('.html_av-submenu-display-click').on( 'click', '.av-width-submenu > a', function (e)
397		{
398			var menu = $(this);
399			toggle_submenu( menu, e );
400		});
401
402
403		//	close mobile menu if click on active menu item
404		$('.html_av-submenu-display-click').on( 'click', '.av-burger-overlay a', function (e)
405		{
406			var loc = window.location.href.match(/(^[^#]*)/)[0];
407			var cur = $(this).attr('href').match(/(^[^#]*)/)[0];
408
409			if( cur == loc )
410			{
411				e.preventDefault();
412				e.stopImmediatePropagation();
413
414				burger.parents('a').eq(0).trigger('click');
415				return false;
416			}
417			return true;
418		});
419
420
421		function toggle_submenu( menu, e )
422		{
423			e.preventDefault();
424			e.stopImmediatePropagation();
425
426			var parent  = menu.parents('li').eq(0);
427
428			parent.toggleClass('av-show-submenu');
429
430			if(parent.is('.av-show-submenu'))
431			{
432				parent.children("ul.sub-menu").slideDown('fast');
433			}
434			else
435			{
436				parent.children("ul.sub-menu").slideUp('fast');
437			}
438		};
439
440
441		(function normalize_layout()
442		{
443			//if we got the menu outside of the main menu container we need to add it to the container as well
444			if( menu_in_logo_container.length )
445			{
446				return;
447			}
448
449			var menu2 = $('#header .main_menu').clone(true),
450				ul = menu2.find('ul.av-main-nav'),
451				id = ul.attr('id');
452
453			if( 'string' == typeof id && '' != id.trim() )
454			{
455				ul.attr('id', id + '-' + cloned_menu_cnt++ );
456			}
457			menu2.find('.menu-item:not(.menu-item-avia-special)').remove();
458			menu2.insertAfter(logo_container.find('.logo').first());
459
460			//check if we got social icons and append it to the secondary menu
461			var social = $('#header .social_bookmarks').clone(true);
462			if( ! social.length )
463			{
464				social = $('.av-logo-container .social_bookmarks').clone(true);
465			}
466
467			if( social.length )
468			{
469				menu2.find('.avia-menu').addClass('av_menu_icon_beside');
470				menu2.append(social);
471			}
472
473			//re select the burger menu if we added a new one
474			burger_wrap = $('.av-burger-menu-main a');
475		}());
476
477
478
479		burger_wrap.on('click', function(e)
480		{
481			if( animating )
482			{
483				return;
484			}
485
486			burger = $(this).find('.av-hamburger'),
487			animating = true;
488
489			if(!menu_generated)
490			{
491				menu_generated = true;
492				burger.addClass("av-inserted-main-menu");
493
494				burger_ul = $('<ul>').attr({id:'av-burger-menu-ul', class:''});
495				var first_level_items = menu.find('> li:not(.menu-item-avia-special)'); //select all first level items that are not special items
496				var	list = create_list( first_level_items , burger_ul);
497
498				burger_ul.find('.noMobile').remove(); //remove any menu items with the class noMobile so user can filter manually if he wants
499				burger_ul.appendTo(inner_overlay);
500				first_level = inner_overlay.find('#av-burger-menu-ul > li');
501
502				if($.fn.avia_smoothscroll)
503				{
504					$('a[href*="#"]', overlay).avia_smoothscroll(overlay);
505				}
506			}
507
508			if(burger.is(".is-active"))
509			{
510				burger.removeClass("is-active");
511				htmlEL.removeClass("av-burger-overlay-active-delayed");
512
513				overlay.animate({opacity:0}, function()
514	    		{
515	    			overlay.css({display:'none'});
516					htmlEL.removeClass("av-burger-overlay-active");
517					animating = false;
518	    		});
519
520 			}
521			else
522			{
523				set_list_container_height();
524
525				var offsetTop = header_main.length ? header_main.outerHeight() + header_main.position().top : header.outerHeight() + header.position().top;
526
527				overlay.appendTo($(e.target).parents('.avia-menu'));
528
529				burger_ul.css({padding:( offsetTop ) + "px 0px"});
530
531				first_level.removeClass('av-active-burger-items');
532
533				burger.addClass("is-active");
534				htmlEL.addClass("av-burger-overlay-active");
535				overlay.css({display:'block'}).animate({opacity:1}, function()
536				{
537					animating = false;
538				});
539
540				setTimeout(function()
541				{
542					htmlEL.addClass("av-burger-overlay-active-delayed");
543				}, 100);
544
545				first_level.each(function(i)
546				{
547					var _self = $(this);
548					setTimeout(function()
549					{
550						_self.addClass('av-active-burger-items');
551					}, (i + 1) * 125);
552				});
553
554			}
555
556			e.preventDefault();
557		});
558	}
559
560})( jQuery );

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.