PageSourceSearch

https://henrico.gov/wp-content/themes/henrico/js/navigation.js?ver=5.1

js henrico.gov collected 2026-10-02 03:23:45 UTC 12,067 bytes, 290 lines download raw bytes

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.