User:Enterprisey/req-helper.js

// ( function ( $, mw ) {   if ( mw.config.get( 'wgAction' ) === 'view' && mw.config.get( 'wgPageName' ).indexOf('Wikipedia:Requested_articles') === 0 && mw.config.get( 'wgPageName' ) !== "Wikipedia:Requested_articles" && !$( "#mw-diff-ntitle1" ).length && !$( "#mw-revision-info" ).length ) {       // Load and display form        mw.loader.using( [ "mediawiki.api", "mediawiki.util" ] ).then( function  { $.getJSON(               mw.util.wikiScript('api'),                {                    format: 'json',                    action: 'query',                    prop: 'revisions',                    rvprop: 'content',                    rvlimit: 1,                    titles: "User:Enterprisey/req-helper.js/tpl-panel.js"                }            ).done( function ( data ) {                var pageId = Object.keys(data.query.pages)[0];                var panelHtml = data.query.pages[pageId].revisions[0]['*'];                $( "#jump-to-nav" ).after( panelHtml );                $( "#req-helper-panel input.view-option" ).click( updateRequestActions );                $( "#req-helper-panel input[type='radio']" ).click( updateRequestDisplay );                // Enable save button if there are requests marked for deletion                $( "#mw-content-text" ).on( "click", "a.delete-action", updateSaveChangesButton ); // Save handler $( "#save-changes" ).click( function ( event ) {                   $( "#save-changes" ).prop( "disabled", true );                    editPage( function ( wikitext ) { $( ".marked-for-deletion" ).each( function ( index, element ) {                           var pageTitle = $( element ).children( "a" ).first.text;                            wikitext = removeRequest( wikitext, pageTitle );                        } ); return wikitext; } );               } ); // end save handler // Mark blue handler $( "#mark-bluelinks" ).click( function ( event ) {                   forEachRequest( function ( element ) { var elemClass = $( element ).attr( "class" ); if( $( "#also-mark-redirects" ).is( ":checked" ) ) { if( elemClass !== "mw-redirect" && elemClass ) return; } else { if( elemClass ) return; }                       if( !$( element ).parent.hasClass( "marked-for-deletion" ) ) { $( element ).parent.addClass( "marked-for-deletion" ); }

// Ensure that the text of the action link is correct if( $( element ).parent.hasClass( "marked-for-deletion" ) ) { $( element ).parent.find( ".delete-action" ).text( "undelete" ); }                   } );                    updateSaveChangesButton;                } ); // end mark handler // Create action links, initially hidden forEachRequest( function ( link ) {                   $( " " )                        .insertAfter( link )                        .addClass( "request-actions" )                        .css( "margin-left", "0.25em" )                        .append( $( " ", { "text": "( ", "class": "action-parenthesis" } ) ) .append( $( "" )                           .text( "search" )                            .addClass( "search-action" )                            .attr( "href", "https://www.google.com/search?q=" + $( link ).text.replace( / /, "+" ) ) ) .append( $( " ", { "text": " | ", "class": "action-separator" } ) ) .append( $( "" )                           .text( "delete" )                            .addClass( "delete-action" )                            .click( function ( e ) { $( link ).parent.toggleClass( "marked-for-deletion" ); if( $( this ).text === "delete" ) { $( this ).text( "undelete" ); } else { $( this ).text( "delete" ); }                           } ) )                        .append( $( " ", { "text": " )", "class": "action-parenthesis" } ) );                } ); // end action link creation loop // Make a style element to be used by updateRequestActions $( "#req-helper-panel" ).append( $( " ", { "id": "visibility-css" } ) ); updateRequestActions; updatePageIssues; } ); // end form-loaded handler       } ); // end mw.loader.using handler } // end initial if block

/**    * Removes a request with the given page title from the given wikitext. * @returns The wikitext, with the specified request removed. */   function removeRequest ( wikitext, pageTitle ) {

// Sanitize the page title so we can put it in a regex // (regex from http://stackoverflow.com/a/3561711) pageTitle = pageTitle.replace(/[-\/\\^$*+?.|[\]{}]/g, '\\$&');

[           "\\*\\s?\\[\\[" + pageTitle + "\\]\\].*?\n", "\\*\\s?\\{\\{req\\|" + pageTitle + "\\}\\}.*?\n" ].forEach( function ( regex ) {           regex = new RegExp( regex, "i" );            wikitext = wikitext.replace( regex, "" );        } ); return wikitext; }   function updateSaveChangesButton  { var numMarkedRequests = $( ".marked-for-deletion" ).length; $( "#save-changes" ).prop( "disabled", numMarkedRequests === 0 ); $( "#save-changes" ).text( numMarkedRequests ? ( "Delete " + numMarkedRequests + " request" + ( ( numMarkedRequests === 1 ) ? "" : "s" ) ) : "Save changes" ); }   // Takes a callback that takes a *link* object function forEachRequest ( callback ) {

// Precompute a list of navboxes var navboxes = arrayFromNodeList( document.getElementsByClassName( "navbox" ) ); var links = arrayFromNodeList( document.querySelectorAll( "#mw-content-text a" ) );

for( var i = 0; i < links.length; i++ ) { var element = links[i]; // Test to make sure it's an actual request if( navboxes.some( function ( navbox ) { return $.contains( navbox, element ); } ) ) continue; if( $( element ).children( ".tocnumber" ).length ) continue; if( $( element ).parent.prop( "tagName" ) !== "LI" ) continue; if( $( element ).parents( "#toc" ).length ) continue; if( $( element ).parent.children( "a" ).first.text !== $( element ).text ) continue; // Run callback callback( element ); }   }    function updateRequestDisplay  { var noSourcesAction = $( "input[name=no-sources]:checked" ).val, someSourcesAction = $( "input[name=some-sources]:checked" ).val; forEachRequest( function ( link ) {           // Highlight articles based on # of provided refs            var listElement = $( link ).parent;            if( listElement.children( ".external" ).length === 0 ) {                if( noSourcesAction === "hide" ) {                    listElement.hide;                } else {                    listElement.show;                    listElement.css( "background-color",  ( $( "input[name=no-sources]:checked" ).val === "highlight" ) ? "#FEE" : "#FFF" );               }            } else {                if( someSourcesAction === "hide" ) {                    listElement.hide;                } else {                    listElement.show;                    listElement.css( "background-color",  ( $( "input[name=some-sources]:checked" ).val === "highlight" ) ? "#EFE" : "#FFF" );               }            }        } ); }   function updateRequestActions  { var showSearch = $( "#show-search-option" ).is( ":checked" ), showDelete = $( "#show-delete-option" ).is( ":checked" ); // Make sure we aren't destroying any deletion state if( !showDelete && $( ".marked-for-deletion" ).length !== 0 ) { if( window.confirm( "You've marked some requests for deletion. " + "Are you sure you want to exit mark-for-deletion mode without deleting the requests?" ) ) {               // Wipe deletion state $( "a.delete-action" ).text( "delete" ); $( "li.marked-for-deletion" ).toggleClass( "marked-for-deletion" ); $( "#save-changes" ).prop( "disabled", true ); } else { // The user is indecisive; get out $( "#show-delete-option" ).prop( "checked", true ); return; }       }        var newVisibilityCss = ""; if( !showSearch && !showDelete ) newVisibilityCss += "span.action-parenthesis{display:none;}"; if( !showSearch ) newVisibilityCss += "a.search-action{display:none;}"; if( !showDelete ) newVisibilityCss += "a.delete-action{display:none;}"; if( !showSearch || !showDelete ) newVisibilityCss += "span.action-separator{display:none;}"; $( "#visibility-css" ).html( newVisibilityCss ); }   function updatePageIssues  { $( "#page-issues" ).empty.append( "" ); var addIssue = function ( issue ) { return $( "" ).html( issue ).appendTo( "#page-issues ul" ); }; $.getJSON(           mw.util.wikiScript('api'),            {                format: 'json',                action: 'query',                prop: 'revisions',                rvprop: 'content',                rvlimit: 1,                titles: mw.config.get( 'wgPageName' )            }        ).done( function ( data ) {            var pageId = Object.keys(data.query.pages)[0];            var wikitext = data.query.pages[pageId].revisions[0]['*'];            // Regex counter from http://stackoverflow.com/a/4009768            var refs = ( wikitext.match( / /g ) || [] ).length;            if( refs ) {                addIssue( refs + " &lt;ref&gt; tag" + ( ( refs === 1 ) ? "" : "s" ) );            }            var noLinkReqs = [];            forEachRequest( function ( element ) { if( [ "" ].indexOf( $( element ).parent.html.substring( 0, 3 ) ) === -1 ) { //console.log( [ "", "" ].indexOf( $( element ).parent.html.substring( 0, 3 ) ) + ", " + $( element ).parent.html.substring( 0, 3 ) ); noLinkReqs.push( $( element ).parent.html ); }           } );            if( noLinkReqs.length ) {                addIssue( noLinkReqs.length + " req" + ( ( noLinkReqs.length === 1 ) ? "" : "s" ) + " without a link" )                    .append( $( "", { "text": "(highlight)", "role": "button", "style": "margin-left: 0.75ch" } ) .click( function ( event ) {                           forEachRequest( function ( element ) { if( noLinkReqs.indexOf( $( element ).parent.html ) !== -1 ) { $( element ).parent.css( "background-color", "#FCC" ); }                           } );                            $( this ).remove;                        } ) );            }            var timestamps = ( wikitext.match( /\(UTC\)/g ) || [] ).length;            if( timestamps ) {            	addIssue( timestamps + " timestamp" + ( ( timestamps === 1 ) ? "" : "s" ) );            }            // Set state overall            if( $( "#page-issues ul li").length ) {                $( "#page-issues" ).css( "background-color", "#FEE" );            } else {                $( "#page-issues" ).css( { "vertical-align": "center", "text-align": "center" } );               $( "#page-issues" ).css( "background-color", "#EFE" );                $( "#page-issues" ).text( "(no issues)" );            }        } ); // End get-page-wikitext handler }   function editPage ( processWikitext ) { $( "#req-helper-panel table").append( "  " ); var status = function ( newStatus ) { return $( " ").appendTo( "#req-helper-panel ul#req-status" ).text( newStatus ); };

status( $( ".marked-for-deletion" ).length + " item(s) to delete." );

var wikitext; var getTextStatus = status( "Getting wikitext..." ); $.getJSON(           mw.util.wikiScript('api'),            {                format: 'json',                action: 'query',                prop: 'revisions',                rvprop: 'content',                rvlimit: 1,                titles: mw.config.get( 'wgPageName' )            }        ).done( function ( data ) {            var pageId = Object.keys(data.query.pages)[0];            var wikitext = data.query.pages[pageId].revisions[0]['*'];            getTextStatus.text( "Got wikitext." );           wikitext = processWikitext( wikitext );            status( "Processed wikitext." );           var saveStatus = status( "Saving page..." );           var plural = ( $( ".marked-for-deletion" ).length === 1 ) ? "" : "s";            ( new mw.Api ).postWithEditToken( { action: "edit", title: mw.config.get( 'wgPageName' ), summary: "Removing " + $( ".marked-for-deletion" ).length + " request" + plural + " (req-helper)", text: wikitext } ).done ( function ( data ) { if( data && data.edit && data.edit.result && data.edit.result == 'Success' ) { saveStatus.html( "Saved page! (" )                       .append( $( "" ) .text( "reload" ) .attr( "href", "#" ) .click( function { document.location.reload( true ); } ) )                        .append( ")" ); } else { saveStatus.text( "There was an error saving the page." ); console.log( "Page save result: " + JSON.stringify( data ) ); }           } );        } ); // end get-current-page-wikitext handler }

// Silly utility function, from https://stackoverflow.com/a/5242912/1757964 function arrayFromNodeList( nl ) { var arr = []; for ( var i = 0, ref = arr.length = nl.length; i < ref; i++ ) { arr[i] = nl[i]; }       return arr; } }( jQuery, mediaWiki ) ); //