1class BaseSwitcher { 2constructor(rootEl){ 3this.root=rootEl; 4this.list=rootEl?.querySelector('.trp-switcher-dropdown-list')||null; 5this.isOpen=false; 6this._pendingFocusOnOpen=false; 7if(!this.root||!this.list) return; 8if(!this.list.id){ 9this.list.id=`trp-list-${Math.random().toString(36).slice(2, 9)}`; 10} 11this._onTe=(e)=> { 12if(e.target!==this.list||e.propertyName!=='max-height') return; 13this.root.classList.remove('is-transitioning'); 14if(!this.isOpen){ 15this.list.hidden=true; 16this.list.setAttribute('inert', ''); 17}else if(this._pendingFocusOnOpen){ 18this._pendingFocusOnOpen=false; 19const first=this.list.querySelector('[role="option"], a, button, [tabindex]:not([tabindex="-1"])' 20); 21first?.focus?.({ preventScroll: true }); 22}}; 23this.list.addEventListener('transitionend', this._onTe); 24this.collapse(); 25this.setAutoWidth(); 26this.bindKeyboard(); 27} 28_hasAnimatedTransition(){ 29if(!this.list) return false; 30const cs=getComputedStyle(this.list); 31const durationsRaw=cs.transitionDuration||''; 32if(!durationsRaw) return false; 33const durations=durationsRaw 34.split(',') 35.map(str=> parseFloat(str)||0); 36return durations.some(d=> d > 0); 37} 38collapse(){ 39this.list.hidden=true; 40this.list.setAttribute('inert', ''); 41this.setExpanded(false); 42this.root.classList.remove('is-transitioning'); 43} 44setAutoWidth(){ 45const bonusWidth=10; 46const cs=getComputedStyle(this.root); 47const declaredWidth=cs.getPropertyValue('--switcher-width').trim(); 48if(declaredWidth==='auto'&&this.root.querySelector('.trp-language-item-name')){ 49const initialWidth=this.root.getBoundingClientRect().width; 50this.root.style.setProperty('--switcher-width', (initialWidth + bonusWidth) + 'px'); 51}} 52setExpanded(open){ 53const trigger=this.root.querySelector('.trp-language-item__current[role="button"]'); 54const val=String(!!open); 55trigger?.setAttribute('aria-expanded', val); 56this.root.classList.toggle('is-open', !!open); 57} 58setOpen(open, { source=null }={}){ 59if(!this.root||!this.list||open===this.isOpen) return; 60const prefersReduced=window.matchMedia?.('(prefers-reduced-motion: reduce)')?.matches; 61const hasTransition = !prefersReduced&&this._hasAnimatedTransition(); 62this.isOpen=open; 63if(!hasTransition){ 64if(open){ 65this.list.hidden=false; 66this.list.removeAttribute('inert'); 67this.setExpanded(true);
68this._pendingFocusOnOpen=(source?.type==='keydown'); 69if(this._pendingFocusOnOpen){ 70this._pendingFocusOnOpen=false; 71const first=this.list.querySelector('[role="option"], a, button, [tabindex]:not([tabindex="-1"])' 72); 73first?.focus?.({ preventScroll: true }); 74}}else{ 75this.setExpanded(false); 76this.list.hidden=true; 77this.list.setAttribute('inert', ''); 78this._pendingFocusOnOpen=false; 79} 80return; 81} 82if(open){ 83this.list.hidden=false; 84this.list.removeAttribute('inert'); 85this._pendingFocusOnOpen=(source?.type==='keydown'); 86this.root.classList.add('is-transitioning'); 87requestAnimationFrame(()=> this.setExpanded(true) ); 88}else{ 89this.root.classList.add('is-transitioning'); 90this.setExpanded(false); 91}} 92bindKeyboard(){ 93const trigger=this.root.querySelector('.trp-language-item__current[role="button"]'); 94if(!trigger) return; 95trigger.addEventListener('keydown', (e)=> { 96const inList = !!e.target.closest?.('.trp-switcher-dropdown-list'); 97if(e.key==='Enter'||e.key===' '){ 98e.preventDefault(); 99this.setOpen(!this.isOpen, { source: e }); 100return; 101} 102if(e.key==='ArrowDown'&&!this.isOpen){ 103e.preventDefault(); 104this.setOpen(true, { source: e }); 105} 106if(e.key==='Escape'){ 107this.setOpen(false, { source: e }); 108trigger.focus?.(); 109}}); 110}} 111class ShortcodeSwitcher extends BaseSwitcher { 112constructor(wrapper){ 113const overlay = 114wrapper.querySelector('.trp-language-switcher.trp-shortcode-overlay') 115|| [...wrapper.querySelectorAll('.trp-language-switcher')] 116.find(el=> el.classList.contains('trp-shortcode-overlay')); 117overlay.hidden=false; 118overlay.removeAttribute('hidden'); 119overlay.removeAttribute('inert'); 120if('inert' in overlay) overlay.inert=false; 121super(overlay); 122if(!this.root||!this.list) return; 123const control=this.root.querySelector('.trp-language-item__current[role="button"]'); 124if(control&&this.list&&!control.hasAttribute('aria-controls')){ 125control.setAttribute('aria-controls', this.list.id); 126} 127const isClickMode = 128this.root.classList.contains('trp-open-on-click') || 129wrapper.dataset.openMode==='click' || 130wrapper.classList.contains('trp-open-on-click'); 131if(isClickMode){ 132this.root.addEventListener('click', (e)=> { 133const inList=e.target.closest('.trp-switcher-dropdown-list'); 134if(!inList){ 135e.preventDefault(); 136e.stopPropagation(); 137this.setOpen(!this.isOpen, { source: e }); 138}}, true); 139this.onDocClick=(evt)=> { 140if(!wrapper.contains(evt.target)) this.setOpen(false, { source: evt }); 141}; 142document.addEventListener('click', this.onDocClick, true); 143wrapper.addEventListener('focusout', ()=> { 144setTimeout(()=> { 145if(!wrapper.contains(document.activeElement)){ 146this.setOpen(false, { source: 'keyboard' }); 147}}, 0); 148}); 149}else{ 150this.root.addEventListener('mouseenter', (e)=> this.setOpen(true, { source: e })); 151this.root.addEventListener('mouseleave', (e)=> this.setOpen(false, { source: e })); 152}} 153} 154class FloaterSwitcher extends BaseSwitcher { 155constructor(el){ 156super(el); 157el.addEventListener('mouseenter', (e)=> this.setOpen(true, { source: e })); 158el.addEventListener('mouseleave', (e)=> this.setOpen(false, { source: e })); 159this.onDocClick=(evt)=> { if(!el.contains(evt.target)) this.setOpen(false, { source: evt });}; 160document.addEventListener('click', this.onDocClick, true); 161}} 162document.addEventListener('DOMContentLoaded', ()=> { 163initLanguageSwitchers(document); 164if(inGutenberg() && 165!getEditorDoc().querySelector(WRAPPER) 166){ 167observeWrapperUntilFound(); 168} 169if(!inGutenberg()) 170observeShortcodeSwitcher(); 171}); 172const TRP_BOUND=new WeakSet(); 173const mark=(el)=> TRP_BOUND.add(el); 174const isMarked=(el)=> TRP_BOUND.has(el); 175const WRAPPER='.trp-shortcode-switcher__wrapper'; 176const OVERLAY='.trp-language-switcher:not(.trp-opposite-button):not(.trp-ald-language-selector)'; 177function inGutenberg(){ 178return document.body?.classList?.contains('block-editor-page') 179|| !!(window.wp?.data?.select?.('core/block-editor')); 180} 181function getEditorDoc(){ 182const ifr=document.querySelector('iframe[name="editor-canvas"], .editor-canvas__iframe'); 183return (ifr&&ifr.contentDocument) ? ifr.contentDocument:document; 184} 185function initLanguageSwitchers(root=document){ 186const floater=root.querySelector('.trp-language-switcher.trp-ls-dropdown:not(.trp-shortcode-switcher):not(.trp-opposite-language)' 187); 188if(floater) 189new FloaterSwitcher(floater); 190root.querySelectorAll(WRAPPER) 191.forEach(wrapper=> { 192const overlay=wrapper.querySelector(OVERLAY); 193if(overlay&&!isMarked(overlay)){ 194mark(overlay); 195new ShortcodeSwitcher(wrapper); 196}}); 197} 198function observeShortcodeSwitcher(){ 199const initWrapper=(wrapper)=> { 200if(!wrapper) 201return; 202const overlay=wrapper.querySelector(OVERLAY); 203if(!overlay||isMarked(overlay) ) 204return; 205mark(overlay); 206new ShortcodeSwitcher(wrapper); 207} 208const mo=new MutationObserver(( mutations)=> { 209for(const m of mutations){ 210for(const n of m.addedNodes){ 211if(n.nodeType!==1) 212continue; 213if(n.matches?.(WRAPPER) ) 214initWrapper(n);
215n.querySelectorAll?.(WRAPPER).forEach(initWrapper); 216}} 217}); 218mo.observe(document, { childList: true, subtree: true }); 219} 220function observeWrapperUntilFound(){ 221const edDoc=getEditorDoc(); 222const existing=edDoc.querySelector(WRAPPER); 223if(existing){ 224initLanguageSwitchers(edDoc); 225return; 226} 227const findCanvasIframe=()=> document.querySelector('iframe[name="editor-canvas"], .editor-canvas__iframe'); 228const iframeNow=findCanvasIframe(); 229if(iframeNow){ 230watchIframe(iframeNow); 231return; 232} 233const outerMO=new MutationObserver(( mutations)=> { 234for(const m of mutations){ 235for(const n of m.addedNodes){ 236if(n.nodeType!==1) continue; 237const iframe = 238n.matches?.('iframe[name="editor-canvas"], .editor-canvas__iframe') 239? n 240: n.querySelector?.('iframe[name="editor-canvas"], .editor-canvas__iframe'); 241if(iframe){ 242outerMO.disconnect(); 243watchIframe(iframe); 244return; 245} 246const wrapper = 247n.matches?.(WRAPPER) 248? n 249: n.querySelector?.(WRAPPER); 250if(wrapper){ 251outerMO.disconnect(); 252initLanguageSwitchers(document); 253return; 254}} 255}}); 256outerMO.observe(document, { childList: true, subtree: true }); 257function watchIframe(iframe){ 258tryAttachInside(); 259iframe.addEventListener('load', tryAttachInside); 260function tryAttachInside(){ 261let doc; 262try { 263doc=iframe.contentDocument||iframe.contentWindow?.document; 264} catch (e){ 265console.warn('Cannot access iframe content due to cross-origin restrictions', e); 266return; 267} 268if(!doc) return; 269const hit=doc.querySelector(WRAPPER); 270if(hit){ 271initLanguageSwitchers(doc); 272return; 273} 274const innerMO=new MutationObserver(( muts)=> { 275for(const mm of muts){ 276for(const nn of mm.addedNodes){ 277if(nn.nodeType!==1) continue; 278if(nn.matches?.(WRAPPER) || 279nn.querySelector?.(WRAPPER) 280){ 281innerMO.disconnect(); 282initLanguageSwitchers(doc); 283return; 284}} 285} 286if(doc.querySelector(WRAPPER)){ 287innerMO.disconnect(); 288initLanguageSwitchers(doc); 289}}); 290innerMO.observe(doc, { childList: true, subtree: true }); 291}} 292};
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.