User:DannyS712/DiscussionCloser.js/sandbox.js

// // Script to make closing discussions easier // @author DannyS712 // based on a script by Abelmoschus Esculentus, but completely rewritten from scratch /* jshint maxerr: 999 */ $( => { var DiscussionCloser = {}; window.DiscussionCloser = DiscussionCloser;

DiscussionCloser.config = { version: 'DEV', debug: true };

DiscussionCloser.init = function { mw.loader.using(		[ 'mediawiki.util', 'mediawiki.api' ],		DiscussionCloser.run	); };

DiscussionCloser.debug = function { if ( DiscussionCloser.config.debug ) { console.log.apply( null, arguments ); } };

DiscussionCloser.run = function { DiscussionCloser.debug( 'Starting DiscussionCloser' ); DiscussionCloser.addCSS; DiscussionCloser.addFakeLinks; };

DiscussionCloser.onErrHandler = function { // Shared error handler alert( 'Something went wrong' ); console.log.apply( null, arguments ); };

DiscussionCloser.addCSS = function { mw.util.addCSS(`	position: fixed;	z-index: 1;	left: 0;	top: 0;	width: 100%;	height: 100%;	overflow: hidden;	background-color: rgba(0,0,0,0.4); }	background-color: #d6d6d6;	margin: 10% auto;	padding: 2px 20px;	border: 1px solid #888;	width: 80%;	max-width: 60em;	font-size: 90%; }	min-height: 7em;	width: 875px;	height: 400px;	overflow-y: scroll; }	min-height: 3em; } .DiscussionCloser-bottom {	margin-bottom: 0.5em; }	background-color: white; }	display: none; }
 * 1) DiscussionCloser-wrapper {
 * 1) DiscussionCloser-interface {
 * 1) DiscussionCloser-interface-body {
 * 1) DiscussionCloser-interface-footer {
 * 1) DiscussionCloser-preview-raw {
 * 1) DiscussionCloser-preview-raw span.mw-editsection {

input[name=DiscussionCloser-radios] { margin-left: 7px; margin-right: 2px; } `); };

DiscussionCloser.addFakeLinks = function { var $sectionHeadings = $( '#mw-content-text' ).find( 'h1,h2,h3,h4,h5,h6' ); var SECTION_FROM_URL_REGEX = /&section=(\d+)/; $sectionHeadings.each( function ( idx, header ) {		var $editSection = $( header ).find( '.mw-editsection' );		// console.log( $editSection );		var editLinkURL = $editSection.children( 'a:first' ).attr( 'href' );		// console.log( editLinkURL );		var sectionNum = SECTION_FROM_URL_REGEX.exec( editLinkURL );		if ( sectionNum === null ) {			// Something went wrong			return;		}		sectionNum = parseInt( sectionNum[1] );		// console.log( sectionNum );		var $closeBracket = $editSection.children.last;		// console.log( $closeBracket );		$closeBracket.before( " | ",			$( ' ' ).append(				$( '' )					.text( 'Close discussion' )					.click( function { console.log( 'Closing discussion for section number: ' + sectionNum ); console.log( $( this ) ); DiscussionCloser.getSectionContent( sectionNum ).then(							function ( currentContent ) {								console.log( currentContent );								DiscussionCloser.showForSection( sectionNum, currentContent );							}						); } )			)		);	} ); };

DiscussionCloser.showForSection = function ( sectionNum, currentContent ) { $( 'body' ).prepend( DiscussionCloser.addInterface( sectionNum, currentContent ) ); document.getElementById( 'DiscussionCloser-interface' ).addEventListener(		'keydown',		function ( key ) {			if ( key.ctrlKey && ( key.keyCode == 10 || key.keyCode == 13 ) ) {				document.getElementById( 'DiscussionCloser-submit' ).click;			} else if ( key.keyCode == 27 ) {				document.getElementById( 'DiscussionCloser-cancel' ).click;			}		}	); };

DiscussionCloser.getTemplateInfo = function ( template ) { // object with // - `supportsStatus` (bool) // - `topText` (string including %RESULT% and optionally %STATUS% ) // - `bottomText` (string) // - `label` (string to show in the interface) var templateInfo = { ArchiveTop: { supportsStatus: true, topText: '', bottomText: '', label: 'Generic archive' },		ArchiveTopRed: { supportsStatus: true, topText: '', bottomText: '', label: 'Generic (red)' },		ArchiveTopYellow: { supportsStatus: true, topText: '', bottomText: '', label: 'Generic (yellow)' },		ArchiveTopGreen: { supportsStatus: true, topText: '', bottomText: '', label: 'Generic (green)' },		ClosedRFCTop: { supportsStatus: false, topText: '', bottomText: '', label: 'Closed RFC' },		RequestedMove: { supportsStatus: false, topText: '', bottomText: '', label: 'Closed RM' },		HiddenArchive: { supportsStatus: false, topText: '', bottomText: '', label: 'Hidden archive' }	};	if ( template === false ) { return templateInfo; }	return templateInfo[ template ]; };

DiscussionCloser.onTopTemplateChange = function ( newTemplate ) { var $statusInput = $( '#DiscussionCloser-status-text' ); if ( DiscussionCloser.getTemplateInfo( newTemplate ).supportsStatus ) { $statusInput.prop( 'disabled', false ); } else { $statusInput.prop( 'disabled', true ); } };

DiscussionCloser.addPreview = function ( sectionNum, currentContent ) { var newText = DiscussionCloser.getNewSectionText( sectionNum, currentContent ); new mw.Api.get( {		action: 'parse',		title: mw.config.get( 'wgPageName' ),		text: newText,		prop: 'text',		pst: '1',		formatversion: 2	} ).then(		function ( result ) {			// console.log( result );			var parsedText = result.parse.text;			$( '#DiscussionCloser-preview-raw' ).html( parsedText );			$( '#DiscussionCloser-preview-wrapper' ).show;		},		DiscussionCloser.onErrHandler	); };

DiscussionCloser.hidePreview = function { $( '#DiscussionCloser-preview-wrapper' ).hide; };

DiscussionCloser.closeDiscussion = function ( sectionNum, currentContent ) { console.log( 'Should try and close discussion now' ); var newText = DiscussionCloser.getNewSectionText( sectionNum, currentContent ); var summary = DiscussionCloser.getEditSummary( currentContent ); var editParams = { action: 'edit', title: mw.config.get( 'wgPageName' ), section: sectionNum, text: newText, summary: summary, notminor: true, nocreate: true, format: 'json', formatversion: 2 };	// console.log( editParams ); new mw.Api.postWithEditToken( editParams ).then(		function ( response ) {			console.log( response );			DiscussionCloser.afterCloseEdit( response );		},		DiscussionCloser.onErrHandler	); };

DiscussionCloser.afterCloseEdit = function ( response ) { if ( response && response.edit && response.edit.result && response.edit.result === 'Success' ) { // Edit succeeded alert( 'Edit saved!' ); $( '#DiscussionCloser-wrapper' ).remove; return; }	alert( 'Something might have gone wrong' ); };

DiscussionCloser.getEditSummary = function ( currentContent ) { // Either `/* sectionName */ ` or an empty string, for the start of the edit summary var maybeMatch = currentContent.match( /^=+\s*(.*?)\s*=/ ); var sectionName = ''; if ( maybeMatch !== null ) { sectionName = '/* ' + maybeMatch[1] + ' */ '; }	var userInputSummary = $( '#DiscussionCloser-edit-summary' ).val; if ( userInputSummary === '' ) { // default userInputSummary = 'Closing discussion'; }	var fullSummary = sectionName + userInputSummary + ' (with DiscussionCloser ' + DiscussionCloser.config.version + ')'; return fullSummary; };

DiscussionCloser.getNewSectionText = function ( sectionNum, currentContent ) { var closeTemplate = $( 'input[name="DiscussionCloser-radios"]:checked' ).attr( 'value' ); var closeTemplateInfo = DiscussionCloser.getTemplateInfo( closeTemplate ); var topText = closeTemplateInfo.topText; if ( closeTemplateInfo.supportsStatus ) { topText = topText.replace(			'%STATUS%',			$( '#DiscussionCloser-status-text' ).val		); }	topText = topText.replace(		'%RESULT%',		$( '#DiscussionCloser-result-text' ).val	); var newText = currentContent.replace(		/^(=.*?=\n)/,		'$1\n' + topText + '\n\n'	); newText = newText + '\n\n' + closeTemplateInfo.bottomText; // console.log( newText ); return newText; };

DiscussionCloser.getSectionContent = function ( sectionNum ) { return new Promise( function ( resolve ) {		new mw.Api.get( { action: 'query', prop: 'revisions', rvprop: 'content', rvslots: '*', rvsection: sectionNum, titles: mw.config.get( 'wgPageName' ), format: 'json', formatversion: 2 } ).then( function ( response ) { console.log( response ); var currentContent = response.query.pages[0].revisions[0].slots.main.content; resolve( currentContent ); },			DiscussionCloser.onErrHandler );	} ); };

DiscussionCloser.addInterface = function ( sectionNum, currentContent ) { var $header = $( ' ' ) .attr( 'id', 'DiscussionCloser-interface-header' ) .text( 'DiscussionCloser' ); var $body = $( ' ' ) .attr( 'id', 'DiscussionCloser-interface-body' ); var $footer = $( ' ' ) .attr( 'id', 'DiscussionCloser-interface-footer' ); var $interface = $( ' ' ) .attr( 'id', 'DiscussionCloser-interface' ) .append(			$header,			$( ' ' ),			$body,			$( ' ' ),			$footer		); var $wrapper = $( ' ' ) .attr( 'id', 'DiscussionCloser-wrapper' ) .append( $interface ); // Body content var $templateOptions = $( ' ' ) .addClass( 'DiscussionCloser-bottom' ) .append(			$( ' ' ).text( 'Options: ' ),			$( ' ' )				.attr( 'type', 'radio' )				.attr( 'name', 'DiscussionCloser-radios' )				.attr( 'value', 'ArchiveTop' )				.attr( 'checked', 'true' ),			$( ' ' ).text( 'Generic' )		); var allTemplates = DiscussionCloser.getTemplateInfo( false ); Object.keys( allTemplates ).forEach(		function ( templateName ) {			if ( templateName !== 'ArchiveTop' ) {				$templateOptions.append( $( ' ' )						.attr( 'type', 'radio' ) .attr( 'name', 'DiscussionCloser-radios' ) .attr( 'value', templateName ), $( ' ' ).text( allTemplates[templateName].label ) );			}		}	);	$templateOptions.children( 'input' ).on( 'change', function {		// console.log( 'Selection changed' );		// console.log( this );		DiscussionCloser.onTopTemplateChange( $( this ).attr( 'value' ) );	} ); var $optionalStatus = $( ' ' ) .addClass( 'DiscussionCloser-bottom' ) .append(			$( ' ' ).text( 'Status (optional): ' ),			$( ' ' )				.attr( 'id', 'DiscussionCloser-status-text' )				.attr( 'type', 'text' )		); var $closingComment = $( ' ' ) .addClass( 'DiscussionCloser-bottom' ) .append(			$( ' ' ).text( 'Discussion result' ),			$( ' ' )				.attr( 'id', 'DiscussionCloser-result-text' )				.attr( 'rows', 15 )				.css( 'resize', 'none' )		); var $editSummary = $( ' ' ) .addClass( 'DiscussionCloser-bottom' ) .append(			$( ' ' ).text( 'Edit summary ("Closing discussion" if left blank): ' ),			$( ' ' )				.attr( 'id', 'DiscussionCloser-edit-summary' )				.attr( 'type', 'text' )		); var $hidePreview = $( ' ' ) .attr( 'id', 'DiscussionCloser-preview-hide' ) .text( 'Hide preview' ); $hidePreview.click( DiscussionCloser.hidePreview ); var $previewDisplay = $( ' ' ) .attr( 'id', 'DiscussionCloser-preview-wrapper' ) .addClass( 'DiscussionCloser-bottom' ) .append(			$( ' ' ).text( 'Preview:' ),			$( ' ' ).attr( 'id', 'DiscussionCloser-preview-raw' ),			$hidePreview		); $previewDisplay.hide; $body.append( $templateOptions, $optionalStatus, $closingComment, $editSummary, $previewDisplay ); // Footer buttons var $submit = $( ' ' ) .attr( 'id', 'DiscussionCloser-submit' ) .text( 'Close discussion' ); var $preview = $( ' ' ) .attr( 'id', 'DiscussionCloser-preview' ) .text( 'View preview' ); var $cancel = $( ' ' ) .attr( 'id', 'DiscussionCloser-cancel' ) .text( 'Cancel' ); $footer.append( $submit, $preview, $cancel ); // console.log( 'currentContent is: ' + currentContent ); $submit.click( function {		// console.log( 'currentContent is: ' + currentContent );		DiscussionCloser.closeDiscussion( sectionNum, currentContent );	} ); $preview.click( function {		// console.log( 'currentContent is: ' + currentContent );		DiscussionCloser.addPreview( sectionNum, currentContent );	} ); $cancel.click( function {		// Can't just $wrapper.remove since at this point it isn't added yet		$( this ).parents( '#DiscussionCloser-wrapper' ).remove;	} ); return $wrapper; };

});

$( document ).ready( function {	var mwConfig = mw.config.get( [ 'wgAction', 'wgPageName' ] );	if ( mwConfig.wgAction !== 'view' ) {		return;	}	if ( $( '#ca-addsection' ).length > 0 || mwConfig.wgPageName == 'Wikipedia:Administrators\'_noticeboard/Edit_warring' || mwConfig.wgPageName == 'Wikipedia:In_the_news/Candidates' ) {		DiscussionCloser.init;	} } );

//