Jump to content

User:The Transhumanist/PortalTool.js

From Wikipedia, the free encyclopedia
Note: After saving, you have to bypass your browser's cache to see the changes. Google Chrome, Firefox, Microsoft Edge and Safari: Hold down the ⇧ Shift key and click the Reload toolbar button. For details and instructions about other browsers, see Wikipedia:Bypass your cache.
// <syntaxhighlight lang="javascript">

/*

(Script under development - not yet functional)

When completed,
this script will do various things to portals. The current funcion being worked on 
is to fetch page names from a category, and insert them into a template as parameters,
on a portal page.	


Brief comments are provided within the source code below. For extensive explanatory 
notes on what the source code does and how it works, see the Script's workshop on 
the talk page. (Not ready yet.)

*/

// ============== Set up ==============

// Start off with a bodyguard function to reserve the aliases mw and $
( function ( mw, $ ) {

    // we can now rely on mw and $ within the safety of our “bodyguard” function, to mean 
    // "mediawiki" and "jQuery", respectively

    // ============== ready() event listener/handler ==============
    // below is jQuery short-hand for $(document).ready(function() { ... });
    // it makes the rest of the script wait until the page's DOM is loaded and ready
    $(function() {
        
        // ============== activation filters ==============
        // Only activate on Vector skin
        if ( mw.config.get( 'skin' ) === 'vector' ) {

            // Run this script only if "Outline " is in the page title
            if (document.title.indexOf("Outline ") != -1) {

                // End of set up
            
                // =================== Prep work =====================
                
                // Variable declarations, etc., go here

                // ================= Core program ================= 

                $( function() {

                    // BODY OF PROGRAM GOES HERE

                } );
            }
        }
    } );
}( mediaWiki, jQuery ) );

// </syntaxhighlight>



// <syntaxhighlight lang="javascript">

/* 

PortalTool.js: will do a bunch of things for portals. Currently, the function
under development is to fetch the page names from a category and insert them in
a template as parameters.

Brief comments are provided within the sourcecode below. For extensive explanatory 
notes on what the source code does and how it works, see the Script's workshop on 
the talk page. (Not ready yet)

*/

// /////////////////////////// PROCESS READ PAGE ////////////////////////////////////

// Start off with a bodyguard function to reserve mw and $ (see Explanatory notes on talk page).
( function ( mw, $) {
    // we can now rely on mw and $ within the safety of our “bodyguard” function, to mean 
    // "mediawiki" and "jQuery", respectively. Those terms are specified after the closing
    // bracket of the function, which is at the end of the program.

    // Enclose this program section within a ready() event listener/handler, which defers 
    // the "handler" while the script "listens" for the "ready event" (which indicates
    // that the page/DOM is done loading). The listener ensures that the handler (a function)
    // is called only after all the DOM elements of the page are ready to be used (otherwise,
    // the script may not have anything to process):
    $(document).ready( function () {

        // Create linked menu item
        var portletlink = mw.util.addPortletLink('p-tb', '#', 'Remove red links', 'rm-redlink', 'Remove red links', 'o');
        // Bind click handler
        $(portletlink).click( function(e) {
            e.preventDefault();     // prevents any default action -- we want only the following actions to run:

            // Do some stuff when clicked...
            // Default parameters, and begin script on regular view of article
            var loc = window.location.href;
            var redlinks; var i;
        
            // Gather all redlinks with class "new"
            redlinks = [];
            var a = document.getElementsByTagName('a');
            for (i = 0; i < a.length; i++) {
                if (a[i].getAttribute('class') == "new") {
                    redlinks[redlinks.length] = a[i].href.replace('https://en.wikipedia.org/w/index.php?title=','').replace('&action=edit&redlink=1','');
                    redlinks[redlinks.length-1] = redlinks[redlinks.length-1].replace(/_/g,' ');
                    redlinks[redlinks.length-1] = decodeURIComponent(redlinks[redlinks.length-1]);
                }
            }

            // Save all redlinks
            if (redlinks.length > 0) {
                var jsonString = JSON.stringify(redlinks);
                localStorage.OLUtils_redlinks = jsonString;

                // If we are in the edit page, then remove redlinks automatically; if we are on the reading page, then go to the edit page
                if (window.location.href.indexOf('action') >= 0) {
                    // (do nothing - it already does it above)
                } else {
                    window.location = window.location.href.substr(0, window.location.href.indexOf('#'))+"?action=edit";
                }    
            } else {
                alert('No redlinks!');
            }
        });     // end of function(e) (click handler)
    });

// //////////////////////////// PROCESS EDIT PAGE ////////////////////////////////

    // In case we have to wait for the page to load...
    // Below is jQuery short-hand for $(document).ready(function() { ... });
    // referred to in English as the "ready() event listener/handler".
    // It makes the script wait until the page's DOM is loaded and ready.
    $(function() {

        // Invoke a function by its name; this one checks the script's localStorage slot
        // (The function itself is defined down the page a little, using the word "function"). 
        check_storage();
    });

    function check_storage() {
        // Check to see if anything is in storage, and if there is, invoke redlinks removal 
        if (localStorage.OLUtils_redlinks !== "") {

            // Invoke a function by its name (it is defined further down the page). 
            // This one removes redlinks, if they exist:
            redlinks_removal();
        }
    }
    
    // Automatic removal of redlinks when stored.
    function redlinks_removal() {
        // Gather saved redlinks
        var redlinks = JSON.parse(localStorage.OLUtils_redlinks);
    
        // Regular expression to escape special characters
        var totalredlinks = 0;
        RegExp.quote = function(str) { return str.replace(/[.?*+^$[\]\\(){}|-]/g, "\\$&"); };
        
        var wpTextbox1 = document.getElementById('wpTextbox1');

        // REMOVE REDLINKED END NODES (PROCESS OUTLINE ENTRIES)
        // initialize incrementer
        var incrementer = 1;

        // while loop with nested for loop
        while (incrementer > 0) {

            // The nested loop (inside the while loop) is a modified version of the 
            // for loop from the "remove embedded redlinks" section below, using the same array
            for (i = 0; i < redlinks.length; i++) {

                // Use nodeScoop1 & 2 to "scoop" up whole entry (the node with the array term), plus the whole next line.
                // I did not use the global parameter, as the while/for loop structure should catch all occurrences
                // Development note: here we need the regular expression for our first scoop target (redlinked entry with pipe, plus next line) 
                var nodeScoop1 = new RegExp('\\n((\\*)+)[ ]*?\\[\\[\\s*'+(RegExp.quote(redlinks[i]))+'\\s*\\|\\s*([^\\]]*)\\s*\\]\\].*?\\n(.*?\\n)','i');
                // Here is the regular expression for our second scoop target (redlinked entry with direct (non-piped) link, plus next line) 
                var nodeScoop2 = new RegExp('\\n((\\*)+)[ ]*?\\[\\[\\s*'+(RegExp.quote(redlinks[i]))+'\\s*\\]\\].*?\\n(.*?\\n)','i');

                // Generate match strings
                var matchString1 = wpTextbox1.value.match(nodeScoop1);
                var matchString2 = wpTextbox1.value.match(nodeScoop2);
                // Declare match patterns
                var patt1 = new RegExp(":");
                var patt2 = new RegExp("( – )|( &ndash\\; )");
                var patt3 = new RegExp("\\*{"+(RegExp.$1.length+1)+"} *");

                // Development note: Process nodeScoop1 (which holds a piped redlink entry and the whole line following it)
                // Determine if matchString1 doesn't match our exclusion criteria. If it doesn't match, delete the entry:
                  if (matchString1 !== null) {

                    // If there is no coloned annotation (that is, does not have ":")
                    if (patt1.test(matchString1) === false) {

                        // If there is no hyphenated annotation (that is, does not have " – " or " &ndash; ")
                        if (patt2.test(matchString1) === false) {

                            // ...and if the line following it is not a child (that is, does not have more asterisks)
                            if (patt3.test(matchString1) === false) {

                                // ... then replace nodeScoop1 with the last line in it, thereby removing the end node entry
                                wpTextbox1.value = wpTextbox1.value.replace(nodeScoop1,"\n$4");
                                incrementer++;
                            }
                        }
                    }
                }        

                // Process nodeScoop2 (which holds a non-piped redlink entry and the whole line following it)
                // Determine if matchString2 doesn't match our exclusion criteria. If it doesn't match, delete the entry:
                // If matchString2 isn't empty
                  if (matchString2 !== null) {

                    // If there is no coloned annotation (that is, does not have ":")
                    if (patt1.test(matchString2) === false) {

                        // If there is no hyphenated annotation (that is, does not have " – " or " &ndash; ")
                        if (patt2.test(matchString2) === false) {

                            // ...and if the line following it is not a child (that is, does not have more asterisks)
                            if (patt3.test(matchString2) === false) {

                                // ... then replace nodeScoop2 with the last line in it, thereby removing the end node entry
                                wpTextbox1.value = wpTextbox1.value.replace(nodeScoop2,"\n$3");
                                incrementer++;
                            }
                        }
                    }
                }        

            }

            // Adjust the counter
            //  If incrementer is >100, set to 100. This eliminates unnecessary dry runs (iterations with no matches).
            // if (incrementer>100) {
            //   incrementer = 100;
            // Otherwise, the loop would have to continue until the decrementer below slowly whittled the counter down to zero.
            //
            // }

            // After the for loop, still within the while loop, subtract 1 from the incrementer.
            // (If this drops the incrementer down to zero, the while loop should terminate). 
            incrementer--;
        }

        // Mop-up section (removes redlinks not removed above)
        // REMOVE EMBEDDED REDLINKS
        for (i = 0; i < redlinks.length; i++) {
            // Regular expression for piped links and direct links
            var reglink1 = new RegExp('\\[\\[\\s*('+RegExp.quote(redlinks[i])+')\\s*\\|\\s*([^\\]]*)\\s*\\]\\]','gi');
            var reglink2 = new RegExp('\\[\\[\\s*('+RegExp.quote(redlinks[i])+')\\s*\\]\\]','gi');
            
            // Remove category rather than simply convert it to unlinked text
            if (redlinks[i].substr(0,9) == "Category:") {
                var reglink3 = new RegExp('\\[\\[\\s*('+RegExp.quote(redlinks[i])+')\\s*\\]\\]\\n','gi');
                wpTextbox1.value = wpTextbox1.value.replace(reglink3,"");
            }
            
            // Remove redlinks and convert to unlinked text
            wpTextbox1.value = wpTextbox1.value.replace(reglink1,"$2");
            wpTextbox1.value = wpTextbox1.value.replace(reglink2,"$1");
        }

        // summary of removed redlinks
        document.getElementById('wpSummary').value += "Removed redlinks using [[User talk:The Transhumanist/RedlinksRemover.js]].";

        // Remove the template(s)
        wpTextbox1.value = wpTextbox1.value.replace(/\{\{[C|c]leanup red links[^\}]*\}\}/g, "");
        wpTextbox1.value = wpTextbox1.value.replace(/\{\{[C|c]leanup Red Link[^\}]*\}\}/g, "");
        wpTextbox1.value = wpTextbox1.value.replace(/\{\{[C|c]leanup redlinks[^\}]*\}\}/g, "");
        wpTextbox1.value = wpTextbox1.value.replace(/\{\{[C|c]leanup-redlinks[^\}]*\}\}/g, "");
        wpTextbox1.value = wpTextbox1.value.replace(/\{\{[T|t]oo many red links[^\}]*\}\}/g, "");
        
        // Clear all saved redlinks
        localStorage.OLUtils_redlinks = '';
    }    
}) ( mediaWiki, jQuery );       //the end of bodyguard function
// END OF PROGRAM

// </syntaxhighlight>