PageSourceSearch

https://heritage.edu/wp-content/themes/enfold/js/avia-snippet-hamburger-menu.js?ver=5.6.12

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