اطلاعیه: از همه ایران دوستان عزیز دعوت می‌کنیم در ایجاد و به‌روزرسانی صفحات جاویدنامان همیاری نمایند. در حال حاضر میتوانید بدون عضویت در ثبت تاریخ کمک نمایید.

مدیاویکی:Common.js

از ویکی‌یاد

نکته: پس از انتشار ممکن است برای دیدن تغییرات نیاز باشد که حافظهٔ نهانی مرورگر خود را پاک کنید.

  • فایرفاکس / سافاری: کلید Shift را نگه دارید و روی دکمهٔ Reload کلیک کنید، یا کلید‌های Ctrl-F5 یا Ctrl-R را با هم فشار دهید (در رایانه‌های اپل مکینتاش کلید‌های ⌘-R)
  • گوگل کروم: کلیدهای Ctrl+Shift+R را با هم فشار دهید (در رایانه‌های اپل مکینتاش کلید‌های ⌘-Shift-R)
  • Edge: کلید Ctrl را نگه‌دارید و روی دکمهٔ Refresh کلیک کنید، یا کلید‌های Ctrl-F5 را با هم فشار دهید
/**
 * Umami Analytics tracking (privacy-focused, self-hosted)
 */
(function() {
    // Create the script element
    var script = document.createElement('script');
    
    // Set attributes exactly as provided by Umami
    script.defer = true;
    script.src = 'https://cloud.umami.is/script.js';
    script.setAttribute('data-website-id', 'f5f75b33-a7ed-4d71-ac5a-7750a48efaa0');
    
    // Append to head (or body – head is preferred for earlier loading)
    document.head.appendChild(script);
})();

/**
 * Gallery to background-cover: set img src as background on .thumb div + hide img
 * → ONLY when the gallerybox is inside an element with class "javidnam"
 */
(function () {
    'use strict';

    function processGalleries() {
        document.querySelectorAll('li.gallerybox').forEach(function (box) {
            // Check if this gallerybox is inside a .javidnam container
            const container = box.closest('.javidnam');
            if (!container) {
                return; // skip if not inside .javidnam
            }

            const thumbDiv = box.querySelector('div.thumb');
            if (!thumbDiv) return;

            // Quick skip: if this thumb is a known broken/placeholder structure
            if (thumbDiv.querySelector('.mw-broken-media, .mw-file-element:not(img), span[typeof="mw:Error"]')) {
                return; // broken file link → leave untouched
            }

            const img = thumbDiv.querySelector('img.mw-file-element');
            if (!img) return;

            const src = img.src && img.src.trim();
            if (!src || src === '' ||
                src.includes('brokenimage') ||
                src.includes('noimage') ||
                src.includes('Special:Redirect/file/') ||
                img.alt === '' || img.alt === null) {
                return;
            }

            // Skip tiny/unloaded images (common for broken ones)
            if (img.naturalWidth <= 4 || img.naturalHeight <= 4 || img.complete === false) {
                return;
            }

            // Already processed?
            if (thumbDiv.dataset.backgroundApplied) {
                return;
            }

            // Apply background
            thumbDiv.style.backgroundImage = 'url(' + src + ')';
            thumbDiv.style.backgroundSize = 'cover';
            thumbDiv.style.backgroundPosition = 'center center';
            thumbDiv.style.backgroundRepeat = 'no-repeat';

            // Hide original img
            img.style.display = 'none';

            // Mark as processed
            thumbDiv.dataset.backgroundApplied = 'true';
        });
    }

    // Run when DOM is ready
    function init() {
        processGalleries();
    }

    if (document.readyState !== 'loading') {
        init();
    } else {
        document.addEventListener('DOMContentLoaded', init);
    }

    // Mutation observer for dynamic content (DPL, AJAX loads, etc.)
    const observer = new MutationObserver(processGalleries);
    observer.observe(document.body, { childList: true, subtree: true });

    // Extra delayed runs for late-loading thumbs / lazy images
    setTimeout(processGalleries, 600);
    setTimeout(processGalleries, 1500);
    setTimeout(processGalleries, 3500);
})();

// Persian digits → Latin digits converter for CAPTCHA inputs
// Works on edit, login, confirm-edit forms (MathCaptcha, FancyCaptcha, etc.)

( function () {
    'use strict';

    // Map Persian/Arabic digits to Latin/ASCII
    const persianToLatin = {
        '۰': '0', '۱': '1', '۲': '2', '۳': '3', '۴': '4',
        '۵': '5', '۶': '6', '۷': '7', '۸': '8', '۹': '9',
        '٠': '0', '١': '1', '٢': '2', '٣': '3', '٤': '4',
        '٥': '5', '٦': '6', '٧': '7', '٨': '8', '٩': '9'
    };

    function normalizeInput( input ) {
        if ( !input || !input.value ) return;

        let oldValue = input.value;
        let newValue = '';

        for ( let char of oldValue ) {
            newValue += persianToLatin[char] || char;
        }

        if ( newValue !== oldValue ) {
            input.value = newValue;
            // Optional visual feedback (green border flash)
            input.style.borderColor = '#4CAF50';
            setTimeout( () => { input.style.borderColor = ''; }, 1200 );
        }
    }

    function attachToCaptchaFields() {
        // Common CAPTCHA input selectors in MediaWiki
        const selectors = [
            '#wpCaptchaWord',
            '#mw-captcha-text',
            'input[name="wpCaptchaWord"]',
            'input[name="captchaWord"]',
            'input[name="fancycaptcha"]',
            '#captchaWord',
            '#captchaInput',
            'input[type="text"][name*="captcha"]',
            'input[type="text"][id*="captcha"]',
            '#mw-confirm-edit-captcha-input'   // sometimes used
        ];

        selectors.forEach( sel => {
            document.querySelectorAll( sel ).forEach( input => {
                if ( input.dataset.persianFixAttached ) return;
                input.dataset.persianFixAttached = 'true';

                // Convert on form submit (main fix)
                const form = input.closest( 'form' );
                if ( form ) {
                    form.addEventListener( 'submit', () => {
                        normalizeInput( input );
                    }, { capture: true } );
                }

                // Also convert live (preview, blur, etc.)
                input.addEventListener( 'input', () => normalizeInput( input ) );
                input.addEventListener( 'blur',   () => normalizeInput( input ) );
            } );
        } );
    }

    // Run once on load
    attachToCaptchaFields();

    // Watch for dynamically added forms (AJAX edit dialog, login popup, etc.)
    const observer = new MutationObserver( attachToCaptchaFields );
    observer.observe( document.body, {
        childList: true,
        subtree: true
    } );

}() );