1/** 2 * navigation.js 3 * 4 * Handles toggling the navigation menu for small screens and enables tab 5 * support for dropdown menus. 6 */ 7( function(window, $, undefined) { 8 $(function () { 9 // desktop_breakpoint is the breakpoint from mobile to desktop view, if this ever changes in css this will have to changes as well 10 var 11 desktop_breakpoint = 991, 12 icon_buttons = $('[id^="toggle-mega_"]'), 13 hasLegacyMobileHeader = $('#search-container, #phone-container, #mobile-search-icon, #mobile-phone-icon, [id^="toggle-mega_"], [id^="mega_"], .dropdown-mega-menu').length > 0, 14 scrolling_ele = window; 15 16 function setScrollEvent (scrolling_ele) { 17 $(scrolling_ele).scroll(function (event) { 18 var 19 header = $('.header-banner'), header_height; 20 header_height = (header.length === 1) ? header.outerHeight() : 100; 21 22 if ($('#emergency-alert').length > 0) { 23 header_height += $('#emergency-alert').outerHeight(); 24 } 25 26 if ($(scrolling_ele).scrollTop() > header_height) { 27 $('#scroll-to-top').addClass('to-top-visible'); 28 } else { 29 $('#scroll-to-top').removeClass('to-top-visible'); 30 } 31 }); 32 } 33 34 35 function init () { 36 scrolling_ele = ($(window).width() <= desktop_breakpoint) ? 'div.body-wrapper' : window; 37 setScrollEvent(scrolling_ele); 38 39 /** 40 * Dropdown or hide the site search bar on mobile 41 * @return null 42 */ 43 // Legacy mobile header toggles: keep only for templates that still render old controls. 44 if (hasLegacyMobileHeader && typeof window.toggleMobileSearch !== 'function') { 45 window.toggleMobileSearch = function (off) { 46 if (off) { 47 $( "#search-container" ).removeClass('search-open'); 48 $( "#mobile-search-icon" ).removeClass('open'); 49 return; 50 } 51 if ($( "#search-container" ).hasClass('search-open')) { 52 $( "#search-container" ).removeClass('search-open'); 53 $( "#mobile-search-icon" ).removeClass('open'); 54 } else { 55 window.toggleMobilePhone(1); 56 $( "#search-container" ).addClass('search-open'); 57 $( "#mobile-search-icon" ).addClass('open'); 58 } 59 }; 60 } 61 62 if (hasLegacyMobileHeader && typeof window.toggleMobilePhone !== 'function') { 63 window.toggleMobilePhone = function (off) { 64 if (off) { 65 $( "#phone-container" ).removeClass('phone-open'); 66 $( "#mobile-phone-icon" ).removeClass('open'); 67 return; 68 } 69 if ($( "#phone-container" ).hasClass('phone-open')) { 70 $( "#phone-container" ).removeClass('phone-open'); 71 $( "#mobile-phone-icon" ).removeClass('open'); 72 } else { 73 window.toggleMobileSearch(1); 74 $( "#phone-container" ).addClass('phone-open'); 75 $( "#mobile-phone-icon" ).addClass('open'); 76 } 77 }; 78 } 79 80 /** 81 * Watches the resizing of the window, if it becomes desktop view than close any open navigation 82 * @param window w 83 * @return null 84 */ 85 $(window).resize(function() { 86 if ($(window).width() > desktop_breakpoint) { 87 scrolling_ele = window; 88 // Close all submenus 89 if (hasLegacyMobileHeader) { 90 toggleSlideOutMegaMenu('all'); 91 if (typeof window.toggleMobileSearch === 'function') { 92 window.toggleMobileSearch(true); 93 } 94 if (typeof window.toggleMobilePhone === 'function') { 95 window.toggleMobilePhone(true); 96 } 97 } 98 99 removeActionLinksSpaceIfNoLinks(); 100 } else { 101 scrolling_ele = 'div.body-wrapper'; 102 } 103 setScrollEvent(scrolling_ele); 104 }); 105 106 if (hasLegacyMobileHeader && $(window).width() > desktop_breakpoint) { 107 removeActionLinksSpaceIfNoLinks(); 108 } 109 110 initLeftNavToggle(); 111 } 112 113 /** 114 * Open and close the submenu for the main navigatoin in mobile view. 115 * @param string id The id of the submenu that I want to close.
116 * @return null 117 */ 118 function toggleSlideOutMegaMenu (id) { 119 var mega_menu = $('#' + id); 120 if (id !== 'all') { 121 if (mega_menu.hasClass('slide-out')) { 122 mega_menu.removeClass('slide-out'); 123 } else { 124 mega_menu.addClass('slide-out'); 125 } 126 } else { 127 // Close all mega menus so they don't stack up 128 var menus = $('[id^="mega_"]'); 129 for (var i = 0, l = menus.length; i < l; i++) { 130 $(menus[i]).removeClass('slide-out'); 131 } 132 } 133 } 134 135 if (hasLegacyMobileHeader) { 136 for (var i = 0, l = icon_buttons.length; i < l; i++) { 137 var ele = $(icon_buttons[i]); 138 var id = ele.attr('id').split('toggle-').pop(); 139 $('#mobile-back-' + id).on('click', function () { 140 toggleSlideOutMegaMenu('all'); 141 }); 142 143 var mega_menu = $('#' + id); 144 if (mega_menu.length) { 145 ele.prop('mega', mega_menu.attr('id')); 146 ele.on('click', function (e) { 147 toggleSlideOutMegaMenu($(this).prop('mega')); 148 }); 149 } 150 } 151 } 152 153 function removeActionLinksSpaceIfNoLinks () { 154 // Remove extra padding added for MM action links if none are present. 155 $('.dropdown-mega-menu').each(function () { 156 if ($(this).find('.mega-actions').length < 1) { 157 $(this).css('padding-bottom', 0); 158 } 159 }); 160 } 161 162 /** 163 * Left nav accordion toggle (mobile only). 164 */ 165 function initLeftNavToggle () { 166 var breakpoint = 992; 167 var $navs = $('.left-nav'); 168 if (!$navs.length) { 169 return; 170 } 171 172 function updateExpanderHeights ($nav) { 173 var $items = $nav.find('li.page_item_has_children'); 174 $items.each(function () { 175 var $icon = $(this).children('i.page_item_expander'); 176 var $link = $(this).children('a'); 177 if ($icon.length && $link.length) { 178 var h = $link.outerHeight(); 179 if (h) { 180 $icon.css('line-height', h + 'px'); 181 } 182 } 183 }); 184 } 185 186 function syncState ($nav, isMobile, collapseOnEnterMobile) { 187 var $list = $nav.find('.leftside-nav-list'); 188 var $toggle = $nav.find('.leftside-nav-toggle'); 189 if (!$list.length || !$toggle.length) { 190 return; 191 } 192 193 if (!isMobile) { 194 $nav.addClass('left-nav-open').removeClass('left-nav-collapsed'); 195 $list.show(); 196 $toggle.attr('aria-expanded', 'true'); 197 $toggle.removeClass('collapsed'); 198 updateExpanderHeights($nav); 199 return; 200 } 201 202 if (collapseOnEnterMobile) { 203 $nav.removeClass('left-nav-open').addClass('left-nav-collapsed'); 204 $list.hide(); 205 $toggle.attr('aria-expanded', 'false'); 206 $toggle.addClass('collapsed'); 207 return; 208 } 209 210 if ($nav.hasClass('left-nav-open')) { 211 $list.show(); 212 $nav.removeClass('left-nav-collapsed'); 213 $toggle.attr('aria-expanded', 'true'); 214 $toggle.removeClass('collapsed'); 215 updateExpanderHeights($nav); 216 } else { 217 $list.hide(); 218 $nav.addClass('left-nav-collapsed'); 219 $toggle.attr('aria-expanded', 'false'); 220 $toggle.addClass('collapsed'); 221 } 222 } 223 224 function bindNav ($nav) { 225 var $list = $nav.find('.leftside-nav-list'); 226 var $toggle = $nav.find('.leftside-nav-toggle'); 227 if (!$list.length || !$toggle.length) { 228 return; 229 } 230 231 var isMobile = $(window).width() < breakpoint; 232 233 if (isMobile) { 234 $nav.removeClass('left-nav-open').addClass('left-nav-collapsed'); 235 $list.hide(); 236 $toggle.attr('aria-expanded', 'false'); 237 $toggle.addClass('collapsed'); 238 } else { 239 $nav.addClass('left-nav-open').removeClass('left-nav-collapsed'); 240 $list.show(); 241 $toggle.attr('aria-expanded', 'true'); 242 $toggle.removeClass('collapsed'); 243 updateExpanderHeights($nav); 244 } 245 246 $toggle.off('click.leftnav').on('click.leftnav', function (e) { 247 if ($(window).width() >= breakpoint) { 248 return; 249 } 250 e.preventDefault(); 251 var isOpen = $nav.hasClass('left-nav-open'); 252 if (isOpen) { 253 $nav.removeClass('left-nav-open').addClass('left-nav-collapsed');
254 $list.slideUp(150, function () { 255 $list.css('display', ''); 256 }); 257 $toggle.attr('aria-expanded', 'false'); 258 $toggle.addClass('collapsed'); 259 } else { 260 $nav.addClass('left-nav-open').removeClass('left-nav-collapsed'); 261 $list.slideDown(150, function () { 262 $list.css('display', ''); 263 updateExpanderHeights($nav); 264 }); 265 $toggle.attr('aria-expanded', 'true'); 266 $toggle.removeClass('collapsed'); 267 } 268 }); 269 } 270 271 $navs.each(function () { 272 bindNav($(this)); 273 }); 274 275 var lastIsMobile = $(window).width() < breakpoint; 276 $(window).off('resize.leftnav').on('resize.leftnav', function () { 277 var isMobile = $(window).width() < breakpoint; 278 $navs.each(function () { 279 var collapseOnEnterMobile = isMobile && !lastIsMobile; 280 syncState($(this), isMobile, collapseOnEnterMobile); 281 }); 282 lastIsMobile = isMobile; 283 }); 284 } 285 286 init(); 287 }); 288 289 290} )(window, jQuery, undefined);
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.