PageSourceSearch

https://graffitheque.eu/themes/freedom-master/asset/js/navigation.js?v=1.0.7

js graffitheque.eu collected 2026-10-07 03:07:33 UTC 4,721 bytes, 177 lines download raw bytes

1/**
2 * File navigation.js.
3 *
4 * Handles toggling the navigation menu for small screens and enables TAB key
5 * navigation support for dropdown menus.
6 */
7
8let mmToggli, mmToggla, mmBody, mmDrawer, mmBacker, mmClones, mmTargets;
9
10document.addEventListener("DOMContentLoaded", function() {
11	let collection, container, menu, links, i, len;
12
13	// collect the menus for mobile
14	collection = document.querySelectorAll( '.main-navigation' );
15
16	// get the toggle menu item (li)
17	mmToggli = document.querySelector( '.main-navigation__toggle' );
18
19	// Exit early if collection is empty or the toggle button is undefined
20	if ( 0 === collection.length || null === mmToggli || 'undefined' === typeof mmToggli ) {
21		console.log( 'Mobile navigation skipped' );
22		return;
23	}
24
25	// the top-most element containing content (i.e. body)
26	mmBody = document.getElementsByTagName( 'body' )[0];
27
28	mmDrawer = document.getElementById( 'menu-drawer' );
29	mmBacker = document.getElementById( 'menu-backer' );
30	mmClones = document.getElementById( 'menu-clones' );
31
32	mmTargets = []; // array of expanded menus in the menu drawer
33
34	// reverse the collection so .main-navigation renders first in the .menu-drawer
35	collection = Array.prototype.slice.call( collection );
36	collection.reverse();
37
38	// Toggle click event.
39	mmToggli.onclick = function(e) {
40		if ( ! mmDrawer.classList.contains( 'toggled' ) ) {
41			openMenuDrawer();
42		} else {
43			closeMenuDrawer();
44		}
45	};
46
47	collection.forEach( container => {
48		menu = container.querySelector( 'ul' );
49
50		// put a clone of the menu in the menu clones container
51		let clone = menu.cloneNode( true );
52		mmClones.appendChild( clone );
53
54		if ( -1 === menu.className.indexOf( 'nav-menu' ) ) {
55			menu.className += ' nav-menu';
56		}
57	} );
58
59	mmClones.querySelectorAll( '*' ).forEach( item => {
60		if( item.id ) {
61			item.id = item.id + "-drawer";
62		}
63	} );
64
65	// Assign the "menu-item-has-children" class to the li elements with ul as child.
66	mmDrawer.querySelectorAll( 'li' ).forEach( item => {
67		for (const child of item.children) {
68			if(child.tagName === 'UL') {
69				item.classList.add('menu-item-has-children');
70
71				// Add submenu header
72				const submenuHeader = document.createElement('li');
73				submenuHeader.setAttribute('class', 'menu-header');
74				submenuHeader.innerHTML = item.innerHTML;
75				child.prepend(submenuHeader);
76			}
77		}
78	});
79
80	mmDrawer.querySelectorAll( '.menu-item-has-children' ).forEach( item => {
81		item.addEventListener( 'click', function( event ) {
82			// stop propagation of child elements
83			item.querySelectorAll( 'li:not(.menu-item-has-children)' ).forEach( child => {
84				child.addEventListener( 'click', function ( event ) {
85					event.stopPropagation();
86				} );
87			} );
88
89			item.classList.add( 'expanded' );
90			mmTargets.push( this );
91			slideMenus( this );
92			scrollMenuToTop();
93			event.stopPropagation();
94			event.preventDefault();
95		} );
96	} );
97
98	mmBacker.addEventListener( 'click', function( event ) {
99		if( mmTargets.length > 0 ) {
100			let collapse = mmTargets.pop();
101			collapse.classList.remove( 'expanded' );
102			slideMenus( this );
103			scrollMenuToTop();
104		}
105		else {
106			closeMenuDrawer();
107		}
108
109		event.preventDefault();
110	} );
111} );
112
113function openMenuDrawer() {
114	backerContext();
115	mmDrawer.querySelectorAll( 'a' ).forEach( item => {
116		item.tabIndex = 0;
117	} );
118	mmBody.classList.add( 'menu-drawer-toggled');
119	mmDrawer.classList.add( 'toggled' );
120	mmToggli.classList.add( 'open' );
121	mmToggli.focus();
122}
123
124function closeMenuDrawer() {
125	// clear the expanded targets array
126	mmTargets = [];
127
128	// remove the expanded class from all menu items
129	mmDrawer.querySelectorAll( '.expanded' ).forEach( item => {
130		item.classList.remove( 'expanded' );
131	} );
132
133	// remove collapsed items from the tabindex
134	mmDrawer.querySelectorAll( 'a' ).forEach( item => {
135		item.tabIndex = -1;
136	} );
137
138	// remove clone transformations
139	mmClones.style.transform = "none";
140
141	mmBody.classList.remove( 'menu-drawer-toggled');
142	mmDrawer.classList.remove( 'toggled' );
143	mmToggli.classList.remove( 'open' );
144	mmToggli.focus();
145}
146
147function slideMenus( target ) {
148	backerContext();
149	target.classList.add( 'expanded' );
150	mmClones.style.transform = "translateX( -" + (100 * mmTargets.length) + "% )";
151}
152
153function backerContext() {
154	if( mmTargets.length > 0 ) {
155		mmBacker.innerHTML = 'Previous Menu';
156	}
157	else {
158		mmBacker.innerHTML = 'Close Menu';
159	}
160}
161
162/**
163 * Scrolls the menu drawer to top.
164 */
165function scrollMenuToTop() {
166	mmDrawer.scrollTo( 0, 0 );
167}
168
169/**
170 * Sets or removes .focus class on an element.
171 */
172function toggleFocus( menuItem ) {
173	mmDrawer.querySelectorAll( '.focus' ).forEach( focusItem => function() {
174		focusItem.classList.remove( 'focus' );
175	} );
176	menuItem.closest( 'li' ).classList.add( 'focus' );
177}

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.