PageSourceSearch

https://www.stlouisfed.org/-/media/themes/frbstl/stlouisfed/stlouisfed/scripts/megamenu-modern-1.js

js stlouisfed.org collected 2026-10-01 07:02:33 UTC 21,738 bytes, 646 lines download raw bytes

1const DEVICE_XLARGE = 1200;
2const DEVICE_LARGE = 992;
3const DEVICE_MEDIUM = 768;
4const DEVICE_SMALL = 576;
5
6function resizeMegaMenu() {
7    //If the window is sized to where the hamburger menu is available, then make the width 100%
8    jQuery('.debug-window').text("Screen size: " + (jQuery(window).width()) + ", header height="+ jQuery("#header").css("height") + " inner width=" + window.innerWidth+ " client width=" + document.documentElement.clientWidth);
9//	if (jQuery(window).width() < DEVICE_MEDIUM) {
10	if (window.innerWidth < DEVICE_MEDIUM) {
11        jQuery('.menu-item').css("width", "100%");
12        jQuery('.menu-item-label').css("width", "100%");
13		
14//		jQuery('.mobile-header').css("display", "flex");
15//		jQuery('.desktop-header').css("display", "none");
16    }
17    //Otherwise, size the menu items between 124 and 150 
18    else
19    {
20//		jQuery('.mobile-header').css("display", "none");
21//		jQuery('.desktop-header').css("display", "flex");
22		
23		jQuery('.menu-item').each(function(index, value) {
24            jQuery(this).css("width", jQuery(this).find('.main-menu-row').css("width"));
25        });
26        var resizeFactor = Math.min(((jQuery(window).width() / DEVICE_XLARGE) * 148), 148);
27//        jQuery('.menu-item').css("width", resizeFactor + "px");
28        jQuery('.menu-item').css("width", "auto");
29
30        var menuLeftOffset = Math.min(((jQuery(window).width() / DEVICE_XLARGE) * 50), 50);
31 //       jQuery('.menu-item-label').css("width", resizeFactor + "px");
32    }    
33}
34
35function isSubMenuOpen(menuitem) {
36	var menuID = jQuery(menuitem).data("id");
37    return jQuery('.sub-menu-' + menuID).hasClass('show-menu');
38
39}
40
41function isClickOutsideSitewideSearch(x, y) {
42	var clickOutside = false;
43	
44	if (jQuery('.hide-sitewide-search').length == 0) {
45		var desktopSearch = jQuery('.sitewide-search')[0];
46		if (y < desktopSearch.offsetTop)
47		{
48			clickOutside = true;
49		} 
50		else 
51		{
52			if (y > desktopSearch.offsetTop + desktopSearch.offsetHeight) {
53				clickOutside = true;
54			}
55		}
56	}
57	
58	return clickOutside;
59}
60
61function isClickOutsideMenu(menuitem, x, y) {
62	var clickOutside = false;
63
64	if (menuitem != undefined) 
65	{
66		if (x < menuitem.offsetLeft) {
67			clickOutside = true;
68		}
69		if (x > menuitem.offsetLeft + menuitem.offsetWidth) {
70			clickOutside = true;
71		}
72	
73		if (y > menuitem.offsetHeight + jQuery('.frbstl-navigation')[0].offsetHeight + jQuery('.frbstl-navigation')[0].offsetTop - window.pageYOffset) {
74			clickOutside = true;
75		}
76	}
77	
78	return clickOutside;
79}
80
81function isAnySubMenuOpen() {
82	var subMenuOpen = false;
83	for (i=0; i<jQuery('.sub-menu').length ; i++)
84	{
85		if (jQuery('.sub-menu')[i].className.indexOf('show-menu') > 0)
86		{
87			subMenuOpen = true;
88		}
89	}
90    return subMenuOpen;
91
92}
93
94function isSearchClosed() {
95    return jQuery('.mobile-sitewide-search').hasClass('hide-mobile-sitewide-search');
96}
97
98function resizeUtilityRow() {
99//    resizeFactor = (jQuery(window).width() - (2 * 196)) / 2;
100//    jQuery('.utility-nav-row').css("margin-left", resizeFactor + "px");
101}
102
103
104function resetToDefault() {
105    //reset the row height of the mobile search row
106    jQuery('.mobile-sitewide-search').parent().removeClass('search-box-height');
107    
108}
109
110function closeMobileMegaMenu() {
111    jQuery('.nav-row').toggleClass('show-nav', false);
112	jQuery('.hamburger-button').removeClass('expanded');
113//    jQuery('.icon-bar.top').toggleClass('transform-pos-45', false);
114//    jQuery('.icon-bar.bottom').toggleClass('transform-neg-45', false);
115//    jQuery('.icon-bar.middle').toggleClass('display-none', false);
116
117}
118
119function openMobileSearchBox() {
120    //Make sure the mega menu is closed.
121    closeMobileMegaMenu();
122    scrollFunction();
123	
124    //position the top of the mobile search window
125    var windowTop = 0;
126    windowTop = jQuery('.mobile-header').height();
127    jQuery('.mobile-sitewide-search').css({"top": windowTop});
128	jQuery('#header').css({"height": "105px"});
129	
130	//position the pulse of the economy arrow
131	if (jQuery('.pote-triangle-down').length > 0) {
132        var topPos = jQuery('.pote-triangle-down').position().top + 55;
133        jQuery(".pote-triangle-down").css({top: topPos + "px"});
134    }
135	
136    //update the height of the row the search box is in to move the content down.
137    jQuery('.mobile-sitewide-search').parent().toggleClass('search-box-height');
138
139    jQuery('.mobile-sitewide-search').toggleClass('hide-mobile-sitewide-search');
140    jQuery('.mobile-search-button-col').toggleClass('search-closed');
141    jQuery('.mobile-search-button-col').toggleClass('search-opened');
142}
143
144function closeMobileSearchBox(resize) {
145    jQuery('.mobile-sitewide-search').parent().removeClass('search-box-height');
146
147    jQuery('.mobile-sitewide-search').toggleClass('hide-mobile-sitewide-search', true);
148    jQuery('.mobile-search-button-col').toggleClass('search-closed', true);
149    jQuery('.mobile-search-button-col').toggleClass('search-opened', false);
150
151    if (window.innerWidth < DEVICE_MEDIUM) {
152	    jQuery('#header').css({"height": "50px"});
153		jQuery('.debug-info').text("just set height in resize function");
154	}
155	
156	//position the pulse of the economy arrow
157	if (jQuery('.pote-triangle-down').length > 0) {
158		if (resize != "resize") {
159            var topPos = jQuery('.pote-triangle-down').position().top - 55;
160            jQuery(".pote-triangle-down").css({top: topPos + "px"});
161		}
162	}
163}
164
165function openDesktopSearchBox() {
166    jQuery('.sitewide-search').toggleClass('hide-sitewide-search');
167    jQuery('.nav-row').toggleClass('hide-menu');
168}
169
170function closeDesktopSearchBox() {
171    jQuery('.sitewide-search').addClass('hide-sitewide-search');
172    jQuery('.nav-row').removeClass('hide-menu');
173}
174
175function initializeMenuState() {
176    jQuery('.sub-menu').removeClass('show-menu');
177    jQuery('.sub-menu').addClass('hide-menu');
178	
179	jQuery('.menu-image').toggleClass('collapsed-menu-image', true);
180	jQuery('.menu-image').removeClass('expanded-menu-image');
181
182}
183
184function openMegaMenu(menuitem) {
185    //For the menu that has been clicked, show the sub menu and position it in the correct place
186    var menuID = jQuery(menuitem).data("id");
187    jQuery('.sub-menu-' + menuID).removeClass('hide-menu');
188    jQuery('.sub-menu-' + menuID).addClass('show-menu');
189    var menuLeft = jQuery('.main-nav').css('margin-left').replace('px', '');
190    jQuery('.sub-menu-' + menuID).css({left: menuLeft + "px"});
191
192    if (jQuery(window).width() > DEVICE_MEDIUM) {
193        var caretLeft = jQuery(menuitem).position().left + jQuery(menuitem).width() / 2 - 15;
194	    jQuery('.triangle-up').css({left: caretLeft + "px"});
195		var topOffset = 7;
196		if (jQuery(window).width() > DEVICE_LARGE) {
197            topOffset = 15;
198        }
199	    var caretTop = jQuery(menuitem).position().top + jQuery(menuitem).height() - topOffset;
200	    jQuery('.triangle-up').css({top: caretTop + "px"});
201    	jQuery('.triangle-up').removeClass('display-none');
202	}
203	
204    //Make sure the currect item is selected
205    jQuery('.menu-item').removeClass('menu-selected');
206    jQuery('.menu-item-' + menuID).toggleClass('menu-selected');
207	
208	//Set the expand image
209	jQuery(menuitem).find('.menu-image').removeClass('collapsed-menu-image');
210	jQuery(menuitem).find('.menu-image').addClass('expanded-menu-image');
211	
212	// aria-expanded
213	// clear any aria-expanded to false
214	jQuery('.menu-item').attr("aria-expanded","false");
215	
216	// set current aria-expanded to true
217    jQuery('.menu-item-' + menuID).attr("aria-expanded","true");
218}
219
220function toggleMegaMenu(menuitem) {
221    //For the menu that has been clicked, show the sub menu and position it in the correct place
222    var menuID = jQuery(menuitem).data("id");
223    jQuery('.sub-menu-' + menuID).toggleClass('hide-menu');
224    jQuery('.sub-menu-' + menuID).toggleClass('show-menu');
225    var menuLeft = jQuery('.main-nav').css('margin-left').replace('px', '');
226    jQuery('.sub-menu-' + menuID).css({left: menuLeft + "px"});
227
228    //Make sure the currect item is selected
229    jQuery('.menu-item').removeClass('menu-selected');
230    jQuery('.menu-item-' + menuID).toggleClass('menu-selected');
231}
232
233function openMobileMegaMenu() {
234    //First, make sure the search window is closed.
235    jQuery('.nav-mobile-search-row').toggleClass('hide-mobile-search', true);
236    jQuery('.mobile-search-button-col').addClass('search-closed');
237    jQuery('.mobile-search-button-col').removeClass('search-opened');
238
239    //Make sure any previously selected menus are un-selected.
240    jQuery('.menu-item').removeClass('menu-selected');
241    jQuery('.sub-menu').removeClass('show-menu');
242    jQuery('.sub-menu').addClass('hide-menu');
243    jQuery('.header-image').removeClass('expanded');
244    jQuery('.header-image').addClass('collapsed');
245    jQuery('.header-sub-item').addClass('menu-collapsed');
246	
247	// aria-expanded
248	// clear any aria-expanded to false
249	jQuery('.menu-item').attr("aria-expanded","false");
250	
251	
252	//Reset the expand image
253	resetExpandImages();
254
255
256    var windowHeight = 52;
257    if (jQuery(window).width() < DEVICE_MEDIUM) {
258        windowHeight = window.innerHeight - jQuery('.site-header').height();
259    }
260    jQuery('.nav-row').css({"height": windowHeight});
261    jQuery('.nav-row').css({"top": navbar.offsetHeight});
262    jQuery('.nav-row').toggleClass('show-nav');
263//    jQuery('.icon-bar.top').toggleClass('transform-pos-45');
264//    jQuery('.icon-bar.bottom').toggleClass('transform-neg-45');
265//    jQuery('.icon-bar.middle').toggleClass('display-none');
266	
267	jQuery('.hamburger-button').toggleClass('expanded');
268}
269
270function setSearchBoxFocus() {
271    //set focus to the search box
272    jQuery('.sitewide-search').find('.search-box-input').focus();
273
274 //   jQuery('.sitewide-search').find('.search-box-input').css({"outline": "none"});
275
276}
277
278function resetExpandImages() {
279	//Set the expand image
280	jQuery('.menu-image').toggleClass('collapsed-menu-image', true);
281	jQuery('.menu-image').removeClass('expanded-menu-image');
282
283}
284
285function closeMegaMenu() {
286    jQuery('.sub-menu').removeClass('show-menu');
287    jQuery('.sub-menu').addClass('hide-menu');
288	
289    if (jQuery(window).width() > DEVICE_MEDIUM) {
290        jQuery('.triangle-up').addClass('display-none');
291	}
292	
293    //Remove the menu selected class too
294    jQuery('.menu-item').removeClass('menu-selected');  
295	
296	//Reset the expand image
297	resetExpandImages();
298	
299	// aria-expanded
300	// clear any aria-expanded to false
301	jQuery('.menu-item').attr("aria-expanded","false");
302
303    event.stopPropagation();
304}
305
306function closeSubMenus() {
307    jQuery('.sub-menu').addClass('hide-menu');
308    jQuery('.menu-item').removeClass('menu-selected');
309	
310    if (jQuery(window).width() > DEVICE_MEDIUM) {
311    	jQuery('.triangle-up').addClass('display-none');
312    }
313	
314	// aria-expanded
315	// clear any aria-expanded to false
316	jQuery('.menu-item').attr("aria-expanded","false");
317}
318
319function turnOnMobileCloseButton(menuitem) {
320    var menuID = jQuery(menuitem).data("id");
321    jQuery('.menu-image-' + menuID).removeClass('display-none');
322}
323
324jQuery(document).ready(function() {
325    //Click on the search icon on desktop mega menu
326    jQuery('.search-menu-item').click(function () {
327        openDesktopSearchBox();
328
329        setSearchBoxFocus();
330    });
331
332    //close the sitewide search if user clicks on the header
333    jQuery('.desktop-header').click(function () {
334 //       closeDesktopSearchBox();
335        closeMegaMenu();
336    });
337
338    //close the sitewide search if user tabs off search-box-button
339    jQuery('.search-box-button').focusout(function () {
340         closeDesktopSearchBox();
341    });
342	
343//	jQuery('.search-box-button').click(function () {
344//         window.location.href = "https://stlouisfed-dev-single.ase2.n.azure.frb.pvt/search";
345//    });
346
347    //open the mobile search box 
348    jQuery('.mobile-search-button-col').click(function () {
349		if (isSearchClosed()) {
350            openMobileSearchBox();
351		} else
352		{
353            closeMobileSearchBox();
354		}
355    });
356
357    jQuery('.sub-menu').click(function (e) {
358		e.stopPropagation();
359	});
360	
361	//Mobile only - Collapse the main submenu when the menu image collapse button is pressed
362    jQuery('.menu-imagezzz').click(function () {
363		//First, close any open menus
364		closeMegaMenu();
365
366        var menuID = jQuery(this).data("id");
367        jQuery('.sub-menu-' + menuID).toggleClass('show-menu');
368        jQuery('.sub-menu-' + menuID).toggleClass('hide-menu');
369        jQuery('.menu-item-' + menuID).toggleClass('menu-selected');
370		
371		//Set the expand image
372	    jQuery('.menu-item-' + menuID).find('.menu-image').toggleClass('collapsed-menu-image');
373	    jQuery('.menu-item-' + menuID).find('.menu-image').toggleClass('expanded-menu-image');
374
375        //hide the close button
376        //jQuery('.menu-image-' + menuID).addClass('display-none');
377		
378		// set current aria-expanded to true
379        jQuery('.menu-item-' + menuID).attr("aria-expanded","true");
380
381        event.stopPropagation();
382    });
383	
384	//Mobile only - Collapse the main submenu when the menu image collapse button is pressed
385    jQuery('.menu-image').click(function () {
386        if (isSubMenuOpen(this)) {
387			// make sure "this" contains a clickable link
388//			if (jQuery(this.className.indexOf('clickable-link')) > 0)
389//			{
390				closeMegaMenu(this);
391//			}
392	    }
393		else {
394            initializeMenuState();
395            openMegaMenu(this.parentNode.parentNode.parentNode);
396		}
397
398        //if this is mobile, then turn on the close image for this menu
399        if (jQuery(window).width() < DEVICE_MEDIUM)
400        {
401            turnOnMobileCloseButton(this);
402        }
403
404        event.stopPropagation();
405    });
406	
407	
408    //open mega menu
409    jQuery('.menu-item').click(function () {
410        //Initialize all the hide and show classes
411//        initializeMenuState();
412
413//        openMegaMenu(this);
414        if (isSubMenuOpen(this)) {
415			// make sure "this" contains a clickable link
416//			if (jQuery(this.className.indexOf('clickable-link')) > 0)
417//			{
418				closeMegaMenu(this);
419//			}
420	    }
421		else {
422            initializeMenuState();
423            openMegaMenu(this);
424		}
425
426        //if this is mobile, then turn on the close image for this menu
427        if (jQuery(window).width() < DEVICE_MEDIUM)
428        {
429            turnOnMobileCloseButton(this);
430        }
431        
432    });
433
434    //Show the mobile navigation when the hamburger button is pressed
435    jQuery('.hamburger-button').click(function () {
436        closeMobileSearchBox();
437        openMobileMegaMenu();
438    });
439
440
441    jQuery('.clickable-link').click(function () {
442		closeMobileMegaMenu();
443		closeMegaMenu();
444	});
445	
446
447
448    //Mobile only - Collapse the sub menu when the header collapse button is pressed
449    jQuery('.header-image').click(function (e) {
450        var subMenuID = jQuery(this).data("id");
451        jQuery('.' + subMenuID).toggleClass('menu-collapsed');
452        jQuery(this).toggleClass('collapsed');
453        jQuery(this).toggleClass('expanded');
454        e.stopPropagation();
455    });
456
457    jQuery('.sub-menu-row').on("click", (function (e) {
458	    if (jQuery(window).width() < DEVICE_MEDIUM) {
459			//find the header image under this menu item
460			var headerimage = jQuery(this).find('.header-image');
461			//click it
462			headerimage.trigger("click");
463			e.stopPropagation();
464		}
465	})
466	);
467
468    jQuery(window).resize(function() {
469        //first, make sure any sub-menus are closed when resizing
470        if (jQuery(window).width() > DEVICE_MEDIUM) {
471            closeSubMenus();
472            closeDesktopSearchBox();
473            closeMobileSearchBox("resize");
474			
475            //make sure to remove any sticky navigation
476            navbar.classList.remove("sticky");  
477            sitewidesearch.classList.remove("sticky");
478
479			jQuery(window).scrollTop(jQuery(window).scrollTop() + 1); 
480			jQuery(window).scrollTop(jQuery(window).scrollTop() - 1); 
481	    } 
482		
483        //also, make sure any mobile windows are closed and hamburger menu is off
484        jQuery('.nav-row').removeClass('show-nav');
485    	jQuery('.hamburger-button').removeClass('expanded');
486 //       jQuery('.icon-bar.top').removeClass('transform-pos-45');
487 //       jQuery('.icon-bar.bottom').removeClass('transform-neg-45');
488 //       jQuery('.icon-bar.middle').removeClass('display-none');
489
490
491        resizeMegaMenu();
492        resizeUtilityRow();
493
494        if (jQuery(window).width() < DEVICE_MEDIUM)
495            {
496                jQuery('.header-sub-item').addClass('menu-collapsed');
497                jQuery('.main-menu-title').removeClass('center-vert-horz');
498                navbar = document.getElementsByClassName('mobile-header')[0];
499                sitewidesearch = document.getElementsByClassName('mobile-sitewide-search')[0];
500 //   		    jQuery('#header').css({"background-color": "#002241"});
501
502                sticky = 0;  
503            }
504            else
505            {
506                jQuery('.header-sub-item').removeClass('menu-collapsed');
507                jQuery('.main-menu-title').addClass('center-vert-horz');
508                navbar = document.getElementsByClassName('frbstl-navigation')[0];
509                sitewidesearch = document.getElementsByClassName('sitewide-search')[0];
510                sticky = document.getElementsByClassName('frbstl-navigation')[0].offsetTop;
511//			    jQuery('#header').css({"background-color": "#ffffff"});
512				
513//				jQuery('#header').css({"height": "auto"});
514            }
515    });
516
517});
518
519//Hide the desktop search anytime user clicks inside the body (but only when in desktop mode)
520jQuery(document).mouseup(function(e) {
521    if (jQuery(window).width() > DEVICE_MEDIUM) {
522		console.log(e.clientX + ', ' + e.clientY);
523		console.log(isClickOutsideMenu(jQuery('.show-menu')[0], e.clientX, e.clientY));
524		
525		if (isClickOutsideMenu(jQuery('.show-menu')[0], e.clientX, e.clientY)) {
526			closeDesktopSearchBox();
527			closeMegaMenu();
528		}
529		
530		if (isClickOutsideSitewideSearch(e.clientX, e.clientY)) {
531			closeDesktopSearchBox();
532		}
533		
534		//var container = jQuery('.sub-menu');
535
536		// If the target of the click isn't the container
537/*         if (isAnySubMenuOpen()) {
538			//make sure the target doesn't contain sub-menu or list item
539			if (jQuery(e.target.toString().indexOf('sub-menu'))[0] < 0) {
540				closeDesktopSearchBox();
541				closeMegaMenu();
542			}
543		} */
544		
545    }
546});
547
548//jQuery('.variant-option').keypress(function(e) {
549//    handleEnter(event);
550//});
551
552var navbar = 0;
553var sitewidesearch = 0;
554var sticky = 0;
555
556jQuery(window).ready(function() {
557
558    if (jQuery(window).width() < DEVICE_MEDIUM)
559        {
560            jQuery('.header-sub-item').addClass('menu-collapsed');
561            jQuery('.main-menu-title').removeClass('center-vert-horz');
562            navbar = document.getElementsByClassName('mobile-header')[0];
563            sitewidesearch = document.getElementsByClassName('mobile-sitewide-search')[0];
564 //   	    jQuery('#header').css({"background-color": "#002241"});
565            sticky = 0;
566			
567			//jQuery(window).trigger('resize');
568       }
569        else
570        {
571            jQuery('.main-menu-title').addClass('center-vert-horz');
572            navbar = document.getElementsByClassName('frbstl-navigation')[0];
573            sitewidesearch = document.getElementsByClassName('sitewide-search')[0];
574            sticky = document.getElementsByClassName('frbstl-navigation')[0].offsetTop;
575 //  		    jQuery('#header').css({"background-color": "#ffffff"});
576       }
577
578
579});
580
581
582
583function showSkipToMain() {
584	jQuery('.skip-to-main').removeClass('hide-skip-to-main');
585	jQuery('.skip-to-main').addClass('show-skip-to-main');
586	jQuery('.skip-main-link').focus();
587}
588function hideSkipToMain() {
589	jQuery('.skip-to-main').addClass('hide-skip-to-main');
590	jQuery('.skip-to-main').removeClass('show-skip-to-main');
591}
592
593document.getElementById("skip-to-main").onfocus = function() {showSkipToMain()};
594jQuery(".skip-to-main-button").focusout( function() {hideSkipToMain()});
595
596//Get the back to top button:
597// Set a variable for our button element.
598var backToTopBtn = document.getElementById("btnBackToTop");
599
600// Capture the scroll function for Sticky Nav and Back To Top button
601window.onload = function() {scrollFunction()};
602window.onscroll = function() {scrollFunction()};
603
604function scrollFunction() {
605	hideSkipToMain();
606	
607    //Sticky Nav
608    if (window.pageYOffset >= sticky) 
609    { 
610        //add the sticky class to the nav bar and the sitewide search
611        if (jQuery(window).width() < DEVICE_MEDIUM) {
612            navbar.classList.add("sticky");
613            sitewidesearch.classList.add("sticky");
614		}
615
616        //add margin top to the content to keep the screen from jumping
617 //       jQuery('#content').css("margin-top", navbar.clientHeight + "px");
618    } 
619    else 
620    {
621        navbar.classList.remove("sticky");  
622        sitewidesearch.classList.remove("sticky");  
623  //      jQuery('#content').css("margin-top", "0px"); 
624    }
625
626    //Back To Top  
627    if (document.body.scrollTop > sticky || document.documentElement.scrollTop > sticky) 
628    {
629        backToTopBtn.style.display = "block";
630    } else {
631        backToTopBtn.style.display = "none";
632    }
633}
634
635// ScrolltoTop function
636var scrollToTop = () => {
637  window.scrollTo(0, 0);
638};
639 // When the button is clicked, run our ScrolltoTop function above!
640 backToTopBtn.onclick = function(e) {
641  e.preventDefault();
642  scrollToTop();
643}
644
645
646

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.