تغییر منو
تغییر منوی شخصی
به سامانه وارد نشدید
Your IP address will be publicly visible if you make any edits.

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

از ویکی‌پرولتار

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

  • فایرفاکس / سافاری: کلید Shift را نگه دارید و روی دکمهٔ Reload کلیک کنید، یا کلید‌های Ctrl-F5 یا Ctrl-R را با هم فشار دهید (در رایانه‌های اپل مکینتاش کلید‌های ⌘-R)
  • گوگل کروم: کلیدهای Ctrl+Shift+R را با هم فشار دهید (در رایانه‌های اپل مکینتاش کلید‌های ⌘-Shift-R)
  • اینترنت اکسپلورر/ Edge: کلید Ctrl را نگه‌دارید و روی دکمهٔ Refresh کلیک کنید، یا کلید‌های Ctrl-F5 را با هم فشار دهید
  • اپرا: Ctrl-F5 را بفشارید.
/* Any JavaScript here will be loaded for all users on every page load. */
/**
 * Dynamic Navigation Bars. See [[Wikipedia:NavFrame]]
 * 
 * Based on script from en.wikipedia.org, 2008-09-15.
 *
 * @source www.mediawiki.org/wiki/MediaWiki:Gadget-NavFrame.js
 * @maintainer Helder.wiki, 2012–2013
 * @maintainer Krinkle, 2013
 */
( function () {

// Set up the words in your language
var collapseCaption = 'hide';
var expandCaption = 'show';

var navigationBarHide = '[' + collapseCaption + ']';
var navigationBarShow = '[' + expandCaption + ']';

/**
 * Shows and hides content and picture (if available) of navigation bars.
 *
 * @param {number} indexNavigationBar The index of navigation bar to be toggled
 * @param {jQuery.Event} e Event object
 */
function toggleNavigationBar( indexNavigationBar, e ) {
	var navChild,
		navToggle = document.getElementById( 'NavToggle' + indexNavigationBar ),
		navFrame = document.getElementById( 'NavFrame' + indexNavigationBar );

	// Prevent browser from jumping to href "#"
	e.preventDefault();

	if ( !navFrame || !navToggle ) {
		return false;
	}

	// If shown now
	if ( navToggle.firstChild.data === navigationBarHide ) {
		for ( navChild = navFrame.firstChild; navChild !== null; navChild = navChild.nextSibling ) {
			if ( $( navChild ).hasClass( 'NavContent' ) || $( navChild ).hasClass( 'NavPic' ) ) {
				navChild.style.display = 'none';
			}
		}
		navToggle.firstChild.data = navigationBarShow;

	// If hidden now
	} else if ( navToggle.firstChild.data === navigationBarShow ) {
		for ( navChild = navFrame.firstChild; navChild !== null; navChild = navChild.nextSibling ) {
			if ( $( navChild ).hasClass( 'NavContent' ) || $( navChild ).hasClass( 'NavPic' ) ) {
				navChild.style.display = 'block';
			}
		}
		navToggle.firstChild.data = navigationBarHide;
	}
}

/**
 * Adds show/hide-button to navigation bars.
 *
 * @param {jQuery} $content
 */
function createNavigationBarToggleButton( $content ) {
	var i, j, navChild, navToggle, navToggleText, isCollapsed,
		indexNavigationBar = 0;
	// iterate over all < div >-elements
	var $divs = $content.find( 'div.NavFrame' );
	$divs.each( function ( i, navFrame ) {
		indexNavigationBar++;
		navToggle = document.createElement( 'a' );
		navToggle.className = 'NavToggle';
		navToggle.setAttribute( 'id', 'NavToggle' + indexNavigationBar );
		navToggle.setAttribute( 'href', '#' );
		$( navToggle ).on( 'click', $.proxy( toggleNavigationBar, null, indexNavigationBar ) );

		isCollapsed = $( navFrame ).hasClass( 'collapsed' );
		// backwards compatibility for old technique where the collapsed class was not yet used
		for ( navChild = navFrame.firstChild; navChild !== null && !isCollapsed; navChild = navChild.nextSibling ) {
			if ( $( navChild ).hasClass( 'NavPic' ) || $( navChild ).hasClass( 'NavContent' ) ) {
				if ( navChild.style.display === 'none' ) {
					isCollapsed = true;
				}
			}
		}
		if ( isCollapsed ) {
			for ( navChild = navFrame.firstChild; navChild !== null; navChild = navChild.nextSibling ) {
				if ( $( navChild ).hasClass( 'NavPic' ) || $( navChild ).hasClass( 'NavContent' ) ) {
					navChild.style.display = 'none';
				}
			}
		}
		navToggleText = document.createTextNode( isCollapsed ? navigationBarShow : navigationBarHide );
		navToggle.appendChild( navToggleText );

		// Find the NavHead and attach the toggle link (Must be this complicated because Moz's firstChild handling is borked)
		for ( j = 0; j < navFrame.childNodes.length; j++ ) {
			if ( $( navFrame.childNodes[j] ).hasClass( 'NavHead' ) ) {
				navToggle.style.color = navFrame.childNodes[j].style.color;
				navFrame.childNodes[j].appendChild( navToggle );
			}
		}
		navFrame.setAttribute( 'id', 'NavFrame' + indexNavigationBar );
	} );
}

mw.hook( 'wikipage.content' ).add( createNavigationBarToggleButton );

}());

/**
 * 
 * Side bar customization
 * 
 */
function ModifySidebar( action, section, name, link ) {
	try {
		switch ( section ) {
			case 'languages':
				var target = 'p-lang';
				break;
			case 'toolbox':
				var target = 'p-tb';
				break;
			case 'navigation':
				var target = 'p-navigation';
				break;
			default:
				var target = 'p-' + section;
				break;
		}

		if ( action == 'add' ) {
			var node = document.getElementById( target )
							   .getElementsByTagName( 'div' )[0]
							   .getElementsByTagName( 'ul' )[0];

			var aNode = document.createElement( 'a' );
			var liNode = document.createElement( 'li' );

			aNode.appendChild( document.createTextNode( name ) );
			aNode.setAttribute( 'href', link );
			liNode.appendChild( aNode );
			liNode.className = 'plainlinks';
			node.appendChild( liNode );
		}

		if ( action == 'remove' ) {
			var list = document.getElementById( target )
							   .getElementsByTagName( 'div' )[0]
							   .getElementsByTagName( 'ul' )[0];

			var listelements = list.getElementsByTagName( 'li' );

			for ( var i = 0; i < listelements.length; i++ ) {
				if (
					listelements[i].getElementsByTagName( 'a' )[0].innerHTML == name ||
					listelements[i].getElementsByTagName( 'a' )[0].href == link
				)
				{
					list.removeChild( listelements[i] );
				}
			}
		}


	} catch( e ) {
		// let's just ignore what's happened
		return;
	}
}

function CustomizeModificationsOfSidebar() {
	// adds [[Special:CategoryTree|Special:CategoryTree]] to toolbox
	ModifySidebar( 'add', 'toolbox', 'List of uploaded files', 'https://en.prolewiki.org/wiki/Special:ListFiles' );
}

jQuery( CustomizeModificationsOfSidebar );


/**
	* Append edit button to non-logged in users that redirects to Request Account.
	* Only applies to Citizen because anon users use Citizen by default and can't change it
	* DISABLED on jan 6 2024 due to non-use. Can be re-enabled by removing the comment lines
**/
/*
(function($, mw) {
    // Wait for the DOM to be ready
    $(document).ready(function() {
        // Check if the user is anonymous, i.e. not logged in
        if (mw.user.isAnon()) {
            // Create the HTML for the "request account" edit button. Styled in MediaWiki:Citizen.css
            var requestAccountEditBtn = '<li id="ca-request-account" class="mw-list-item">' +
                '<a href="/wiki/Special:RequestAccount" title="Edit page">Make a correction</a>' +
                '</li>';

            // Insert the button after the #ca-history element
            $('#ca-history').after(requestAccountEditBtn);
        }
    });
})(jQuery, mediaWiki);
*/

/**
	* Append icons to Citizen sidebar starting under Megamenu (drawer)
**/
/* Library */
(function($, mw) {
    // Wait for the DOM to be ready
    $(document).ready(function() {
            var libraryLink = '<a class="citizen-header__item sidebar-library" href="/wiki/ProleWiki:Library" title="Library"><div class="citizen-header__button"></div></a>';
    
            $('.citizen-drawer').after(libraryLink);
    });
})(jQuery, mediaWiki);

/* Essays*/
(function($, mw) {
    // Wait for the DOM to be ready
    $(document).ready(function() {
            var essaysLink = '<a class="citizen-header__item sidebar-essays" href="/wiki/ProleWiki:Essays" title="Essays"><div class="citizen-header__button"></div></a>';
    
            $('.sidebar-library').after(essaysLink);
    });
})(jQuery, mediaWiki);

/* Upload file icon */
(function($, mw) {
    // Wait for the DOM to be ready
    $(document).ready(function() {
        if (!mw.user.isAnon()) {
            // Create the HTML for the "Upload file" icon + link
            var uploadFileIcon = '<a class="citizen-header__item sidebar-upload" href="/wiki/Special:Upload" title="Upload file"><div class="citizen-header__button"></div></a>';
    
            // Insert the icon HTML after the existing icon container element
            $('.sidebar-essays').after(uploadFileIcon);
        }
    });
})(jQuery, mediaWiki);

/**
	* Adding hyperlink icons to headings
**/
(function($, mw) {
    $(document).ready(function() {
        // Shared smooth scroll function
        function smoothScroll(targetId) {
            const target = document.getElementById(targetId);
            if (target) {
                target.scrollIntoView({
                    behavior: 'smooth',
                    block: 'start'
                });
            }
        }

        // 1. Handler for TOC and regular anchor links
        $(document).on('click', 'a[href^="#"]:not(.heading-hyperlink)', function(event) {
            const href = $(this).attr('href');
            const targetId = href.replace(/^#/, '');

            event.preventDefault();
            smoothScroll(targetId);
            
            if (history.pushState) {
                history.pushState(null, null, href);
            } else {
                window.location.hash = href;
            }
        });

        // 2. Special handler for our hyperlink icons
        function handleHeadingLinkClick(event) {
            const href = $(this).attr('href');
            const targetId = href.replace(/^#/, '');
            
            // Stop propagation FIRST to prevent section collapse
            event.stopPropagation();
            event.preventDefault();
            
            smoothScroll(targetId);
            
            // Update URL without jump
            if (history.pushState) {
                history.pushState(null, null, href);
            } else {
                window.location.hash = href;
            }
        }

        // Add hyperlink buttons with dedicated handler
        function addHyperlinkButton(selector) {
            $(selector).each(function() {
                const $headline = $(this);
                const sectionId = $headline.attr('id');
                if (!sectionId) return;

                const hyperlinkButton = $('<a>', {
                    href: '#' + sectionId,
                    class: 'heading-hyperlink citizen-ui-icon mw-ui-icon-wikimedia-link',
                    title: 'Direct link to this section',
                    'aria-label': 'Direct link to this section',
                    'data-no-preview': 'true'
                }).on('click', handleHeadingLinkClick);

                $headline.append(hyperlinkButton);
            });
        }

        // Target headings
        addHyperlinkButton('h2 .mw-headline');
        addHyperlinkButton('h3 .mw-headline');
        addHyperlinkButton('h4 .mw-headline');
        addHyperlinkButton('h5 .mw-headline');
    });
})(jQuery, mediaWiki);
/*end hyperlink in heading*/


// If we're on the Collection page and are still rendering:
if ($("#renderingProgress").length) {
  // Refresh in 5 seconds:
  setTimeout(location.reload.bind(location), 5000);
}

/**
 * Adding sepia mode to theme selector in gear icon, WORK IN PROGRESS
**/
(function() {
    // Immediately apply theme from localStorage to prevent flash
    const storedTheme = localStorage.getItem('skin-theme-clientpref');
    const html = document.documentElement;
    
    // Remove all theme classes
    html.classList.remove(
        'skin-citizen-light',
        'skin-citizen-dark',
        'skin-citizen-auto',
        'skin-citizen-sepia'
    );
    
    // Apply stored theme or default to 'os'
    const theme = storedTheme || 'os';
    if (theme === 'day') {
        html.classList.add('skin-citizen-light');
    } else if (theme === 'night') {
        html.classList.add('skin-citizen-dark');
    } else if (theme === 'os') {
        html.classList.add('skin-citizen-auto');
    } else if (theme === 'sepia') {
        html.classList.add('skin-citizen-sepia');
    }

    // The rest of the code runs after mediawiki loads
    mw.loader.using('mediawiki.util').then(function() {
        function handleThemeChange(selectedValue) {
            // Same class switching as above
            html.classList.remove(
                'skin-citizen-light',
                'skin-citizen-dark',
                'skin-citizen-auto',
                'skin-citizen-sepia'
            );
            
            if (selectedValue === 'day') {
                html.classList.add('skin-citizen-light');
            } else if (selectedValue === 'night') {
                html.classList.add('skin-citizen-dark');
            } else if (selectedValue === 'os') {
                html.classList.add('skin-citizen-auto');
            } else if (selectedValue === 'sepia') {
                html.classList.add('skin-citizen-sepia');
            }
            
            localStorage.setItem('skin-theme-clientpref', selectedValue);
        }

        function addSepiaOption() {
            const container = document.querySelector('#skin-client-prefs-skin-theme form');
            if (!container) {
                setTimeout(addSepiaOption, 300);
                return;
            }

            if (document.getElementById('skin-client-pref-skin-theme-value-sepia')) {
                return;
            }

            const template = container.querySelector('.citizen-client-prefs-radio');
            if (!template) return;

            const sepiaRadio = template.cloneNode(true);
            const input = sepiaRadio.querySelector('input');
            const label = sepiaRadio.querySelector('label');

            input.id = 'skin-client-pref-skin-theme-value-sepia';
            input.value = 'sepia';
            input.name = 'skin-client-pref-skin-theme-group';
            input.dataset.eventName = 'skin-client-pref-skin-theme-value-sepia';
            input.checked = (storedTheme === 'sepia');
            
            label.setAttribute('for', input.id);
            label.textContent = 'Sepia';
            label.id = 'sepia-style-label';

            container.appendChild(sepiaRadio);
        }

        // Add event listener for theme changes
        document.addEventListener('change', function(event) {
            const radio = event.target;
            if (radio.matches('input[type="radio"][name="skin-client-pref-skin-theme-group"]')) {
                handleThemeChange(radio.value);
            }
        });

        addSepiaOption();
    });
})();
/*end sepia code*/


//Function START: displaying join us testimonial
(function($, mw) {
    // Wait for the DOM to be ready
    $(document).ready(function() {
        console.log("Document is ready and script is running");
        
        const thresholdHeight = 375; //live value should be ~350-400
        const testimonials = [
            '<span>"The ProleWiki community is very welcoming and diverse, with a genuine curiosity towards a broad spectrum of topics, plus a democratic and empathetic approach to learning and decision-making."</span><br><a href="https://en.prolewiki.org/wiki/Comrade:ComradeTrash">ComradeTrash</a>',
            '<span>"Working with ProleWiki has given me the space and drive to learn more, both as a communist and as a professional. I never feel throttled or unable to voice my ideas to the project, and then make them into reality."</span><br><a href="https://en.prolewiki.org/wiki/Comrade:CriticalResist">CriticalResist</a>',
            '<span>"ProleWiki is a lively environment for self-directed socialist education. They are very supportive of indigenous peoples globally, which in this era is hard to find, so among socialists ProleWiki are very principled. The editorship strives for quality."<br><a href="https://en.prolewiki.org/wiki/Comrade:Charhapiti">Charhapiti',
            '<span>"As a trans woman, I have never felt more accepted by any other community but that of ProleWiki. It is one of the few leftist spaces online which is principled enough to truly uphold its stance as a consistent ally of the queer community."</span><br><a href="https://en.prolewiki.org/wiki/Comrade:https://en.prolewiki.org/wiki/Comrade:Local_Gay_Communist_-_LGC">Local Gay Communist - LGC'
        ];

            const joinUsDiv = document.getElementById('joinUs');
            const testimonialContainer = document.getElementById('homepage-testimonial');

            // Check if the elements exist
            if (joinUsDiv && testimonialContainer) {
                const joinUsHeight = joinUsDiv.offsetHeight;
                //console.log("Join Us Div Height:", joinUsHeight);

                if (joinUsHeight >= thresholdHeight) {
                    const randomTestimonial = testimonials[Math.floor(Math.random() * testimonials.length)];
                    testimonialContainer.innerHTML = randomTestimonial;
                    testimonialContainer.style.display = 'block';
                } else {
                    testimonialContainer.style.display = 'none';
                }
            } else {
                //console.log("Either joinUsDiv or testimonialContainer is missing.");
            }
        });
})(jQuery, mediaWiki);
//Function END: displaying join us testimonial