@@ -12,19 +12,6 @@ function createComponent(html) {
1212 // Web component class representing a course card.
1313 class NavHeader extends HTMLElement {
1414
15- // Creates an instance of CourseCard
16- constructor ( ) {
17- super ( ) ;
18- }
19-
20- /**
21- * Returns an array of properties to observe.
22- * @returns {Array } An array of property names.
23- */
24- static get observedAttributes ( ) {
25- return [ 'name' ] ;
26- }
27-
2815 /**
2916 * Called when an attribute is defined or changed.
3017 * @param {string } property - The name of the attribute.
@@ -42,116 +29,118 @@ function createComponent(html) {
4229 const shadow = this . attachShadow ( { mode : 'open' } ) ;
4330 shadow . innerHTML = html ;
4431
45- const menuButton = shadow . querySelector ( '.hamburger-menu' ) ;
46- const menuToggle = shadow . getElementById ( 'menu-toggle' ) ;
47- const dropdownMenu = shadow . querySelector ( '.dropdown-menu' ) ;
48- const searchResults = shadow . getElementById ( 'search-results' ) ;
49- const menuItems = dropdownMenu . querySelectorAll ( 'a' ) ;
32+ // Variables
33+ // --------------------------------------------------------------------------------------------------
34+ // Dropdown navigation menu
35+ const menuButton = shadow . querySelector ( '.hamburger-menu' ) ;
36+ const menuToggle = shadow . getElementById ( 'menu-toggle' ) ;
37+ // Search
38+ const searchForm = shadow . getElementById ( 'search-form' ) ;
39+ const searchInput = shadow . getElementById ( 'search-input' ) ;
40+ const searchBar = shadow . querySelector ( '.search-bar' ) ;
41+ const clearIcon = shadow . getElementById ( 'clear-icon' ) ;
42+ const searchResults = shadow . getElementById ( 'search-results' ) ;
5043
51- // Toggle dropdown menu on hamburger menu click
52- menuButton . addEventListener ( 'click' , ( ) => { this . toggleMenu ( menuToggle , dropdownMenu , menuItems ) } ) ;
53- menuButton . addEventListener ( 'keydown' , ( event ) => {
54- if ( event . key === 'Enter' ) { this . toggleMenu ( menuToggle , dropdownMenu , menuItems ) } ;
55- } )
56- // Hide search results
44+ // Event listeners for dropdown navigation menu
45+ // --------------------------------------------------------------------------------------------------
46+ // Toggle dropdown menu
47+ menuButton . addEventListener ( 'click' , ( ) => { this . toggleMenu ( ) } ) ;
48+ menuButton . addEventListener ( 'keydown' , ( event ) => { if ( event . key === 'Enter' ) { this . toggleMenu ( ) } } ) ;
49+
50+ // Hide search results if hamburger menu is focused
5751 menuButton . addEventListener ( 'focus' , ( ) => { searchResults . style . display = 'none' ; } )
5852
59- // Hide nav dropdowns when user clicks outside of menu
60- const contentBody = document . querySelector ( '#content' ) ;
61- contentBody . addEventListener ( 'click' , ( ) => {
62- // Hide menu if open
63- if ( menuToggle . checked ) {
64- this . toggleMenu ( menuToggle , dropdownMenu , menuItems ) ;
65- }
66- // Hide search results
67- searchResults . style . display = 'none' ;
68- } )
53+ // Hide dropdown menu for keyboard navigation when first link in document is focused
54+ const firstLink = document . querySelector ( 'a' ) ;
55+ firstLink . addEventListener ( 'focus' , ( ) => { if ( menuToggle . checked ) { this . toggleMenu ( ) } } ) ;
6956
70- // Focus on search
71- const searchInput = shadow . getElementById ( 'search-input' ) ;
72- const searchBar = shadow . querySelector ( '.search-bar' ) ;
73- // If focus is on search
74- searchInput . addEventListener ( 'focus' , ( ) => {
75- // Update search bar styling
76- searchBar . classList . add ( 'search-bar-focused' ) ;
77- // Hide menu if open
78- if ( menuToggle . checked ) {
79- this . toggleMenu ( menuToggle , dropdownMenu , menuItems ) ;
80- }
81- // Display search results
82- searchResults . style . display = 'block' ;
83- } )
84- // If focus is off of search
85- searchInput . addEventListener ( 'blur' , ( ) => {
86- // Update search bar styling
87- searchBar . classList . remove ( 'search-bar-focused' ) ;
88- } )
89-
90- // Clear search
91- const clearIcon = shadow . getElementById ( 'clear-icon' ) ;
92- clearIcon . addEventListener ( 'click' , ( ) => { this . clearSearch ( searchInput , searchResults ) } ) ;
93- clearIcon . addEventListener ( 'keydown' , ( event ) => {
94- if ( event . key === 'Enter' ) { this . clearSearch ( searchInput , searchResults ) } ;
95- } )
96-
97- // Search
98- const searchForm = shadow . getElementById ( 'search-form' ) ;
99- // Await submission of search input
100- searchForm . addEventListener ( 'submit' , ( event ) => {
101- // Prevent page from reloading
102- event . preventDefault ( ) ;
103- // Get user search input
104- const input = searchInput . value ;
105- // Make search call
106- $ ( searchInput ) . tipuesearch ( input , searchInput , searchResults , 'web-component' ) ;
107- // Get search results
108- const results = shadow . querySelectorAll ( '.tipue_search_content_title' ) ;
109- results . forEach ( result => {
110- result . addEventListener ( 'click' , this . handleResultClick . bind ( this ) ) ;
111- } )
112- // Get dropdowns from search results
113- const accordions = shadow . querySelectorAll ( '.cordion' ) ;
114- accordions . forEach ( accordion => {
115- accordion . addEventListener ( 'click' , this . handleResultDropdown . bind ( this ) ) ;
57+ // Event listeners for all menus
58+ // --------------------------------------------------------------------------------------------------
59+ // Hide dropdowns when user clicks outside of search results or nav menu
60+ const contentBody = document . querySelector ( '#content' ) ;
61+ contentBody . addEventListener ( 'click' , ( ) => {
62+ if ( menuToggle . checked ) { this . toggleMenu ( ) } ;
63+ searchResults . style . display = 'none' ;
11664 } )
117- } ) ;
11865
119- // Hide dropdown menu for keyboard navigation
120- const firstLink = document . querySelector ( 'a' ) ;
121- firstLink . addEventListener ( 'focus' , ( ) => {
122- // Hide menu if open
123- if ( menuToggle . checked ) {
124- this . toggleMenu ( menuToggle , dropdownMenu , menuItems ) ;
125- }
126- } )
66+ // Event listeners for search
67+ // --------------------------------------------------------------------------------------------------
68+ // On focus of search
69+ searchInput . addEventListener ( 'focus' , ( ) => {
70+ // Highlight search input field
71+ searchBar . classList . add ( 'search-bar-focused' ) ;
72+ // Hide dropdown nav menu if open
73+ if ( menuToggle . checked ) { this . toggleMenu ( ) } ;
74+ // Display search results
75+ searchResults . style . display = 'block' ;
76+ } )
77+ // On blur of search
78+ searchInput . addEventListener ( 'blur' , ( ) => { searchBar . classList . remove ( 'search-bar-focused' ) } ) ;
79+
80+ // Clear search
81+ clearIcon . addEventListener ( 'click' , ( ) => { this . clearSearch ( ) } ) ;
82+ clearIcon . addEventListener ( 'keydown' , ( event ) => { if ( event . key === 'Enter' ) { this . clearSearch ( ) } } ) ;
83+
84+ // Submission of search input
85+ searchForm . addEventListener ( 'submit' , ( event ) => {
86+ // Prevent page from reloading
87+ event . preventDefault ( ) ;
88+ // Get user search input
89+ const input = searchInput . value ;
90+ // Make search call
91+ $ ( searchInput ) . tipuesearch ( input , searchInput , searchResults , 'web-component' ) ;
92+ // Get search results
93+ const results = shadow . querySelectorAll ( '.tipue_search_content_title' ) ;
94+ // Clear search after result is clicked
95+ results . forEach ( result => {
96+ result . addEventListener ( 'click' , this . clearSearch . bind ( this ) ) ;
97+ } )
98+ // Get dropdowns from search results
99+ const accordions = shadow . querySelectorAll ( '.cordion' ) ;
100+ accordions . forEach ( accordion => {
101+ accordion . addEventListener ( 'click' , this . handleResultDropdown . bind ( this ) ) ;
102+ } )
103+ } ) ;
127104 }
128105
129- // Toggle dropdown menu
130- toggleMenu ( menuToggle , dropdownMenu , menuItems ) {
106+ // Toggle dropdown navigation menu
107+ toggleMenu ( ) {
108+ const component = document . querySelector ( 'nav-header' ) ;
109+ const shadow = component . shadowRoot ;
110+ const menuToggle = shadow . getElementById ( 'menu-toggle' ) ;
111+ const dropdownMenu = shadow . querySelector ( '.dropdown-menu' ) ;
112+ const menuItems = dropdownMenu . querySelectorAll ( 'a' ) ;
113+
131114 // Update checked state of menuToggle
132115 var checkedState = menuToggle . checked ? false : true ;
133116 menuToggle . checked = checkedState ;
134117 // Update display of dropdown menu based on checked state
135118 if ( checkedState ) {
136119 dropdownMenu . style . height = '35em' ;
120+ // Make menu items focusable
137121 for ( let i = 0 ; i < menuItems . length ; i ++ ) {
138122 menuItems [ i ] . tabIndex = '0' ;
139123 }
140124 } else {
141125 dropdownMenu . style . height = '0em' ;
126+ // Make menu items non-focusable
142127 for ( let i = 0 ; i < menuItems . length ; i ++ ) {
143128 menuItems [ i ] . tabIndex = '-1' ;
144129 }
145130 }
146131 }
147132
148- // Handle search result dropdown interaction
133+ /**
134+ * Handle search result dropdown interaction
135+ * @param {event } event - User event
136+ */
149137 handleResultDropdown ( event ) {
150138 const button = event . target ;
151139 const parent = button . parentElement ;
152140 const grandparent = parent . parentElement ;
153141 var arrow ;
154142 var description ;
143+
155144 // Check if user clicked on button - assign variables
156145 if ( button . classList . contains ( 'cordion' ) ) {
157146 arrow = button . firstChild ;
@@ -166,24 +155,19 @@ function createComponent(html) {
166155 description . classList . toggle ( 'search_content_drop' ) ;
167156 }
168157
169- // Clear search after result is clicked
170- handleResultClick ( ) {
158+ // Clear search
159+ clearSearch ( ) {
171160 const component = document . querySelector ( 'nav-header' ) ;
172161 const shadow = component . shadowRoot ;
173162 const searchResults = shadow . getElementById ( 'search-results' ) ;
174163 const searchInput = shadow . getElementById ( 'search-input' ) ;
175- this . clearSearch ( searchInput , searchResults ) ;
176- }
177164
178- // Clear search
179- clearSearch ( searchInput , searchResults ) {
180165 // Remove input value
181166 searchInput . value = "" ;
182167 const input = searchInput . value ;
183168 // Make search call
184169 $ ( searchInput ) . tipuesearch ( input , searchInput , searchResults , 'web-component' ) ;
185170 // Hide search results
186- // searchResults.classList.add('hide-results');
187171 searchResults . style . display = 'none' ;
188172 }
189173 }
0 commit comments