User:Enterprisey/req-helper.js
Appearance
Code that you insert on this page could contain malicious content capable of compromising your account. If you import a script from another page with "importScript", "mw.loader.load", "iusc", or "lusc", take note that this causes you to dynamically load a remote script, which could be changed by others. Editors are responsible for all edits and actions they perform, including by scripts. User scripts are not centrally supported and may malfunction or become inoperable due to software changes. A guide to help you find broken scripts is available. If you are unsure whether code you are adding to this page is safe, you can ask at the appropriate village pump. This code will be executed when previewing this page. |
This user script seems to have a documentation page at User:Enterprisey/req-helper. |
//<nowiki>
( 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 ) {
$( "<span>" )
.insertAfter( link )
.addClass( "request-actions" )
.css( "margin-left", "0.25em" )
.append( $( "<span>", { "text": "( ", "class": "action-parenthesis" } ) )
.append( $( "<a>" )
.text( "search" )
.addClass( "search-action" )
.attr( "href", "https://www.google.com/search?q=" + $( link ).text().replace( / /, "+" ) ) )
.append( $( "<span>", { "text": " | ", "class": "action-separator" } ) )
.append( $( "<a>" )
.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( $( "<span>", { "text": " )", "class": "action-parenthesis" } ) );
} ); // end action link creation loop
// Make a style element to be used by updateRequestActions
$( "#req-helper-panel" ).append( $( "<style>", { "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( "<ul></ul>" );
var addIssue = function ( issue ) { return $( "<li>" ).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( /<ref>/g ) || [] ).length;
if( refs ) {
addIssue( refs + " <ref> tag" + ( ( refs === 1 ) ? "" : "s" ) );
}
var noLinkReqs = [];
forEachRequest( function ( element ) {
if( [ "<a ", "<i>" ].indexOf( $( element ).parent().html().substring( 0, 3 ) ) === -1 ) {
//console.log( [ "<a>", "<i>" ].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( $( "<a>", { "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( "<tr><td colspan=5><ul id='req-status'></ul></td></tr>" );
var status = function ( newStatus ) { return $( "<li> ").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 + " ([[User:APerson/req-helper|req-helper]])",
text: wikitext
} ).done ( function ( data ) {
if( data && data.edit && data.edit.result && data.edit.result == 'Success' ) {
saveStatus.html( "<b>Saved page!</b> (" )
.append( $( "<a>" )
.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 ) );
//</nowiki>