MediaWiki:Common.js: Difference between revisions

help with saint of the day parsing
(add JavaScript-Based Time Zone Detection)
(help with saint of the day parsing)
 
Line 1: Line 1:
/* Any JavaScript here will be loaded for all users on every page load. */
/* Any JavaScript here will be loaded for all users on every page load. */
// Utility function to set/get cookies as a fallback for localStorage
// Utility functions for cookies
function setCookie(name, value, days) {
function setCookie(name, value, days) {
     const expires = new Date(Date.now() + days * 864e5).toUTCString();
     const expires = new Date(Date.now() + days * 864e5).toUTCString();
Line 11: Line 11:


mw.hook('wikipage.content').add(function($content) {
mw.hook('wikipage.content').add(function($content) {
    // Only process for anonymous users
     if (mw.user.isAnon()) {
     if (mw.user.isAnon()) {
         // Detect user's time zone, with fallback to UTC
         // Detect user's time zone
         let userTimeZone;
         let userTimeZone;
         try {
         try {
Line 22: Line 21:
         }
         }


         // Cache time zone in localStorage and cookie for persistence
         // Cache time zone
         try {
         try {
             localStorage.setItem('wiki_user_timezone', userTimeZone);
             localStorage.setItem('wiki_user_timezone', userTimeZone);
Line 30: Line 29:
         }
         }


         // Define timestamp selectors, including extension-specific ones
         // Timestamp selectors
         const timestampSelectors = [
         const timestampSelectors = [
             '.mw-changeslist-date', // Recent changes
             '.mw-changeslist-date', // Recent changes
Line 39: Line 38:
             'span.history-user-info span', // User signatures
             'span.history-user-info span', // User signatures
             '.smw-timestamp', // Semantic MediaWiki
             '.smw-timestamp', // Semantic MediaWiki
             '.dpl-timestamp' // DynamicPageList
             '.dpl-timestamp', // DynamicPageList
            '.custom-time' // Custom {{#time:F j}} or {{#time:F d}}
         ].join(',');
         ].join(',');


        // Optimize by scoping to main content area
         const timestamps = $content.find(timestampSelectors);
         const timestamps = $content.find(timestampSelectors);
        // Get user's interface language for internationalization
         const userLang = mw.config.get('wgUserLanguage') || 'en-US';
         const userLang = mw.config.get('wgUserLanguage') || 'en-US';


        // Debounced timestamp update for performance
         const updateTimestamps = debounce(function() {
         const updateTimestamps = debounce(function() {
             timestamps.each(function() {
             timestamps.each(function() {
                 const $element = $(this);
                 const $element = $(this);
                 let utcTime = $element.attr('data-mw-timestamp') || $element.text().trim();
                 let utcTime = $element.attr('data-mw-timestamp') || $element.text().trim();
                let isLeadingZeroFormat = false;
                 try {
                 try {
                     // Parse UTC timestamp with early error handling
                     // Detect {{#time:F j}} (e.g., "September 7") or {{#time:F d}} (e.g., "September 07")
                    if (/^[A-Za-z]+ \d{1,2}$/.test(utcTime)) {
                        isLeadingZeroFormat = utcTime.match(/^[A-Za-z]+ 0\d$/); // Check for leading zero (e.g., "September 07")
                        utcTime = `${utcTime}, ${new Date().getFullYear()} 00:00:00 UTC`;
                    }
 
                     let date;
                     let date;
                     try {
                     try {
Line 64: Line 67:
                     }
                     }


                    // Format options for user's time zone and language
                     const options = {
                     const options = {
                         timeZone: userTimeZone,
                         timeZone: userTimeZone,
                         year: 'numeric',
                         year: 'numeric',
                         month: 'short',
                         month: 'long',
                         day: 'numeric',
                         day: isLeadingZeroFormat ? '2-digit' : 'numeric', // Use leading zeros if input has them
                         hour: 'numeric',
                         hour: 'numeric',
                         minute: 'numeric',
                         minute: 'numeric',
                         second: 'numeric',
                         second: 'numeric',
                         hour12: userLang === 'en-US' // 12-hour for en-US, 24-hour for others
                         hour12: userLang === 'en-US'
                     };
                     };
                     const formattedTime = date.toLocaleString(userLang, options);
                     const formattedTime = date.toLocaleString(userLang, {
                        timeZone: userTimeZone,
                        month: 'long',
                        day: isLeadingZeroFormat ? '2-digit' : 'numeric'
                    });
                     const timeZoneAbbr = new Intl.DateTimeFormat(userLang, {
                     const timeZoneAbbr = new Intl.DateTimeFormat(userLang, {
                         timeZone: userTimeZone,
                         timeZone: userTimeZone,
Line 82: Line 88:
                         || userTimeZone.split('/').pop().replace('_', ' ') || userTimeZone;
                         || userTimeZone.split('/').pop().replace('_', ' ') || userTimeZone;


                    // Update timestamp
                     $element.text(`${formattedTime} (${timeZoneAbbr})`);
                     $element.text(`${formattedTime} (${timeZoneAbbr})`);
                     $element.attr('title', `Original UTC: ${utcTime}`);
                     $element.attr('title', `Original UTC: ${utcTime}`);
Line 95: Line 100:
});
});


// Non-intrusive prompt triggered on scroll or time zone mismatch
// Non-intrusive prompt
let prompted = false;
let prompted = false;
const currentZone = Intl.DateTimeFormat().resolvedOptions().timeZone;
const currentZone = Intl.DateTimeFormat().resolvedOptions().timeZone;
Line 133: Line 138:
}
}


// Debounce utility
function debounce(func, wait) {
function debounce(func, wait) {
     let timeout;
     let timeout;