MediaWiki:Common.js: Difference between revisions

From MDrivenWiki
No edit summary
No edit summary
Line 1: Line 1:
/* Any JavaScript here will be loaded for all users on every page load. */
// ==UserScript==
$(document).ready(function () {
// @name        MediaWiki Clean Delete
    $.get(mw.util.wikiScript('api'), {
// @namespace  MediaWikiScripts
        action: 'query',
// @description Adds a 'Clean Delete' action link to pages for admins to delete pages and clean up incoming links and redirects.
        meta: 'userinfo',
// ==/UserScript==
        format: 'json'
 
     }).done(function (data) {
mw.loader.using(['mediawiki.api', 'mediawiki.util', 'oojs-ui'], function () {
         if (data.query.userinfo.id !== 0) {  
     function addCleanDeleteLink() {
             var username = data.query.userinfo.name;
         if (mw.config.get('wgUserGroups').indexOf('sysop') !== -1) {
            var userLink = mw.util.getUrl('User:' + username);
             if ($('#ca-cleandelete').length === 0) {
            var logoutLink = mw.util.getUrl('Special:Logout');
                var $link = $('<div>').attr('id', 'ca-cleandelete').attr('class', 'mw-list-item').append(
            $('#user-info').html('<a href="' + userLink + '" class="text-white">' + username + '</a>' +
                    $('<a>').attr('href', '#').attr('class', 'ca-cleandelete').text('Clean Delete').click(function (e) {
                                ' &nbsp;|&nbsp; <a href="' + logoutLink + '" class="text-white">Logout</a>');
                        e.preventDefault();
                        gatherAllDecisions(mw.config.get('wgPageName'));
                    })
                );
                $('#p-actions .tab-group').append($link);
            }
         }
         }
     });
     }
});


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


document.getElementById('offcanvas-toggler').addEventListener('click', function() {
        askForLinkHandling(pageTitle, decisions, windowManager, function () {
    var sidebar = document.getElementById('offcanvas-menu');
            confirmDeletion(pageTitle, decisions, windowManager, function () {
    if (sidebar.classList.contains('show')) {
                showLoadingDialog(windowManager, function (loadingDialog, updateLoadingText) {
        sidebar.classList.remove('show');
                    executeAllActions(pageTitle, decisions, function () {
    } else {
                        loadingDialog.close();
         sidebar.classList.add('show');
                        location.reload();
                    }, updateLoadingText);
                });
            });
         });
     }
     }
});


    function askForLinkHandling(pageTitle, decisions, windowManager, callback) {
        function LinkHandlingDialog(config) {
            LinkHandlingDialog.super.call(this, config);
        }
        OO.inheritClass(LinkHandlingDialog, OO.ui.ProcessDialog);


        LinkHandlingDialog.static.name = 'linkHandlingDialog';
        LinkHandlingDialog.static.title = 'Handle Links and Redirects';
        LinkHandlingDialog.static.actions = [
            { action: 'continue', label: 'Continue', flags: ['primary', 'progressive'] },
            { action: 'cancel', label: 'Cancel', flags: ['safe', 'close'] }
        ];


        LinkHandlingDialog.prototype.initialize = function () {
            LinkHandlingDialog.super.prototype.initialize.apply(this, arguments);


$(document).ready(function() {
            this.radioSelect = new OO.ui.RadioSelectWidget({
    $('#offcanvas-close').on('click', function() {
                items: [
        $('#offcanvas-menu').removeClass('show');
                    new OO.ui.RadioOptionWidget({ data: 'delete', label: 'Delete Links and Redirects' }),
    });
                    new OO.ui.RadioOptionWidget({ data: 'change', label: 'Change Target of Links and Redirects' })
});
                ]
            });


document.addEventListener('DOMContentLoaded', function() {
            var fieldset = new OO.ui.FieldsetLayout({
    var form = document.querySelector('.namespace-search-form');
                items: [
    if (form) {
                    new OO.ui.FieldLayout(this.radioSelect, {
        form.addEventListener('submit', function(e) {
                        label: 'Specify how you would like to handle all incoming links and redirects:',
            var input = form.querySelector('#bs-extendedsearch-input');
                        align: 'top'
            if (input) {
                    })
                var namespace = mw.config.get('wgCanonicalNamespace');
                 ]
                if (namespace && namespace.length > 0) {
             });
                    input.value = namespace + ": " + input.value;
                 }
             }
        });
    }
});


(function($) {
            this.content = new OO.ui.PanelLayout({
    'use strict';
                padded: true,
                expanded: false
            });


    var css = [
            this.content.$element.append(fieldset.$element);
        '#suggestion-container {',
            this.$body.append(this.content.$element);
        '    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>');
        LinkHandlingDialog.prototype.getActionProcess = function (action) {
 
            var dialog = this;
    function showSuggestions() {
            var process = new OO.ui.Process(function () {
        var query = $(this).val();
                if (action === 'continue') {
        if (query.length > 0) {  
                    var choice = dialog.radioSelect.findSelectedItem();
            var apiUrl = "https://wiki.mdriven.net/api.php";
                    if (choice && choice.data === 'change') {
            var requestData = {
                        dialog.close().then(function () {
                action: "bs-extendedsearch-autocomplete",
                             askForNewTarget(pageTitle, decisions, windowManager, callback);
                format: "json",
                         });
                q: JSON.stringify({
                     } else {
                    query: {
                        decisions.links = '';
                        bool: {
                        dialog.close().then(function () {
                             must: {
                            callback();
                                match: {
                        });
                                    ac_ngram: {
                    }
                                        query: query
                 } else if (action === 'cancel') {
                                    }
                     dialog.close().then(function () {
                                }
                         windowManager.destroy();
                            }
                         }
                     },
                    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);
                 }
                 }
             });
             });
         }
            return process;
    }
         };


  function hideSuggestions(event) {
        windowManager.addWindows([new LinkHandlingDialog()]);
    if (!$(event.target).closest('#suggestion-container').length) {
         windowManager.openWindow('linkHandlingDialog');
         $('#suggestion-box').empty();
     }
     }
}


function selectSuggestion(event) {
    function askForNewTarget(pageTitle, decisions, windowManager, callback) {
    event.preventDefault();  // Prevent the mousedown event from triggering blur on the search input
        function NewTargetDialog(config) {
    var selectedText = $(this).text();
            NewTargetDialog.super.call(this, config);
    window.location.href = '/index.php?title=' + encodeURIComponent(selectedText);
        }
}
        OO.inheritClass(NewTargetDialog, OO.ui.ProcessDialog);


        NewTargetDialog.static.name = 'newTargetDialog';
        NewTargetDialog.static.title = 'Specify New Target';
        NewTargetDialog.static.actions = [
            { action: 'continue', label: 'Continue', flags: ['primary', 'progressive'] },
            { action: 'cancel', label: 'Cancel', flags: ['safe', 'close'] }
        ];


  $('.search-input').on('input', showSuggestions);
        NewTargetDialog.prototype.initialize = function () {
$(document).on('click', hideSuggestions); 
            NewTargetDialog.super.prototype.initialize.apply(this, arguments);
$('#suggestion-box').on('mousedown', '.suggestion-item', selectSuggestion);  


            this.input = new OO.ui.TextInputWidget({
                value: '',
                placeholder: 'Enter new target'
            });


})(jQuery);
            var fieldset = new OO.ui.FieldsetLayout({
                items: [
                    new OO.ui.FieldLayout(this.input, {
                        label: 'Enter the new target page name to update all links and redirects:',
                        align: 'top'
                    })
                ]
            });


$(document).ready(function() {
            this.content = new OO.ui.PanelLayout({
    // Function to toggle a section open or closed
                padded: true,
    function toggleSection(element) {
                expanded: false
        var submenu = $(element).next('.submenu');
            });
        submenu.toggle();
    }


    // Function to open the submenu containing the current page link and scroll to it
            this.content.$element.append(fieldset.$element);
    function openCurrentPageSubmenuAndScroll() {
            this.$body.append(this.content.$element);
        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
        NewTargetDialog.prototype.getActionProcess = function (action) {
             setTimeout(function() {
             var dialog = this;
                 // Calculate the position of the current page link
             var process = new OO.ui.Process(function () {
                var position = currentPageLink.offset().top - $('#navMenu').offset().top + $('#navMenu').scrollTop();
                 if (action === 'continue') {
                    decisions.links = dialog.input.getValue();
                    dialog.close().then(function () {
                        callback();
                    });
                } else if (action === 'cancel') {
                    dialog.close().then(function () {
                        windowManager.destroy();
                    });
                }
            });
            return process;
        };


                // Scroll the menu to the active item
        windowManager.addWindows([new NewTargetDialog()]);
                $('#navMenu').animate({
        windowManager.openWindow('newTargetDialog');
                    scrollTop: position
                }, 500);
            }, 100); // Delay of 100 milliseconds
        }
     }
     }


     // Event delegation for dynamically loaded content
     function confirmDeletion(pageTitle, decisions, windowManager, callback) {
    $('#navMenu').on('click', '.menu-header', function() {
         var dialog = new OO.ui.MessageDialog();
         toggleSection(this);
        windowManager.addWindows([dialog]);
    });


     // Open the submenu containing the current page link and scroll to it
        windowManager.openWindow(dialog, {
     openCurrentPageSubmenuAndScroll();
            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 showLoadingDialog(windowManager, callback) {
        function LoadingDialog(config) {
            LoadingDialog.super.call(this, config);
        }
        OO.inheritClass(LoadingDialog, OO.ui.ProcessDialog);


document.getElementById('menu-toggle').addEventListener('click', function() {
        LoadingDialog.static.name = 'loadingDialog';
    var navMenu = document.getElementById('navMenu');
        LoadingDialog.static.title = 'Deleting Links and Redirects';
    var bodyContent = document.getElementById('bodyContent');


    if (navMenu.style.display === 'none' || navMenu.style.display === '') {
        LoadingDialog.prototype.initialize = function () {
        navMenu.style.display = 'block';
            LoadingDialog.super.prototype.initialize.apply(this, arguments);
        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() {
            this.loadingLabel = new OO.ui.LabelWidget({ label: 'Starting...' });
    $('.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() {
            this.content = new OO.ui.PanelLayout({
        $('.bs-extendedsearch-filter-button-button').each(function() {
                padded: true,
            $(this).append('<span class="fa fa-chevron-down"></span>');
                expanded: false
        });
            });
});


document.addEventListener("scroll", function() {
            this.content.$element.append(this.loadingLabel.$element);
    var sidebar = document.getElementById("navMenu");
            this.$body.append(this.content.$element);
    var footerHeight = 100;
        };
    var windowHeight = window.innerHeight;


    var scrollBottomPosition = window.scrollY + windowHeight;
        LoadingDialog.prototype.getActionProcess = function (action) {
    var footerTopPosition = document.documentElement.offsetHeight - footerHeight;
            return new OO.ui.Process();
        };


    if (scrollBottomPosition <= footerTopPosition) {
        windowManager.addWindows([new LoadingDialog()]);
         sidebar.style.height = "100vh";
         windowManager.openWindow('loadingDialog').then(function (opened) {
    } else {
            opened.then(function (dialog) {
        sidebar.style.height = "calc(100vh - 110px)";
                callback(dialog, function (text) {
                    dialog.loadingLabel.setLabel(text);
                });
            });
        });
     }
     }
});


mw.loader.using('jquery', function() {
     function executeAllActions(pageTitle, decisions, callback, updateLoadingText) {
     $(document).ready(function() {
         var api = new mw.Api();
         var $toc = $('#toc').clone();
        $('#toc').remove();
        $('#tocContainer').html($toc);


 
        var tasks = [
        $('#tocContainer').css({
            function (resolve) {
            position: '-webkit-sticky',  
                if (decisions.links === '') {
            position: 'sticky',
                    updateLoadingText('Removing all links and redirects...');
            top: '0',  
                    removeAllLinksAndRedirects(pageTitle, api, function () {
            padding: '15px',
                        updateLoadingText('All links and redirects removed.');
             margin: '0 auto',  
                        resolve();
             borderRadius: '5px',  
                    });
            maxWidth: '280px',
                } else {
            maxHeight: 'max-content',
                    updateLoadingText('Updating all links and redirects...');
            overflowY: 'auto',
                    updateAllLinksAndRedirects(pageTitle, decisions.links, api, function () {
            height: '90vh',
                        updateLoadingText('All links and redirects updated.');
             zIndex: 1000
                        resolve();
         });
                    });
                }
             },
             function (resolve) {
                updateLoadingText('Deleting the page...');
                performDeletion(pageTitle, api, function () {
                    updateLoadingText('Page deleted.');
                    resolve();
                });
             }
         ];


         $('#tocContainer .toctitle').css({
         (function executeTasks(i) {
            fontSize: '16px',
            if (i < tasks.length) {
            fontWeight: '600',
                tasks[i](function () {
             color: '#555',
                    executeTasks(i + 1);
            borderBottom: '1px solid #ccc',
                });
             paddingBottom: '10px',
             } else {
            marginBottom: '10px'
                callback();
         });
             }
         })(0);
    }


         $('#tocContainer ul').css({
    function updateAllLinksAndRedirects(pageTitle, newTarget, api, callback) {
             margin: 0,
         handleLinks(pageTitle, newTarget, 'update', api, function () {
            padding: '0 0 0 20px',
             handleRedirects(pageTitle, newTarget, 'update', api, callback);
            listStyleType: 'none',
            fontSize: '14px',
            lineHeight: '1.6'
         });
         });
    }


         $('#tocContainer li').css({
    function removeAllLinksAndRedirects(pageTitle, api, callback) {
             marginBottom: '5px',  
         handleLinks(pageTitle, '', 'remove', api, function () {
             handleRedirects(pageTitle, '', 'remove', api, callback);
         });
         });
    }


        $('#tocContainer a').css({
    function handleLinks(pageTitle, newTarget, action, api, callback) {
             color: '#555',  
        api.get({
             textDecoration: 'none',
             action: 'query',
        }).hover(
             list: 'backlinks',
             function() { $(this).css({textDecoration: 'underline', color: '#000'}); },
             bltitle: pageTitle,
             function() { $(this).css({textDecoration: 'none', color: '#555'}); }
            blfilterredir: 'nonredirects',
 
             bllimit: 'max'
         );
         }).done(function (data) {
    });
            if (data.query.backlinks) {
});
                var promises = data.query.backlinks.map(function (link) {
 
                    return new Promise(function (resolve) {
$(document).ready(function() {
                        if (action === 'update') {
    var $inputElement = $('.oo-ui-textInputWidget-type-search .oo-ui-inputWidget-input');
                            updateLink(link.title, newTarget, api).then(resolve);
    if ($inputElement.length) {
                        } else {
        $inputElement.on('keydown', function(event) {
                            removeLink(link.title, api).then(resolve);
            if (event.key === 'Enter') {
                        }
                 event.preventDefault();
                    });
                 $inputElement.addClass('search-input');
                 });
                Promise.all(promises).then(callback);
            } else {
                 callback();
             }
             }
        }).fail(function (error) {
            console.error('Error fetching backlinks:', error);
            updateLoadingText('Error fetching backlinks: ' + error);
            callback();
         });
         });
     }
     }
});
$(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 handleRedirects(pageTitle, newTarget, action, api, callback) {
     function applyChanges() {
         api.get({
         console.log('applyChanges function called');
            action: 'query',
        var $searchInput = $('input[type="search"].oo-ui-inputWidget-input');
            list: 'backlinks',
         var $searchWidgetResults = $('.oo-ui-searchWidget-results');
            bltitle: pageTitle,
        if ($searchInput.length && $searchWidgetResults.length) {
            blfilterredir: 'redirects',
            console.log('Input element found:', $searchInput);
            bllimit: 'max'
            $searchInput.addClass('search-input-edit');
         }).done(function (data) {
            console.log('Class "search-input" added to input element');
            if (data.query.backlinks) {
 
                var promises = data.query.backlinks.map(function (redirect) {
            if ($searchWidgetResults.next('#suggestion-container-edit').length === 0) {
                    return new Promise(function (resolve) {
                 $('<div id="suggestion-container-edit"></div>').insertAfter($searchWidgetResults);
                        if (action === 'update') {
                 console.log('Suggestion container added after .oo-ui-searchWidget-results element');
                            updateLink(redirect.title, newTarget, api).then(resolve);
                        } else {
                            removeLink(redirect.title, api).then(resolve);
                        }
                    });
                });
                 Promise.all(promises).then(callback);
            } else {
                 callback();
             }
             }
        }).fail(function (error) {
            console.error('Error fetching redirects:', error);
            updateLoadingText('Error fetching redirects: ' + error);
            callback();
        });
    }


            $searchInput.on('input', showSuggestions);
    function updateLink(pageTitle, newTarget, api) {
          $('#suggestion-container').css('width', $searchInput.outerWidth());
        return api.postWithToken('csrf', {
         } else {
            action: 'edit',
             console.log('Input element or .oo-ui-searchWidget-results not found, retrying...');
            title: pageTitle,
            setTimeout(applyChanges, 100);
            text: function (text) {
         }
                return text.replace(new RegExp('\\[\\[' + mw.util.escapeRegExp(pageTitle) + '(\\|[^\\]]+)?\\]\\]', 'g'), '[[' + newTarget + '$1]]');
            },
            summary: 'Updated redirect to new target [[' + newTarget + ']]'
         }).fail(function (error) {
             console.error('Error updating link:', error);
         });
     }
     }


     function checkVeActiveClass() {
     function removeLink(pageTitle, api) {
         console.log('Checking for ve-active class');
         return api.postWithToken('csrf', {
        var $htmlTag = $('html');
            action: 'edit',
        if ($htmlTag.hasClass('ve-active')) {
            title: pageTitle,
            console.log('ve-active class detected on HTML tag');
            text: function (text) {
             applyChanges();
                return text.replace(new RegExp('\\[\\[' + mw.util.escapeRegExp(pageTitle) + '(\\|[^\\]]+)?\\]\\]', 'g'), '');
         } else {
             },
             console.log('ve-active class not yet detected, retrying...');
            summary: 'Removed link to [[' + pageTitle + ']]'
            setTimeout(checkVeActiveClass, 100);
         }).fail(function (error) {
         }
             console.error('Error removing link:', error);
         });
     }
     }


     function showSuggestions() {
     function performDeletion(pageTitle, api, callback) {
         var query = $(this).val();
         api.postWithToken('csrf', {
        if (query.length > 0) {
             action: 'delete',
             var apiUrl = "https://wiki.mdriven.net/api.php";
            title: pageTitle,
            var requestData = {
            reason: 'Automated clean delete by admin'
                action: "bs-extendedsearch-autocomplete",
        }).done(function () {
                format: "json",
            console.log('Page deleted:', pageTitle);
                q: JSON.stringify({
            callback();
                    query: {
        }).fail(function (error) {
                        bool: {
            console.error('Error during clean deletion:', error);
                            must: {
             callback();
                                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-container-edit').empty();
                    $.each(suggestions, function(index, suggestion) {
                        var displayText = suggestion.namespace_text === 'Pages' ? suggestion.basename : suggestion.namespace_text + ':' + suggestion.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');
     mw.hook('wikipage.content').add(addCleanDeleteLink);
    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));
    });

Revision as of 22:41, 7 July 2024

// ==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) {
            if ($('#ca-cleandelete').length === 0) {
                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'));
                    })
                );
                $('#p-actions .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 () {
                showLoadingDialog(windowManager, function (loadingDialog, updateLoadingText) {
                    executeAllActions(pageTitle, decisions, function () {
                        loadingDialog.close();
                        location.reload();
                    }, updateLoadingText);
                });
            });
        });
    }

    function askForLinkHandling(pageTitle, decisions, windowManager, callback) {
        function LinkHandlingDialog(config) {
            LinkHandlingDialog.super.call(this, config);
        }
        OO.inheritClass(LinkHandlingDialog, OO.ui.ProcessDialog);

        LinkHandlingDialog.static.name = 'linkHandlingDialog';
        LinkHandlingDialog.static.title = 'Handle Links and Redirects';
        LinkHandlingDialog.static.actions = [
            { action: 'continue', label: 'Continue', flags: ['primary', 'progressive'] },
            { action: 'cancel', label: 'Cancel', flags: ['safe', 'close'] }
        ];

        LinkHandlingDialog.prototype.initialize = function () {
            LinkHandlingDialog.super.prototype.initialize.apply(this, arguments);

            this.radioSelect = new OO.ui.RadioSelectWidget({
                items: [
                    new OO.ui.RadioOptionWidget({ data: 'delete', label: 'Delete Links and Redirects' }),
                    new OO.ui.RadioOptionWidget({ data: 'change', label: 'Change Target of Links and Redirects' })
                ]
            });

            var fieldset = new OO.ui.FieldsetLayout({
                items: [
                    new OO.ui.FieldLayout(this.radioSelect, {
                        label: 'Specify how you would like to handle all incoming links and redirects:',
                        align: 'top'
                    })
                ]
            });

            this.content = new OO.ui.PanelLayout({
                padded: true,
                expanded: false
            });

            this.content.$element.append(fieldset.$element);
            this.$body.append(this.content.$element);
        };

        LinkHandlingDialog.prototype.getActionProcess = function (action) {
            var dialog = this;
            var process = new OO.ui.Process(function () {
                if (action === 'continue') {
                    var choice = dialog.radioSelect.findSelectedItem();
                    if (choice && choice.data === 'change') {
                        dialog.close().then(function () {
                            askForNewTarget(pageTitle, decisions, windowManager, callback);
                        });
                    } else {
                        decisions.links = '';
                        dialog.close().then(function () {
                            callback();
                        });
                    }
                } else if (action === 'cancel') {
                    dialog.close().then(function () {
                        windowManager.destroy();
                    });
                }
            });
            return process;
        };

        windowManager.addWindows([new LinkHandlingDialog()]);
        windowManager.openWindow('linkHandlingDialog');
    }

    function askForNewTarget(pageTitle, decisions, windowManager, callback) {
        function NewTargetDialog(config) {
            NewTargetDialog.super.call(this, config);
        }
        OO.inheritClass(NewTargetDialog, OO.ui.ProcessDialog);

        NewTargetDialog.static.name = 'newTargetDialog';
        NewTargetDialog.static.title = 'Specify New Target';
        NewTargetDialog.static.actions = [
            { action: 'continue', label: 'Continue', flags: ['primary', 'progressive'] },
            { action: 'cancel', label: 'Cancel', flags: ['safe', 'close'] }
        ];

        NewTargetDialog.prototype.initialize = function () {
            NewTargetDialog.super.prototype.initialize.apply(this, arguments);

            this.input = new OO.ui.TextInputWidget({
                value: '',
                placeholder: 'Enter new target'
            });

            var fieldset = new OO.ui.FieldsetLayout({
                items: [
                    new OO.ui.FieldLayout(this.input, {
                        label: 'Enter the new target page name to update all links and redirects:',
                        align: 'top'
                    })
                ]
            });

            this.content = new OO.ui.PanelLayout({
                padded: true,
                expanded: false
            });

            this.content.$element.append(fieldset.$element);
            this.$body.append(this.content.$element);
        };

        NewTargetDialog.prototype.getActionProcess = function (action) {
            var dialog = this;
            var process = new OO.ui.Process(function () {
                if (action === 'continue') {
                    decisions.links = dialog.input.getValue();
                    dialog.close().then(function () {
                        callback();
                    });
                } else if (action === 'cancel') {
                    dialog.close().then(function () {
                        windowManager.destroy();
                    });
                }
            });
            return process;
        };

        windowManager.addWindows([new NewTargetDialog()]);
        windowManager.openWindow('newTargetDialog');
    }

    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 showLoadingDialog(windowManager, callback) {
        function LoadingDialog(config) {
            LoadingDialog.super.call(this, config);
        }
        OO.inheritClass(LoadingDialog, OO.ui.ProcessDialog);

        LoadingDialog.static.name = 'loadingDialog';
        LoadingDialog.static.title = 'Deleting Links and Redirects';

        LoadingDialog.prototype.initialize = function () {
            LoadingDialog.super.prototype.initialize.apply(this, arguments);

            this.loadingLabel = new OO.ui.LabelWidget({ label: 'Starting...' });

            this.content = new OO.ui.PanelLayout({
                padded: true,
                expanded: false
            });

            this.content.$element.append(this.loadingLabel.$element);
            this.$body.append(this.content.$element);
        };

        LoadingDialog.prototype.getActionProcess = function (action) {
            return new OO.ui.Process();
        };

        windowManager.addWindows([new LoadingDialog()]);
        windowManager.openWindow('loadingDialog').then(function (opened) {
            opened.then(function (dialog) {
                callback(dialog, function (text) {
                    dialog.loadingLabel.setLabel(text);
                });
            });
        });
    }

    function executeAllActions(pageTitle, decisions, callback, updateLoadingText) {
        var api = new mw.Api();

        var tasks = [
            function (resolve) {
                if (decisions.links === '') {
                    updateLoadingText('Removing all links and redirects...');
                    removeAllLinksAndRedirects(pageTitle, api, function () {
                        updateLoadingText('All links and redirects removed.');
                        resolve();
                    });
                } else {
                    updateLoadingText('Updating all links and redirects...');
                    updateAllLinksAndRedirects(pageTitle, decisions.links, api, function () {
                        updateLoadingText('All links and redirects updated.');
                        resolve();
                    });
                }
            },
            function (resolve) {
                updateLoadingText('Deleting the page...');
                performDeletion(pageTitle, api, function () {
                    updateLoadingText('Page deleted.');
                    resolve();
                });
            }
        ];

        (function executeTasks(i) {
            if (i < tasks.length) {
                tasks[i](function () {
                    executeTasks(i + 1);
                });
            } else {
                callback();
            }
        })(0);
    }

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

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

    function handleLinks(pageTitle, newTarget, action, api, callback) {
        api.get({
            action: 'query',
            list: 'backlinks',
            bltitle: pageTitle,
            blfilterredir: 'nonredirects',
            bllimit: 'max'
        }).done(function (data) {
            if (data.query.backlinks) {
                var promises = data.query.backlinks.map(function (link) {
                    return new Promise(function (resolve) {
                        if (action === 'update') {
                            updateLink(link.title, newTarget, api).then(resolve);
                        } else {
                            removeLink(link.title, api).then(resolve);
                        }
                    });
                });
                Promise.all(promises).then(callback);
            } else {
                callback();
            }
        }).fail(function (error) {
            console.error('Error fetching backlinks:', error);
            updateLoadingText('Error fetching backlinks: ' + error);
            callback();
        });
    }

    function handleRedirects(pageTitle, newTarget, action, api, callback) {
        api.get({
            action: 'query',
            list: 'backlinks',
            bltitle: pageTitle,
            blfilterredir: 'redirects',
            bllimit: 'max'
        }).done(function (data) {
            if (data.query.backlinks) {
                var promises = data.query.backlinks.map(function (redirect) {
                    return new Promise(function (resolve) {
                        if (action === 'update') {
                            updateLink(redirect.title, newTarget, api).then(resolve);
                        } else {
                            removeLink(redirect.title, api).then(resolve);
                        }
                    });
                });
                Promise.all(promises).then(callback);
            } else {
                callback();
            }
        }).fail(function (error) {
            console.error('Error fetching redirects:', error);
            updateLoadingText('Error fetching redirects: ' + error);
            callback();
        });
    }

    function updateLink(pageTitle, newTarget, api) {
        return api.postWithToken('csrf', {
            action: 'edit',
            title: pageTitle,
            text: function (text) {
                return text.replace(new RegExp('\\[\\[' + mw.util.escapeRegExp(pageTitle) + '(\\|[^\\]]+)?\\]\\]', 'g'), '[[' + newTarget + '$1]]');
            },
            summary: 'Updated redirect to new target [[' + newTarget + ']]'
        }).fail(function (error) {
            console.error('Error updating link:', error);
        });
    }

    function removeLink(pageTitle, api) {
        return api.postWithToken('csrf', {
            action: 'edit',
            title: pageTitle,
            text: function (text) {
                return text.replace(new RegExp('\\[\\[' + mw.util.escapeRegExp(pageTitle) + '(\\|[^\\]]+)?\\]\\]', 'g'), '');
            },
            summary: 'Removed link to [[' + pageTitle + ']]'
        }).fail(function (error) {
            console.error('Error removing link:', error);
        });
    }

    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();
        });
    }

    mw.hook('wikipage.content').add(addCleanDeleteLink);
});
This page was edited 146 days ago on 08/26/2024. What links here