PageSourceSearch

https://homevietnameserestaurants.com/wp-content/plugins/translate-switcher/public/js/switcher.js?ver=5.6.3

js homevietnameserestaurants.com collected 2026-10-08 21:01:47 UTC 23,226 bytes, 601 lines download raw bytes

1/**
2 * Translate Switcher — front-end (vanilla JS, no dependencies).
3 */
4( function () {
5	'use strict';
6
7	var data = window.TSData || {};
8	var mobileBreakpoint = parseInt( data.mobileBreakpoint, 10 ) || 782;
9	var observer = null;
10	var scheduled = false;
11	var dropdownSequence = 0;
12
13	/* ── Viewport mode ───────────────────────────────────────── */
14	function syncViewportMode() {
15		var mobile = window.innerWidth <= mobileBreakpoint;
16		document.documentElement.classList.toggle( 'ts-mobile-active', mobile );
17		return mobile;
18	}
19
20	/* ── Floating visibility / dismissal ─────────────────────── */
21	function safeStorage( type ) {
22		try {
23			var storage = type === 'local' ? window.localStorage : window.sessionStorage;
24			var probe = '__ts_probe__';
25			storage.setItem( probe, '1' );
26			storage.removeItem( probe );
27			return storage;
28		} catch ( e ) {
29			return null;
30		}
31	}
32
33	function initFloatingDismiss() {
34		var floats = document.querySelectorAll( '.ts-floating[data-ts-dismiss-key]' );
35		for ( var i = 0; i < floats.length; i++ ) {
36			( function ( floating ) {
37				var key = floating.getAttribute( 'data-ts-dismiss-key' ) || '';
38				var days = parseInt( floating.getAttribute( 'data-ts-dismiss-days' ), 10 ) || 0;
39				var storage = safeStorage( days > 0 ? 'local' : 'session' );
40				var stored = storage && key ? storage.getItem( key ) : null;
41				var dismissed = false;
42
43				if ( days > 0 && stored ) {
44					var expires = parseInt( stored, 10 ) || 0;
45					dismissed = expires > Date.now();
46					if ( ! dismissed && storage ) { storage.removeItem( key ); }
47				} else if ( days === 0 && stored === '1' ) {
48					dismissed = true;
49				}
50
51				if ( dismissed ) { floating.hidden = true; }
52
53				var button = floating.querySelector( '.ts-floating-dismiss' );
54				if ( ! button ) { return; }
55				button.addEventListener( 'click', function () {
56					floating.hidden = true;
57					if ( ! storage || ! key ) { return; }
58					if ( days > 0 ) {
59						storage.setItem( key, String( Date.now() + days * 86400000 ) );
60					} else {
61						storage.setItem( key, '1' );
62					}
63				} );
64			} )( floats[ i ] );
65		}
66	}
67
68	/* Keep top floating controls below visible sticky/fixed headers. */
69	function resolveFloatingHeaderAvoidance() {
70		var floats = document.querySelectorAll( '.ts-floating[data-ts-avoid-header="1"]' );
71		if ( ! floats.length ) { return; }
72
73		var selectors = '#wpadminbar, header, #masthead, .site-header, .sticky-header, .header-sticky, .elementor-location-header, [data-elementor-type="header"]';
74		var headers;
75		try { headers = document.querySelectorAll( selectors ); } catch ( e ) { headers = []; }
76
77		for ( var i = 0; i < floats.length; i++ ) {
78			var floating = floats[ i ];
79			floating.style.removeProperty( '--ts-header-avoid-y' );
80			if ( floating.hidden || ! isVisible( floating ) ) { continue; }
81
82			var floatStyle = window.getComputedStyle ? window.getComputedStyle( floating ) : null;
83			if ( ! floatStyle || floatStyle.top === 'auto' ) { continue; }
84			var baseTop = parseFloat( floatStyle.top );
85			if ( isNaN( baseTop ) || baseTop > Math.max( 220, window.innerHeight * 0.3 ) ) { continue; }
86
87			var candidates = [];
88			for ( var h = 0; h < headers.length; h++ ) {
89				var header = headers[ h ];
90				if ( header === floating || header.contains( floating ) || ! isVisible( header ) ) { continue; }
91				var headerStyle = window.getComputedStyle ? window.getComputedStyle( header ) : null;
92				if ( ! headerStyle || ( headerStyle.position !== 'fixed' && headerStyle.position !== 'sticky' ) ) { continue; }
93				var rect = header.getBoundingClientRect();
94				if ( rect.bottom <= 0 || rect.height > window.innerHeight * 0.5 || rect.top > Math.max( 120, window.innerHeight * 0.15 ) ) { continue; }
95				candidates.push( { top: rect.top, bottom: rect.bottom } );
96			}
97
98			// Resolve stacked bars (for example wp-admin bar + sticky site header).
99			candidates.sort( function ( a, b ) { return a.top - b.top; } );
100			var obstruction = 0;
101			for ( var c = 0; c < candidates.length; c++ ) {
102				if ( candidates[ c ].top <= obstruction + 8 ) {
103					obstruction = Math.max( obstruction, Math.ceil( candidates[ c ].bottom ) );
104				}
105			}
106			if ( obstruction > 0 ) {
107				floating.style.setProperty( '--ts-header-avoid-y', obstruction + 'px' );
108			}
109		}
110	}
111
112	/* ── Emoji flag support detection ────────────────────────── */
113	function supportsFlagEmoji() {
114		try {
115			var canvas = document.createElement( 'canvas' );
116			if ( ! canvas.getContext ) { return false; }
117			var ctx = canvas.getContext( '2d' );
118			if ( ! ctx ) { return false; }
119			canvas.width = 24;
120			canvas.height = 16;
121			ctx.font = '16px sans-serif';
122			ctx.textBaseline = 'top';
123			ctx.fillText( '\uD83C\uDDEC\uD83C\uDDE7', 0, 0 ); // 🇬🇧
124			var px = ctx.getImageData( 6, 6, 1, 1 ).data;
125			return ! ( px[ 0 ] === px[ 1 ] && px[ 1 ] === px[ 2 ] );
126		} catch ( e ) {
127			return false;
128		}
129	}
130
131	function applyFlagFallback( root ) {
132		if ( data.flagMode && data.flagMode !== 'emoji' ) { return; }
133		if ( supportsFlagEmoji() ) { return; }
134		root = root || document;
135		var flags = root.querySelectorAll( '.ts-flag-emoji[data-chip]' );
136		for ( var i = 0; i < flags.length; i++ ) {
137			var chip = flags[ i ].getAttribute( 'data-chip' ) || '';
138			flags[ i ].textContent = chip;
139			flags[ i ].classList.remove( 'ts-flag-emoji' );
140			flags[ i ].classList.add( 'ts-flag-chip' );
141		}
142	}
143
144	/* ── Active state ────────────────────────────────────────── */
145	function markActive( root ) {
146		var cur = data.current || '';
147		if ( ! cur ) { return; }
148		root = root || document;
149		var items = root.querySelectorAll( '.ts-pill, .ts-flag-item, .ts-minimal-item, .ts-option-link' );
150		for ( var i = 0; i < items.length; i++ ) {
151			var parent = items[ i ].parentNode;
152			var lang = items[ i ].getAttribute( 'data-lang' ) || ( parent && parent.getAttribute ? parent.getAttribute( 'data-lang' ) : '' );
153			if ( lang === cur ) {
154				items[ i ].classList.add( 'ts-active' );
155				items[ i ].setAttribute( 'aria-current', 'page' );
156			}
157		}
158	}
159
160	/* ── Dropdown / theme-isolated menu disclosure ───────────── */
161	function dropdownButton( dd ) {
162		return dd ? dd.querySelector( '.ts-selected' ) : null;
163	}
164
165	function dropdownMenu( dd ) {
166		if ( ! dd ) { return null; }
167		return dd._tsMenu || dd.querySelector( '.ts-menu' );
168	}
169
170	function switchingState( switcher ) {
171		if ( ! switcher ) { return; }
172		switcher.classList.add( 'ts-switching' );
173		window.setTimeout( function () {
174			if ( switcher && switcher.classList ) { switcher.classList.remove( 'ts-switching' ); }
175		}, 2500 );
176	}
177
178	function positionPortalMenu( dd ) {
179		var menu = dropdownMenu( dd );
180		var button = dropdownButton( dd );
181		if ( ! menu || ! button || ! menu.classList.contains( 'ts-menu-portal' ) ) { return; }
182
183		var rect = button.getBoundingClientRect();
184		var viewportWidth = document.documentElement.clientWidth || window.innerWidth;
185		var viewportHeight = document.documentElement.clientHeight || window.innerHeight;
186		var gap = 4;
187		var edge = 8;
188
189		menu.style.minWidth = Math.max( 1, Math.ceil( rect.width ) ) + 'px';
190		menu.style.maxWidth = Math.max( 1, viewportWidth - edge * 2 ) + 'px';
191		menu.style.visibility = 'hidden';
192		menu.classList.add( 'ts-portal-open' );
193
194		var menuRect = menu.getBoundingClientRect();
195		var width = Math.min( menuRect.width || rect.width, viewportWidth - edge * 2 );
196		var height = Math.min( menuRect.height || 0, viewportHeight - edge * 2 );
197		var left = Math.max( edge, Math.min( rect.left, viewportWidth - edge - width ) );
198		var roomBelow = viewportHeight - rect.bottom - edge;
199		var roomAbove = rect.top - edge;
200		var openAbove = height > roomBelow && roomAbove > roomBelow;
201		var top = openAbove ? Math.max( edge, rect.top - height - gap ) : Math.min( viewportHeight - edge - height, rect.bottom + gap );
202
203		menu.style.left = Math.round( left ) + 'px';
204		menu.style.top = Math.max( edge, Math.round( top ) ) + 'px';
205		menu.style.visibility = '';
206	}
207
208	function portalMenu( dd ) {
209		var menu = dropdownMenu( dd );
210		if ( ! menu || ! document.body ) { return; }
211		dd._tsMenu = menu;
212		if ( menu.parentNode !== document.body ) {
213			document.body.appendChild( menu );
214		}
215		menu.classList.add( 'ts-menu-portal', 'ts-portal-open' );
216		positionPortalMenu( dd );
217	}
218
219	function restoreMenu( dd ) {
220		var menu = dropdownMenu( dd );
221		if ( ! menu ) { return; }
222		menu.classList.remove( 'ts-portal-open', 'ts-menu-portal' );
223		menu.style.removeProperty( 'left' );
224		menu.style.removeProperty( 'top' );
225		menu.style.removeProperty( 'min-width' );
226		menu.style.removeProperty( 'max-width' );
227		menu.style.removeProperty( 'visibility' );
228		if ( menu.parentNode !== dd ) { dd.appendChild( menu ); }
229	}
230
231	function closeDropdown( dd, restoreFocus ) {
232		if ( ! dd ) { return; }
233		dd.classList.remove( 'ts-open' );
234		var button = dropdownButton( dd );
235		if ( button ) { button.setAttribute( 'aria-expanded', 'false' ); }
236		restoreMenu( dd );
237		if ( restoreFocus && button ) { button.focus(); }
238	}
239
240	function closeAll( except ) {
241		var dds = document.querySelectorAll( '.ts-dropdown.ts-open' );
242		for ( var i = 0; i < dds.length; i++ ) {
243			if ( dds[ i ] !== except ) { closeDropdown( dds[ i ], false ); }
244		}
245	}
246
247	function openDropdown( dd, focusEdge ) {
248		if ( ! dd ) { return; }
249		closeAll( dd );
250		dd.classList.add( 'ts-open' );
251		var button = dropdownButton( dd );
252		if ( button ) { button.setAttribute( 'aria-expanded', 'true' ); }
253		portalMenu( dd );
254
255		if ( focusEdge ) {
256			var menu = dropdownMenu( dd );
257			var links = menu ? menu.querySelectorAll( '.ts-option-link' ) : [];
258			if ( links.length ) { links[ focusEdge === 'last' ? links.length - 1 : 0 ].focus(); }
259		}
260	}
261
262	function bindDropdown( dd, switcher ) {
263		if ( ! dd || dd.getAttribute( 'data-ts-bound' ) === '1' ) { return; }
264		dd.setAttribute( 'data-ts-bound', '1' );
265		var button = dropdownButton( dd );
266		var menu = dropdownMenu( dd );
267		if ( ! button || ! menu ) { return; }
268		dd._tsMenu = menu;
269		dropdownSequence++;
270		var menuId = 'ts-language-menu-js-' + dropdownSequence;
271		menu.id = menuId;
272		button.setAttribute( 'aria-controls', menuId );
273
274		button.addEventListener( 'click', function ( e ) {
275			e.preventDefault();
276			e.stopPropagation();
277			if ( dd.classList.contains( 'ts-open' ) ) { closeDropdown( dd, false ); }
278			else { openDropdown( dd, '' ); }
279		} );
280
281		button.addEventListener( 'keydown', function ( e ) {
282			if ( e.key === 'ArrowDown' || e.key === 'ArrowUp' ) {
283				e.preventDefault();
284				e.stopPropagation();
285				openDropdown( dd, e.key === 'ArrowUp' ? 'last' : 'first' );
286			} else if ( e.key === 'Escape' ) {
287				e.preventDefault();
288				e.stopPropagation();
289				closeDropdown( dd, true );
290			}
291		} );
292
293		menu.addEventListener( 'click', function ( e ) {
294			var link = e.target.closest ? e.target.closest( '.ts-option-link' ) : null;
295			if ( ! link ) { return; }
296			e.stopPropagation();
297			switchingState( switcher );
298		} );
299
300		menu.addEventListener( 'keydown', function ( e ) {
301			var links = menu.querySelectorAll( '.ts-option-link' );
302			if ( ! links.length ) { return; }
303			var idx = -1;
304			for ( var i = 0; i < links.length; i++ ) {
305				if ( links[ i ] === document.activeElement ) { idx = i; break; }
306			}
307			if ( e.key === 'ArrowDown' ) {
308				e.preventDefault(); e.stopPropagation(); links[ ( idx + 1 + links.length ) % links.length ].focus();
309			} else if ( e.key === 'ArrowUp' ) {
310				e.preventDefault(); e.stopPropagation(); links[ ( idx - 1 + links.length ) % links.length ].focus();
311			} else if ( e.key === 'Home' ) {
312				e.preventDefault(); e.stopPropagation(); links[ 0 ].focus();
313			} else if ( e.key === 'End' ) {
314				e.preventDefault(); e.stopPropagation(); links[ links.length - 1 ].focus();
315			} else if ( e.key === 'Escape' ) {
316				e.preventDefault(); e.stopPropagation(); closeDropdown( dd, true );
317			}
318		} );
319	}
320
321	function bindSwitcher( switcher ) {
322		if ( ! switcher || switcher.getAttribute( 'data-ts-interactions' ) === '1' ) { return; }
323		switcher.setAttribute( 'data-ts-interactions', '1' );
324		bindDropdown( switcher.querySelector( '.ts-dropdown' ), switcher );
325		switcher.addEventListener( 'click', function ( e ) {
326			var link = e.target.closest ? e.target.closest( '.ts-pill, .ts-flag-item, .ts-minimal-item' ) : null;
327			if ( ! link || ! switcher.contains( link ) ) { return; }
328			e.stopPropagation();
329			switchingState( switcher );
330		} );
331	}
332
333	function bindSwitchers( root ) {
334		root = root || document;
335		if ( root.matches && root.matches( '.ts-switcher' ) ) { bindSwitcher( root ); }
336		var switchers = root.querySelectorAll ? root.querySelectorAll( '.ts-switcher' ) : [];
337		for ( var i = 0; i < switchers.length; i++ ) { bindSwitcher( switchers[ i ] ); }
338	}
339
340	function bindInteractions() {
341		bindSwitchers( document );
342		document.addEventListener( 'click', function ( e ) {
343			if ( ! e.target.closest || ! e.target.closest( '.ts-dropdown, .ts-menu-portal' ) ) { closeAll( null ); }
344		} );
345	}
346
347	/* ── Universal header mount ──────────────────────────────── */
348	function mountHeaderSwitchers() {
349		var template = document.getElementById( 'ts-header-mount-template' );
350		if ( ! template || ! template.content ) { return false; }
351
352		var selector = template.getAttribute( 'data-ts-selector' ) || '';
353		var placement = template.getAttribute( 'data-ts-placement' ) || 'append';
354		var targets;
355		try {
356			targets = document.querySelectorAll( selector );
357		} catch ( e ) {
358			return false;
359		}
360
361		var mounted = false;
362		for ( var i = 0; i < targets.length; i++ ) {
363			var target = targets[ i ];
364			if ( target.getAttribute( 'data-ts-header-mounted' ) === '1' ) { continue; }
365
366			// Avoid duplicating an existing switcher already placed in the target.
367			if ( ( placement === 'append' || placement === 'prepend' ) && target.querySelector( '.ts-switcher' ) ) {
368				target.setAttribute( 'data-ts-header-mounted', '1' );
369				continue;
370			}
371
372			var node = template.content.firstElementChild.cloneNode( true );
373			node.setAttribute( 'data-ts-mounted', '1' );
374
375			if ( placement === 'prepend' ) {
376				target.insertBefore( node, target.firstChild );
377			} else if ( placement === 'before' && target.parentNode ) {
378				target.parentNode.insertBefore( node, target );
379			} else if ( placement === 'after' && target.parentNode ) {
380				target.parentNode.insertBefore( node, target.nextSibling );
381			} else {
382				target.appendChild( node );
383			}
384
385			target.setAttribute( 'data-ts-header-mounted', '1' );
386			applyFlagFallback( node );
387			markActive( node );
388			bindSwitchers( node );
389			mounted = true;
390		}
391		return mounted;
392	}
393
394	/* ── Classic-menu vertical alignment guard ────────────────── */
395	function menuItemControl( item ) {
396		if ( ! item || ! item.querySelector ) { return null; }
397		return item.querySelector( '.ts-selected, .ts-pill, .ts-flag-item, .ts-minimal-item' ) || item.querySelector( '.ts-switcher' ) || item;
398	}
399
400	function adjacentMenuReference( item, controlRect ) {
401		var candidates = [ item.previousElementSibling, item.nextElementSibling ];
402		var best = null;
403		var bestScore = -1;
404		for ( var i = 0; i < candidates.length; i++ ) {
405			var sibling = candidates[ i ];
406			if ( ! sibling || sibling.classList.contains( 'ts-menu-switcher' ) || sibling.classList.contains( 'ts-menu-shortcode-item' ) || ! isVisible( sibling ) ) { continue; }
407			var ref = sibling.querySelector ? sibling.querySelector( 'a, button, [role="button"]' ) : null;
408			if ( ! ref || ! isVisible( ref ) ) { ref = sibling; }
409			var rect = ref.getBoundingClientRect();
410			if ( rect.width <= 0 || rect.height <= 0 ) { continue; }
411
412			// Same-row controls overlap vertically even when their centres differ.
413			// Stacked/mobile menu rows do not, so they are intentionally ignored.
414			var overlap = Math.min( controlRect.bottom, rect.bottom ) - Math.max( controlRect.top, rect.top );
415			var minOverlap = Math.min( controlRect.height, rect.height ) * 0.35;
416			if ( overlap < minOverlap ) { continue; }
417			var delta = ( rect.top + rect.height / 2 ) - ( controlRect.top + controlRect.height / 2 );
418			if ( Math.abs( delta ) > 24 ) { continue; }
419			var score = overlap - Math.abs( delta ) * 0.1;
420			if ( score > bestScore ) {
421				best = { delta: delta };
422				bestScore = score;
423			}
424		}
425		return best;
426	}
427
428	function alignClassicMenuSwitchers() {
429		var items = document.querySelectorAll( '.ts-menu-switcher, .ts-menu-shortcode-item' );
430		for ( var i = 0; i < items.length; i++ ) {
431			items[ i ].classList.remove( 'ts-menu-align-adjusted' );
432			items[ i ].style.removeProperty( '--ts-menu-shift-y' );
433		}
434		if ( ! items.length || window.innerWidth <= mobileBreakpoint ) { return; }
435
436		for ( var j = 0; j < items.length; j++ ) {
437			var item = items[ j ];
438			if ( ! isVisible( item ) ) { continue; }
439			var control = menuItemControl( item );
440			if ( ! control || ! isVisible( control ) ) { continue; }
441			var rect = control.getBoundingClientRect();
442			var ref = adjacentMenuReference( item, rect );
443			if ( ! ref || Math.abs( ref.delta ) < 0.75 ) { continue; }
444			item.style.setProperty( '--ts-menu-shift-y', Math.round( ref.delta * 10 ) / 10 + 'px' );
445			item.classList.add( 'ts-menu-align-adjusted' );
446		}
447	}
448
449	/* ── Mobile header collision guard ───────────────────────── */
450	function isVisible( el ) {
451		if ( ! el ) { return false; }
452		var style = window.getComputedStyle ? window.getComputedStyle( el ) : null;
453		if ( style && ( style.display === 'none' || style.visibility === 'hidden' ) ) { return false; }
454		var rect = el.getBoundingClientRect();
455		return rect.width > 0 && rect.height > 0;
456	}
457
458	function intersects( a, b ) {
459		return a.left < b.right && a.right > b.left && a.top < b.bottom && a.bottom > b.top;
460	}
461
462	function collectMenuToggles() {
463		var selectors = [
464			'button.menu-toggle',
465			'.menu-toggle',
466			'.navbar-toggler',
467			'.elementor-menu-toggle',
468			'.mobile-menu-toggle',
469			'.mobile-nav-toggle',
470			'.ast-mobile-menu-trigger-fill',
471			'.ast-button-wrap .menu-toggle',
472			'[data-toggle="collapse"][data-target*="menu"]',
473			'[aria-controls*="menu"]'
474		];
475		var found = [];
476		for ( var i = 0; i < selectors.length; i++ ) {
477			var nodes;
478			try { nodes = document.querySelectorAll( selectors[ i ] ); } catch ( e ) { nodes = []; }
479			for ( var j = 0; j < nodes.length; j++ ) {
480				var candidate = nodes[ j ];
481				// Never treat Translate Switcher's own disclosure controls as a
482				// site navigation toggle. The dropdown button intentionally uses
483				// aria-controls="ts-language-menu-*", which matches the generic
484				// [aria-controls*="menu"] fallback used for unknown themes.
485				// Including it here makes a centred mobile floating switcher
486				// collide with itself and shift away from the requested centre.
487				if ( candidate.closest && candidate.closest( '.ts-switcher, .ts-menu-portal' ) ) { continue; }
488				if ( found.indexOf( candidate ) === -1 && isVisible( candidate ) ) { found.push( candidate ); }
489			}
490		}
491		return found;
492	}
493
494	function resolveMobileHeaderCollisions() {
495		var switchers = document.querySelectorAll( '.ts-context-menu, .ts-context-header-mount, .ts-context-floating' );
496		for ( var i = 0; i < switchers.length; i++ ) {
497			switchers[ i ].classList.remove( 'ts-auto-shift', 'ts-collision-compact' );
498			switchers[ i ].style.removeProperty( '--ts-auto-shift-x' );
499		}
500
501		if ( ! syncViewportMode() || ! switchers.length ) { return; }
502		var toggles = collectMenuToggles();
503		if ( ! toggles.length ) { return; }
504
505		var gap = 10;
506		var viewportWidth = document.documentElement.clientWidth || window.innerWidth;
507		for ( var s = 0; s < switchers.length; s++ ) {
508			var sw = switchers[ s ];
509			if ( ! isVisible( sw ) ) { continue; }
510
511			var swRect = sw.getBoundingClientRect();
512			var hit = null;
513			for ( var t = 0; t < toggles.length; t++ ) {
514				var toggle = toggles[ t ];
515				// Defensive second guard: even if a future selector broadens the
516				// toggle list, a switcher must never resolve a collision against a
517				// control inside itself (or an ancestor wrapping itself).
518				if ( sw.contains( toggle ) || toggle.contains( sw ) ) { continue; }
519				var toggleRect = toggle.getBoundingClientRect();
520				if ( intersects( swRect, toggleRect ) ) {
521					hit = toggleRect;
522					break;
523				}
524			}
525			if ( ! hit ) { continue; }
526
527			// First reduce only the colliding switcher to a flag/code-sized control.
528			sw.classList.add( 'ts-collision-compact' );
529			swRect = sw.getBoundingClientRect();
530			if ( ! intersects( swRect, hit ) ) { continue; }
531
532			var shift = ( ( hit.left + hit.right ) / 2 ) >= ( ( swRect.left + swRect.right ) / 2 )
533				? -( swRect.right - hit.left + gap )
534				: ( hit.right - swRect.left + gap );
535
536			var minShift = 8 - swRect.left;
537			var maxShift = viewportWidth - 8 - swRect.right;
538			shift = Math.max( minShift, Math.min( maxShift, shift ) );
539
540			if ( Math.abs( shift ) >= 1 ) {
541				sw.style.setProperty( '--ts-auto-shift-x', Math.round( shift ) + 'px' );
542				sw.classList.add( 'ts-auto-shift' );
543			}
544		}
545	}
546
547	function scheduleLayoutPass() {
548		if ( scheduled ) { return; }
549		scheduled = true;
550		window.requestAnimationFrame( function () {
551			scheduled = false;
552			mountHeaderSwitchers();
553			alignClassicMenuSwitchers();
554			resolveFloatingHeaderAvoidance();
555			resolveMobileHeaderCollisions();
556			var open = document.querySelectorAll( '.ts-dropdown.ts-open' );
557			for ( var i = 0; i < open.length; i++ ) { positionPortalMenu( open[ i ] ); }
558		} );
559	}
560
561	function observeDynamicHeaders() {
562		if ( ! window.MutationObserver || ! document.body ) { return; }
563		observer = new MutationObserver( function ( mutations ) {
564			var relevant = false;
565			for ( var i = 0; i < mutations.length; i++ ) {
566				for ( var j = 0; j < mutations[ i ].addedNodes.length; j++ ) {
567					var node = mutations[ i ].addedNodes[ j ];
568					if ( ! node || node.nodeType !== 1 ) { continue; }
569					bindSwitchers( node );
570					if ( ( node.matches && node.matches( '.ts-switcher, header, #masthead, .site-header' ) ) || ( node.querySelector && node.querySelector( '.ts-switcher' ) ) ) { relevant = true; }
571				}
572			}
573			if ( relevant || document.getElementById( 'ts-header-mount-template' ) ) { scheduleLayoutPass(); }
574		} );
575		observer.observe( document.body, { childList: true, subtree: true } );
576	}
577
578	function init() {
579		syncViewportMode();
580		applyFlagFallback( document );
581		markActive( document );
582		bindInteractions();
583		initFloatingDismiss();
584		mountHeaderSwitchers();
585		alignClassicMenuSwitchers();
586		resolveFloatingHeaderAvoidance();
587		resolveMobileHeaderCollisions();
588		observeDynamicHeaders();
589
590		window.addEventListener( 'resize', scheduleLayoutPass );
591		window.addEventListener( 'orientationchange', scheduleLayoutPass );
592		window.addEventListener( 'load', scheduleLayoutPass );
593		window.addEventListener( 'scroll', scheduleLayoutPass, { passive: true } );
594	}
595
596	if ( document.readyState === 'loading' ) {
597		document.addEventListener( 'DOMContentLoaded', init );
598	} else {
599		init();
600	}
601} )();

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.