注意:儲存之後,你可能要兜過你嘅瀏覽器快取至睇到更改。Internet Explorer: 撳住Ctrl掣再撳重新整理掣。 Firefox: 撳住Shift掣再撳重新載入(又或者撳Ctrl-Shift-R)。 Google Chrome同埋Safari用戶就噉撳個重載掣。
// If TwinkleConfig aint exist.
if( typeof( TwinkleConfig ) == 'undefined' ) {
	TwinkleConfig = {};
}

/**
 TwinkleConfig.summaryAd (string)
 If ad should be added or not to summary, default [[WP:TWINKLE|TWINKLE]]
 */
if( typeof( TwinkleConfig.summaryAd ) == 'undefined' ) {
	TwinkleConfig.summaryAd = " using [[WP:TWINKLE|TW]]";
}

/**
 TwinkleConfig.watchProdPages (boolean)
 If, when applying prod template to page, watch it, default true
 */
if( typeof( TwinkleConfig.watchProdPages ) == 'undefined' ) {
	TwinkleConfig.watchProdPages = true;
}

function twinkleprod() {
	if( wgNamespaceNumber != 0 || wgCurRevisionId == false ) {
		return;
	}
	mw.util.addPortletLink( 'p-cactions', "javascript:twinkleprod.callback()", "prod", "tw-prod", "Propose deletion via WP:PROD", "");
}
$(twinkleprod);

twinkleprod.callback = function twinkleprodCallback() {
	var Window = new SimpleWindow( 800, 400 );
	Window.setTitle( "WP:PROD" );
	var form = new QuickForm( twinkleprod.callback.evaluate );
	var field = form.append( {
			type: 'field',
			label: 'Reason for proposed deletion'
		} );
	field.append( {
			type: 'textarea',
			name: 'reason',
			label: 'Reason:'
		} );
	field.append( { type:'submit' } );

	var result = form.render();
	Window.setContent( result );
	Window.display();
}

twinkleprod.callback.evaluate = function twinkleprodCallbackEvaluate(e) {
	var form = e.target;
	var reason = form.reason.value;

	wgPageName = wgPageName.replace(/_/g, ' ');

	Status.init( form );
	Status.status( 'checking if article already is proposed for deletion...' );

	var xmlhttp = sajax_init_object();
	xmlhttp.query = {
		'title': wgPageName,
		'action': 'submit'
	};
	xmlhttp.reason = reason;
	xmlhttp.overrideMimeType('text/xml');
	xmlhttp.open( 'GET' , mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/index.php?' + QueryString.create( xmlhttp.query ), true);
	xmlhttp.onload = function() {
		var form = this.responseXML.getElementById('editform');
		var text = form.wpTextbox1.value;

		var tag_re = /(\{\{(?:db-?|delete|[aitcmrs]fd|md1)[^{}]*?\|?[^{}]*?\}\})/;

		if( tag_re.test( text ) ) {
			Status.warn( 'Page already tagged with a deletion template, aborting procedure' );
			return;
		}
		Status.info( 'no tag found, proceeding to tag' );
		var postData = {
			'wpMinoredit': undefined, // Per memo
			'wpWatchthis': form.wpWatchthis.checked ? '' : undefined,
			'wpStarttime': form.wpStarttime.value,
			'wpEdittime': form.wpEdittime.value,
			'wpAutoSummary': form.wpAutoSummary.value,
			'wpEditToken': form.wpEditToken.value,
			'wpSummary': "Proposing article for deletion per [[WP:PROD]]." + TwinkleConfig.summaryAd,
			'wpTextbox1': "\{\{subst:prod|1=" + this.reason + "}}\n" + text
		};
		var xmlhttp = sajax_init_object();
		xmlhttp.overrideMimeType('text/xml');
		xmlhttp.open( 'POST' , mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/index.php?' + QueryString.create( this.query ), true);
		xmlhttp.setRequestHeader('Content-type','application/x-www-form-urlencoded');
		xmlhttp.onload = function() { Status.info( 'Article tagged.' );}
		xmlhttp.send( QueryString.create( postData ) );

		Status.status( 'Getting data for first contributor...' );

		var xmlhttp = sajax_init_object();
		xmlhttp.query = {
			'action': 'query',
			'prop': 'revisions',
			'titles': wgPageName,
			'rvlimit': 1,
			'rvprop': 'user',
			'rvdir': 'newer',
			'format': 'xml'
		}
		xmlhttp.overrideMimeType('text/xml');
		xmlhttp.open( 'GET' , mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/api.php?' + QueryString.create( xmlhttp.query ), true );
		xmlhttp.onload = function() {
			var user = this.responseXML.documentElement.getElementsByTagName('rev')[0].getAttribute('user');
			Status.info( 'found user ' + user + ' as first contributor, proceeding to notify user...' );

			var xmlhttp = sajax_init_object();
			xmlhttp.query = {
				'title': 'User talk:' + user,
				'action': 'submit'
			};
			xmlhttp.params = this.params;
			xmlhttp.overrideMimeType('text/xml');
			xmlhttp.open( 'GET' , mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/index.php?' + QueryString.create( xmlhttp.query ), true );
			xmlhttp.onload = function() {
				var form = this.responseXML.getElementById( 'editform' );
				var text = form.wpTextbox1.value;
				text += "\n\{\{subst:PRODWarning|1=" + wgPageName + "\}\} \~\~\~\~";
				var postData = {
					'wpMinoredit': form.wpMinoredit.checked ? '' : undefined,
					'wpWatchthis': form.wpWatchthis.checked ? '' : undefined,
					'wpStarttime': form.wpStarttime.value,
					'wpEdittime': form.wpEdittime.value,
					'wpAutoSummary': form.wpAutoSummary.value,
					'wpEditToken': form.wpEditToken.value,
					'wpSummary': 'PROD nomination of \[\[' + wgPageName + '\]\].' + TwinkleConfig.summaryAd,
					'wpTextbox1': text
				};
				var xmlhttp = sajax_init_object();
				xmlhttp.overrideMimeType('text/xml');
				xmlhttp.open( 'POST' , mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/index.php?' + QueryString.create( this.query ), true);
				xmlhttp.setRequestHeader('Content-type','application/x-www-form-urlencoded');
				xmlhttp.onload = function() { Status.info( 'User notification complete.' );}
				xmlhttp.send( QueryString.create( postData ) );

			}
			xmlhttp.send( null );
		}
		xmlhttp.send( null );
	}
	xmlhttp.send( null );
}