The official discord link if you wish to join the discord: https://discord.gg/j5RKwCvAFu

Support the wiki on our official Ko-Fi page or Patreon page!

MediaWiki:Common.js: Difference between revisions

From The Codex
Speedster
Speedster (talk | contribs) (Reverted edits by Speedster (talk) to last revision by GiverOfThePeace)
m
Line 317: Line 317:
// Custom Scripts
// Custom Scripts


// Recent Changes Script
if (!rcwidget) {
if (typeof rcwidget !== 'undefined') {
     var rcwidget = {};
    // Clean up existing instance
     rcwidget.onlyshowores = (typeof onlyshowores !== 'undefined') ? onlyshowores : false;
    if (rcwidget.cleanup) {
    rcwidget.orestolerance = (typeof orestolerance !== 'undefined') ? orestolerance : 0.70;
        rcwidget.cleanup();
    rcwidget.fetchtime = (typeof rcfetchtime !== 'undefined') ? rcfetchtime : 0.5
     }
 
}
     rcwidget.addToSidebar = function(text) {
         if (mw.config.get("skin") == "timeless") {
var rcwidget = (function() {
             $('<div class="sidebar-chunk" id="rcwidget"><div class="sidebar-inner">' + text + '</div></div>').appendTo("#mw-related-navigation");
    // Private variables
             $("#catlinks-sidebar").appendTo("#mw-related-navigation");
    let fetchInterval = null;
             $("#other-languages").appendTo("#mw-related-navigation");
     let updateInterval = null;
    // Configuration
    const config = {
        onlyshowores: (typeof onlyshowores !== 'undefined') ? onlyshowores : false,
        orestolerance: (typeof orestolerance !== 'undefined') ? orestolerance : 0.70,
        fetchtime: (typeof rcfetchtime !== 'undefined') ? rcfetchtime : 0.5
    };
    // Utility functions
     function generateTimeAgo(hours, minutes, seconds) {
        if (hours > 0) {
            return `${hours}${hours === 1 ? ' hour' : ' hours'} ago`;
        } else if (minutes > 0) {
            return `${minutes}${minutes === 1 ? ' minute' : ' minutes'} ago`;
         } else if (seconds > 0) {
            return `${seconds}${seconds === 1 ? ' second' : ' seconds'} ago`;
        }
        return 'just now';
    }
    function createChangeHTML(change) {
        try {
            const baseUrl = mw.config.get("wgScript");
            let html = '<li>';
            // Handle ORES scoring
            const shouldBold = change.type === "edit" &&
                            change.oresscores?.damaging?.true >= config.orestolerance;
            if (shouldBold) {
                html += '<b>';
            }
             // User link
            html += `<a href="${baseUrl}/User_talk:${encodeURIComponent(change.user)}">${change.user}</a> `;
            // Change type specific content
            if (change.type === "edit") {
                if (change.tags.includes("mw-undo")) {
                    html += `<a href="${baseUrl}/Project:Undo">undid</a> an `;
                } else if (change.tags.includes("mw-rollback")) {
                    html += `<a href="${baseUrl}/Project:Rollback">rolled back</a> `;
                }
                html += `<a href="${baseUrl}/Special:Diff/${change.revid}">edit</a> to `;
            }
            // Page link
            if (change.ns === 3) {
                html += `left a message for <a href="${baseUrl}/${encodeURIComponent(change.title)}">${change.title.replace("User talk:", "")}</a>`;
             } else if (change.type === "new") {
                html += `created the page <a href="${baseUrl}/${encodeURIComponent(change.title)}">${change.title}</a>`;
             } else {
                html += `<a href="${baseUrl}/${encodeURIComponent(change.title)}">${change.title}</a>`;
            }
            if (shouldBold) {
                html += '</b>';
            }
            // Timestamp
            const changeDate = new Date(change.timestamp);
            const currDate = new Date();
            const mildate = new Date(currDate - changeDate);
            html += `<br><small class="rcwidget-date" data-revtimestamp="${change.timestamp}">` +
                  generateTimeAgo(mildate.getUTCHours(), mildate.getUTCMinutes(), mildate.getUTCSeconds()) +
                  '</small></li>';
            return html;
        } catch (error) {
            console.error('Error generating change HTML:', error);
            return '';
         }
         }
    }
        $('<div class="portal" role="navigation" id="rcwidget" aria-labelledby="p-rcwidget-label">' + text + '</div>').prependTo("#mw-panel");
        $('<div role="navigation" class="portlet generated-sidebar" id="rcwidget" aria-labelledby="p-rcwidget-label">' + text + '</div>').prependTo("#sidebar");
    // Main widget functions
        $('<div class="portlet" id="rcwidget">' + text + '</div>').prependTo("#mw_portlets");
    function addToSidebar(text) {
        $("#p-navigation").prependTo("#mw-panel");
        try {
        $("#p-search").prependTo("#quickbar");
            const skin = mw.config.get("skin");
        $('#p-logo').prependTo("#mw-site-navigation");
        $('#p-logo').prependTo("#mw-panel");
            // Clean up any existing widgets
        $('#p-logo').prependTo("#sidebar");  
            $('.rcwidget-instance').remove();
        $('#p-logo').prependTo("#mw_portlets");
        $('ul.hlist:first').appendTo('#mw-mf-page-left');
            const widget = $('<div>')
 
                .addClass('rcwidget-instance')
         if (mw.config.get("skin") == "vector" || mw.config.get("skin") == "vector-2022" ) {
                .html(text);
             $("#rcwidget").addClass("mw-portlet mw-portlet-navigation vector-menu vector-menu-portal");
            if (skin === "timeless") {
                widget.addClass("sidebar-chunk")
                    .appendTo("#mw-related-navigation");
                $("#catlinks-sidebar, #other-languages").appendTo("#mw-related-navigation");
            } else if (skin === "vector" || skin === "vector-2022") {
                widget.addClass("mw-portlet mw-portlet-navigation vector-menu vector-menu-portal")
                    .prependTo("#mw-panel");
            } else {
                widget.addClass("portlet")
                    .prependTo("#mw_portlets");
            }
            // Handle navigation elements
            $("#p-navigation").prependTo("#mw-panel");
            $("#p-search").prependTo("#quickbar");
            $('#p-logo').prependTo("#mw-site-navigation, #mw-panel, #sidebar, #mw_portlets");
            $('ul.hlist:first').appendTo('#mw-mf-page-left');
         } catch (error) {
             console.error('Error adding sidebar:', error);
         }
         }
     }
     };
 
     function fetch() {
     rcwidget.fetch = function() {
         if (!document.hasFocus()) {
         if (!document.hasFocus()) {
             return;
             window.setTimeout(rcwidget.fetch, rcwidget.fetchtime * 1000);
         }
         } else {
            var returnHTML = "";
        $.get(mw.config.get("wgScriptPath") + "/api.php", {
            returnHTML += "<ul>";
            action: "query",
           
            format: "json",
            $.get(mw.config.get("wgScriptPath") + "/api.php", {
            list: "recentchanges",
                "action": "query",
            rcnamespace: "0|3",
                "format": "json",  
            rcprop: "title|timestamp|flags|loginfo|oresscores|parsedcomment|user|ids|tags",
                "list": "recentchanges",
            rcshow: "!bot" + (config.onlyshowores ? "|oresreview" : ""),
                "rcnamespace": "0|3",
            rctoponly: true,
                "rcprop": "title|timestamp|flags|loginfo|oresscores|parsedcomment|user|ids|tags",
            rclimit: "50",
                "rcshow": "!bot" + (rcwidget.onlyshowores ? "|oresreview" : ""),
            rctype: "edit|new"
                "rctoponly": true,
        })
                "rclimit": "50",
        .done(function(result) {
                "rctype": "edit|new"
            try {
            }).done(function(result) {
                 if (result.error) {
                 if (result.error) {
                     throw new Error(result.error.info);
                     console.error(result.error.info);
                    window.setTimeout(rcwidget.fetch, rcwidget.fetchtime * 1000);
                } else {
                    var currDate = new Date();
                    for (var change of result.query.recentchanges) {
                        var changeDate = new Date(change.timestamp);
                        var mildate = new Date(currDate - changeDate);
                        var seconds = mildate.getUTCSeconds();
                        var minutes = mildate.getUTCMinutes();
                        var hours = mildate.getUTCHours();
 
                        if (typeof change.oresscores != 'undefined') {
                            if (typeof change.oresscores.damaging != 'undefined') {
                                if (typeof change.oresscores.damaging.true != 'undefined') {
                                    if (rcwidget.onlyshowores && change.oresscores.damaging.true < rcwidget.orestolerance) {
                                        continue;
                                    } else {
                                        returnHTML += "<li>";
                                        if (change.type == "edit" && change.oresscores.damaging) {
                                            if (change.oresscores.damaging.true >= rcwidget.orestolerance) {
                                                returnHTML += "<b>";
                                            }
                                        }
                                        returnHTML += '<a href="User_talk:' + change.user + '">' + change.user + '</a> ';
                                       
                                        switch (change.type) {
                                            case "edit":
                                                if (change.tags.includes("mw-undo")) {
                                                    returnHTML += "<a href=\"Project:Undo\">undid</a> an <a href=\"Special:Diff/" + change.revid + "\">edit</a> to <a href=\"" + change.title + "\">" + change.title + '</a>';
                                                } else if (change.tags.includes("mw-rollback")) {
                                                    returnHTML += "<a href=\"Project:Rollback\">rolled back</a> edits to <a href=\"Special:Diff/" + change.revid + "\">edit</a> to <a href=\"" + change.title + "\">" + change.title + '</a>';
                                                } else if (change.ns == 3) {
                                                    returnHTML += 'left a message for <a href="' + change.title + '">' + change.title.replace("User talk:", "") + "</a>";
                                                } else {
                                                    returnHTML += "made an <a href=\"Special:Diff/" + change.revid + "\">edit</a> to <a href=\"" + change.title + "\">" + change.title + '</a>';
                                                }
                                                break;
                                            case "new":
                                                if (change.ns == 3) {
                                                    returnHTML += 'left a message for <a href="' + change.title + '">' + change.title.replace("User talk:", "") + "</a>";
                                                } else {
                                                    returnHTML += "created the page <a href=\"" + change.title + "\">" + change.title + '</a>';
                                                }
                                                break;
                                        }
 
                                        if (change.type == "edit" && change.oresscores.damaging) {
                                            if (change.oresscores.damaging.true >= rcwidget.orestolerance) {
                                                returnHTML += "</b>";
                                            }
                                        }
 
                                        returnHTML += "<br><small class=\"rcwidget-date\" data-revtimestamp=\"" + change.timestamp + "\">";
                                        if (hours > 0) {
                                            returnHTML += " " + hours + ((hours == 1) ? " hour" : " hours") + " ago";
                                        } else if (minutes > 0) {
                                            returnHTML += " " + minutes + ((minutes == 1) ? " minute" : " minutes") + " ago";
                                        } else if (seconds > 0) {
                                            returnHTML += " " + seconds + ((seconds == 1) ? " second" : " seconds") + " ago";
                                        }
                                        returnHTML += "</small>";
                                        returnHTML += "</li>";
                                    }
                                }
                            }
                        }
                    }
                   
                    returnHTML += "<li><a href=\"Special:RecentChanges\">View all recent changes</a></li>"
                    returnHTML += "</ul>";
                   
                    $("#rcwidget-content").html(returnHTML);
                   
                    if ($("#rcwidget-content").text().toLowerCase() == "View all recent changes".toLowerCase()) {
                        $("#rcwidget-content").html("<ul><li>No recent changes found.</li></ul>");
                    }
                 }
                 }
                  
                 if (!result.query?.recentchanges) {
                 window.setTimeout(rcwidget.fetch, rcwidget.fetchtime * 1000);
                    throw new Error('Invalid API response structure');
             }).fail(function(result) {
                 }
                window.setTimeout(rcwidget.fetch, rcwidget.fetchtime * 1000);
             });
                const changes = result.query.recentchanges
                    .filter(change => {
                        if (!config.onlyshowores) return true;
                        return change.oresscores?.damaging?.true >= config.orestolerance;
                    })
                    .map(createChangeHTML)
                    .filter(html => html);
                let html = '<ul>' + changes.join('');
                // Add "View all" link
                html += `<li><a href="${mw.config.get("wgScript")}/Special:RecentChanges">View all recent changes</a></li></ul>`;
                const $content = $("#rcwidget-content");
                $content.html(changes.length ? html : "<ul><li>No recent changes found.</li></ul>");
            } catch (error) {
                console.error('Error processing recent changes:', error);
                $("#rcwidget-content").html("<ul><li>Error loading recent changes.</li></ul>");
             }
        })
        .fail(function(jqXHR, textStatus, errorThrown) {
            console.error('API request failed:', textStatus, errorThrown);
            $("#rcwidget-content").html("<ul><li>Error loading recent changes.</li></ul>");
        });
    }
    function updateTimestamps() {
        $('.rcwidget-date').each(function() {
            try {
                const $this = $(this);
                const changeDate = new Date($this.data('revtimestamp'));
                const currDate = new Date();
                const mildate = new Date(currDate - changeDate);
                $this.html(generateTimeAgo(
                    mildate.getUTCHours(),
                    mildate.getUTCMinutes(),
                    mildate.getUTCSeconds()
                ));
             } catch (error) {
                console.error('Error updating timestamp:', error);
            }
        });
    }
    function init() {
        if (!window.jQuery || !window.mw) {
            console.error('Required dependencies (jQuery or MediaWiki) not found');
            return;
         }
         }
        try {
            const baseUrl = mw.config.get("wgScript");
            const skin = mw.config.get('skin');
            const widgetContent = (skin === 'vector' || skin === 'vector-2022') ?
                `<div id="rcwidget-label" lang="en" dir="ltr">
                    <span><a href="${baseUrl}/Special:RecentChanges">Recent changes</a></span>
                </div>
                <div class="mw-portlet-body body pBody" id="rcwidget-content" style="height:250px;overflow:hidden;">
                    Loading...
                </div>` :
                `<h3 id="rcwidget-label" lang="en" dir="ltr">
                    <span><a href="${baseUrl}/Special:RecentChanges">Recent changes</a></span>
                </h3>
                <div class="mw-portlet-body body pBody" id="rcwidget-content" style="height:250px;overflow:hidden;">
                    Loading...
                </div>`;
            addToSidebar(widgetContent);
            // Set up intervals
            fetch();
            fetchInterval = window.setInterval(fetch, config.fetchtime * 1000);
            updateInterval = window.setInterval(updateTimestamps, config.fetchtime * 1000);
        } catch (error) {
            console.error('Error initializing widget:', error);
        }
    }
    function cleanup() {
        try {
            if (fetchInterval) {
                clearInterval(fetchInterval);
            }
            if (updateInterval) {
                clearInterval(updateInterval);
            }
            $('.rcwidget-instance').remove();
        } catch (error) {
            console.error('Error cleaning up widget:', error);
        }
    }
    // Public API
    return {
        init: init,
        cleanup: cleanup,
        fetch: fetch
     };
     };
})();
 
    $("#rcwidget-content").css("height", "auto");
// Initialize widget when ready
    $("#rcwidget-content").css("overflow", "auto");
$(document).ready(rcwidget.init);
 
    $(document).ready(function() {
        rcwidget.addToSidebar((mw.config.get('skin') == 'vector' || mw.config.get('skin') == 'vector-2022') ?
            '<div id="rcwidget-label" lang="en" dir="ltr"><span><a href="Special:RecentChanges">Recent changes</a></span></div><div class="mw-portlet-body body pBody" id="rcwidget-content" style="height:250px;overflow:hidden;">Loading...</div>' :
            '<h3 id="rcwidget-label" lang="en" dir="ltr"><span><a href="Special:RecentChanges">Recent changes</a></span></h3><div class="mw-portlet-body body pBody" id="rcwidget-content" style="height:250px;overflow:hidden;">Loading...</div>');
       
        rcwidget.fetch();
 
        window.setInterval(function() {
            var currDate = new Date();
            $('.rcwidget-date').each(function() {
                var changeDate = new Date($(this).data('revtimestamp'));
                var mildate = new Date(currDate - changeDate);
                var seconds = mildate.getUTCSeconds();
                var minutes = mildate.getUTCMinutes();
                var hours = mildate.getUTCHours();
 
                if (hours > 0) {
                    $(this).html(hours + ((hours == 1) ? " hour" : " hours") + " ago");
                } else if (minutes > 0) {
                    $(this).html(minutes + ((minutes == 1) ? " minute" : " minutes") + " ago");
                } else if (seconds > 0) {
                    $(this).html(seconds + ((seconds == 1) ? " second" : " seconds") + " ago");
                }
            })
        }, rcwidget.fetchtime);
    });
}

Revision as of 03:24, 28 October 2024

/* Any JavaScript here will be loaded for all users on every page load. */

window.AutoEditDropdownConfig = {
    expandedAreaContribute: true,
    expandedAreaEdit: false
};

window.ajaxRefresh = 60000;
window.ajaxPages = [
    'Special:RecentChanges',
    'Special:Contributions',
    'Special:Log',
    'Special:Log/move',
    'Special:AbuseLog',
    'Special:NewFiles',
    'Special:NewPages',
    'Special:Watchlist',
    'Special:Statistics',
    'Special:ListFiles',
];
window.AjaxRCRefreshText = 'Auto-refresh';
window.AjaxRCRefreshHoverText = 'Automatically refresh the page';

window.UserTagsJS = {
    modules: {},
    tags: {
        // group: { associated tag data },
        founder: {
            u: 'Founder',
            order: 1
        },
        bureaucrat: {
            u: 'Bureaucrat',
            order: 2
        },
        'former-bureaucrat': {
            u: 'Retired Bureaucrat',
            order: 3
        },
        sysop: {
            u: 'Administrator',
            order: 4
        },
        'former-sysop': {
            u: 'Retired Administrator',
            order: 5
        },
        'bot-global': {
            u: 'Global Bot',
            order: 7
        },
        bot: {
            u: 'Bot',
            order: 8
        },
        'content-moderator': {
            u: 'Content Moderator',
            order: 10
        },
        'former-content-moderator': {
            u: 'Retired Content Moderator',
            order: 11
        },
        threadmoderator: {
            u: 'Discussion Moderator',
            order: 13
        },
        'former-threadmoderator': {
            u: 'Retired Discussion Moderator',
            order: 14
        },
        chatmoderator: {
            u: 'Chat Moderator',
            order: 16
        },
        'former-chatmoderator': {
            u: 'Retired Chat Moderator',
            order: 17
        },
        rollback: {
            u: 'Rollback',
            order: 19
        },
        'former-rollback': {
            u: 'Former Rollback',
            order: 20
        },
        calc: {
            u: 'Calc Group',
            order: 22
        },
        'former-calc': {
            u: 'Retired Calc Group',
            order: 23
        },
        guru: {
            u: 'Guru',
            order: 40
        },
        'js-helper': {
            u: 'JS Helper',
            order: 51
        },
        'css-helper': {
            u: 'CSS Helper',
            order: 52
        },
        'image-helper': {
            u: 'Image Helper',
            order: 53
        },
        'template-helper': {
            u: 'Templates Helper',
            order: 54
        },
        'human-resources': {
            u: 'Human Resources',
            order: 55
        },
        'former-human-resources': {
            u: 'Retired Human Resources',
            order: 56
        },        
        consultant: {
            u: 'Consultant',
            order: 100
        },
        bannedfromchat: {
            u: 'Banned from Chat',
            order: 500
        },
        inactive: {
            u: 'Inactive',
            order: 1 / 0
        }
    }
};
UserTagsJS.modules.inactive = {
    days: 30,
    zeroIsInactive: true // 0 edits = inactive
};
UserTagsJS.modules.nonuser = (mediaWiki.config.get('skin') === 'monobook');
UserTagsJS.modules.autoconfirmed = true; // Switch on Autoconfirmed User check
UserTagsJS.modules.newuser = {
    computation: function(days, edits) {
        // If the expression is true then they will be marked as a new user
        // If the expression is false then they won't.
        // In this instance, newuser is removed as soon as the user gets 30
        // edits, OR as soon as they have been present for 10 days, whichever
        // happens first.
        return days < 10 && edits < 30;
    }
};
// NOTE: bannedfromchat displays in Oasis but is not a user-identity group so must be checked manually
UserTagsJS.modules.mwGroups = [
    'bureaucrat',
    'sysop',
    'bot',
    'bot-global',
    'content-moderator',
    'threadmoderator', 
    'chatmoderator',
    'patroller',
    'rollback',
    'bannedfromchat'
];

UserTagsJS.modules.metafilter = {
	'inactive': [
        'sysop',
        'bureaucrat',
        'bot',
        'bot-global',
        'staff',
        'util',
        'vstf'
    ], 
    'sysop': ['bot', 'bot-global'], // Remove "Administrator" tag from bots and global bots
    'content-moderator': ['bureaucrat', 'sysop'], // Remove "Content Moderator" tag from bureaucrats and administrators
    'threadmoderator': ['bureaucrat', 'sysop'], // Remove "Discussions Moderator" tag from bureaucrats and administrators
    'chatmoderator': ['bureaucrat', 'sysop'], // Remove "Chat Moderator" tag from bureaucrats and administrators
    'rollback': ['bureaucrat', 'sysop'] // Remove "Rollback" tag from bureaucrats and administrators
};
// UserTagsJS.modules.stopblocked = true; //Enabled by default
//Manually turn off by changing true -> false

// Username script // 

(function () { 

mw.config.get('wgUserName');

if (mw.config.get('wgUserName') !== null) $('span.insertusername').text(mw.config.get('wgUserName'));
	 
})();

// Bureaucrat promotion warning message //
!function() {
    if (mw.config.get('wgCanonicalSpecialPageName') !== 'Userrights') return;
    $('#mw-content-text').on('change', '#wpGroup-bureaucrat', function() {
    if ($('#wpGroup-bureaucrat').attr('checked') && !confirm('Do you truly want to appoint a bureaucrat?')) $('#wpGroup-bureaucrat').attr('checked', null);
    });
}();

window.pPreview = $.extend(true, window.pPreview, {RegExp: (window.pPreview || {}).RegExp || {} });
window.pPreview.noimage = 'https://thecodex.wiki/images/e/e6/Site-logo.png';
window.pPreview.tlen = 1000;

//==============================================================
// Sorts content on Special:WhatLinksHere alphabetically
//==============================================================
 
(function($) {
    if (mw.config.get('wgCanonicalSpecialPageName') !== 'Whatlinkshere') return;
    var sorted_list,
        $list = $('#mw-whatlinkshere-list');
    sorted_list = $list.children('li').sort(function (a, b) {
        return ($(a).find('a:first').attr('title') > 
        $(b).find('a:first').attr('title')) ? 1 : -1;});
    $list.children('li').remove();
    $list.append(sorted_list);
})(jQuery);

//==============================================================
// Personalized imports
//==============================================================
// Import scripts if user has one of the following ranks:
/* Rollback, Content Moderator, Admin, Bureaucrat, Content Volunteer, */

(function(){
const wgUserGroups = mw.config.get('wgUserGroups');

if(wgUserGroups.includes('rollback') || 
   wgUserGroups.includes('content-moderator') ||
   wgUserGroups.includes('sysop') ||
   wgUserGroups.includes('bureaucrat') ||
   wgUserGroups.includes('content-volunteer') ||
   wgUserGroups.includes('vstf') ||
   wgUserGroups.includes('helper') ||
   wgUserGroups.includes('staff')){
      importArticles({
            type: 'script',
            articles: [
            'u:dev:MediaWiki:AjaxRename/code.js'
        ]
    });
}

if(wgUserGroups.includes('sysop') ||
   wgUserGroups.includes('bureaucrat') ||
   wgUserGroups.includes('content-volunteer') ||
   wgUserGroups.includes('vstf') ||
   wgUserGroups.includes('helper') ||
   wgUserGroups.includes('staff')){
      importArticles({
            type: 'script',
            articles: [
            'u:dev:MediaWiki:WHAM/code.2.js',
            'u:dev:MediaWiki:AjaxUserRights.js'
        ]
    });
}
}());
//==============================================================
// Category Sorter Resolution
//==============================================================
!function(cfg) {
    // sorts categories by name
    // do not bother anons
    if (cfg.loaded || !mw.config.get('wgUserName')) return;
    cfg.loaded = !0;
    
    var targets = [
            '#mw-normal-catlinks:first > ul:first > li',
            '#mw-hidden-catlinks:first > ul:first > li',
            '#articleCategories .category',
        ];
    
    function sorter(a, b) {
        // locale will be determined automatically. probably. works on my machine
        return (a.textContent || '').localeCompare(b.textContent || '');
    }// sorter

    $(function() {
        targets.forEach(function(target) {
            var $target = $(target),
                $parent = $target.parent(),// cache parent, cuz it will be lost after .remove
                sorted = $target.sort(sorter);
            $target.remove();
            $parent.append(sorted);
        });
    });
}((window.fng = window.fng || {}).catsorter = window.fng.catsorter || {});

window.AddRailModule = ['Template:RailModule', 'Template:NewPagesModule'];

// Template:Tabs
$(function() {
	// If a sub-tab is "selected", make the parent tabs also "selected"
	$('.at-selected').parents('.article-tabs li').each(function () {
		$(this).addClass('at-selected');
	});

	// Margin fix
	$('.article-tabs .at-selected .article-tabs').each(function () {
		// Get height of subtabs
		var $TabsHeight = $(this).height();

		// Increase bottom margin of main tabs
		$(this).parents('.article-tabs').last().css('margin-bottom' , '+=' + $TabsHeight);
	});
});
// END of Template:Tabs

// Script for floating actions scroll

// Custom Scripts

if (!rcwidget) {
    var rcwidget = {};
    rcwidget.onlyshowores = (typeof onlyshowores !== 'undefined') ? onlyshowores : false;
    rcwidget.orestolerance = (typeof orestolerance !== 'undefined') ? orestolerance : 0.70;
    rcwidget.fetchtime = (typeof rcfetchtime !== 'undefined') ? rcfetchtime : 0.5

    rcwidget.addToSidebar = function(text) {
        if (mw.config.get("skin") == "timeless") {
            $('<div class="sidebar-chunk" id="rcwidget"><div class="sidebar-inner">' + text + '</div></div>').appendTo("#mw-related-navigation");
            $("#catlinks-sidebar").appendTo("#mw-related-navigation");
            $("#other-languages").appendTo("#mw-related-navigation");
        }
        $('<div class="portal" role="navigation" id="rcwidget" aria-labelledby="p-rcwidget-label">' + text + '</div>').prependTo("#mw-panel");
        $('<div role="navigation" class="portlet generated-sidebar" id="rcwidget" aria-labelledby="p-rcwidget-label">' + text + '</div>').prependTo("#sidebar");
        $('<div class="portlet" id="rcwidget">' + text + '</div>').prependTo("#mw_portlets");
        $("#p-navigation").prependTo("#mw-panel");
        $("#p-search").prependTo("#quickbar");
        $('#p-logo').prependTo("#mw-site-navigation");
        $('#p-logo').prependTo("#mw-panel");
        $('#p-logo').prependTo("#sidebar"); 
        $('#p-logo').prependTo("#mw_portlets");
        $('ul.hlist:first').appendTo('#mw-mf-page-left');

        if (mw.config.get("skin") == "vector" || mw.config.get("skin") == "vector-2022" ) {
            $("#rcwidget").addClass("mw-portlet mw-portlet-navigation vector-menu vector-menu-portal");
        }
    };

    rcwidget.fetch = function() {
        if (!document.hasFocus()) {
            window.setTimeout(rcwidget.fetch, rcwidget.fetchtime * 1000);
        } else {
            var returnHTML = "";
            returnHTML += "<ul>";
            
            $.get(mw.config.get("wgScriptPath") + "/api.php", {
                "action": "query",
                "format": "json", 
                "list": "recentchanges",
                "rcnamespace": "0|3",
                "rcprop": "title|timestamp|flags|loginfo|oresscores|parsedcomment|user|ids|tags",
                "rcshow": "!bot" + (rcwidget.onlyshowores ? "|oresreview" : ""),
                "rctoponly": true,
                "rclimit": "50",
                "rctype": "edit|new"
            }).done(function(result) {
                if (result.error) {
                    console.error(result.error.info);
                    window.setTimeout(rcwidget.fetch, rcwidget.fetchtime * 1000);
                } else {
                    var currDate = new Date();
                    for (var change of result.query.recentchanges) {
                        var changeDate = new Date(change.timestamp);
                        var mildate = new Date(currDate - changeDate);
                        var seconds = mildate.getUTCSeconds();
                        var minutes = mildate.getUTCMinutes();
                        var hours = mildate.getUTCHours();

                        if (typeof change.oresscores != 'undefined') {
                            if (typeof change.oresscores.damaging != 'undefined') {
                                if (typeof change.oresscores.damaging.true != 'undefined') {
                                    if (rcwidget.onlyshowores && change.oresscores.damaging.true < rcwidget.orestolerance) {
                                        continue;
                                    } else {
                                        returnHTML += "<li>";
                                        if (change.type == "edit" && change.oresscores.damaging) {
                                            if (change.oresscores.damaging.true >= rcwidget.orestolerance) {
                                                returnHTML += "<b>";
                                            }
                                        }
                                        returnHTML += '<a href="User_talk:' + change.user + '">' + change.user + '</a> ';
                                        
                                        switch (change.type) {
                                            case "edit":
                                                if (change.tags.includes("mw-undo")) {
                                                    returnHTML += "<a href=\"Project:Undo\">undid</a> an <a href=\"Special:Diff/" + change.revid + "\">edit</a> to <a href=\"" + change.title + "\">" + change.title + '</a>';
                                                } else if (change.tags.includes("mw-rollback")) {
                                                    returnHTML += "<a href=\"Project:Rollback\">rolled back</a> edits to <a href=\"Special:Diff/" + change.revid + "\">edit</a> to <a href=\"" + change.title + "\">" + change.title + '</a>';
                                                } else if (change.ns == 3) {
                                                    returnHTML += 'left a message for <a href="' + change.title + '">' + change.title.replace("User talk:", "") + "</a>";
                                                } else {
                                                    returnHTML += "made an <a href=\"Special:Diff/" + change.revid + "\">edit</a> to <a href=\"" + change.title + "\">" + change.title + '</a>';
                                                }
                                                break;
                                            case "new":
                                                if (change.ns == 3) {
                                                    returnHTML += 'left a message for <a href="' + change.title + '">' + change.title.replace("User talk:", "") + "</a>";
                                                } else {
                                                    returnHTML += "created the page <a href=\"" + change.title + "\">" + change.title + '</a>';
                                                }
                                                break;
                                        }

                                        if (change.type == "edit" && change.oresscores.damaging) {
                                            if (change.oresscores.damaging.true >= rcwidget.orestolerance) {
                                                returnHTML += "</b>";
                                            }
                                        }

                                        returnHTML += "<br><small class=\"rcwidget-date\" data-revtimestamp=\"" + change.timestamp + "\">";
                                        if (hours > 0) {
                                            returnHTML += " " + hours + ((hours == 1) ? " hour" : " hours") + " ago";
                                        } else if (minutes > 0) {
                                            returnHTML += " " + minutes + ((minutes == 1) ? " minute" : " minutes") + " ago";
                                        } else if (seconds > 0) {
                                            returnHTML += " " + seconds + ((seconds == 1) ? " second" : " seconds") + " ago";
                                        }
                                        returnHTML += "</small>";
                                        returnHTML += "</li>";
                                    }
                                }
                            }
                        }
                    }
                    
                    returnHTML += "<li><a href=\"Special:RecentChanges\">View all recent changes</a></li>"
                    returnHTML += "</ul>";
                    
                    $("#rcwidget-content").html(returnHTML);
                    
                    if ($("#rcwidget-content").text().toLowerCase() == "View all recent changes".toLowerCase()) {
                        $("#rcwidget-content").html("<ul><li>No recent changes found.</li></ul>");
                    }
                }
                
                window.setTimeout(rcwidget.fetch, rcwidget.fetchtime * 1000);
            }).fail(function(result) {
                window.setTimeout(rcwidget.fetch, rcwidget.fetchtime * 1000);
            });
        }
    };

    $("#rcwidget-content").css("height", "auto");
    $("#rcwidget-content").css("overflow", "auto");

    $(document).ready(function() {
        rcwidget.addToSidebar((mw.config.get('skin') == 'vector' || mw.config.get('skin') == 'vector-2022') ? 
            '<div id="rcwidget-label" lang="en" dir="ltr"><span><a href="Special:RecentChanges">Recent changes</a></span></div><div class="mw-portlet-body body pBody" id="rcwidget-content" style="height:250px;overflow:hidden;">Loading...</div>' :
            '<h3 id="rcwidget-label" lang="en" dir="ltr"><span><a href="Special:RecentChanges">Recent changes</a></span></h3><div class="mw-portlet-body body pBody" id="rcwidget-content" style="height:250px;overflow:hidden;">Loading...</div>');
        
        rcwidget.fetch();

        window.setInterval(function() {
            var currDate = new Date();
            $('.rcwidget-date').each(function() {
                var changeDate = new Date($(this).data('revtimestamp'));
                var mildate = new Date(currDate - changeDate);
                var seconds = mildate.getUTCSeconds();
                var minutes = mildate.getUTCMinutes();
                var hours = mildate.getUTCHours();

                if (hours > 0) {
                    $(this).html(hours + ((hours == 1) ? " hour" : " hours") + " ago");
                } else if (minutes > 0) {
                    $(this).html(minutes + ((minutes == 1) ? " minute" : " minutes") + " ago");
                } else if (seconds > 0) {
                    $(this).html(seconds + ((seconds == 1) ? " second" : " seconds") + " ago");
                }
            })
        }, rcwidget.fetchtime);
    });
}