MediaWiki:Common.js: Difference between revisions

From MDrivenWiki
No edit summary
No edit summary
 
(5 intermediate revisions by the same user not shown)
Line 414: Line 414:
// ==/UserScript==
// ==/UserScript==


mw.loader.using(['mediawiki.api', 'mediawiki.util', 'oojs-ui']).then(function () {
mw.loader.using(['mediawiki.api', 'mediawiki.util', 'oojs-ui'], function () {
     function addCleanDeleteLink() {
     function addCleanDeleteLink() {
         if (mw.config.get('wgUserGroups').indexOf('sysop') !== -1) {
         if (mw.config.get('wgUserGroups').indexOf('sysop') !== -1) {
Line 420: Line 420:
                 $('<a>').attr('href', '#').attr('class', 'ca-cleandelete').text('Clean Delete').click(function (e) {
                 $('<a>').attr('href', '#').attr('class', 'ca-cleandelete').text('Clean Delete').click(function (e) {
                     e.preventDefault();
                     e.preventDefault();
                     confirmDeletion(mw.config.get('wgPageName'));
                     gatherAllDecisions(mw.config.get('wgPageName'));
                 })
                 })
             );
             );
Line 427: Line 427:
     }
     }


     function confirmDeletion(pageTitle) {
     function gatherAllDecisions(pageTitle) {
        var decisions = {};
         var windowManager = new OO.ui.WindowManager();
         var windowManager = new OO.ui.WindowManager();
         $('body').append(windowManager.$element);
         $('body').append(windowManager.$element);


        askForLinkHandling(pageTitle, decisions, windowManager, function() {
            confirmDeletion(pageTitle, decisions, windowManager, function() {
                executeAllActions(pageTitle, decisions, windowManager);
            });
        });
    }
    function askForLinkHandling(pageTitle, decisions, windowManager, callback) {
        var dialog = new OO.ui.MessageDialog();
        var input = new OO.ui.TextInputWidget({
            value: '',
            placeholder: 'Enter new target or leave blank to remove'
        });
        var fieldset = new OO.ui.FieldsetLayout({
            items: [
                new OO.ui.FieldLayout(input, {
                    label: 'Enter a new target page name to update all links and redirects. You can specify a namespace explicitly (e.g., "User:ExamplePage") or leave it blank to remove all links and redirects. If no namespace is provided, the current namespace of the page being deleted will be used by default.',
                    align: 'top'
                })
            ]
        });
        windowManager.addWindows([dialog]);
        windowManager.openWindow(dialog, {
            title: 'Handle Links and Redirects',
            message: 'Please specify how you would like to handle all incoming links and redirects:',
            actions: [
                { label: 'Continue', action: 'continue', flags: ['primary'] },
                { label: 'Cancel', action: 'cancel' }
            ],
            content: fieldset.$element
        }).closed.then(function (result) {
            if (result.action === 'continue') {
                decisions.links = input.getValue();
                callback();
            } else {
                windowManager.destroy();
            }
        });
    }
    function confirmDeletion(pageTitle, decisions, windowManager, callback) {
         var dialog = new OO.ui.MessageDialog();
         var dialog = new OO.ui.MessageDialog();
         windowManager.addWindows([dialog]);
         windowManager.addWindows([dialog]);


         var config = {
         windowManager.openWindow(dialog, {
             title: 'Confirm Page Deletion',
             title: 'Confirm Page Deletion',
             message: 'Are you sure you want to delete "' + pageTitle + '" and clean up all related links and redirects?',
             message: 'Are you sure you want to delete "' + pageTitle + '" after handling all links and redirects?',
             actions: [
             actions: [
                 { action: 'confirm', label: 'Delete', flags: ['primary', 'destructive'] },
                 { label: 'Confirm Deletion', action: 'confirm', flags: ['primary', 'destructive'] },
                 { action: 'reject', label: 'Cancel' }
                 { label: 'Cancel', action: 'cancel' }
             ]
             ]
         };
         }).closed.then(function (data) {
 
        windowManager.openWindow(dialog, config).closed.then(function (data) {
             if (data.action === 'confirm') {
             if (data.action === 'confirm') {
                 deletePageWithCleanup(pageTitle);
                 decisions.deletion = true;
                callback();
            } else {
                windowManager.destroy();
             }
             }
            windowManager.destroy();
         });
         });
     }
     }


     function deletePageWithCleanup(pageTitle) {
     function executeAllActions(pageTitle, decisions, windowManager) {
         var api = new mw.Api();
         var api = new mw.Api();
         api.get({
         if (decisions.links !== undefined) {
            action: 'query',
             if (decisions.links === '') {
            meta: 'tokens',
                 removeAllLinksAndRedirects(pageTitle, api);
            type: 'csrf'
             } else {
        }).done(function (data) {
                 updateAllLinksAndRedirects(pageTitle, decisions.links, api);
             var csrfToken = data.query.tokens.csrftoken;
            }
            api.postWithToken('csrf', {
        }
                 action: 'delete',
        if (decisions.deletion) {
                title: pageTitle,
            performDeletion(pageTitle, api, function() {
                reason: 'Automated clean delete by admin',
                 windowManager.destroy();
             }).done(function (deletionResult) {
                 console.log('Page deleted:', deletionResult);
                handleIncomingLinks(pageTitle, csrfToken);
                updateRedirects(pageTitle, csrfToken);
            }).fail(function (error) {
                 console.error('Error during clean deletion:', error);
             });
             });
         });
         }
    }
 
    function updateAllLinksAndRedirects(pageTitle, newTarget, api) {
        handleLinks(pageTitle, newTarget, 'update', api);
        handleRedirects(pageTitle, newTarget, 'update', api);
    }
 
    function removeAllLinksAndRedirects(pageTitle, api) {
        handleLinks(pageTitle, '', 'remove', api);
        handleRedirects(pageTitle, '', 'remove', api);
     }
     }


     function handleIncomingLinks(pageTitle, token) {
     function handleLinks(pageTitle, newTarget, action, api) {
        var api = new mw.Api();
         api.get({
         api.get({
             action: 'query',
             action: 'query',
             list: 'backlinks',
             list: 'backlinks',
             bltitle: pageTitle,
             bltitle: pageTitle,
            blfilterredir: 'nonredirects',
             bllimit: 'max'
             bllimit: 'max'
         }).done(function (data) {
         }).done(function (data) {
             if (data.query.backlinks) {
             if (data.query.backlinks) {
                 data.query.backlinks.forEach(function(link) {
                 data.query.backlinks.forEach(function (link) {
                     showDialogForLinkUpdateOrRemoval(link, pageTitle, token);
                     if (action === 'update') {
                        updateLink(link.title, newTarget, api);
                    } else {
                        removeLink(link.title, api);
                    }
                 });
                 });
             }
             }
Line 489: Line 541:
     }
     }


     function showDialogForLinkUpdateOrRemoval(link, pageTitle, token) {
     function handleRedirects(pageTitle, newTarget, action, api) {
        var windowManager = new OO.ui.WindowManager();
        $('body').append(windowManager.$element);
 
        var dialog = new OO.ui.MessageDialog();
        windowManager.addWindows([dialog]);
 
        var input = new OO.ui.TextInputWidget({
            value: 'Main_Page'
        });
 
        var content = new OO.ui.PanelLayout({
            padded: true,
            expanded: false,
            content: [
                new OO.ui.LabelWidget({ label: 'For link from ' + link.title + ', type a new target page name to update the link, or leave empty to delete the link:' }),
                input
            ]
        });
 
        var config = {
            title: 'Update or Remove Link',
            message: content.$element,
            actions: [
                { action: 'save', label: 'Submit', flags: ['primary'] },
                { action: 'cancel', label: 'Cancel' }
            ]
        };
 
        windowManager.openWindow(dialog, config).closed.then(function(data) {
            if (data.action === 'save') {
                var userAction = input.getValue();
                if (userAction === '') {
                    removeLink(link.title, pageTitle, token);
                } else {
                    updateLink(link.title, pageTitle, userAction, token);
                }
            }
            windowManager.destroy();
        });
    }
 
    function updateLink(pageTitle, oldTarget, newTarget, token) {
        var api = new mw.Api();
        api.get({
            action: 'parse',
            page: pageTitle,
            prop: 'wikitext'
        }).done(function(contentResult) {
            var content = contentResult.parse.wikitext['*'];
            var updatedContent = content.replace(new RegExp('\\[\\[' + oldTarget + '\\]\\]', 'g'), '[[' + newTarget + ']]');
 
            api.postWithToken('csrf', {
                action: 'edit',
                title: pageTitle,
                text: updatedContent,
                summary: 'Updated link from [[' + oldTarget + ']] to [[' + newTarget + ']]',
                token: token
            });
        });
    }
 
    function removeLink(pageTitle, target, token) {
        var api = new mw.Api();
        api.get({
            action: 'parse',
            page: pageTitle,
            prop: 'wikitext'
        }).done(function(contentResult) {
            var content = contentResult.parse.wikitext['*'];
            var updatedContent = content.replace(new RegExp('\\[\\[' + target + '\\]\\]', 'g'), '');
 
            api.postWithToken('csrf', {
                action: 'edit',
                title: pageTitle,
                text: updatedContent,
                summary: 'Removed broken link to [[' + target + ']]',
                token: token
            });
        });
    }
 
    function updateRedirects(pageTitle, token) {
        var api = new mw.Api();
         api.get({
         api.get({
             action: 'query',
             action: 'query',
Line 581: Line 550:
         }).done(function (data) {
         }).done(function (data) {
             if (data.query.backlinks) {
             if (data.query.backlinks) {
                 data.query.backlinks.forEach(function(redirect) {
                 data.query.backlinks.forEach(function (redirect) {
                     showDialogForRedirectUpdateOrRemoval(redirect, pageTitle, token);
                     if (action === 'update') {
                        updateLink(redirect.title, newTarget, api);
                    } else {
                        removeLink(redirect.title, api);
                    }
                 });
                 });
             }
             }
Line 588: Line 561:
     }
     }


     function showDialogForRedirectUpdateOrRemoval(redirect, pageTitle, token) {
     function updateLink(pageTitle, newTarget, api) {
         var windowManager = new OO.ui.WindowManager();
         api.postWithToken('csrf', {
        $('body').append(windowManager.$element);
            action: 'edit',
 
            title: pageTitle,
        var dialog = new OO.ui.MessageDialog();
            text: '#REDIRECT [[' + newTarget + ']]',
        windowManager.addWindows([dialog]);
             summary: 'Updated redirect to new target [[' + newTarget + ']]',
 
        var input = new OO.ui.TextInputWidget({
             value: 'Main_Page'
         });
         });
    }


         var content = new OO.ui.PanelLayout({
    function removeLink(pageTitle, api) {
             padded: true,
         api.postWithToken('csrf', {
             expanded: false,
             action: 'delete',
             content: [
             title: pageTitle,
                new OO.ui.LabelWidget({ label: 'Redirect from ' + redirect.title + ' currently points to a deleted page. Enter a new target or leave empty to delete the redirect:' }),
             reason: 'Removing unnecessary link or redirect',
                input
            ]
         });
         });
    }


        var config = {
    function performDeletion(pageTitle, api, callback) {
            title: 'Update or Remove Redirect',
        api.postWithToken('csrf', {
             message: content.$element,
             action: 'delete',
            actions: [
            title: pageTitle,
                { action: 'save', label: 'Submit', flags: ['primary'] },
            reason: 'Automated clean delete by admin',
                { action: 'cancel', label: 'Cancel' }
         }).done(function () {
            ]
             console.log('Page deleted:', pageTitle);
         };
            callback();
 
        }).fail(function (error) {
        windowManager.openWindow(dialog, config).closed.then(function(data) {
            console.error('Error during clean deletion:', error);
             if (data.action === 'save') {
             callback();
                var newTarget = input.getValue();
                if (newTarget === '') {
                    api.postWithToken('csrf', {
                        action: 'delete',
                        title: redirect.title,
                        reason: 'Removing unnecessary redirect',
                        token: token
                    });
                } else {
                    api.postWithToken('csrf', {
                        action: 'edit',
                        title: redirect.title,
                        text: '#REDIRECT [[' + newTarget + ']]',
                        summary: 'Updated redirect to new target [[' + newTarget + ']]',
                        token: token
                    });
                }
             }
            windowManager.destroy();
         });
         });
     }
     }

Latest revision as of 22:51, 30 June 2024

/* Any JavaScript here will be loaded for all users on every page load. */
$(document).ready(function () {
    $.get(mw.util.wikiScript('api'), {
        action: 'query',
        meta: 'userinfo',
        format: 'json'
    }).done(function (data) {
        if (data.query.userinfo.id !== 0) { 
            var username = data.query.userinfo.name;
            var userLink = mw.util.getUrl('User:' + username);
            var logoutLink = mw.util.getUrl('Special:Logout');
            $('#user-info').html('<a href="' + userLink + '" class="text-white">' + username + '</a>' + 
                                 ' &nbsp;|&nbsp; <a href="' + logoutLink + '" class="text-white">Logout</a>');
        }
    });
});


document.getElementById('offcanvas-toggler').addEventListener('click', function() {
    var sidebar = document.getElementById('offcanvas-menu');
    if (sidebar.classList.contains('show')) {
        sidebar.classList.remove('show');
    } else {
        sidebar.classList.add('show');
    }
});




$(document).ready(function() {
    $('#offcanvas-close').on('click', function() {
        $('#offcanvas-menu').removeClass('show');
    });
});

document.addEventListener('DOMContentLoaded', function() {
    var form = document.querySelector('.namespace-search-form');
    if (form) {
        form.addEventListener('submit', function(e) {
            var input = form.querySelector('#bs-extendedsearch-input');
            if (input) {
                var namespace = mw.config.get('wgCanonicalNamespace');
                if (namespace && namespace.length > 0) {
                    input.value = namespace + ": " + input.value;
                }
            }
        });
    }
});

(function($) {
    'use strict';

    var css = [
        '#suggestion-container {',
        '    position: relative;',
        '    width: 100%;',
        '}',
        '#suggestion-box {',
        '    position: absolute;',
        '    top: 100%;', 
        '    left: 0;', 
        '    width: 100%;', 
        '    margin-top: 5px;', 
        '    background-color: #fff;',
        '    z-index: 1000;',
        '}',
        '.suggestion-item {',
        '    padding: 8px;',
        '    cursor: pointer;',
        '}',
        '.suggestion-item:hover {',
        '    background-color: #e0e0e0;',
        '}'
    ].join('\n');
    $('head').append('<style type="text/css">' + css + '</style>');

    $('#suggestion-container').append('<div id="suggestion-box"></div>');

    function showSuggestions() {
        var query = $(this).val();
        if (query.length > 0) { 
            var apiUrl = "https://wiki.mdriven.net/api.php";
            var requestData = {
                action: "bs-extendedsearch-autocomplete",
                format: "json",
                q: JSON.stringify({
                    query: {
                        bool: {
                            must: {
                                match: {
                                    ac_ngram: {
                                        query: query
                                    }
                                }
                            }
                        }
                    },
                    size: 8
                }),
                searchData: JSON.stringify({
                    namespace: 0,
                    value: query,
                    mainpage: ""
                })
            };
            $.ajax({
                url: apiUrl,
                data: requestData,
                dataType: "json",
                method: "GET",
                success: function(data) {
                    var suggestions = data.suggestions || [];
                    $('#suggestion-box').empty();
                    $.each(suggestions, function(index, suggestion) {
                        var item = $('<div class="suggestion-item"></div>').text(suggestion.basename);
                        $('#suggestion-box').append(item);
                    });
                },
                error: function(jqxhr, textStatus, error) {
                    console.error('Error fetching suggestions:', error);
                }
            });
        }
    }

   function hideSuggestions(event) {
    if (!$(event.target).closest('#suggestion-container').length) {
        $('#suggestion-box').empty();
    }
}

function selectSuggestion(event) {
    event.preventDefault();  // Prevent the mousedown event from triggering blur on the search input
    var selectedText = $(this).text();
    window.location.href = '/index.php?title=' + encodeURIComponent(selectedText);
}


   $('.search-input').on('input', showSuggestions);
$(document).on('click', hideSuggestions);  
$('#suggestion-box').on('mousedown', '.suggestion-item', selectSuggestion); 


})(jQuery);

$(document).ready(function() {
    // Function to toggle a section open or closed
    function toggleSection(element) {
        var submenu = $(element).next('.submenu');
        submenu.toggle();
    }

    // Function to open the submenu containing the current page link and scroll to it
    function openCurrentPageSubmenuAndScroll() {
        var currentPageLink = $('#navMenu .current-page');
        if (currentPageLink.length) {
            // Open the parent submenu(s) of the current page link
            currentPageLink.parents('.submenu').show();

            // Delay the scrolling to allow for any dynamic layout changes
            setTimeout(function() {
                // Calculate the position of the current page link
                var position = currentPageLink.offset().top - $('#navMenu').offset().top + $('#navMenu').scrollTop();

                // Scroll the menu to the active item
                $('#navMenu').animate({
                    scrollTop: position
                }, 500);
            }, 100); // Delay of 100 milliseconds
        }
    }

    // Event delegation for dynamically loaded content
    $('#navMenu').on('click', '.menu-header', function() {
        toggleSection(this);
    });

    // Open the submenu containing the current page link and scroll to it
    openCurrentPageSubmenuAndScroll();
});

document.getElementById('menu-toggle').addEventListener('click', function() {
    var navMenu = document.getElementById('navMenu');
    var bodyContent = document.getElementById('bodyContent');

    if (navMenu.style.display === 'none' || navMenu.style.display === '') {
        navMenu.style.display = 'block';
        bodyContent.style.display = 'none';  // Hide body content when nav menu is displayed
    } else {
        navMenu.style.display = 'none';
        bodyContent.style.display = 'block';  // Show body content when nav menu is hidden
    }
});

$(document).ready(function() {
    $('.video__navigation .navigation-item').click(function() {
        var videoID = $(this).data('video');
        var startTime = $(this).data('start');
        var newSrc = 'https://www.youtube.com/embed/' + videoID + '?start=' + startTime + '&autoplay=1';
        
        $('.video__wrapper iframe').attr('src', newSrc);
    });
});

$(document).ready(function() {
        $('.bs-extendedsearch-filter-button-button').each(function() {
            $(this).append('<span class="fa fa-chevron-down"></span>');
        });
});

document.addEventListener("scroll", function() {
    var sidebar = document.getElementById("navMenu");
    var footerHeight = 100;
    var windowHeight = window.innerHeight;

    var scrollBottomPosition = window.scrollY + windowHeight;
    var footerTopPosition = document.documentElement.offsetHeight - footerHeight;

    if (scrollBottomPosition <= footerTopPosition) {
        sidebar.style.height = "100vh";
    } else {
        sidebar.style.height = "calc(100vh - 110px)";
    }
});

mw.loader.using('jquery', function() {
    $(document).ready(function() {
        var $toc = $('#toc').clone();
        $('#toc').remove(); 
        $('#tocContainer').html($toc);

   
        $('#tocContainer').css({
            position: '-webkit-sticky', 
            position: 'sticky',
            top: '0', 
            padding: '15px',
            margin: '0 auto', 
            borderRadius: '5px', 
            maxWidth: '280px',
            maxHeight: 'max-content',
            overflowY: 'auto',
            height: '90vh',
            zIndex: 1000
        });

        $('#tocContainer .toctitle').css({
            fontSize: '16px',
            fontWeight: '600',
            color: '#555',
            borderBottom: '1px solid #ccc',
            paddingBottom: '10px',
            marginBottom: '10px'
        });

        $('#tocContainer ul').css({
            margin: 0,
            padding: '0 0 0 20px',
            listStyleType: 'none',
            fontSize: '14px',
            lineHeight: '1.6' 
        });

        $('#tocContainer li').css({
            marginBottom: '5px', 
        });

        $('#tocContainer a').css({
            color: '#555', 
            textDecoration: 'none',
        }).hover(
            function() { $(this).css({textDecoration: 'underline', color: '#000'}); },
            function() { $(this).css({textDecoration: 'none', color: '#555'}); }

        );
    });
});

$(document).ready(function() {
    var $inputElement = $('.oo-ui-textInputWidget-type-search .oo-ui-inputWidget-input');
    if ($inputElement.length) {
        $inputElement.on('keydown', function(event) {
            if (event.key === 'Enter') {
                event.preventDefault();
                $inputElement.addClass('search-input');
            }
        });
    }
});

$(document).ready(function() {
    var $inputElement = $('.oo-ui-textInputWidget-type-search .oo-ui-inputWidget-input');
    if ($inputElement.length) {
        $inputElement.addClass('search-input');
        console.log('Class "search-input" added to the input element.');
    } else {
        console.log('Input element not found.');
    }
});

$(document).ready(function() {
    function applyChanges() {
        console.log('applyChanges function called');
        var $searchInput = $('input[type="search"].oo-ui-inputWidget-input');
        var $searchWidgetResults = $('.oo-ui-searchWidget-results');
        if ($searchInput.length && $searchWidgetResults.length) {
            console.log('Input element found:', $searchInput);
            $searchInput.addClass('search-input-edit');
            console.log('Class "search-input" added to input element');

            if ($searchWidgetResults.next('#suggestion-container-edit').length === 0) {
                $('<div id="suggestion-container-edit"></div>').insertAfter($searchWidgetResults);
                console.log('Suggestion container added after .oo-ui-searchWidget-results element');
            }

            $searchInput.on('input', showSuggestions);
           $('#suggestion-container').css('width', $searchInput.outerWidth());
        } else {
            console.log('Input element or .oo-ui-searchWidget-results not found, retrying...');
            setTimeout(applyChanges, 100);
        }
    }

    function checkVeActiveClass() {
        console.log('Checking for ve-active class');
        var $htmlTag = $('html');
        if ($htmlTag.hasClass('ve-active')) {
            console.log('ve-active class detected on HTML tag');
            applyChanges();
        } else {
            console.log('ve-active class not yet detected, retrying...');
            setTimeout(checkVeActiveClass, 100);
        }
    }

    function showSuggestions() {
        var query = $(this).val();
        if (query.length > 0) {
            var apiUrl = "https://insider.mdriven.net/api/search";
            var requestData = {
                q: query
            };
            $.ajax({
                url: apiUrl,
                data: requestData,
                dataType: "json",
                method: "GET",
                success: function(data) {
                    var suggestions = data || [];
                    $('#suggestion-container-edit').empty();
                    $.each(suggestions, function(index, suggestion) {
                        var source = suggestion._source;
                        var displayText = source.namespace_text + ':' + source.basename;
                        var item = $('<div class="suggestion-item-edit"></div>').text(displayText);
                        item.on('click', function() {
                            $('input[type="search"].oo-ui-inputWidget-input').val(displayText);
                            $('#suggestion-container-edit').empty();
                        });
                        $('#suggestion-container-edit').append(item);
                    });
                },
                error: function(jqxhr, textStatus, error) {
                    console.error('Error fetching suggestions:', error);
                }
            });
        } else {
            $('#suggestion-container-edit').empty(); // Clear suggestions if query is empty
        }
    }

    console.log('Starting to check for ve-active class');
    checkVeActiveClass();
});

$('<style type="text/css">#suggestion-container-edit { position: static; border: 1px solid #ccc; background: white; z-index: 10000; width: 100%; overflow-y: auto; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); } .suggestion-item-edit { padding: 8px; cursor: pointer; } .suggestion-item-edit:hover { background: #f0f0f0; }</style>').appendTo('head');

$(document).ready(function() {
        var signInLink = $('#user-info a');
        var currentUrl = encodeURIComponent(window.location.pathname + window.location.search + window.location.hash);
        signInLink.attr('href', signInLink.attr('href').replace('<CURRENT_URL>', currentUrl));
    });


document.addEventListener('DOMContentLoaded', function() {
    var images = document.querySelectorAll('.thumbimage');
    var overlay = document.createElement('div');
    overlay.className = 'image-overlay';
    document.body.appendChild(overlay);

    var overlayImage = document.createElement('img');
    overlay.appendChild(overlayImage);

    images.forEach(function(image) {
        image.addEventListener('click', function(event) {
            event.preventDefault();
            event.stopPropagation();

            overlayImage.src = image.src;
            overlay.classList.add('show');
        });
    });

    overlay.addEventListener('click', function() {
        overlay.classList.remove('show');
    });
});

// ==UserScript==
// @name        MediaWiki Clean Delete
// @namespace   MediaWikiScripts
// @description Adds a 'Clean Delete' action link to pages for admins to delete pages and clean up incoming links and redirects.
// ==/UserScript==

mw.loader.using(['mediawiki.api', 'mediawiki.util', 'oojs-ui'], function () {
    function addCleanDeleteLink() {
        if (mw.config.get('wgUserGroups').indexOf('sysop') !== -1) {
            var $link = $('<div>').attr('id', 'ca-cleandelete').attr('class', 'mw-list-item').append(
                $('<a>').attr('href', '#').attr('class', 'ca-cleandelete').text('Clean Delete').click(function (e) {
                    e.preventDefault();
                    gatherAllDecisions(mw.config.get('wgPageName'));
                })
            );
            $('.tab-group').append($link);
        }
    }

    function gatherAllDecisions(pageTitle) {
        var decisions = {};
        var windowManager = new OO.ui.WindowManager();
        $('body').append(windowManager.$element);

        askForLinkHandling(pageTitle, decisions, windowManager, function() {
            confirmDeletion(pageTitle, decisions, windowManager, function() {
                executeAllActions(pageTitle, decisions, windowManager);
            });
        });
    }

    function askForLinkHandling(pageTitle, decisions, windowManager, callback) {
        var dialog = new OO.ui.MessageDialog();
        var input = new OO.ui.TextInputWidget({
            value: '',
            placeholder: 'Enter new target or leave blank to remove'
        });

        var fieldset = new OO.ui.FieldsetLayout({
            items: [
                new OO.ui.FieldLayout(input, {
                    label: 'Enter a new target page name to update all links and redirects. You can specify a namespace explicitly (e.g., "User:ExamplePage") or leave it blank to remove all links and redirects. If no namespace is provided, the current namespace of the page being deleted will be used by default.',
                    align: 'top'
                })
            ]
        });

        windowManager.addWindows([dialog]);
        windowManager.openWindow(dialog, {
            title: 'Handle Links and Redirects',
            message: 'Please specify how you would like to handle all incoming links and redirects:',
            actions: [
                { label: 'Continue', action: 'continue', flags: ['primary'] },
                { label: 'Cancel', action: 'cancel' }
            ],
            content: fieldset.$element
        }).closed.then(function (result) {
            if (result.action === 'continue') {
                decisions.links = input.getValue();
                callback();
            } else {
                windowManager.destroy();
            }
        });
    }

    function confirmDeletion(pageTitle, decisions, windowManager, callback) {
        var dialog = new OO.ui.MessageDialog();
        windowManager.addWindows([dialog]);

        windowManager.openWindow(dialog, {
            title: 'Confirm Page Deletion',
            message: 'Are you sure you want to delete "' + pageTitle + '" after handling all links and redirects?',
            actions: [
                { label: 'Confirm Deletion', action: 'confirm', flags: ['primary', 'destructive'] },
                { label: 'Cancel', action: 'cancel' }
            ]
        }).closed.then(function (data) {
            if (data.action === 'confirm') {
                decisions.deletion = true;
                callback();
            } else {
                windowManager.destroy();
            }
        });
    }

    function executeAllActions(pageTitle, decisions, windowManager) {
        var api = new mw.Api();
        if (decisions.links !== undefined) {
            if (decisions.links === '') {
                removeAllLinksAndRedirects(pageTitle, api);
            } else {
                updateAllLinksAndRedirects(pageTitle, decisions.links, api);
            }
        }
        if (decisions.deletion) {
            performDeletion(pageTitle, api, function() {
                windowManager.destroy();
            });
        }
    }

    function updateAllLinksAndRedirects(pageTitle, newTarget, api) {
        handleLinks(pageTitle, newTarget, 'update', api);
        handleRedirects(pageTitle, newTarget, 'update', api);
    }

    function removeAllLinksAndRedirects(pageTitle, api) {
        handleLinks(pageTitle, '', 'remove', api);
        handleRedirects(pageTitle, '', 'remove', api);
    }

    function handleLinks(pageTitle, newTarget, action, api) {
        api.get({
            action: 'query',
            list: 'backlinks',
            bltitle: pageTitle,
            blfilterredir: 'nonredirects',
            bllimit: 'max'
        }).done(function (data) {
            if (data.query.backlinks) {
                data.query.backlinks.forEach(function (link) {
                    if (action === 'update') {
                        updateLink(link.title, newTarget, api);
                    } else {
                        removeLink(link.title, api);
                    }
                });
            }
        });
    }

    function handleRedirects(pageTitle, newTarget, action, api) {
        api.get({
            action: 'query',
            list: 'backlinks',
            bltitle: pageTitle,
            blfilterredir: 'redirects',
            bllimit: 'max'
        }).done(function (data) {
            if (data.query.backlinks) {
                data.query.backlinks.forEach(function (redirect) {
                    if (action === 'update') {
                        updateLink(redirect.title, newTarget, api);
                    } else {
                        removeLink(redirect.title, api);
                    }
                });
            }
        });
    }

    function updateLink(pageTitle, newTarget, api) {
        api.postWithToken('csrf', {
            action: 'edit',
            title: pageTitle,
            text: '#REDIRECT [[' + newTarget + ']]',
            summary: 'Updated redirect to new target [[' + newTarget + ']]',
        });
    }

    function removeLink(pageTitle, api) {
        api.postWithToken('csrf', {
            action: 'delete',
            title: pageTitle,
            reason: 'Removing unnecessary link or redirect',
        });
    }

    function performDeletion(pageTitle, api, callback) {
        api.postWithToken('csrf', {
            action: 'delete',
            title: pageTitle,
            reason: 'Automated clean delete by admin',
        }).done(function () {
            console.log('Page deleted:', pageTitle);
            callback();
        }).fail(function (error) {
            console.error('Error during clean deletion:', error);
            callback();
        });
    }

    $(document).ready(function() {
        addCleanDeleteLink();
    });
});
This page was edited 3 days ago on 07/01/2024. What links here