![]() |
VOOZH | about |
Note: After saving, you have to bypass your browser's cache to see the changes.
Google Chrome, Firefox, Microsoft Edge, and Safari: Hold down the key and click the Reload toolbar button.
For details and instructions about other browsers, see Wikipedia:Bypass your cache.
/// <reference types="types-mediawiki" /> /* global mw */ mw.hook('wikipage.content').add(($content)=>{ $content.find('time.localized-time').each((_,/** @type {HTMLTimeElement} */element)=>{ if(!element.dateTime)element.dateTime=element.textContent; if(!element.title)element.title=element.textContent; element.classList.add('explain'); letdateFormatOptions={ month:'long', day:'numeric', hour:'numeric', minute:'numeric', hour12:false, timeZoneName:'long', }; constsetOption=function(optionName,attributeName){ constattributeValue=$(element).attr(attributeName); if(attributeValue=='none') dateFormatOptions[optionName]=undefined; elseif(attributeValue!=undefined) dateFormatOptions[optionName]=attributeValue; }; setOption('year','data-year-format'); setOption('month','data-month-format'); setOption('day','data-day-format'); setOption('weekday','data-weekday-format'); setOption('hour','data-hour-format'); setOption('minute','data-minute-format'); setOption('second','data-second-format'); setOption('timeZoneName','data-timezone-format'); constlang=$(element).attr('data-lang')||'en-US'; try{ constdate=newDate(element.dateTime); element.textContent=date.toLocaleDateString(lang,dateFormatOptions); }catch(error){ console.error(error); } }); // overenginnered countdown timer $content.find('time.countdown').each((_,/** @type {HTMLTimeElement} */element)=>{ if(!element.dateTime)element.dateTime=element.textContent; if(!element.title)element.title=element.textContent; constcontroller=newAbortController(); updateCountdown(element,controller); constnow=Date.now(); constdelta=1000-(now%1000); setTimeout(()=>{ animationInterval(1000,controller.signal,()=>{ updateCountdown(element,controller); }); },delta); }); }); functionupdateCountdown( /** @type {HTMLTimeElement} */element, /** @type {AbortController} */controller ){ try{ constdate=newDate(element.dateTime); constnow=Date.now(); constdelta=date-now; if(delta<=0){ constroot=element.closest('.countdown-root'); root.querySelectorAll('.countdown-active').forEach((/** @type {HTMLElement} */el)=>{ el.style.display='none'; }); root.querySelectorAll('.countdown-done').forEach((/** @type {HTMLElement} */el)=>{ el.style.display=''; }); controller.abort(); return; } constdays=Math.floor(delta/86400000); consthours=Math.floor((delta%86400000)/3600000); constminutes=Math.floor((delta%3600000)/60000); constseconds=Math.floor((delta%60000)/1000); const/** @type {string[]} */parts=[]; if(days>0)parts.push(`${days} day${days===1?'':'s'}`); if(days<30&&hours>0)parts.push(`${hours} hour${hours===1?'':'s'}`); if(days===0&&(hours>0||minutes>0))parts.push(`${minutes} minute${minutes===1?'':'s'}`); if(days===0&&(hours>0||minutes>0||seconds>0))parts.push(`${seconds} second${seconds===1?'':'s'}`); constcountdownText=(()=>{ // https://stackoverflow.com/a/53879103 if(parts.length===1)returnparts[0]; constfirsts=parts.slice(0,parts.length-1); constlast=parts[parts.length-1]; constlastConnector=parts.length>2?', and ':' and '; returnfirsts.join(', ')+lastConnector+last; })(); element.textContent=countdownText; }catch(error){ console.error(error); controller.abort(); } } functionanimationInterval( /** @type {number} */ms, /** @type {AbortSignal} */signal, /** @type {(time: number) => void} */callback ){ conststart=document.timeline?document.timeline.currentTime:performance.now(); functionframe(/** @type {number} */time){ if(signal.aborted)return; callback(time); scheduleFrame(time); } functionscheduleFrame(/** @type {number} */time){ constelapsed=time-start; constroundedElapsed=Math.round(elapsed/ms)*ms; consttargetNext=start+roundedElapsed+ms; constdelay=targetNext-performance.now(); setTimeout(()=>requestAnimationFrame(frame),delay); } scheduleFrame(start); }