Toggle menu
Toggle personal menu
Not logged in
Your IP address will be publicly visible if you make any edits.

MediaWiki:Common.js: Difference between revisions

MediaWiki interface page
CriticalResist (talk | contribs)
final pass: bringing back hoverline custom color. Everything works from this point ------------------
CriticalResist (talk | contribs)
minified JS, let's see if it works. This is exactly the same version as the previous revision, just minified. To edit, go back to previous rev.
Line 1: Line 1:
/* Any JavaScript here will be loaded for all users on every page load. */
function ModifySidebar(e,t,i,a){try{switch(t){case"languages":var n="p-lang";break;case"toolbox":var n="p-tb";break;case"navigation":var n="p-navigation";break;default:var n="p-"+t}if("add"==e){var o=document.getElementById(n).getElementsByTagName("div")[0].getElementsByTagName("ul")[0],l=document.createElement("a"),r=document.createElement("li");l.appendChild(document.createTextNode(i)),l.setAttribute("href",a),r.appendChild(l),r.className="plainlinks",o.appendChild(r)}if("remove"==e)for(var s=document.getElementById(n).getElementsByTagName("div")[0].getElementsByTagName("ul")[0],c=s.getElementsByTagName("li"),d=0;d<c.length;d++)(c[d].getElementsByTagName("a")[0].innerHTML==i||c[d].getElementsByTagName("a")[0].href==a)&&s.removeChild(c[d])}catch(f){return}}function CustomizeModificationsOfSidebar(){ModifySidebar("add","toolbox","List of uploaded files","https://en.prolewiki.org/wiki/Special:ListFiles")}!function(){var e="[hide]",t="[show]";function i(i,a){var n,o=document.getElementById("NavToggle"+i),l=document.getElementById("NavFrame"+i);if(a.preventDefault(),!l||!o)return!1;if(o.firstChild.data===e){for(n=l.firstChild;null!==n;n=n.nextSibling)($(n).hasClass("NavContent")||$(n).hasClass("NavPic"))&&(n.style.display="none");o.firstChild.data=t}else if(o.firstChild.data===t){for(n=l.firstChild;null!==n;n=n.nextSibling)($(n).hasClass("NavContent")||$(n).hasClass("NavPic"))&&(n.style.display="block");o.firstChild.data=e}}mw.hook("wikipage.content").add(function a(n){var o,l,r,s,c,d=0;n.find("div.NavFrame").each(function(a,n){for(d++,(r=document.createElement("a")).className="NavToggle",r.setAttribute("id","NavToggle"+d),r.setAttribute("href","#"),$(r).on("click",$.proxy(i,null,d)),c=$(n).hasClass("collapsed"),l=n.firstChild;null!==l&&!c;l=l.nextSibling)($(l).hasClass("NavPic")||$(l).hasClass("NavContent"))&&"none"===l.style.display&&(c=!0);if(c)for(l=n.firstChild;null!==l;l=l.nextSibling)($(l).hasClass("NavPic")||$(l).hasClass("NavContent"))&&(l.style.display="none");for(s=document.createTextNode(c?t:e),r.appendChild(s),o=0;o<n.childNodes.length;o++)$(n.childNodes[o]).hasClass("NavHead")&&(r.style.color=n.childNodes[o].style.color,n.childNodes[o].appendChild(r));n.setAttribute("id","NavFrame"+d)})})}(),jQuery(CustomizeModificationsOfSidebar),$(function(){var e=$(".citizen-drawer");if(e.length){var t=[{cls:"sidebar-library",href:"/wiki/ProleWiki:Library",title:"Library"},{cls:"sidebar-essays",href:"/wiki/ProleWiki:Essays",title:"Essays"}];mw.user.isAnon()||t.push({cls:"sidebar-upload",href:"/wiki/Special:Upload",title:"Upload file"});for(var i=t.length-1;i>=0;i--){var a=t[i];e.after('<a class="citizen-header__item '+a.cls+'" href="'+a.href+'" title="'+a.title+'"><div class="citizen-header__button"></div></a>')}}(function e(){var t=$("h2, h3, h4, h5").find(".mw-headline");function i(e){var t=document.getElementById(e);t&&window.scrollTo({top:t.offsetTop,behavior:"smooth"})}t.length&&(t.each(function(){var e=$(this),t=e.attr("id");if(t){var a=$('<a href="#'+t+'" 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"></a>');a.on("click",function(e){e.preventDefault(),e.stopPropagation(),i(t),history.replaceState(null,null,"#"+t)}),e.append(a)}}),$(document).on("click",'a[href^="#"]:not(.heading-hyperlink)',function(e){var t=this.href,a=t.substring(t.indexOf("#")+1);a&&(e.preventDefault(),i(a),history.replaceState(null,null,"#"+a))}))})(),$("#renderingProgress").length&&setTimeout(function(){location.reload()},5e3)}),$(function(){(function e(){var t=document.documentElement,i=5===new Date().getMonth(),a=[{value:"day",label:"Light",className:"skin-citizen-light"},{value:"os",label:"Auto",className:"skin-citizen-auto"},{value:"night",label:"Dark",className:"skin-citizen-dark"},{value:"sepia",label:"Sepia",className:"skin-citizen-sepia",labelId:"sepia-style-label"}];function n(e){for(var i=0;i<a.length;i++)t.classList.remove(a[i].className);for(var n=0;n<a.length;n++)if(a[n].value===e){t.classList.add(a[n].className);break}localStorage.setItem("skin-theme-clientpref",e)}i&&a.push({value:"trans",label:"Trans",className:"skin-citizen-trans",labelId:"trans-style-label"});var o=localStorage.getItem("skin-theme-clientpref")||"day";"trans"!==o||i||(o="day"),n(o),$(document).on("change",'input[name="skin-client-pref-skin-theme-group"]',function(){n(this.value)}),function e(){var t=document.getElementById("skin-client-prefs-skin-theme");if(!t)return setTimeout(e,100);var i=t.querySelector("form"),n=i.querySelector(".citizen-client-prefs-radio");if(n)for(var l=0;l<a.length;l++){var r=a[l],s="skin-client-pref-skin-theme-value-"+r.value;if(!document.getElementById(s)){var c=n.cloneNode(!0),d=c.querySelector("input"),f=c.querySelector("label");d.id=s,d.value=r.value,d.name="skin-client-pref-skin-theme-group",d.checked=o===r.value,f.setAttribute("for",s),f.textContent=r.label,r.labelId&&(f.id=r.labelId),i.appendChild(c)}}}()})(),function e(){var t=document.documentElement,i="skin-font-clientpref",a=[{value:"sans",label:"Sans",className:"font-sans"},{value:"serif",label:"Serif",className:"font-serif"},{value:"dyslexic",label:"Accessibility",className:"font-dyslexic"}],n=localStorage.getItem(i)||"sans";function o(e){for(var n=0;n<a.length;n++)t.classList.remove(a[n].className);if("sans"!==e){for(var o=0;o<a.length;o++)if(a[o].value===e){t.classList.add(a[o].className);break}}localStorage.setItem(i,e)}o(n),$(document).on("change",'input[name="skin-client-pref-font-group"]',function(){o(this.value)}),function e(){if(!document.getElementById("skin-client-prefs-font")){var t=document.getElementById("citizen-client-prefs");if(!t)return setTimeout(e,100);var i=document.createElement("div");i.className="mw-portlet mw-portlet-js citizen-menu",i.id="skin-client-prefs-font",i.innerHTML='<div class="citizen-menu__heading">Typeface</div><div class="citizen-menu__content"><ul class="citizen-menu__content-list"><li class="mw-list-item mw-list-item-js"><form></form></li></ul></div>';var o=document.getElementById("skin-client-prefs-citizen-feature-custom-font-size");o?o.nextSibling?o.parentNode.insertBefore(i,o.nextSibling):o.parentNode.appendChild(i):t.appendChild(i);var l=document.querySelector(".citizen-client-prefs-radio"),r=i.querySelector("form");if(l&&r)for(var s=0;s<a.length;s++){var c=a[s],d="skin-client-pref-font-value-"+c.value,f=l.cloneNode(!0),p=f.querySelector("input"),u=f.querySelector("label");p.id=d,p.value=c.value,p.name="skin-client-pref-font-group",p.checked=n===c.value,u.setAttribute("for",d),u.textContent=c.label,u.className=u.className+" "+c.className,u.id=c.value+"-font-label",r.appendChild(f)}}}()}()}),"ontouchstart"in window||navigator.maxTouchPoints>0||$(function(){var e,t,i,a,n,o=document.documentElement,l=!1;"ontouchstart"in window||$(document).on("keydown",function(e){(48===e.keyCode||96===e.keyCode)&&!$(e.target).is("input, textarea, [contenteditable]")&&(l=!l,o.classList.toggle("reading-mode",l),l&&window._paq&&_paq.push(["trackGoal",12]))}),e=$('<div id="hover-line"></div>').css({position:"fixed",left:0,width:"100%",height:"1.5em",pointerEvents:"none",zIndex:1,transition:"top 0.1s ease, background-color 0.3s ease",display:"none",backgroundColor:"var(--color-hoverline, rgba(255,255,150,0.2))"}).appendTo("body"),$(document).on("mousemove",function(t){if(!l){e.hide();return}var i,a=document.elementFromPoint(t.clientX,t.clientY);if(!a||!$(a).closest("p, li")[0]){e.hide();return}if(document.caretRangeFromPoint)i=document.caretRangeFromPoint(t.clientX,t.clientY);else if(document.caretPositionFromPoint){var n=document.caretPositionFromPoint(t.clientX,t.clientY);n&&((i=document.createRange()).setStart(n.offsetNode,n.offset),i.collapse(!0))}if(!i){e.hide();return}var o=i.getBoundingClientRect();if(!o||0===o.height){e.hide();return}e.css({top:o.top+"px",height:o.height+"px",display:"block"})}),t=$('<div id="reading-progress-wrapper"></div>').css({position:"fixed",bottom:0,left:0,width:"100%",height:"12px",zIndex:9999,pointerEvents:"auto"}).appendTo("body"),i=$('<div id="reading-progress-bar"></div>').css({position:"absolute",bottom:0,left:0,height:"4px",backgroundColor:"var(--color-progress-bar)",width:"0%",transition:"width 0.1s ease-out",pointerEvents:"none"}).appendTo(t),a=$('<div id="reading-progress-tooltip"></div>').css({position:"fixed",padding:"2px 6px",backgroundColor:"#333",color:"#fff",fontSize:"1em",borderRadius:"3px",pointerEvents:"none",zIndex:1e4,display:"none"}).appendTo("body"),n=0,$(window).on("scroll",function(){if(!l){t.hide();return}t.show();var e=$(window).scrollTop(),a=$(document).height(),o=$(window).height(),r=Math.min(100,e/(a-o)*100);Math.abs(r-n)>.5&&(i.width(r+"%"),n=r)}),t.hover(function(){l&&a.show()},function(){a.hide()}),t.on("mousemove",function(e){if(l){var t=$(window).scrollTop(),i=$(document).height(),n=$(window).height();a.text(Math.round(Math.min(100,t/(i-n)*100))+"%").css({left:e.clientX+8+"px",bottom:"16px"})}})}),mw.loader.using(["ext.visualEditor.desktopArticleTarget.init"]).then(function(){mw.hook("ve.activationComplete").add(function(){var e=setInterval(function(){var t=$(".ve-init-mw-welcomeDialog-content");if(t.length&&(clearInterval(e),!t.data("custom-appended"))){t.append('<br><br>Please read our <strong><a href="/wiki/Principles">Principles</a></strong> and <strong><a href="/wiki/Encyclopedic_tone_guide">Encyclopedic tone guide</a><strong> first to make sure your edit is approved!'),t.data("custom-appended",!0);var i=OO.ui.WindowManager.static.currentWindow;i&&"function"==typeof i.updateSize&&i.updateSize()}},200)})}),$(function(){var e=$("#wpBio");if(e.length){var t="form-bio-autosave",i=$('<div id="autosave-status" style="font-size:0.8em;color:gray;height:1.2em;margin-top:5px;"></div>'),a="";e.after(i);var n=localStorage.getItem(t);n&&(e.val(n),a=n,o("Restored previous work")),e.on("input",function(){var i=e.val();i!==a&&(o("Saving..."),setTimeout(function(){localStorage.setItem(t,i),a=i,o("Saved locally")},2e3))}),e.closest("form").on("submit",function(){localStorage.removeItem(t)})}function o(e){i.text(e).stop().fadeIn().delay(3e3).fadeOut()}}),$(function(){var e=$("#joinUs"),t=$("#homepage-testimonial");if(e.length&&t.length){var i=['<span>"The ProleWiki community is very welcoming and diverse..."</span><br><a href="https://en.prolewiki.org/wiki/Comrade:ComradeTrash">ComradeTrash</a>','<span>"Working with ProleWiki has given me space to learn..."</span><br><a href="https://en.prolewiki.org/wiki/Comrade:CriticalResist">CriticalResist</a>','<span>"ProleWiki is a lively environment for socialist education..."<br><a href="https://en.prolewiki.org/wiki/Comrade:Charhapiti">Charhapiti</a>','<span>"As a trans woman, I have never felt more accepted..."</span><br><a href="https://en.prolewiki.org/wiki/Comrade:Local_Gay_Communist_-_LGC">Local Gay Communist</a>'];e.height()>=375&&t.html(i[Math.floor(Math.random()*i.length)]).show()}});
 
//Matomo accurate tracking (no more 0 second visits)
//_paq.push(['enableHeartBeatTimer']);
 
/**
* 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 );
 
/** ==================== Citizen Skin Enhancements (sidebar icons, heading hyperlinks, collection refresh) ==================== **/
$(function() {
    // Add sidebar icons in correct order
    var $header = $('.citizen-drawer');
    if ($header.length) {
        var icons = [
            {cls: 'sidebar-library', href: '/wiki/ProleWiki:Library', title: 'Library'},
            {cls: 'sidebar-essays', href: '/wiki/ProleWiki:Essays', title: 'Essays'}
        ];
       
        if (!mw.user.isAnon()) {
            icons.push({cls: 'sidebar-upload', href: '/wiki/Special:Upload', title: 'Upload file'});
        }
       
        // Create elements in reverse order to ensure correct positioning
        for (var i = icons.length - 1; i >= 0; i--) {
            var icon = icons[i];
            $header.after(
                '<a class="citizen-header__item ' + icon.cls +
                '" href="' + icon.href + '" title="' + icon.title + '">' +
                '<div class="citizen-header__button"></div></a>'
            );
        }
    }
 
    // Heading hyperlinks
    function setupHeadingLinks() {
        var $headings = $('h2, h3, h4, h5').find('.mw-headline');
        if (!$headings.length) return;
 
        function smoothScroll(targetId) {
            var target = document.getElementById(targetId);
            if (target) {
                window.scrollTo({
                    top: target.offsetTop,
                    behavior: 'smooth'
                });
            }
        }
 
        // Create hyperlink buttons with proper event handling
        $headings.each(function() {
            var $headline = $(this),
                id = $headline.attr('id');
           
            if (!id) return;
           
            var $link = $(
                '<a href="#' + id + '" 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"></a>'
            );
           
            // Add specific click handler to prevent section collapse
            $link.on('click', function(e) {
                e.preventDefault();
                e.stopPropagation(); // Prevent event from bubbling to section toggle
                smoothScroll(id);
                history.replaceState(null, null, '#' + id);
            });
           
            $headline.append($link);
        });
 
        // Handle other anchor clicks (not the hyperlink buttons)
        $(document).on('click', 'a[href^="#"]:not(.heading-hyperlink)', function(e) {
            var href = this.href;
            var id = href.substring(href.indexOf('#') + 1);
            if (!id) return;
           
            e.preventDefault();
            smoothScroll(id);
            history.replaceState(null, null, '#' + id);
        });
    }
    setupHeadingLinks();
 
    // Collection rendering check
    if ($("#renderingProgress").length) {
        setTimeout(function() {
            location.reload();
        }, 5000);
    }
});
 
/** ==================== Combined Preferences Setup (custom typefaces, themes) ==================== **/
$(function() {
    // Shared setup for both theme and font pickers
    function initPreferences() {
        setupThemePicker();
        setupFontPicker();
    }
   
    /** ===== Theme Picker ===== **/
    function setupThemePicker() {
        var html = document.documentElement;
        var currentMonth = new Date().getMonth();
        var isJune = currentMonth === 5;
        var themes = [
            {value: 'day', label: 'Light', className: 'skin-citizen-light'},
            {value: 'os', label: 'Auto', className: 'skin-citizen-auto'},
            {value: 'night', label: 'Dark', className: 'skin-citizen-dark'},
            {value: 'sepia', label: 'Sepia', className: 'skin-citizen-sepia', labelId: 'sepia-style-label'}
        ];
 
        if (isJune) {
            themes.push({
                value: 'trans',  
                label: 'Trans',  
                className: 'skin-citizen-trans',
                labelId: 'trans-style-label'
            });
        }
 
        function applyTheme(themeValue) {
            // Batch class operations by looping and removing each class
            for (var i = 0; i < themes.length; i++) {
                html.classList.remove(themes[i].className);
            }
           
            for (var j = 0; j < themes.length; j++) {
                if (themes[j].value === themeValue) {
                    html.classList.add(themes[j].className);
                    break;
                }
            }
            localStorage.setItem('skin-theme-clientpref', themeValue);
        }
 
        var storedTheme = localStorage.getItem('skin-theme-clientpref') || 'day';
        if (storedTheme === 'trans' && !isJune) storedTheme = 'day';
        applyTheme(storedTheme);
 
        function addThemeOptions() {
            var themeContainer = document.getElementById('skin-client-prefs-skin-theme');
            if (!themeContainer) {
                return setTimeout(addThemeOptions, 100);
            }
           
            var form = themeContainer.querySelector('form');
            var template = form.querySelector('.citizen-client-prefs-radio');
            if (!template) return;
           
            for (var i = 0; i < themes.length; i++) {
                var theme = themes[i];
                var radioId = 'skin-client-pref-skin-theme-value-' + theme.value;
                if (document.getElementById(radioId)) continue;
               
                var radioElement = template.cloneNode(true);
                var input = radioElement.querySelector('input');
                var label = radioElement.querySelector('label');
               
                input.id = radioId;
                input.value = theme.value;
                input.name = 'skin-client-pref-skin-theme-group';
                input.checked = (storedTheme === theme.value);
               
                label.setAttribute('for', radioId);
                label.textContent = theme.label;
               
                if (theme.labelId) {
                    label.id = theme.labelId;
                }
               
                form.appendChild(radioElement);
            }
        }
 
        $(document).on('change', 'input[name="skin-client-pref-skin-theme-group"]', function() {
            applyTheme(this.value);
        });
       
        addThemeOptions();
    }
 
    /** ===== Typeface Picker ===== **/
function setupFontPicker() {
    var html = document.documentElement;
    var FONT_STORAGE_KEY = 'skin-font-clientpref';
    var TEXT_SIZE_ID = 'skin-client-prefs-citizen-feature-custom-font-size';
   
    var fonts = [
        {value: 'sans', label: 'Sans', className: 'font-sans'},
        {value: 'serif', label: 'Serif', className: 'font-serif'},
        {value: 'dyslexic', label: 'Accessibility', className: 'font-dyslexic'}
    ];
 
    var activeFont = localStorage.getItem(FONT_STORAGE_KEY) || 'sans';
 
    function applyFont(fontValue) {
        for (var i = 0; i < fonts.length; i++) {
            html.classList.remove(fonts[i].className);
        }
       
        if (fontValue !== 'sans') {
            for (var j = 0; j < fonts.length; j++) {
                if (fonts[j].value === fontValue) {
                    html.classList.add(fonts[j].className);
                    break;
                }
            }
        }
        localStorage.setItem(FONT_STORAGE_KEY, fontValue);
    }
 
    applyFont(activeFont);
 
    function addFontOptions() {
        var fontSection = document.getElementById('skin-client-prefs-font');
        if (fontSection) return;
       
        var prefsPanel = document.getElementById('citizen-client-prefs');
        if (!prefsPanel) {
            return setTimeout(addFontOptions, 100);
        }
       
        // Create new section using string HTML (ES5 safe)
        var section = document.createElement('div');
        section.className = 'mw-portlet mw-portlet-js citizen-menu';
        section.id = 'skin-client-prefs-font';
 
        section.innerHTML =  
            '<div class="citizen-menu__heading">Typeface</div>' +
            '<div class="citizen-menu__content">' +
                '<ul class="citizen-menu__content-list">' +
                    '<li class="mw-list-item mw-list-item-js">' +
                        '<form></form>' +
                    '</li>' +
                '</ul>' +
            '</div>';
       
        var textSizeSection = document.getElementById(TEXT_SIZE_ID);
        if (textSizeSection) {
            if (textSizeSection.nextSibling) {
                textSizeSection.parentNode.insertBefore(section, textSizeSection.nextSibling);
            } else {
                textSizeSection.parentNode.appendChild(section);
            }
        } else {
            prefsPanel.appendChild(section);
        }
       
        var template = document.querySelector('.citizen-client-prefs-radio');
        var form = section.querySelector('form');
        if (!template || !form) return;
       
        for (var i = 0; i < fonts.length; i++) {
            var font = fonts[i];
            var radioId = 'skin-client-pref-font-value-' + font.value;
           
            var radioElement = template.cloneNode(true);
            var input = radioElement.querySelector('input');
            var label = radioElement.querySelector('label');
           
            input.id = radioId;
            input.value = font.value;
            input.name = 'skin-client-pref-font-group';
            input.checked = (activeFont === font.value);
           
            label.setAttribute('for', radioId);
            label.textContent = font.label;
           
            // Add custom font class to the label
            label.className = label.className + ' ' + font.className;
           
            // Add ID for styling if needed
            label.id = font.value + '-font-label';
           
            form.appendChild(radioElement);
        }
    }
 
    $(document).on('change', 'input[name="skin-client-pref-font-group"]', function() {
        applyFont(this.value);
    });
   
    addFontOptions();
}
   
    initPreferences();
});
 
/** ==================== Reading mode and features ==================== **/
/** (trigger, hoverline, progress bar) */
// Skip loading reading mode if not on desktop device:
if (!('ontouchstart' in window || navigator.maxTouchPoints > 0)) {
$(function() {
    var html = document.documentElement,
        readingModeClass = 'reading-mode',
        isReadingMode = false;
   
    // Toggle reading mode
    function toggleReadingMode() {
        isReadingMode = !isReadingMode;
        html.classList.toggle(readingModeClass, isReadingMode);
       
        if (isReadingMode && window._paq) {
            _paq.push(['trackGoal', 12]);
        }
    }
   
    // Keyboard shortcut (desktop only)
    if (!('ontouchstart' in window)) {
        $(document).on('keydown', function(e) {
            if ((e.keyCode === 48 || e.keyCode === 96) && // 0 key
                !$(e.target).is('input, textarea, [contenteditable]')) {
                toggleReadingMode();
            }
        });
    }
   
    // Hover line feature
    function setupHoverLine() {
        var $line = $('<div id="hover-line"></div>').css({
            position: 'fixed',
            left: 0,
            width: '100%',
            height: '1.5em',
            pointerEvents: 'none',
            zIndex: 1,
            transition: 'top 0.1s ease, background-color 0.3s ease',
            display: 'none',
            backgroundColor: 'var(--color-hoverline, rgba(255,255,150,0.2))'
        }).appendTo('body');
       
        $(document).on('mousemove', function(e) {
            if (!isReadingMode) {
                $line.hide();
                return;
            }
           
            var el = document.elementFromPoint(e.clientX, e.clientY);
            if (!el) {
                $line.hide();
                return;
            }
           
            var paragraph = $(el).closest('p, li')[0];
            if (!paragraph) {
                $line.hide();
                return;
            }
           
            var range;
            if (document.caretRangeFromPoint) {
                range = document.caretRangeFromPoint(e.clientX, e.clientY);
            } else if (document.caretPositionFromPoint) {
                var pos = document.caretPositionFromPoint(e.clientX, e.clientY);
                if (pos) {
                    range = document.createRange();
                    range.setStart(pos.offsetNode, pos.offset);
                    range.collapse(true);
                }
            }
           
            if (!range) {
                $line.hide();
                return;
            }
           
            var rect = range.getBoundingClientRect();
            if (!rect || rect.height === 0) {
                $line.hide();
                return;
            }
           
            $line.css({
                top: rect.top + 'px',
                height: rect.height + 'px',
                display: 'block'
            });
        });
    }
    setupHoverLine();
   
    // Progress bar feature with hover tooltip
    function setupProgressBar() {
        // Create wrapper container
        var $wrapper = $('<div id="reading-progress-wrapper"></div>').css({
            position: 'fixed',
            bottom: 0,
            left: 0,
            width: '100%',
            height: '12px',
            zIndex: 9999,
            pointerEvents: 'auto'
        }).appendTo('body');
       
        // Create progress bar
        var $bar = $('<div id="reading-progress-bar"></div>').css({
            position: 'absolute',
            bottom: 0,
            left: 0,
            height: '4px',
            backgroundColor: 'var(--color-progress-bar)',
            width: '0%',
            transition: 'width 0.1s ease-out',
            pointerEvents: 'none'
        }).appendTo($wrapper);
       
        // Create tooltip
        var $tooltip = $('<div id="reading-progress-tooltip"></div>').css({
            position: 'fixed',
            padding: '2px 6px',
            backgroundColor: '#333',
            color: '#fff',
            fontSize: '1em',
            borderRadius: '3px',
            pointerEvents: 'none',
            zIndex: 10000,
            display: 'none'
        }).appendTo('body');
       
        var lastPercent = 0;
       
        // Update progress on scroll
        $(window).on('scroll', function() {
            if (!isReadingMode) {
                $wrapper.hide();
                return;
            }
           
            $wrapper.show();
            var scrollTop = $(window).scrollTop(),
                docHeight = $(document).height(),
                winHeight = $(window).height(),
                percent = Math.min(100, scrollTop / (docHeight - winHeight) * 100);
           
            if (Math.abs(percent - lastPercent) > 0.5) {
                $bar.width(percent + '%');
                lastPercent = percent;
            }
        });
       
        // Show/hide tooltip on hover
        $wrapper.hover(
            function() {
                if (!isReadingMode) return;
                $tooltip.show();
            },
            function() {
                $tooltip.hide();
            }
        );
       
        // Update tooltip position and text
        $wrapper.on('mousemove', function(e) {
            if (!isReadingMode) return;
           
            var scrollTop = $(window).scrollTop(),
                docHeight = $(document).height(),
                winHeight = $(window).height(),
                percent = Math.min(100, scrollTop / (docHeight - winHeight) * 100);
           
            $tooltip.text(Math.round(percent) + '%')
                  .css({
                      left: (e.clientX + 8) + 'px',
                      bottom: '16px'
                  });
        });
    }
    setupProgressBar();
});
} //end reading mode IF statement
 
/** ==================== Visual Editor Welcome Message ==================== **/
mw.loader.using(['ext.visualEditor.desktopArticleTarget.init']).then(function () {
    mw.hook('ve.activationComplete').add(function () {
        var checkDialog = setInterval(function () {
            var $dialogContent = $('.ve-init-mw-welcomeDialog-content');
            if ($dialogContent.length) {
                clearInterval(checkDialog);
 
                // Only append once
                if (!$dialogContent.data('custom-appended')) {
                    $dialogContent.append(
                        '<br><br>Please read our <strong><a href="/wiki/Principles">Principles</a></strong> and <strong><a href="/wiki/Encyclopedic_tone_guide">Encyclopedic tone guide</a><strong> first to make sure your edit is approved!'
                    );
                    $dialogContent.data('custom-appended', true);
 
                    // Resize the OOUI dialog to fit new content
                    var dialog = OO.ui.WindowManager.static.currentWindow;
                    if (dialog && typeof dialog.updateSize === 'function') {
                        dialog.updateSize();
                    }
                }
            }
        }, 200);
    });
});
 
/** ==================== Accreq Form Autosave ==================== **/
$(function() {
    var $textarea = $('#wpBio');
    if (!$textarea.length) return;
   
    var STORAGE_KEY = 'form-bio-autosave',
        $status = $('<div id="autosave-status" style="font-size:0.8em;color:gray;height:1.2em;margin-top:5px;"></div>'),
        lastValue = '';
   
    $textarea.after($status);
   
    // Restore saved content
    var saved = localStorage.getItem(STORAGE_KEY);
    if (saved) {
        $textarea.val(saved);
        lastValue = saved;
        showStatus('Restored previous work');
    }
   
    // Setup autosave
    $textarea.on('input', function() {
        var current = $textarea.val();
        if (current === lastValue) return;
       
        showStatus('Saving...');
        setTimeout(function() {
            localStorage.setItem(STORAGE_KEY, current);
            lastValue = current;
            showStatus('Saved locally');
        }, 2000);
    });
   
    // Clear on form submit
    $textarea.closest('form').on('submit', function() {
        localStorage.removeItem(STORAGE_KEY);
    });
   
    function showStatus(msg) {
        $status.text(msg).stop().fadeIn().delay(3000).fadeOut();
    }
});
 
/** ==================== Join us homepage testimonials ==================== **/
$(function() {
    var $joinUs = $('#joinUs'),
        $testimonial = $('#homepage-testimonial');
   
    if (!$joinUs.length || !$testimonial.length) return;
   
    var testimonials = [
        '<span>"The ProleWiki community is very welcoming and diverse..."</span><br><a href="https://en.prolewiki.org/wiki/Comrade:ComradeTrash">ComradeTrash</a>',
        '<span>"Working with ProleWiki has given me space to learn..."</span><br><a href="https://en.prolewiki.org/wiki/Comrade:CriticalResist">CriticalResist</a>',
        '<span>"ProleWiki is a lively environment for socialist education..."<br><a href="https://en.prolewiki.org/wiki/Comrade:Charhapiti">Charhapiti</a>',
        '<span>"As a trans woman, I have never felt more accepted..."</span><br><a href="https://en.prolewiki.org/wiki/Comrade:Local_Gay_Communist_-_LGC">Local Gay Communist</a>'
    ];
   
    if ($joinUs.height() >= 375) {
        $testimonial.html(
            testimonials[Math.floor(Math.random() * testimonials.length)]
        ).show();
    }
});

Revision as of 12:17, 1 August 2025

function ModifySidebar(e,t,i,a){try{switch(t){case"languages":var n="p-lang";break;case"toolbox":var n="p-tb";break;case"navigation":var n="p-navigation";break;default:var n="p-"+t}if("add"==e){var o=document.getElementById(n).getElementsByTagName("div")[0].getElementsByTagName("ul")[0],l=document.createElement("a"),r=document.createElement("li");l.appendChild(document.createTextNode(i)),l.setAttribute("href",a),r.appendChild(l),r.className="plainlinks",o.appendChild(r)}if("remove"==e)for(var s=document.getElementById(n).getElementsByTagName("div")[0].getElementsByTagName("ul")[0],c=s.getElementsByTagName("li"),d=0;d<c.length;d++)(c[d].getElementsByTagName("a")[0].innerHTML==i||c[d].getElementsByTagName("a")[0].href==a)&&s.removeChild(c[d])}catch(f){return}}function CustomizeModificationsOfSidebar(){ModifySidebar("add","toolbox","List of uploaded files","https://en.prolewiki.org/wiki/Special:ListFiles")}!function(){var e="[hide]",t="[show]";function i(i,a){var n,o=document.getElementById("NavToggle"+i),l=document.getElementById("NavFrame"+i);if(a.preventDefault(),!l||!o)return!1;if(o.firstChild.data===e){for(n=l.firstChild;null!==n;n=n.nextSibling)($(n).hasClass("NavContent")||$(n).hasClass("NavPic"))&&(n.style.display="none");o.firstChild.data=t}else if(o.firstChild.data===t){for(n=l.firstChild;null!==n;n=n.nextSibling)($(n).hasClass("NavContent")||$(n).hasClass("NavPic"))&&(n.style.display="block");o.firstChild.data=e}}mw.hook("wikipage.content").add(function a(n){var o,l,r,s,c,d=0;n.find("div.NavFrame").each(function(a,n){for(d++,(r=document.createElement("a")).className="NavToggle",r.setAttribute("id","NavToggle"+d),r.setAttribute("href","#"),$(r).on("click",$.proxy(i,null,d)),c=$(n).hasClass("collapsed"),l=n.firstChild;null!==l&&!c;l=l.nextSibling)($(l).hasClass("NavPic")||$(l).hasClass("NavContent"))&&"none"===l.style.display&&(c=!0);if(c)for(l=n.firstChild;null!==l;l=l.nextSibling)($(l).hasClass("NavPic")||$(l).hasClass("NavContent"))&&(l.style.display="none");for(s=document.createTextNode(c?t:e),r.appendChild(s),o=0;o<n.childNodes.length;o++)$(n.childNodes[o]).hasClass("NavHead")&&(r.style.color=n.childNodes[o].style.color,n.childNodes[o].appendChild(r));n.setAttribute("id","NavFrame"+d)})})}(),jQuery(CustomizeModificationsOfSidebar),$(function(){var e=$(".citizen-drawer");if(e.length){var t=[{cls:"sidebar-library",href:"/wiki/ProleWiki:Library",title:"Library"},{cls:"sidebar-essays",href:"/wiki/ProleWiki:Essays",title:"Essays"}];mw.user.isAnon()||t.push({cls:"sidebar-upload",href:"/wiki/Special:Upload",title:"Upload file"});for(var i=t.length-1;i>=0;i--){var a=t[i];e.after('<a class="citizen-header__item '+a.cls+'" href="'+a.href+'" title="'+a.title+'"><div class="citizen-header__button"></div></a>')}}(function e(){var t=$("h2, h3, h4, h5").find(".mw-headline");function i(e){var t=document.getElementById(e);t&&window.scrollTo({top:t.offsetTop,behavior:"smooth"})}t.length&&(t.each(function(){var e=$(this),t=e.attr("id");if(t){var a=$('<a href="#'+t+'" 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"></a>');a.on("click",function(e){e.preventDefault(),e.stopPropagation(),i(t),history.replaceState(null,null,"#"+t)}),e.append(a)}}),$(document).on("click",'a[href^="#"]:not(.heading-hyperlink)',function(e){var t=this.href,a=t.substring(t.indexOf("#")+1);a&&(e.preventDefault(),i(a),history.replaceState(null,null,"#"+a))}))})(),$("#renderingProgress").length&&setTimeout(function(){location.reload()},5e3)}),$(function(){(function e(){var t=document.documentElement,i=5===new Date().getMonth(),a=[{value:"day",label:"Light",className:"skin-citizen-light"},{value:"os",label:"Auto",className:"skin-citizen-auto"},{value:"night",label:"Dark",className:"skin-citizen-dark"},{value:"sepia",label:"Sepia",className:"skin-citizen-sepia",labelId:"sepia-style-label"}];function n(e){for(var i=0;i<a.length;i++)t.classList.remove(a[i].className);for(var n=0;n<a.length;n++)if(a[n].value===e){t.classList.add(a[n].className);break}localStorage.setItem("skin-theme-clientpref",e)}i&&a.push({value:"trans",label:"Trans",className:"skin-citizen-trans",labelId:"trans-style-label"});var o=localStorage.getItem("skin-theme-clientpref")||"day";"trans"!==o||i||(o="day"),n(o),$(document).on("change",'input[name="skin-client-pref-skin-theme-group"]',function(){n(this.value)}),function e(){var t=document.getElementById("skin-client-prefs-skin-theme");if(!t)return setTimeout(e,100);var i=t.querySelector("form"),n=i.querySelector(".citizen-client-prefs-radio");if(n)for(var l=0;l<a.length;l++){var r=a[l],s="skin-client-pref-skin-theme-value-"+r.value;if(!document.getElementById(s)){var c=n.cloneNode(!0),d=c.querySelector("input"),f=c.querySelector("label");d.id=s,d.value=r.value,d.name="skin-client-pref-skin-theme-group",d.checked=o===r.value,f.setAttribute("for",s),f.textContent=r.label,r.labelId&&(f.id=r.labelId),i.appendChild(c)}}}()})(),function e(){var t=document.documentElement,i="skin-font-clientpref",a=[{value:"sans",label:"Sans",className:"font-sans"},{value:"serif",label:"Serif",className:"font-serif"},{value:"dyslexic",label:"Accessibility",className:"font-dyslexic"}],n=localStorage.getItem(i)||"sans";function o(e){for(var n=0;n<a.length;n++)t.classList.remove(a[n].className);if("sans"!==e){for(var o=0;o<a.length;o++)if(a[o].value===e){t.classList.add(a[o].className);break}}localStorage.setItem(i,e)}o(n),$(document).on("change",'input[name="skin-client-pref-font-group"]',function(){o(this.value)}),function e(){if(!document.getElementById("skin-client-prefs-font")){var t=document.getElementById("citizen-client-prefs");if(!t)return setTimeout(e,100);var i=document.createElement("div");i.className="mw-portlet mw-portlet-js citizen-menu",i.id="skin-client-prefs-font",i.innerHTML='<div class="citizen-menu__heading">Typeface</div><div class="citizen-menu__content"><ul class="citizen-menu__content-list"><li class="mw-list-item mw-list-item-js"><form></form></li></ul></div>';var o=document.getElementById("skin-client-prefs-citizen-feature-custom-font-size");o?o.nextSibling?o.parentNode.insertBefore(i,o.nextSibling):o.parentNode.appendChild(i):t.appendChild(i);var l=document.querySelector(".citizen-client-prefs-radio"),r=i.querySelector("form");if(l&&r)for(var s=0;s<a.length;s++){var c=a[s],d="skin-client-pref-font-value-"+c.value,f=l.cloneNode(!0),p=f.querySelector("input"),u=f.querySelector("label");p.id=d,p.value=c.value,p.name="skin-client-pref-font-group",p.checked=n===c.value,u.setAttribute("for",d),u.textContent=c.label,u.className=u.className+" "+c.className,u.id=c.value+"-font-label",r.appendChild(f)}}}()}()}),"ontouchstart"in window||navigator.maxTouchPoints>0||$(function(){var e,t,i,a,n,o=document.documentElement,l=!1;"ontouchstart"in window||$(document).on("keydown",function(e){(48===e.keyCode||96===e.keyCode)&&!$(e.target).is("input, textarea, [contenteditable]")&&(l=!l,o.classList.toggle("reading-mode",l),l&&window._paq&&_paq.push(["trackGoal",12]))}),e=$('<div id="hover-line"></div>').css({position:"fixed",left:0,width:"100%",height:"1.5em",pointerEvents:"none",zIndex:1,transition:"top 0.1s ease, background-color 0.3s ease",display:"none",backgroundColor:"var(--color-hoverline, rgba(255,255,150,0.2))"}).appendTo("body"),$(document).on("mousemove",function(t){if(!l){e.hide();return}var i,a=document.elementFromPoint(t.clientX,t.clientY);if(!a||!$(a).closest("p, li")[0]){e.hide();return}if(document.caretRangeFromPoint)i=document.caretRangeFromPoint(t.clientX,t.clientY);else if(document.caretPositionFromPoint){var n=document.caretPositionFromPoint(t.clientX,t.clientY);n&&((i=document.createRange()).setStart(n.offsetNode,n.offset),i.collapse(!0))}if(!i){e.hide();return}var o=i.getBoundingClientRect();if(!o||0===o.height){e.hide();return}e.css({top:o.top+"px",height:o.height+"px",display:"block"})}),t=$('<div id="reading-progress-wrapper"></div>').css({position:"fixed",bottom:0,left:0,width:"100%",height:"12px",zIndex:9999,pointerEvents:"auto"}).appendTo("body"),i=$('<div id="reading-progress-bar"></div>').css({position:"absolute",bottom:0,left:0,height:"4px",backgroundColor:"var(--color-progress-bar)",width:"0%",transition:"width 0.1s ease-out",pointerEvents:"none"}).appendTo(t),a=$('<div id="reading-progress-tooltip"></div>').css({position:"fixed",padding:"2px 6px",backgroundColor:"#333",color:"#fff",fontSize:"1em",borderRadius:"3px",pointerEvents:"none",zIndex:1e4,display:"none"}).appendTo("body"),n=0,$(window).on("scroll",function(){if(!l){t.hide();return}t.show();var e=$(window).scrollTop(),a=$(document).height(),o=$(window).height(),r=Math.min(100,e/(a-o)*100);Math.abs(r-n)>.5&&(i.width(r+"%"),n=r)}),t.hover(function(){l&&a.show()},function(){a.hide()}),t.on("mousemove",function(e){if(l){var t=$(window).scrollTop(),i=$(document).height(),n=$(window).height();a.text(Math.round(Math.min(100,t/(i-n)*100))+"%").css({left:e.clientX+8+"px",bottom:"16px"})}})}),mw.loader.using(["ext.visualEditor.desktopArticleTarget.init"]).then(function(){mw.hook("ve.activationComplete").add(function(){var e=setInterval(function(){var t=$(".ve-init-mw-welcomeDialog-content");if(t.length&&(clearInterval(e),!t.data("custom-appended"))){t.append('<br><br>Please read our <strong><a href="/wiki/Principles">Principles</a></strong> and <strong><a href="/wiki/Encyclopedic_tone_guide">Encyclopedic tone guide</a><strong> first to make sure your edit is approved!'),t.data("custom-appended",!0);var i=OO.ui.WindowManager.static.currentWindow;i&&"function"==typeof i.updateSize&&i.updateSize()}},200)})}),$(function(){var e=$("#wpBio");if(e.length){var t="form-bio-autosave",i=$('<div id="autosave-status" style="font-size:0.8em;color:gray;height:1.2em;margin-top:5px;"></div>'),a="";e.after(i);var n=localStorage.getItem(t);n&&(e.val(n),a=n,o("Restored previous work")),e.on("input",function(){var i=e.val();i!==a&&(o("Saving..."),setTimeout(function(){localStorage.setItem(t,i),a=i,o("Saved locally")},2e3))}),e.closest("form").on("submit",function(){localStorage.removeItem(t)})}function o(e){i.text(e).stop().fadeIn().delay(3e3).fadeOut()}}),$(function(){var e=$("#joinUs"),t=$("#homepage-testimonial");if(e.length&&t.length){var i=['<span>"The ProleWiki community is very welcoming and diverse..."</span><br><a href="https://en.prolewiki.org/wiki/Comrade:ComradeTrash">ComradeTrash</a>','<span>"Working with ProleWiki has given me space to learn..."</span><br><a href="https://en.prolewiki.org/wiki/Comrade:CriticalResist">CriticalResist</a>','<span>"ProleWiki is a lively environment for socialist education..."<br><a href="https://en.prolewiki.org/wiki/Comrade:Charhapiti">Charhapiti</a>','<span>"As a trans woman, I have never felt more accepted..."</span><br><a href="https://en.prolewiki.org/wiki/Comrade:Local_Gay_Communist_-_LGC">Local Gay Communist</a>'];e.height()>=375&&t.html(i[Math.floor(Math.random()*i.length)]).show()}});