//<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.wiki.x.io/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://up.wiki.x.io/wikipedia/commons/a/ad/Question_mark_grey.png";
switch( status ) {
case "d":
text = "Doesn't exist";
imageSrc = "https://up.wiki.x.io/wikipedia/commons/5/5f/Red_X.svg";
break;
case "e":
text = "Exists";
imageSrc = "https://up.wiki.x.io/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://up.wiki.x.io/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>
importScript('User:Wugapodes/Capricorn.js'); // Backlink: [[User:Wugapodes/Capricorn.js]]
importScript('User:Chlod/Scripts/Coordinator.js'); // Backlink: [[User:Chlod/Scripts/Coordinator.js]]
importScript('User:SD0001/AFC-submit-wizard.js'); // Backlink: [[User:SD0001/AFC-submit-wizard.js]]
importScript('User:SD0001/AFC-submit-wizard2.js'); // Backlink: [[User:SD0001/AFC-submit-wizard2.js]]
importScript('User:Awesome Aasim/xfdvote.js'); // Backlink: [[User:Awesome Aasim/xfdvote.js]]
importScript('User:Awesome Aasim/redirectcreator.js'); // Backlink: [[User:Awesome Aasim/redirectcreator.js]]
importScript('User:Guywan/Scripts/12HourFormat.js'); // Backlink: [[User:Guywan/Scripts/12HourFormat.js]]
importScript('User:DannyS712/RemindMe.js'); // Backlink: [[User:DannyS712/RemindMe.js]]
importScript('User:Bility/statusupdate.js'); // Backlink: [[User:Bility/statusupdate.js]]
importScript('User:LordVoldemort728/code0.js'); // Backlink: [[User:LordVoldemort728/code0.js]]
importScript('User:Evad37/OneClickArchiver.js'); // Backlink: [[User:Evad37/OneClickArchiver.js]]
importScript('User:Technical_13/Scripts/OneClickArchiver.js'); // Backlink: [[User:Technical_13/Scripts/OneClickArchiver.js]]
importScript('User:LordVoldemort728/Capricorn.js'); // Backlink: [[User:LordVoldemort728/Capricorn.js]]
importScript('User:DannyS712/copyvio-check.js'); // Backlink: [[User:DannyS712/copyvio-check.js]]
importScript('User:Lourdes/PageCuration.js'); // Backlink: [[User:Lourdes/PageCuration.js]]
importScript('User:MPGuy2824/MoveToDraft.js'); // Backlink: [[User:MPGuy2824/MoveToDraft.js]]
importScript('User:Evad37/rater.js'); // Backlink: [[User:Evad37/rater.js]]
importScript('User:Phlsph7/HighlightUnreferencedPassages.js'); // Backlink: [[User:Phlsph7/HighlightUnreferencedPassages.js]]
importScript('User:Theopolisme/Scripts/adminhighlighter.js'); // Backlink: [[User:Theopolisme/Scripts/adminhighlighter.js]]
importScript('User:Ale_jrb/Scripts/statusCheck.js'); // Backlink: [[User:Ale_jrb/Scripts/statusCheck.js]]
importScript('User:Ale jrb/Scripts/statusCheck.js'); // Backlink: [[User:Ale jrb/Scripts/statusCheck.js]]
importScript('User:Enterprisey/AFCRHS.js'); // Backlink: [[User:Enterprisey/AFCRHS.js]]
importScript('User:Novem Linguae/Scripts/ReviewStatus.js'); // Backlink: [[User:Novem Linguae/Scripts/ReviewStatus.js]]
importScript('User:Novem Linguae/Scripts/DraftCleaner.js'); // Backlink: [[User:Novem Linguae/Scripts/DraftCleaner.js]]
importScript('User:Anomie/hide-images.js'); // Backlink: [[User:Anomie/hide-images.js]]