Diff: STRATO-apps/wordpress_03/app/wp-includes/js/admin-bar.js

Keine Baseline-Datei – Diff nur gegen leer.
Zur Liste
1 -
1 + /**
2 + * @output wp-includes/js/admin-bar.js
3 + */
4 + /**
5 + * Admin bar with Vanilla JS, no external dependencies.
6 + *
7 + * @since 5.3.1
8 + *
9 + * @param {Object} document The document object.
10 + * @param {Object} window The window object.
11 + * @param {Object} navigator The navigator object.
12 + *
13 + * @return {void}
14 + */
15 + ( function( document, window, navigator ) {
16 + document.addEventListener( 'DOMContentLoaded', function() {
17 + var adminBar = document.getElementById( 'wpadminbar' ),
18 + topMenuItems,
19 + allMenuItems,
20 + adminBarLogout,
21 + adminBarSearchForm,
22 + shortlink,
23 + skipLink,
24 + mobileEvent,
25 + adminBarSearchInput,
26 + i;
27 +
28 + if ( ! adminBar || ! ( 'querySelectorAll' in adminBar ) ) {
29 + return;
30 + }
31 +
32 + topMenuItems = adminBar.querySelectorAll( 'li.menupop' );
33 + allMenuItems = adminBar.querySelectorAll( '.ab-item' );
34 + adminBarLogout = document.querySelector( '#wp-admin-bar-logout a' );
35 + adminBarSearchForm = document.getElementById( 'adminbarsearch' );
36 + shortlink = document.getElementById( 'wp-admin-bar-get-shortlink' );
37 + skipLink = adminBar.querySelector( '.screen-reader-shortcut' );
38 + mobileEvent = /Mobile\/.+Safari/.test( navigator.userAgent ) ? 'touchstart' : 'click';
39 +
40 + // Remove nojs class after the DOM is loaded.
41 + removeClass( adminBar, 'nojs' );
42 +
43 + if ( 'ontouchstart' in window ) {
44 + // Remove hover class when the user touches outside the menu items.
45 + document.body.addEventListener( mobileEvent, function( e ) {
46 + if ( ! getClosest( e.target, 'li.menupop' ) ) {
47 + removeAllHoverClass( topMenuItems );
48 + }
49 + } );
50 +
51 + // Add listener for menu items to toggle hover class by touches.
52 + // Remove the callback later for better performance.
53 + adminBar.addEventListener( 'touchstart', function bindMobileEvents() {
54 + for ( var i = 0; i < topMenuItems.length; i++ ) {
55 + topMenuItems[i].addEventListener( 'click', mobileHover.bind( null, topMenuItems ) );
56 + }
57 +
58 + adminBar.removeEventListener( 'touchstart', bindMobileEvents );
59 + } );
60 + }
61 +
62 + // Scroll page to top when clicking on the admin bar.
63 + adminBar.addEventListener( 'click', scrollToTop );
64 +
65 + for ( i = 0; i < topMenuItems.length; i++ ) {
66 + // Adds or removes the hover class based on the hover intent.
67 + window.hoverintent(
68 + topMenuItems[i],
69 + addClass.bind( null, topMenuItems[i], 'hover' ),
70 + removeClass.bind( null, topMenuItems[i], 'hover' )
71 + ).options( {
72 + timeout: 180
73 + } );
74 +
75 + // Toggle hover class if the enter key is pressed.
76 + topMenuItems[i].addEventListener( 'keydown', toggleHoverIfEnter );
77 + }
78 +
79 + // Remove hover class if the escape key is pressed.
80 + for ( i = 0; i < allMenuItems.length; i++ ) {
81 + allMenuItems[i].addEventListener( 'keydown', removeHoverIfEscape );
82 + }
83 +
84 + if ( adminBarSearchForm ) {
85 + adminBarSearchInput = document.getElementById( 'adminbar-search' );
86 +
87 + // Adds the adminbar-focused class on focus.
88 + adminBarSearchInput.addEventListener( 'focus', function() {
89 + addClass( adminBarSearchForm, 'adminbar-focused' );
90 + } );
91 +
92 + // Removes the adminbar-focused class on blur.
93 + adminBarSearchInput.addEventListener( 'blur', function() {
94 + removeClass( adminBarSearchForm, 'adminbar-focused' );
95 + } );
96 + }
97 +
98 + if ( shortlink ) {
99 + shortlink.addEventListener( 'click', clickShortlink );
100 + }
101 +
102 + // Prevents the toolbar from covering up content when a hash is present in the URL.
103 + if ( window.location.hash ) {
104 + window.scrollBy( 0, -32 );
105 + }
106 +
107 + // Clear sessionStorage on logging out.
108 + if ( adminBarLogout ) {
109 + adminBarLogout.addEventListener( 'click', emptySessionStorage );
110 + }
111 + } );
112 +
113 + /**
114 + * Remove hover class for top level menu item when escape is pressed.
115 + *
116 + * @since 5.3.1
117 + *
118 + * @param {Event} event The keydown event.
119 + */
120 + function removeHoverIfEscape( event ) {
121 + var wrapper;
122 +
123 + if ( event.which !== 27 ) {
124 + return;
125 + }
126 +
127 + wrapper = getClosest( event.target, '.menupop' );
128 +
129 + if ( ! wrapper ) {
130 + return;
131 + }
132 +
133 + wrapper.querySelector( '.menupop > .ab-item' ).focus();
134 + removeClass( wrapper, 'hover' );
135 + }
136 +
137 + /**
138 + * Toggle hover class for top level menu item when enter is pressed.
139 + *
140 + * @since 5.3.1
141 + *
142 + * @param {Event} event The keydown event.
143 + */
144 + function toggleHoverIfEnter( event ) {
145 + var wrapper;
146 +
147 + // Follow link if pressing Ctrl and/or Shift with Enter (opening in a new tab or window).
148 + if ( event.which !== 13 || event.ctrlKey || event.shiftKey ) {
149 + return;
150 + }
151 +
152 + if ( !! getClosest( event.target, '.ab-sub-wrapper' ) ) {
153 + return;
154 + }
155 +
156 + wrapper = getClosest( event.target, '.menupop' );
157 +
158 + if ( ! wrapper ) {
159 + return;
160 + }
161 +
162 + event.preventDefault();
163 +
164 + if ( hasClass( wrapper, 'hover' ) ) {
165 + removeClass( wrapper, 'hover' );
166 + } else {
167 + addClass( wrapper, 'hover' );
168 + }
169 + }
170 +
171 + /**
172 + * Toggle hover class for mobile devices.
173 + *
174 + * @since 5.3.1
175 + *
176 + * @param {NodeList} topMenuItems All menu items.
177 + * @param {Event} event The click event.
178 + */
179 + function mobileHover( topMenuItems, event ) {
180 + var wrapper;
181 +
182 + if ( !! getClosest( event.target, '.ab-sub-wrapper' ) ) {
183 + return;
184 + }
185 +
186 + event.preventDefault();
187 +
188 + wrapper = getClosest( event.target, '.menupop' );
189 +
190 + if ( ! wrapper ) {
191 + return;
192 + }
193 +
194 + if ( hasClass( wrapper, 'hover' ) ) {
195 + removeClass( wrapper, 'hover' );
196 + } else {
197 + removeAllHoverClass( topMenuItems );
198 + addClass( wrapper, 'hover' );
199 + }
200 + }
201 +
202 + /**
203 + * Handles the click on the Shortlink link in the adminbar.
204 + *
205 + * @since 3.1.0
206 + * @since 5.3.1 Use querySelector to clean up the function.
207 + *
208 + * @param {Event} event The click event.
209 + * @return {boolean} Returns false to prevent default click behavior.
210 + */
211 + function clickShortlink( event ) {
212 + var wrapper = event.target.parentNode,
213 + input;
214 +
215 + if ( wrapper ) {
216 + input = wrapper.querySelector( '.shortlink-input' );
217 + }
218 +
219 + if ( ! input ) {
220 + return;
221 + }
222 +
223 + // (Old) IE doesn't support preventDefault, and does support returnValue.
224 + if ( event.preventDefault ) {
225 + event.preventDefault();
226 + }
227 +
228 + event.returnValue = false;
229 +
230 + addClass( wrapper, 'selected' );
231 +
232 + input.focus();
233 + input.select();
234 + input.onblur = function() {
235 + removeClass( wrapper, 'selected' );
236 + };
237 +
238 + return false;
239 + }
240 +
241 + /**
242 + * Clear sessionStorage on logging out.
243 + *
244 + * @since 5.3.1
245 + */
246 + function emptySessionStorage() {
247 + if ( 'sessionStorage' in window ) {
248 + try {
249 + for ( var key in sessionStorage ) {
250 + if ( key.indexOf( 'wp-autosave-' ) > -1 ) {
251 + sessionStorage.removeItem( key );
252 + }
253 + }
254 + } catch ( er ) {}
255 + }
256 + }
257 +
258 + /**
259 + * Check if element has class.
260 + *
261 + * @since 5.3.1
262 + *
263 + * @param {HTMLElement} element The HTML element.
264 + * @param {string} className The class name.
265 + * @return {boolean} Whether the element has the className.
266 + */
267 + function hasClass( element, className ) {
268 + var classNames;
269 +
270 + if ( ! element ) {
271 + return false;
272 + }
273 +
274 + if ( element.classList && element.classList.contains ) {
275 + return element.classList.contains( className );
276 + } else if ( element.className ) {
277 + classNames = element.className.split( ' ' );
278 + return classNames.indexOf( className ) > -1;
279 + }
280 +
281 + return false;
282 + }
283 +
284 + /**
285 + * Add class to an element.
286 + *
287 + * @since 5.3.1
288 + *
289 + * @param {HTMLElement} element The HTML element.
290 + * @param {string} className The class name.
291 + */
292 + function addClass( element, className ) {
293 + if ( ! element ) {
294 + return;
295 + }
296 +
297 + if ( element.classList && element.classList.add ) {
298 + element.classList.add( className );
299 + } else if ( ! hasClass( element, className ) ) {
300 + if ( element.className ) {
301 + element.className += ' ';
302 + }
303 +
304 + element.className += className;
305 + }
306 +
307 + var menuItemToggle = element.querySelector( 'a' );
308 + if ( className === 'hover' && menuItemToggle && menuItemToggle.hasAttribute( 'aria-expanded' ) ) {
309 + menuItemToggle.setAttribute( 'aria-expanded', 'true' );
310 + }
311 + }
312 +
313 + /**
314 + * Remove class from an element.
315 + *
316 + * @since 5.3.1
317 + *
318 + * @param {HTMLElement} element The HTML element.
319 + * @param {string} className The class name.
320 + */
321 + function removeClass( element, className ) {
322 + var testName,
323 + classes;
324 +
325 + if ( ! element || ! hasClass( element, className ) ) {
326 + return;
327 + }
328 +
329 + if ( element.classList && element.classList.remove ) {
330 + element.classList.remove( className );
331 + } else {
332 + testName = ' ' + className + ' ';
333 + classes = ' ' + element.className + ' ';
334 +
335 + while ( classes.indexOf( testName ) > -1 ) {
336 + classes = classes.replace( testName, '' );
337 + }
338 +
339 + element.className = classes.replace( /^[\s]+|[\s]+$/g, '' );
340 + }
341 +
342 + var menuItemToggle = element.querySelector( 'a' );
343 + if ( className === 'hover' && menuItemToggle && menuItemToggle.hasAttribute( 'aria-expanded' ) ) {
344 + menuItemToggle.setAttribute( 'aria-expanded', 'false' );
345 + }
346 + }
347 +
348 + /**
349 + * Remove hover class for all menu items.
350 + *
351 + * @since 5.3.1
352 + *
353 + * @param {NodeList} topMenuItems All menu items.
354 + */
355 + function removeAllHoverClass( topMenuItems ) {
356 + if ( topMenuItems && topMenuItems.length ) {
357 + for ( var i = 0; i < topMenuItems.length; i++ ) {
358 + removeClass( topMenuItems[i], 'hover' );
359 + }
360 + }
361 + }
362 +
363 + /**
364 + * Scrolls to the top of the page.
365 + *
366 + * @since 3.4.0
367 + *
368 + * @param {Event} event The Click event.
369 + *
370 + * @return {void}
371 + */
372 + function scrollToTop( event ) {
373 + // Only scroll when clicking on the wpadminbar, not on menus or submenus.
374 + if (
375 + event.target &&
376 + event.target.id !== 'wpadminbar' &&
377 + event.target.id !== 'wp-admin-bar-top-secondary'
378 + ) {
379 + return;
380 + }
381 +
382 + try {
383 + window.scrollTo( {
384 + top: -32,
385 + left: 0,
386 + behavior: 'smooth'
387 + } );
388 + } catch ( er ) {
389 + window.scrollTo( 0, -32 );
390 + }
391 + }
392 +
393 + /**
394 + * Get closest Element.
395 + *
396 + * @since 5.3.1
397 + *
398 + * @param {HTMLElement} el Element to get parent.
399 + * @param {string} selector CSS selector to match.
400 + */
401 + function getClosest( el, selector ) {
402 + if ( ! window.Element.prototype.matches ) {
403 + // Polyfill from https://developer.mozilla.org/en-US/docs/Web/API/Element/matches.
404 + window.Element.prototype.matches =
405 + window.Element.prototype.matchesSelector ||
406 + window.Element.prototype.mozMatchesSelector ||
407 + window.Element.prototype.msMatchesSelector ||
408 + window.Element.prototype.oMatchesSelector ||
409 + window.Element.prototype.webkitMatchesSelector ||
410 + function( s ) {
411 + var matches = ( this.document || this.ownerDocument ).querySelectorAll( s ),
412 + i = matches.length;
413 +
414 + while ( --i >= 0 && matches.item( i ) !== this ) { }
415 +
416 + return i > -1;
417 + };
418 + }
419 +
420 + // Get the closest matching elent.
421 + for ( ; el && el !== document; el = el.parentNode ) {
422 + if ( el.matches( selector ) ) {
423 + return el;
424 + }
425 + }
426 +
427 + return null;
428 + }
429 +
430 + } )( document, window, navigator );
431 +