User:Red-tailed sock/cv-revdel.js

// // Attribution: Enterprisey and Red-tailed Hawk // Licenses: CC BY-SA 3.0 unported and GFDL // License link (CC): https://creativecommons.org/licenses/by-sa/3.0/legalcode // License link (GNU): https://www.gnu.org/licenses/fdl-1.3.html

$( function {    var ADVERT = " (cv-revdel (Red-tailed hawk's version))";    var SUMMARY = "Requesting copyvio revdel" + ADVERT;    var SUMMARY_TALK = "Add note about recent copyvio" + ADVERT;    var CCLEAN_TPL = "Cclean";    var pageName; // Current page name    var urlCounter = 1;    var api;

/**    * Make a link to a given oldid of the current page. */   function makeOldidLink( oldid ) { var href = "/w/index.php?title=" + encodeURIComponent( pageName ) + "&oldid=" + oldid; var link = document.createElement( "a" ); link.href = href; link.textContent = oldid; return link; }

/**    * Add the appropriate copyvio-revdel template to the current page. */   function addCvRevdel( urls ) { var deferred = $.Deferred;

var template = "{" + "{copyvio-revdel"; template += urls.map( function ( u, idx ) {                   var num = idx == 0 ? "" : ( idx + 1 );                    return "|url" + num + "=" + u;                } ).join( "" ); var rows = document.querySelectorAll( "#cv-revdel tr" ); var num; for( var i = 1, n = rows.length; i < n; i++ ) { template += "|start" + i + "=" + rows[i].childNodes[0].textContent + ( rows[i].childNodes[2].childNodes[0].checked ? ( "|end" + i + "=" + rows[i].childNodes[1].textContent ) : "" ); }       template = template + "|CopyPatrol="+ document.getElementById("copypatrol-url0").value; template += "}}";

api.postWithToken( "csrf", {           action: "edit",            title: pageName,            summary: SUMMARY,            prependtext: template + "\n"        } ).done( function ( d ) {            if( d && d.edit && d.edit.result && d.edit.result == "Success" ) {                $( "#cv-rd-status" ).text( "Success!" );               deferred.resolve;            } else if( d && d.error ) {                $( "#cv-rd-status" ).html( "Error! Edit failed: " + d.error.info );                console.log( d );                deferred.reject;            } else {                $( "#cv-rd-status" ).html( "Error! Edit failed." );               console.log( d );                deferred.reject;            }        } ).fail( function ( code, result ) {            console.log( code, result );            if( result && result.error && result.error.spamblacklist ) {                $( "#cv-rd-status" ).html( "Error! The following URLs were on the spam blacklist: " + result.error.spamblacklist.matches.join( ", " ) + ". Consider removing the 'https://' or 'http://' from the beginning to make them not links." );           } else {                $( "#cv-rd-status" ).html( api.getErrorMessage( result ) );            }            deferred.reject;        } );

return deferred; }

function addCclean( urls ) { var deferred = $.Deferred, template = "{" + "{subst:cclean|url=" + urls.join( " " ) + "}}", talkNs = mw.config.get( "wgNamespaceNumber" ) | 1, talkNsName = mw.config.get( "wgFormattedNamespaces" )[ talkNs ], talkPage = talkNsName + ":" + mw.config.get( "wgTitle" ); api.postWithToken( "csrf", {           action: "edit",            title: talkPage,            summary: SUMMARY_TALK,            appendtext: "\n\n" + template        } ).done( function ( d ) {            if( d && d.edit && d.edit.result && d.edit.result == "Success" ) {                deferred.resolve;            } else {                deferred.reject;                console.log( d );            }        } ).fail( function ( code, result ) {            deferred.reject;            $( "#cv-rd-status" ).append( "Also, while editing " + talkPage + ", this error happened: " + api.getErrorMessage( result ) );           console.log( code, result );        } ); return deferred; }

/**    * Load the main cv-revdel panel and add buttons/other stuff to     * the history UI     */ function load( evt ) { if( evt ) evt.preventDefault;

// Don't load the panel for a second time if it's already there if( document.getElementById( "cv-revdel" ) ) return;

api = new mw.Api;

// Style for the panel mw.util.addCSS(           "#cv-revdel { border: thin solid rgb(197, 197, 197); " +            "box-shadow: 0px 3px 8px rgba(0, 0, 0, 0.25); border-radius: 3px;" +            "padding: 2em; display: inline-block }" +            "#cv-revdel table { margin: 1em 0 }" +            "#cv-revdel td { padding: 0 0.5em }" +            "#cv-revdel a.disabled {color: gray;text-decoration: line-through;font-style: italic;}" +            "#cv-rd-submit { margin-right: 1em }"+            "#cv-rd-urls input { width: 50%; min-width: 30em; }"+            "#cv-rd-urls div { margin-bottom: 0.35em; }"+            "#cv-revdel div.bottom-row { margin-top: 1em; }"+            "#cv-rd-add-range { margin-right: 0.5em; }"        );

// Add the panel itself var panel = document.createElement( "div" ); panel.id = "cv-revdel"; var urlHTML = " " + " URL: "+ "Remove " + " "+           "Add another "; var copyPatrolHTML = "  CopyPatrol URL: "; panel.innerHTML = " Instructions: Select a range of revisions using " + "the radio buttons you would normally use for comparing two " + "revisions, then click 'Add range to revdel template' to add the " + "range to the template. 'Include end?' should be unchecked to tag " + "only the single revision in the 'Start' column. Fill in URLs, and " + "then click 'Submit' to place the template. " + urlHTML + " \n\n "+ copyPatrolHTML + " " + "" + "Add to " + ( ( mw.config.get( "wgNamespaceNumber" ) % 2 ) ? "this" : "talk" ) + " page "+ " Submit " + "Close "+ " ";        document.getElementById( "bodyContent" ).insertBefore( panel,            document.getElementById( "mw-content-text" ) );

// Add range-add buttons before each of the buttons // that say "Compare selected revisions" var cmpSelRevsBtns = document.getElementsByClassName( "historysubmit" ); for( var i = 0, n = cmpSelRevsBtns.length; i < n; i++ ) { var rangeBtn = document.createElement( "button" ); rangeBtn.textContent = "Add range to revdel template"; rangeBtn.className = "mw-ui-button + mw-ui-progressive"; rangeBtn.id = "cv-rd-add-range"; cmpSelRevsBtns[i].parentNode.insertBefore( rangeBtn, cmpSelRevsBtns[i] ); rangeBtn.addEventListener( "click", function ( evt ) {               evt.preventDefault;

var oldidStart = document.querySelector( "li.selected.after" ).dataset.mwRevid; var oldidEnd = document.querySelector( "li.selected.before" ).dataset.mwRevid;

// Add new row to ranges table var rangesTable = document.getElementById( "cv-rd-ranges" ).getElementsByTagName( "tbody" )[0]; var newRow = rangesTable.insertRow( rangesTable.rows.length ); newRow.insertCell( 0 ).appendChild( makeOldidLink( oldidStart ) ); newRow.insertCell( 1 ).appendChild( makeOldidLink( oldidEnd ) ); newRow.insertCell( 2 ).innerHTML = ""; newRow.cells[2].childNodes[0].checked = true; newRow.cells[2].childNodes[0].addEventListener( "click", function {                    this.parentNode.previousElementSibling.childNodes[0].className = this.checked ? "" : "disabled";                } ); var deleteBtn = document.createElement( "button" ); deleteBtn.textContent = "Delete"; deleteBtn.className = "delete"; deleteBtn.addEventListener( "click", function {                    this.parentNode.parentNode.parentNode.removeChild( this.parentNode.parentNode );               } ); newRow.insertCell( 3 ).appendChild( deleteBtn ); } );       }

// Panel submission handler document.getElementById( "cv-rd-submit" ).addEventListener( "click", function {            $( this ).prop( "disabled", true );            $( "#cv-rd-status" ).empty;            var urls = Array.prototype.map.call( document.getElementById( "cv-rd-urls" ).children, function ( e ) { return e.children[1].value; } );           var deferreds = [ addCvRevdel( urls ) ];            if( document.getElementById( "cv-rd-cclean" ).checked ) {                deferreds.push( addCclean( urls ) );            }            $.when.apply( $, deferreds ).then( function  { // Return to content page document.querySelector( "#ca-view a" ).click; }, function { $( this ).prop( "disabled", false ); }.bind( this ) );       } );

// "Add URL" handler document.getElementById( "cv-rd-url-add" ).addEventListener( "click", function {            var numUrls = document.querySelectorAll( "#cv-rd-urls div" ).length;            if( numUrls < 3 ) {                var newDiv = document.createElement( "div" );                newDiv.innerHTML = "URL: "+                    ""+                    "Remove ";                document.getElementById( "cv-rd-urls" ).appendChild( newDiv );                urlCounter++;                this.disabled = numUrls >= 2;            }        } );

// Remove URL handler document.getElementById( "cv-rd-urls" ).addEventListener( "click", function ( e ) {           var numUrls = document.querySelectorAll( "#cv-rd-urls div" ).length;            if( e.target && e.target.nodeType === 1 && numUrls > 1 && e.target.tagName.toLowerCase === "button" ) {               this.removeChild( document.getElementById( e.target.previousElementSibling.getAttribute( "id" ) ).parentNode );                document.getElementById( "cv-rd-url-add" ).disabled = false;            }        } );

// Close handler document.getElementById( "cv-rd-close" ).addEventListener( "click", function {            $( "#cv-revdel" ).remove;            $( ".cv-rd-add-range" ).remove;        } );

document.querySelector( "#cv-rd-urls input" ).focus; }

mw.loader.using( [ "mediawiki.api", "mediawiki.util" ], function {

pageName = mw.config.get( "wgPageName" );

if( mw.config.get( "wgAction" ) == "history" ) { var link = mw.util.addPortletLink( "p-cactions", "#", "Request CV revdel", "pt-cv-revdel" ); link.addEventListener( "click", load ); if( mw.util.getParamValue( "open_cv_revdel" ) === "true" ) { load; }       } else if( mw.config.get( "wgNamespaceNumber" ) >= 0 ) { var historyPage = mw.util.getUrl( pageName, { "action": "history", "open_cv_revdel": "true" } ); var link = mw.util.addPortletLink( "p-cactions", historyPage, "Request CV revdel", "pt-cv-revdel" ); }   } ); } ); //