User:Enterprisey/delsort.js
(Redirected from User:EnterpriseyBot/delsort.js)
//<nowiki>( function ( $, mw ) { mw.loader.load( "jquery.chosen" ); mw.loader.load( "mediawiki.ui.input", "text/css" ); var afdcCategories = { "m": "Media and music", "o": "Organization, corporation, or product", "b": "Biographical", "s": "Society topics", "w": "Web or Internet", "g": "Games or sports", "t": "Science and technology", "f": "Fiction and the arts", "p": "Places and transportation", "i": "Indiscernible or unclassifiable topic", "u": "Not sorted yet" }; var ADVERTISEMENT = " ([[User:Enterprisey/delsort|assisted]])"; var currentAfdcCat = ""; var currentDelsortCategories = []; if ( mw.config.get( "wgPageName" ).indexOf("Wikipedia:Articles_for_deletion/") != -1 && mw.config.get( "wgPageName" ).indexOf("Wikipedia:Articles_for_deletion/Log/") == -1) { var portletLink = mw.util.addPortletLink("p-cactions", "#", "Delsort", "pt-delsort", "Perform deletion sorting"); // Load list of delsort categories var delsortCategoriesPromise = $.ajax( { url: "https://en.wikipedia.org/w/index.php?action=raw&title=" + encodeURIComponent( "Wikipedia:WikiProject Deletion sorting/Computer-readable.json" ) + "&maxage=86400&smaxage=86400", dataType: "json" } ) $( portletLink ).click( function ( e ) { e.preventDefault(); // Validation for new custom fields var validateCustomCat = function ( container ) { var categoryName = container.children( "input" ).first().val(); $.getJSON( mw.util.wikiScript("api"), { format: "json", action: "query", prop: "pageprops", titles: "Wikipedia:WikiProject Deletion sorting/" + categoryName } ).done( function ( data ) { var setStatus = function ( status ) { var text = "Not sure"; var imageSrc = "https://upload.wikimedia.org/wikipedia/commons/a/ad/Question_mark_grey.png"; switch( status ) { case "d": text = "Doesn't exist"; imageSrc = "https://upload.wikimedia.org/wikipedia/commons/5/5f/Red_X.svg"; break; case "e": text = "Exists"; imageSrc = "https://upload.wikimedia.org/wikipedia/commons/1/16/Allowed.svg"; break; } container.children( ".category-status" ).empty() .append( $( "<img>", { "src": imageSrc, "style": "padding: 0 5px; width: 20px; height: 20px" } ) ) .append( text ); }; if( data && data.query && data.query.pages ) { if( data.query.pages.hasOwnProperty( "-1" ) ) { setStatus( "d" ); } else { setStatus( "e" ); } } else { setStatus( "n" ); } } ); }; // Define a function to add a new custom field, used below var addCustomField = function ( e ) { $( "<div>" ) .appendTo( "#delsort-td" ) .css( "width", "100%" ) .css( "margin", "0.25em auto" ) .append( $( "<input>" ) .attr( "type", "text" ) .addClass( "mw-ui-input mw-ui-input-inline custom-delsort-field" ) .change( function ( e ) { validateCustomCat( $( this ).parent() ); } ) ) .append( $( "<span>" ).addClass( "category-status" ) ) .append( " (" ) .append( $( "<img>", { "src": "https://upload.wikimedia.org/wikipedia/commons/a/a2/Crystal_128_reload.svg", "style": "width: 15px; height: 15px; cursor: pointer" } ) .click( function ( e ) { validateCustomCat( $( this ).parent() ); } ) ) .append( ")" ) .append( $( "<button>" ) .addClass( "mw-ui-button mw-ui-destructive mw-ui-quiet" ) .text( "Remove" ) .click( function () { $( this ).parent().remove(); } ) ); }; $( "#mw-content-text" ).prepend('<div style="border: thin solid rgb(197, 197, 197); box-shadow: 0px 3px 8px rgba(0, 0, 0, 0.25); border-radius: 3px; padding: 5px; position: relative;" id="delsort">' +' <div id="delsort-title" style="font-size: larger; font-weight: bold; text-align: center;">Select a deletion sorting category</div>' +' <table style="margin: 2em auto; border-collapse: collapse;" id="delsort-table">' +' <tr style="font-size: larger"><th>AFDC</th><th>DELSORT</th></tr>' +' <tr>' +' <td style="padding-right: 10px;">' +' <table id="afdc">' +' </table>' +' </td>' +' <td style="border-left: solid black thick; padding-left: 10px; vertical-align: top;" id="delsort-td">' +' <select multiple="multiple" data-placeholder="Select a deletion sorting category..."></select>' +' <button id="add-custom-button" class="mw-ui-button mw-ui-progressive mw-ui-quiet">Add custom</button>' +' </td>' +' </tr>' +' </table>' +' <button style="position: absolute; top: 5px; right: 5px;" id="close-button" class="mw-ui-button mw-ui-destructive mw-ui-quiet">Close</button>' +'</div>' ); $( "#add-custom-button" ).click( addCustomField ); $( "#close-button" ).click( function () { $( "#delsort" ).remove(); } ); var afdcHtml = ""; Object.keys( afdcCategories ).forEach( function ( code, i ) { if ( i % 2 === 0 ) afdcHtml += "<tr>"; afdcHtml += "<td><input type='radio' name='afdc' value='" + code + "' id='afdc-" + code + "' /><label for='afdc-" + code + "'>" + afdcCategories[ code ] + "</label></td>"; if ( i % 2 !== 0 ) afdcHtml += "</tr>"; } ); // If there are an odd number of AFDC cats, we need to close off the last row if ( Object.keys( afdcCategories ).length % 2 !== 0 ) afdcHtml += "</tr>"; $( "#afdc" ).html( afdcHtml ); // Build the deletion sorting categories delsortCategoriesPromise.done( function ( delsortCategories ) { $.each( delsortCategories, function ( groupName, categories ) { var group = $( "<optgroup>" ) .appendTo( "#delsort select" ) .attr( "label", groupName ); $.each( categories, function ( index, category ) { group.append( $( "<option>" ) .val( category ) .text( category ) .addClass( "delsort-category" ) ); } ); } ); getWikitext( mw.config.get( "wgPageName" ) ).then( function ( wikitext ) { autofillAfdc( wikitext ); // Autofill the delsort box var DELSORT_RE = /:<small class="delsort-notice">(.+?)<\/small>/g; var DELSORT_LIST_RE = /\[\[Wikipedia:WikiProject Deletion sorting\/(.+?)\|.+?\]\]/; var delsortMatch; var delsortListMatch; do { delsortMatch = DELSORT_RE.exec( wikitext ); if( delsortMatch !== null ) { delsortListMatch = DELSORT_LIST_RE.exec( delsortMatch[1] ); if( delsortListMatch !== null ) { currentDelsortCategories.push( delsortListMatch[1] ); var delsortOption = document.querySelector( "option.delsort-category[value='" + delsortListMatch[1] + "']" ); if( delsortOption ) { delsortOption.selected = true; } } } } while( delsortMatch ); // Now that we've updated the underlying <select>, ask Chosen to // update the visible search box $( "#delsort select" ).trigger( "chosen:updated" ); } ); // end getWikitext } ); // end delsortCategoriesPromise // Initialize the special chosen.js select box // (some code stolen from http://stackoverflow.com/a/27445788) $( "#delsort select" ).chosen(); $( "#delsort .chzn-container" ).css( "text-align", "left" ); // Add the button that triggers sorting $( "#delsort" ).append( $( "<div>" ) .css( "text-align", "center" ) .append( $( "<button> ") .addClass( "mw-ui-button" ) .addClass( "mw-ui-progressive" ) .attr( "id", "sort-button" ) .text( "Save changes" ) .click( function () { // Make a status list $( "#delsort" ).append( $( "<ul> ") .attr( "id", "status" ) ); // Build a list of categories var categories = $( "#delsort select" ).val() || []; $( ".custom-delsort-field" ).each( function ( index, element ) { categories.push( $( element ).val() ); } ); categories = categories.filter( Boolean ); // remove empty strings categories = removeDups( categories ); // Only allow categories that aren't already there categories = categories.filter( function ( elem ) { return currentDelsortCategories.indexOf( elem ) < 0; } ); // Obtain the target AFDC category, brought to you by http://stackoverflow.com/a/24886483/1757964 var afdcTarget = document.querySelector("input[name='afdc']:checked").value; // Actually do the delsort saveChanges( categories, afdcTarget ); } ) ) ); } ); } // End if ( mw.config.get( "wgPageName" ).indexOf('Wikipedia:Articles_for_deletion/') ... ) /* * Autofills the AFDC radio button group based on the current * page's wikitext */ function autofillAfdc( wikitext ) { var regexMatch = /REMOVE THIS TEMPLATE WHEN CLOSING THIS AfD(?:\|(.*))?}}/.exec( wikitext ); if ( regexMatch ) { var templateParameter = regexMatch[1]; if ( templateParameter ) { currentAfdcCat = templateParameter; if ( templateParameter.length === 1 ) { var currentClass = templateParameter.toLowerCase(); $( "#afdc-" + currentClass ).prop( "checked", true ); } } } } /* * Saves the changes to the current discussion page by adding delsort notices (if applicable) and updating the AFDC cat */ function saveChanges( cats, afdcTarget ) { var changingAfdcCat = currentAfdcCat.toLowerCase() !== afdcTarget; // Indicate to the user that we're doing some deletion sorting $( "#delsort-table" ).remove(); $( "#delsort #sort-button" ) .text( "Sorting " + ( changingAfdcCat ? "and categorizing " : "" ) + "discussion..." ) .prop( "disabled", true ) .fadeOut( 400, function () { $( this ).remove(); } ); var categoryTitleComponent = ( cats.length === 1 ) ? ( "the \"" + cats[0] + "\" category" ) : ( cats.length + " categories" ); var afdcTitleComponent = changingAfdcCat ? " and categorizing it as " + afdcCategories[ afdcTarget ] : ""; $( "#delsort-title" ) .html( "Sorting discussion into " + categoryTitleComponent + afdcTitleComponent + "<span id=\"delsort-dots\"></span>" ); // Start the animation, using super-advanced techniques var animationInterval = setInterval( function () { $( "#delsort-dots" ).text( $( "#delsort-dots" ).text() + "." ); if( $( "#delsort-dots" ).text().length > 3 ) { $( "#delsort-dots" ).text( "" ); } }, 600 ); // Place (a) notification(s) on the discussion and update its AFDC cat var editDiscussionDeferred = postDelsortNoticesAndUpdateAfdc( cats, afdcTarget ); // List the discussion at the DELSORT pages var deferreds = cats.map( listAtDelsort ); // We still have to wait for the discussion to be edited deferreds.push( editDiscussionDeferred ); // When everything's done, say something $.when.apply( $, deferreds ).then( function () { // Call the done hook if( window.delsortDoneHook ) { window.delsortDoneHook(); } // We're done! $( "#delsort-title" ) .text( "Done " + ( changingAfdcCat ? "updating the discussion's AFDC category and " : "" ) + "sorting discussion into " + categoryTitleComponent + "." ); showStatus( "<b>Done!</b> " + ( changingAfdcCat ? "The discussion's AFDC was updated and it was" : "Discussion was" ) + " sorted into " + categoryTitleComponent + ". (" ) .append( $( "<a>" ) .text( "reload" ) .attr( "href", "#" ) .click( function () { document.location.reload( true ); } ) ) .append( ")" ); clearInterval( animationInterval ); } ); } /* * Adds a new status to the status list, and returns the newly-displayed element. */ function showStatus( newStatus ) { return $( "<li>" ) .appendTo( "#delsort ul#status" ) .html( newStatus ); } /* * Adds some notices to the discussion page that this discussion was sorted. */ function postDelsortNoticesAndUpdateAfdc( cats, afdcTarget ) { var changingAfdcCat = currentAfdcCat.toLowerCase() !== afdcTarget, deferred = $.Deferred(), statusElement = showStatus( "Updating the discussion page..." ); getWikitext( mw.config.get( "wgPageName" ) ).then( function ( wikitext ) { try { statusElement.html( "Processing wikitext..." ); // Process wikitext // First, add delsort notices wikitext += createDelsortNotices( cats ); // Then, update the AFDC category var afdcMatch = wikitext.match( /REMOVE THIS TEMPLATE WHEN CLOSING THIS AfD/ ); if ( afdcMatch && afdcMatch[ 0 ] ) { var afdcMatchIndex = wikitext.indexOf( afdcMatch[ 0 ] ) + afdcMatch[ 0 ].length, charAfterTemplateName = wikitext[ afdcMatchIndex ]; if ( charAfterTemplateName === "}" ) { wikitext = wikitext.slice( 0, afdcMatchIndex ) + "|" + afdcTarget.toUpperCase() + wikitext.slice( afdcMatchIndex ); } else if ( charAfterTemplateName === "|" ) { wikitext = wikitext.replace( "|" + currentAfdcCat + "}}", "|" + afdcTarget.toUpperCase() + "}}" ); } } statusElement.html( "Processed wikitext. Saving..." ); var catPlural = ( cats.length === 1 ) ? "" : "s"; $.ajax( { url: mw.util.wikiScript( "api" ), type: "POST", dataType: "json", data: { format: "json", action: "edit", title: mw.config.get( "wgPageName" ), summary: "Updating nomination page with notices" + ( changingAfdcCat ? " and new AFDC cat" : "" ) + ADVERTISEMENT, token: mw.user.tokens.get( "csrfToken" ), text: wikitext } } ).done ( function ( data ) { if ( data && data.edit && data.edit.result && data.edit.result == "Success" ) { statusElement.html( cats.length + " notice" + catPlural + " placed on the discussion!" ); if ( changingAfdcCat ) { if ( currentAfdcCat ) { var formattedCurrentAfdcCat = currentAfdcCat.length === 1 ? afdcCategories[ currentAfdcCat.toLowerCase() ] : currentAfdcCat; showStatus( "Discussion's AFDC category was changed from " + formattedCurrentAfdcCat + " to " + afdcCategories[ afdcTarget ] + "." ); } else { showStatus( "Discussion categorized under " + afdcCategories[ afdcTarget ] + " with AFDC." ); } } deferred.resolve(); } else { statusElement.html( "While editing the current discussion page, the edit query returned an error. =(" ); deferred.reject(); } } ).fail ( function() { statusElement.html( "While editing the current discussion page, the AJAX request failed." ); deferred.reject(); } ); } catch ( e ) { statusElement.html( "While getting the current page content, there was an error." ); console.log( "Current page content request error: " + e.message ); deferred.reject(); } } ).fail( function () { statusElement.html( "While getting the current content, there was an AJAX error." ); deferred.reject(); } ); return deferred; } /* * Turns a list of delsort categories into a number of delsort template notice substitutions. */ function createDelsortNotices( cats ) { if ( Array.isArray(cats) && ! cats.length ) return ''; var appendText = "\n{{subst:Deletion sorting/multi"; cats.forEach( function ( cat ) { appendText += "|" + cat; } ); return appendText + "|sig=~~" + "~~}}"; // string concat to prevent it from being transformed into my signature } /* * Adds a listing at the DELSORT page for the category. */ function listAtDelsort( cat ) { // Make a status element just for this category var statusElement = showStatus( "Listing this discussion at DELSORT/" + cat + "..." ); // Clarify our watchlist behavior for this edit var allowedWatchlistBehaviors = ["watch", "unwatch", "preferences", "nochange"]; var watchlistBehavior = "nochange"; // no watchlist change by default if( window.delsortWatchlist && allowedWatchlistBehaviors.indexOf( window.delsortWatchlist.toLowerCase() ) >= 0 ) { watchlistBehavior = window.delsortWatchlist.toLowerCase(); } var listTitle = "Wikipedia:WikiProject Deletion sorting/" + cat; // First, get the current wikitext for the DELSORT page return $.getJSON( mw.util.wikiScript("api"), { format: "json", action: "query", prop: "revisions", rvprop: "content", rvslots: "main", rvlimit: 1, titles: listTitle, redirects: "true", formatversion: 2, } ).then( function ( data ) { var wikitext = data.query.pages[0].revisions[0].slots.main.content; var properTitle = data.query.pages[0].title; try { statusElement.html( "Got the DELSORT/" + cat + " listing wikitext, processing..." ); // Actually edit the content to include the new listing var newDelsortContent = wikitext.replace("directly below this line -->", "directly below this line -->\n\{\{" + mw.config.get("wgPageName") + "\}\}"); // Then, replace the DELSORT listing with the new content $.ajax( { url: mw.util.wikiScript( "api" ), type: "POST", dataType: "json", data: { format: "json", action: "edit", title: properTitle, summary: "Listing [[" + mw.config.get("wgPageName") + "]]" + ADVERTISEMENT, token: mw.user.tokens.get( "csrfToken" ), text: newDelsortContent, watchlist: watchlistBehavior } } ).done ( function ( data ) { if ( data && data.edit && data.edit.result && data.edit.result == "Success" ) { statusElement.html( "Listed page at <a href=" + mw.util.getUrl( listTitle ) + ">the " + cat + " deletion sorting list</a>!" ); } else { statusElement.html( "While listing at DELSORT/" + cat + ", the edit query returned an error. =(" ); } } ).fail ( function() { statusElement.html( "While listing at DELSORT/" + cat + ", the ajax request failed." ); } ); } catch ( e ) { statusElement.html( "While getting the DELSORT/" + cat + " content, there was an error." ); console.log( "DELSORT content request error: " + e.message ); //console.log( "DELSORT content request response: " + JSON.stringify( data ) ); } } ).fail( function () { statusElement.html( "While getting the DELSORT/" + cat + " content, there was an AJAX error." ); } ); } /** * Gets the wikitext of a page with the given title (namespace required). */ function getWikitext( title ) { return $.getJSON( mw.util.wikiScript("api"), { format: "json", action: "query", prop: "revisions", rvprop: "content", rvslots: "main", rvlimit: 1, titles: title, formatversion: 2, } ).then( function ( data ) { return data.query.pages[0].revisions[0].slots.main.content; } ); } /** * Removes duplicates from an array. */ function removeDups( arr ) { var obj = {}; for( var i = 0; i < arr.length; i++ ) { obj[arr[i]] = 0; } return Object.keys( obj ); }}( jQuery, mediaWiki ) );//</nowiki>
🔥 Top keywords: Main PageSpecial:SearchPage 3Wikipedia:Featured picturesHouse of the DragonUEFA Euro 2024Bryson DeChambeauJuneteenthInside Out 2Eid al-AdhaCleopatraDeaths in 2024Merrily We Roll Along (musical)Jonathan GroffJude Bellingham.xxx77th Tony AwardsBridgertonGary PlauchéKylian MbappéDaniel RadcliffeUEFA European Championship2024 ICC Men's T20 World CupUnit 731The Boys (TV series)Rory McIlroyN'Golo KantéUEFA Euro 2020YouTubeRomelu LukakuOpinion polling for the 2024 United Kingdom general electionThe Boys season 4Romania national football teamNicola CoughlanStereophonic (play)Gene WilderErin DarkeAntoine GriezmannProject 2025