Usuário:Tonelada/Testes/MediaWiki:Gadget-fastbuttons.js

Nota: Depois de publicar, poderá ter de contornar a cache do seu navegador para ver as alterações.

  • Firefox / Safari: Pressione Shift enquanto clica Recarregar, ou pressione Ctrl-F5 ou Ctrl-R (⌘-R no Mac)
  • Google Chrome: Pressione Ctrl-Shift-R (⌘-Shift-R no Mac)
  • Internet Explorer / Edge: Pressione Ctrl enquanto clica Recarregar, ou pressione Ctrl-F5
  • Opera: Pressione Ctrl-F5.
/*!
 * FastButtons
 *
 * @author [[es:User:Racso]] (versão original do script, na Wikipédia em espanhol)
 * @author [[en:User:Macy]] (versão adaptada para a Wikipédia inglesa)
 * @author [[pt:User:Danilo.mac]]
 * @author [[pt:User:Helder.wiki]]
 * @author [[pt:User:!Silent]]
 * @source [[en:User:Macy/FastButtons.js]] ([[en:Special:PermaLink/230473471]])
 * @source [[es:Special:PrefixIndex/User:Racso/FB]]
 * @see [[MediaWiki:Gadget-fastbuttons.js/buttonsList.js]]
 * @help [[WP:Scripts/FastButtons]]
 */
/* jshint laxbreak: true, unused: true, newcap: false */
/* global mediaWiki, jQuery, wikEd, WikEdUpdateFrame */
 
( function( mw, $, window ) {
'use strict';
 
var fb,
	api = new mw.Api();
 
/**
 * @class FastButtons
 */
function FastButtons() {
	/**
	 * Timestamp of the current version
	 * @property {string} version
	 */
	this.version = /*{{subst:Autossubstituição/Estampa com data e hora|js|.*/ '2020-10-08 10:01:41 (UTC)' /*}}.*/;
 
	/**
	 * List of buttons
	 * @property {object}
	 */
	this.buttons = {};
 
	/**
	 * Target for insertion of menu buttons
	 * @property {jQuery}
	 */
	this.$menu = $( '<div id="fb-menu"></div>' );
 
	/**
	 * Target for insertion of submenu buttons
	 * @property {jQuery}
	 */
	this.$submenu = $( '<div id="fb-submenu"></div>' );
 
	/**
	 * Target for insertion of page information
	 * @property {jQuery}
	 */
	this.$pageInfo = $( '<span id="fb-pageInfo"></span>' );
}
 
/**
 * Public
 */
FastButtons.prototype = {
	/**
	 * Messages
	 * @see [[mw:ResourceLoader/Default_modules#mediaWiki.message]]
	 * @return {string}
	 */
	message: function( /*name[, $1[, $2[, ... $N ]]]*/ ) {
		return mw.message.apply( this, arguments ).plain();
	},
 
	/**
	 * Open a prompt
	 *
	 * @param name Name of prompt
	 */
	openPrompt: function( name/*[, extraArg[, extraArg2[, extraArg3[, ... extraArgN ]]]]*/ ) {
		new fb.Prompt( name ).open.apply( undefined, arguments );
	},
 
	/**
	 * Edit a page
	 *
	 * @param {object} info Edit info
	 * @see [[mw:API:Edit]] and [[w:pt:MediaWiki:Gadget-mediawiki.api.ptwiki.js]]
	 * @return {jQuery.Deferred}
	 */
	editPage: function( info ) {
		info.done = {
			success: info.done,
			apiError: function( error ) {
				fb.notify(
					$.parseHTML(
						fb.message( 'fb-notify-apiErrorEdit', error.code, error.info ) + fb.message( 'fb-notify-errorSufix' )
					)
				);
			},
			unknownError: function() {
				fb.notify(
					$.parseHTML(
						fb.message( 'fb-notify-editFail' ) + fb.message( 'fb-notify-errorSufix' )
					)
				);
			}
		};
 
		return api.editPage( info );
	},
 
	/**
	 * Notifications
	 *
	 * @param {string} text Notification text
	 * @param {mw.notification.defaults} [options] Additional options of notification
	 * @see [[mw:ResourceLoader/Default modules#mw.notify]]
	 * @return {jQuery.Promise}
	 */
	notify: function( text, options ) {
		var optionsDefault = {
			title: fb.message( 'fb-notify-title' ),
			autoHide: false
		};
 
		if ( $.isPlainObject( options ) ) {
			$.extend( optionsDefault, options );
		}
 
		return mw.notify( text, optionsDefault );
	},
 
	/**
	 * Refresh or submit an edit (in edit page) the pages
	 *
	 * @param {string} [code] Only if action === 'move' or 'redirect'
	 * @param {string} [url] url
	 */
	refreshPage: function( code, url ) {
		if ( typeof localStorage !== 'undefined' ) {
			localStorage[ 'fb-success' ] = ( code === 'move' ) ? 'move' : 'edit';
		}
 
		if ( fb.action === 'view' ) {
			location.href = mw.util.getUrl( url ) + ( ( code === 'redirect' ) ? '?redirect=no' : '' );
		} else if ( $.inArray( fb.action, [ 'edit', 'submit' ] ) !== -1 ) {
			$( '#editform' ).unbind( 'submit' ).trigger( 'submit' );
		}
	},
 
	/**
	 * Creates a dialog
	 *
	 * @param {jQuery.dialog} info Dialog info
	 * @return {jQuery}
	 */
	dialog: function( info ) {
		var $fbDialog = $( '<div id="fb-dialog" class="ui-widget"></div>' ).append( info.content );
 
		if ( $( '#fb-dialog' ).length ) {
			$( '#fb-dialog' ).dialog( 'close' );
		}
 
		if ( !info.modal ) {
			info.modal = true;
		}
 
		$.extend( info, {
			title: fb.message( 'fb-dialog-titlePrefix' ) + ( info.title ? ' - ' + info.title : '' ),
			open: function() {
				$( '.ui-dialog-titlebar-close' ).hide();
			},
			close: function() {
				$fbDialog.dialog( 'destroy' ).remove();
			}
		} );
 
		return $fbDialog.dialog( info );
	},
 
	/**
	 * Changes the content of the submenu
	 *
	 * @param {string} items The new buttons for the new submenu
	 * @param {boolean} append Appends in submenu instead of replace all content
	 * @param {number|number[]} [justEnable] If needs include only some buttons of the list.
	 *  The numbers are the index in the array of buttons ("items" param).
	 *     @example
	 *     fb.changeSubmenu(
	 *         fb.buttons.maintenance,
	 *         false,
	 *         [ 14, 16, 20 ]
	 *     );
	 * @return {jQuery}
	 */
	changeSubmenu: function( list, append, justEnable ) {
		var item,
			i = 0;
 
		$( '.tipsy' ).remove();
 
		if ( !append ) {
			fb.$submenu.empty().show();
		}
 
		if ( !$.isArray( list ) ) {
			list = [ list ];
		}
 
		if ( justEnable && !$.isArray( justEnable ) ) {
			justEnable = [ justEnable ];
		}
 
		while ( i < list.length ) {
			item = list[ i++ ];
 
			if ( $.isFunction( item ) ) {
				item();
			} else if ( ( typeof item === 'string' ) || ( item instanceof jQuery ) ) {
				fb.$submenu.append( item );
			} else {
				if ( justEnable && $.inArray( i, justEnable ) === -1 ) {
					item.disable = true;
				}
 
				fb.addButton( fb.$submenu, item );
			}
		}
 
		return fb.$submenu.find( 'a, span' ).tipsy( {
			html: true
		} );
	},
 
	/**
	 * Appends content in submenu
	 *
	 * @see this.changeSubmenu
	 */
	appendSubmenu: function( items ) {
		return fb.changeSubmenu( items, true );
	},
 
	/**
	 * Edit function
	 *
	 * @param {string} code A template name, possibly preceded by "subst:" and optionally followed by "|" and some parameter(s)
	 *     @example
	 *     "não remova"or "subst:ER|5" or "subst:ESR-matrad|1=~~' + '~~|língua='"
	 *
	 * @param {string|null} [extraText] Extra text for templates and redirects
	 * @param {string} [sum] Summary of edit
	 * @param {boolean} [warn]
	 * @return {jQuery.Deferred}
	 */
	run: function( code, extraText, sum, warn ) {
		var rcid,
			apiDeferred = $.Deferred();
 
		if ( $.inArray( fb.action, [ 'edit', 'submit' ] ) !== -1 ) {
			fb.manipulateTextPage( code, extraText, sum, $( '#wpTextbox1' ).val(), true, warn );
		} else if ( fb.action === 'view' ) {
			rcid = mw.util.getParamValue(
				'rcid',
				mw.util.$content.find( 'div.patrollink a' ).attr( 'href' ) || ''
			);
 
			if ( rcid ) {
				fb.notify( fb.message( 'fb-notify-patrollingPage' ) );
				fb.callAPI( 'patrolPage' );
			}
 
			fb.notify( fb.message( 'fb-notify-getPageContent' ) );
 
			api.getCurrentPageText().done( function( value ) {
				fb.manipulateTextPage( code, extraText, sum, value, false, warn ).done( function() {
					apiDeferred.resolve();
				} );
			} );
		}
 
		return apiDeferred.promise();
	}
};
 
/**
 * Create new button links
 *
 * @param {jQuery|Array|Object} $target A jQuery object representing the target or
 *  an object representing a button (see 'buttons' param below) or
 *  an Array of this kind of objects
 *  (Defaults to fb.$menu if it is not an instance of jQuery)
 * @param buttons {Object} Button atributes and others informations of the new button
 * @param buttons.action {string|Function}
 * @param buttons.text {string}
 * @param buttons.title {string}
 * @param [buttons.sum] {string}
 * @param [buttons.label] {string}
 * @param [buttons.prompt] {string}
 * @param [buttons.disable] {boolean}
 * @param [buttons.after] {string}
 * @param [buttons.warn] {boolean}
 * @param [buttons.type] {string}
 */
FastButtons.prototype.addButton = function( $target, buttons ) {
	var comment, props, button,
		i = 0,
		doNothing = function( event ) {
			event.preventDefault();
		},
		buttonClick = function( btn ) {
			return function( event ) {
				var question = ( typeof btn.action === 'string' && btn.action.substr( 0, 2 ) === 'ER' )
					? fb.message( 'fb-dialog-note' )
					: btn.prompt,
					promptCallback = function( comment ) {
						if ( $.isFunction( btn.action ) ) {
							btn.action();
						} else {
							fb.run( btn.action, comment, btn.sum, btn.warn );
						}
					};
 
				doNothing( event );
 
				if ( $( this ).parent().attr( 'id' ) === 'fb-menu' ) {
					$( '.fb-menu-open' ).removeClass( 'fb-menu-open' );
				}
 
				if ( fb.textButton === 'Informações sobre a página'
					&& fb.$submenu.text().indexOf( fb.message( 'fb-loading' ) ) !== -1
				) {
					fb.notShowInfo = true;
				}
 
				if ( fb.$submenu.text() !== fb.message( 'fb-loading' )
					&& typeof btn.action !== 'string'
					&& ( fb.textButton === btn.text
						&& $.inArray( fb.textButton, [ 'Semirrápida', 'Consenso', 'Mover' ] ) === -1
					) || ( btn.text === 'Eliminação'
						&& $.inArray( fb.textButton, [ 'Semirrápida', 'Consenso', 'VDA', 'Suspeito de VDA' ] ) !== -1
					)
				) {
					fb.textButton = '';
 
					return fb.$submenu.empty().hide();
				}
 
				if ( fb.$submenu.html() !== ''
					&& ( typeof btn.action === 'string' && $.inArray( btn.text, [ 'Eliminação', '#R', 'ER1' ] ) !== -1 )
				) {
					fb.$submenu.empty().hide();
				}
 
				if ( question ) {
					comment = fb.openPrompt( 'defaultPrompt', question, btn.label, promptCallback );
				} else {
					promptCallback( comment );
				}
 
				if ( $.isFunction( btn.action ) ) {
					fb.textButton = btn.text;
				}
 
				if ( $.isFunction( btn.action ) && $.inArray( btn.text, [ 'Semirrápida', 'Consenso' ] ) === -1 ) {
					$( this ).addClass( 'fb-menu-open' );
				}
			};
		};
 
	if ( !$target.jquery ) {
		//if $target is not an instance of jQuery, use it as 'buttons'
		buttons = $target;
		$target = fb.$menu;
	}
 
	if ( !$.isArray( buttons ) ) {
		buttons = [ buttons ];
	}
 
	while ( i < buttons.length ) {
		button = buttons[ i++ ];
		props = {
			'title': button.title,
			'text': button.text,
			'class': 'fb-button '
		};
 
		if ( button.disable ) {
			props[ 'class' ] += 'fb-disabled-button';
			props.click = doNothing;
			props.title = '';
		} else {
			props[ 'class' ] += 'fb-' + ( button.type || ( $.isFunction( button.action )
				? 'menu'
				: 'action' )
			) + '-button';
			props.click = buttonClick( button );
		}
 
		if ( button.after && $( '.fb-button' ).length ) {
			$( '.fb-button' ).eq( button.after ).after( $( '<a></a>', props ), '' );
		} else {
			$target.append( $( '<a></a>', props ), ' ' );
		}
	}
};
 
/**
 * API calls
 *
 * @param {string} code Type of request. See "this.ProcessAPI"
 * @param {string} [extra] Used only when "code" param is:
 *	"pageQuality" -> Can be 'noCallback' or 'noBeforeRequest' or
 *	"requestDeletion" -> Can be "true" (boolean value)
 * @param {boolean} [noCallback]
 * @return {jQuery.Deferred}
 */
FastButtons.prototype.callAPI = function( code, extra, noCallback ) {
	var $doRequest,
		processAPI = new fb.ProcessAPI( code ),
		requestParams = processAPI.params,
		callbackFunction = noCallback ? false : processAPI.callback;
 
	if ( $.inArray( code, [ 'PV', 'PN', 'MR' ] ) !== -1
		&& fb.$submenu.html() === fb.message( 'fb-loading' )
	) {
		return;
	} else if ( code === 'requestDeletion' ) {
		return processAPI.callback( extra );
	}
 
	if ( code === 'esb' ) {
		requestParams.apprefix = 'Esboço-' + $( '#fb-esb-input' ).val();
	} else if ( $.inArray( code, [ 'MR', 'PN', 'PV' ] ) !== -1 ) {
		fb.changeSubmenu( fb.message( 'fb-loading' ) );
	}
 
	if ( $.isPlainObject( callbackFunction ) ) {
		if ( code === 'pageQuality' ) {
			if ( extra === 'noCallback' ) {
				return callbackFunction.beforeRequest();
			}
		} else {
			callbackFunction.beforeRequest();
		}
 
		callbackFunction = callbackFunction.callback;
	}
 
	requestParams.format = 'json';
 
	if ( !requestParams.action ) {
		requestParams.action = 'query';
	}
 
	$doRequest = ( requestParams.action !== 'query' ) ? $.post : $.get;
 
	return $doRequest(
		mw.util.wikiScript( 'api' ),
		requestParams,
		function( data ) {
			if ( !data ) {
				return fb.log( fb.message( 'fb-log-unableGetList', requestParams.list ) );
			}
 
			if ( callbackFunction ) {
				callbackFunction.call(
					$.isPlainObject( processAPI.callback ) ? processAPI.callback : processAPI,
					data.query,
					code,
					data
				);
			}
		}
	);
};
 
/**
 * Sends a warning to a user
 *
 * @param {string} type Type of warning
 */
FastButtons.prototype.sendWarning = function( type/*[, extraArg[, extraArg2[, ... extraArgN ]]]*/ ) {
	var warnInfo,
		warn = new fb.Warn( type ),
		apiDeferred = $.Deferred();
 
	warn.process.apply( undefined, Array.prototype.slice.call( arguments, 1 ) ).done( function() {
		warnInfo = warn.info;
 
		$( '#fb-dialog' ).dialog( 'close' );
 
		fb.notify( fb.message( 'fb-notify-sendWarning' ) );
 
		fb.editPage( {
			watchlist: 'preferences',
			minor: true,
			title: 'User talk:' + warnInfo.userName,
			appendtext: '\n\n{' + '{subst:Aviso-' + warnInfo.template + '}} ~~' + '~~',
			summary: warnInfo.summary +  fb.summaryDefault,
			done: function() {
				apiDeferred.resolve();
 
				if ( !warnInfo.isPE ) {
					fb.refreshPage();
				}
			}
		} );
	} );
 
	return apiDeferred.promise();
};
 
/**
 * Manipulate the text page
 *
 * @param {string} code See "fb.run"
 * @param {string} extraText See "fb.run"
 * @param {string} sum Summary of edit
 * @param {string} value Text of page
 * @param {boolean} isEditPage If is the edit page
 * @param {boolean} warn If a warning is sent
 */
FastButtons.prototype.manipulateTextPage = function( code, extraText, sum, value, isEditPage, warn ) {
	var fbSummary,
		apiDeferred = $.Deferred(),
		editCallback = function( e ) {
			if ( isEditPage ) {
				e.preventDefault();
			}
 
			if ( code === 'subst:apagar' || ( code.indexOf( 'av-' ) === -1
				&& /(ES?R|VDA|suspeito)/.test( code )
				&& !/ER(\|(1\b|7|8|9|12|18|C1|D1|D2|U1|U2|R2))/i.test( code )
			) ) {
				if ( code !== 'subst:apagar' ) {
					fb.sendWarning( 'elimination', code );
				} else {
					apiDeferred.resolve();
				}
			} else if ( warn ) {
				fb.sendWarning( 'maintenanceTags', code );
			} else if ( code === 'em manutenção' ) {
				fb.openPrompt( 'maintenance' );
			} else {
				fb.refreshPage( code );
			}
		};
 
	if ( code !== 'redirect'
		&& /\{\{(subst:)?(?:ER|ESR(2?|-banda|-bio|-empresa|-bsre|-organização|-matrad)|apagar|VDA|Usuário(\(a\))?\:Salebot\/Impróprio)[\|\}]/i.test( value )
		&& fb.nsNum !== 3
	) {
		alert( fb.message( 'fb-alreadyExistsEliminationTag' ) );
 
		return false;
	}
 
	if ( code.indexOf( 'ER' ) === 0 ) {
		extraText = extraText ? '|3=' + extraText : '';
		extraText = '{' + '{' + code + '|2=~~' + '~~' + extraText + '}}\n';
		extraText = ( fb.nsNum === 10 ) ? '<noinclude>' + extraText + '</noinclude>' : extraText;
		value = extraText + value;
		fbSummary = fb.message( 'fb-summary-requestElimination', code.substring( 3 ) );
	} else if ( code === 'redirect' ) {
		extraText = extraText.split( '|2=' );
 
		if ( fb.nsNum === 14 ) {
			value = '{' + '{Redirecionamento de categoria|' + extraText[ 0 ] + '|2=' + extraText[ 1 ] + '}}';
			fbSummary = fb.message( 'fb-summary-categoryRedirect', extraText[ 0 ], extraText[ 1 ] );
		} else {
			value = '#REDIRECIONAMENTO [[' + extraText[ 0 ] + ']]';
			fbSummary = fb.message( 'fb-summary-redirect', extraText[ 0 ], ( ( extraText[ 1 ] !== '' ) ? ' (' + extraText[ 1 ] + ')' : '' ) );
		}
	} else {
		extraText = extraText ? '|1=' + extraText : '';
		extraText = '{' + '{' + code + extraText + '}}';
 
		if ( code.indexOf( 'matrad' ) !== -1 ) {
			extraText = extraText.replace( '1=', 'língua=' );
		}
 
		if ( fb.nsNum === 3 ) {
			if ( /(bv-av|bem-vind)/.test( code ) ) {
				value = extraText + ' ~~' + '~~\n' + value;
			} else {
				value += '\n\n' + extraText + ' ~~' + '~~';
			}
 
			fbSummary = fb.message( 'fb-summary-addMessage', code.replace( 'subst:', '' ) );
		} else if ( code.indexOf( 'Esboço' ) === 0 ) {
			if ( /\n\n\[\[/.test( value ) ) {
				value = value.substring( 0, value.search( /\n\n\[\[/ ) ) + '\n\n\n'
					+ extraText + value.substring( value.search( /\n\n\[\[/ ) );
			} else {
				value += '\n\n' + extraText;
			}
 
			fbSummary = fb.message( 'fb-summary-stub' );
		} else if ( code === 'Sem interwiki' ) {
			value = value + '\n\n' + extraText + '';
		} else {
			value = extraText + '\n' + value;
			value = ( /subst:(apagar|ESR)/.test( code ) && fb.nsNum === 10 )
				? '<noinclude>' + value + '</noinclude>'
				: value;
 
			if ( code.indexOf( 'ESR' ) !== -1 ) {
				fbSummary = fb.message( 'fb-summary-ESR' );
			} else if ( code.search( /\b(f-referências|[sm](ais)?[-\s]notas(-bpv)?)\b/ ) !== -1 ) {
				value = value.replace( /\{\{Sem[-\s]fontes([-\s]bpv)?.+\}/g, '' );
			}
		}
 
		fbSummary = sum || fbSummary || fb.message( 'fb-summary-addTag' );
 
		if ( code.indexOf( 'subst:VDA' ) !== -1 ) {
			value = ( fb.nsNum === 10 ) ? '<noinclude>' + extraText + '</noinclude>' : extraText;
		}
	}
 
	if ( isEditPage ) {
		$( '#wpTextbox1' ).val( value );
		$( '#wpSummary' ).val(
			$( '#wpSummary' ).val()
			+ ( $( '#wpSummary' ).val() !== '' ? '; ' : '' )
			+ fbSummary +  fb.summaryDefault
		);
 
		//wikEd compatibility
		if ( typeof wikEd !== 'undefined' ) {
			if ( wikEd.useWikEd ) {
				WikEdUpdateFrame();
			}
		}
 
		$( '#editform' ).submit( editCallback );
 
		return apiDeferred.promise();
	}
 
	fb.disableAllButtons();
 
	fb.notify( fb.message( 'fb-notify-editingPage' ) );
 
	fb.editPage( {
		watchlist: 'preferences',
		minor: true,
		summary: fbSummary +  fb.summaryDefault,
		text: value,
		done: editCallback
	} );
 
	return apiDeferred.promise();
};
 
/**
 * Initialize the gadget
 */
FastButtons.prototype.init = function() {
	var ipAddress, buttonsLength,
		pageNotExist = !!( mw.util.getParamValue( 'redlink' ) === '1'
			|| $( '.noarticletext' ).length
			|| ( fb.nsNum === 14 && $( '.noarticletext' ).length ) );
 
	if ( typeof localStorage !== 'undefined' ) {
		if ( localStorage[ 'fb-success' ] ) {
			fb.notify( fb.message( 'fb-notify-' + localStorage[ 'fb-success' ] + 'Success' ), {
				autoHide: true
			} );
 
			delete localStorage[ 'fb-success' ];
		}
	}
 
	if ( mw.config.get( 'skin' ) === 'modern' ) {
		$( '#contentSub' ).before( fb.$menu ).before( fb.$submenu );
	} else {
		$( 'h1' ).first().after( fb.$submenu ).after( fb.$menu );
	}
 
	if ( fb.pageName !== 'Wikipédia:Página_principal'
		&& $.inArray( fb.action, [ 'view', 'edit', 'submit' ] ) !== -1
	) {
		if ( $.inArray( fb.nsNum, [ 2, 3 ] ) !== -1
			&& fb.title.indexOf( mw.config.get( 'wgUserName' ) ) === 0
		) {
			fb.addButton( {
				action: 'ER|1',
				text: 'ER1',
				title: 'Marcar subpágina do próprio usuário para eliminação',
				disable: pageNotExist
			} );
		} else if ( fb.nsNum !== -1 ) {
			fb.addButton( {
				action: function() {
					fb.changeSubmenu( fb.buttons.elimination );
				},
				text: 'Eliminação',
				title: 'Exibe as opções de eliminação para esta página',
				disable: pageNotExist
			} );
		}
 
 
		if ( $.inArray( fb.nsNum, [ 0, 4, 12, 102 ] ) !== -1 ) {
			fb.addButton( {
				action: function() {
					buttonsLength = fb.buttons.maintenance.length;
 
					fb.changeSubmenu(
						fb.buttons.maintenance,
						false,
						( $.inArray( fb.nsNum, [ 4, 12 ] ) !== -1 )
							? [ buttonsLength - 3, buttonsLength - 2, buttonsLength - 1 ]
							: undefined
					);
				},
				text: 'Manutenção',
				title: 'Exibir predefinições para manutenção',
				disable: pageNotExist
			} );
		}
 
		if ( fb.nsNum % 2 === 0 ) {
			fb.addButton( {
				action: 'redirect',
				text: '#R',
				title: 'Redirecionar para outro título',
				prompt: 'Informe a página e o motivo do redirecionamento',
				label: 'Página|2=Motivo[' + ( fb.nsNum !== 14 ) + ']',
				disable: $.inArray( fb.nsNum, [ 6, 8, 828 ] ) !== -1
			} );
		}
 
		if ( $.inArray( fb.nsNum, [ 0, 102 ] ) !== -1 ) {
			fb.addButton( [ {
					action: function() {
						fb.changeSubmenu( [ {
								action: 'Esboço',
								text: 'Esboço',
								title: 'Artigo ainda pouco desenvolvido'
							},
 
							fb.fieldForStubs
						] );
					},
					text: 'Esboço',
					title: 'Exibir predefinições para esboços',
					disable: pageNotExist
				}, {
					action: function() {
						fb.changeSubmenu( fb.searchButtons );
					},
					text: 'Busca',
					title: 'Exibir opções para a busca de fontes'
				}
			] );
		}
 
		if ( $.inArray( fb.nsNum, [ 2, 3 ] ) !== -1 || mw.config.get( 'wgCanonicalSpecialPageName' ) === 'Contributions' ) {
			ipAddress = ( $.inArray( fb.nsNum, [ 2, 3 ] ) !== -1 )
				? fb.title.split( '/' )[ 0 ]
				: ( mw.util.getUrl().split( '/' )[ 3 ] || mw.util.getParamValue( 'target' ) );
 
			if ( mw.util.isIPv4Address( ipAddress ) || mw.util.isIPv6Address( ipAddress ) ) {
				fb.addButton( {
					action: function() {
						fb.callAPI( 'anon' );
					},
					text: 'Sobre o IP',
					title: 'Exibir informações sobre este IP',
					disable: mw.config.get( 'wgCanonicalSpecialPageName' ) === 'Contributions'
						&& !( mw.util.getUrl().split( '/' )[ 3 ] || mw.util.getParamValue( 'target' ) )
				} );
			} else {
				fb.addButton( {
					action: function() {
						fb.callAPI( 'usu' );
					},
					text: 'Sobre a conta',
					title: 'Exibir informações sobre esta conta',
					disable: mw.config.get( 'wgCanonicalSpecialPageName' ) === 'Contributions'
						&& !( mw.util.getUrl().split( '/' )[ 3 ] || mw.util.getParamValue( 'target' ) )
				} );
			}
		}
 
		if ( fb.nsNum === 3 ) {
			fb.addButton( {
				action: function() {
					fb.changeSubmenu( fb.buttons.warn );
				},
				text: 'Aviso',
				title: 'Exibir lista de predefinições para avisos',
				disable: mw.config.get( 'wgUserName' ) === window.unescape( mw.util.getUrl().split( ':' )[ 1 ] )
			} );
		} else if ( fb.nsNum === 14 ) {
			fb.addButton( {
				action: function() {
					fb.changeSubmenu( fb.catScanButtons );
				},
				text: 'CatScan',
				title: 'Exibir opções do CatScan para procurar páginas nesta categoria',
				disable: pageNotExist
			} );
		}
	}
 
	fb.addButton( [ {
			action: function() {
				fb.changeSubmenu( [ fb.message( 'fb-loading' ), fb.$pageInfo.empty().hide() ] );
 
				api.getCurrentPageText().done( function( value ) {
					if ( value === undefined ) {
						fb.callAPI( 'deletionLogs' );
					} else {
						if ( $.inArray( fb.nsNum, [ 2, 3, 8, 828 ] ) === -1 ) {
							fb.callAPI( 'backLinks' );
						} else {
							fb.callAPI( 'requestDeletion' );
						}
					}
				} );
			},
			text: 'Informações sobre a página',
			title: 'Exibe informações sobre a página',
			disable: ( fb.nsNum === -1 || $.inArray( fb.action, [ 'view', 'edit', 'submit', 'history' ] ) === -1 )
		}, {
			action: fb.movePage,
			text: 'Mover a página',
			title: 'Exibe as opções para moção da página',
			disable: fb.nsNum === -1 || pageNotExist
		}, {
			action: function() {
				fb.changeSubmenu( fb.buttons.list );
			},
			text: 'Listar',
			title: 'Exibe os botões que listam edições nas páginas novas, mudanças recentes e páginas vigiadas'
		}
	] );
 
	fb.$menu.find( 'a' ).tipsy();
};
 
/**
 * Private
 */
 
/**
 * @object fb Instance of FastButtons constructor
 */
fb = new FastButtons();
 
$.extend( fb, {
 
	/**
	 * @property nsNum
	 */
	nsNum: mw.config.get( 'wgNamespaceNumber' ),
 
	/**
	 * @property title
	 */
	title: mw.config.get( 'wgTitle' ),
 
	/**
	 * @property pageName
	 */
	pageName: mw.config.get( 'wgPageName' ),
 
	/**
	 * @property action
	 */
	action: mw.config.get( 'wgAction' ),
 
	/**
	 * @property userName
	 */
	userName: ( mw.config.get( 'wgCanonicalSpecialPageName' ) !== 'Contributions' )
		? mw.config.get( 'wgTitle' ).split( '/' )[ 0 ]
		: window.decodeURI( mw.util.getUrl().split( '/' )[ 3 ] || mw.util.getParamValue( 'target' ) ),
 
	/**
	 * Log errors
	 * @param {string} errorText Text describing the error
	 */
	log: function( errorText ) {
		throw new Error( fb.message( 'fb-log-prefix' ) + ': ' + errorText );
	},
 
	/**
	 * Disable all buttons
	 */
	disableAllButtons: function() {
		$( '.fb-button' ).each( function() {
			$( this ).addClass( 'fb-disabled-button' ).unbind( 'click' );
			$( this ).attr( 'original-title', '' );
		} );
	},
 
	/**
	 * Format dates
	 *
	 * @param {string} unformattedDate The date
	 * @param {boolean} [noHours] If it'sn't necessary to use the hours
	 * @return {string}
	 */
	formatDate: function( unformattedDate, noHours ) {
		var date = new Date( unformattedDate ),
			formattedDate = '';
 
		if ( !noHours ) {
			formattedDate = date.getHours().toString().replace( /^(\d)$/, '0$1' )
			+ 'h' + date.getMinutes() + 'min' + fb.message( 'fb-concatDate' );
		}
 
		formattedDate += [
			date.getDate().toString().replace( /^(\d)$/, '0$1' ),
			mw.config.get( 'wgMonthNames' )[ date.getMonth() + 1 ], // In JS and CSS subpages, the month name appears in English
			date.getFullYear()
		].join( fb.message( 'fb-concatDate' ) );
 
		return formattedDate;
	},
 
	/***
	 * Add an input for stubs
	 */
	fieldForStubs: function() {
		var $stubInput, $okButton,
			ok = function() {
				if ( $stubInput.val() === '' ) {
					return $stubInput.addClass( 'fb-fill-field' );
				}
 
				$stubInput.removeClass( 'fb-fill-field' );
 
				fb.run( 'Esboço-' + $( '#fb-esb-input' ).val() );
			};
 
		$stubInput = $( '<input type="text" id="fb-esb-input" size="24" />' )
			.autocomplete( {
				source: function( request, response ) {
					fb.callAPI( 'esb' ).done( function( data ) {
						response( $.map( data.query.allpages, function( item ) {
							return item.title.replace( /^Predefinição:Esboço-/gi, '' );
						} ) );
					} );
				}
			} )
			.keyup( function( e ) {
				if ( e.which === $.ui.keyCode.ENTER ) {
					ok();
				}
			} );
 
		$okButton = $( '<input value="OK" type="button" class="fb-button fb-action-button" />' ).click( ok );
 
		fb.appendSubmenu( [ ' Esboço-', $stubInput, ' ', $okButton ] );
	},
 
	/**
	 * Add the search buttons
	 */
	searchButtons: function() {
		var item,
			i = 0,
			list = fb.buttons.search,
			search = encodeURIComponent(
				fb.title.indexOf( ' ' ) !== -1
					? '"' + fb.title + '"'
					: fb.title
			);
 
		while ( i < list.length ) {
			item = list[ i++ ];
 
			fb.appendSubmenu( $( '<a></a>', {
				'class': 'fb-button fb-link-button',
				'target': '_blank',
				'href': item.url + search,
				'text': item.text,
				'title': item.desc
			} ) );
		}
	},
 
	/**
	 * Add the CatScan buttons
	 */
	catScanButtons: function() {
		var item,
			i = 0,
			list = fb.buttons.cat,
			catScanUrl = '//toolserver.org/~daniel/WikiSense/CategoryIntersect.php?'
				+ $.param( {
					wikilang:  mw.config.get( 'wgContentLanguage' ),
					wikifam: '.wikipedia.org',
					userlang: mw.config.get( 'wgUserLanguage' ),
					basecat: fb.title,
					basedeep: '1',
					go: 'Examinar',
					format: 'html',
					mode: ''
				} );
 
		fb.changeSubmenu( fb.message( 'fb-catScan' ) + ': ' );
 
		while ( i < list.length ) {
			item = list[ i++ ];
 
			fb.appendSubmenu( $('<a></a>', {
				'class': 'fb-button fb-link-button',
				'target': '_blank',
				'href': catScanUrl + item.url,
				'text': item.text,
				'title': item.desc
			} ) );
		}
	},
 
	/**
	 * Move pages
	 */
	movePage: function() {
		var ns, namespaces, params, $movePage, $newTitle, $reason;
 
		if ( !$( '#ca-move' ).length ) {
			return fb.changeSubmenu( fb.message( 'fb-page-move-noPermissions' ) );
		}
 
		namespaces = {
			0: '(Principal)',
			1: 'Discussão',
			2: 'Usuário(a)',
			3: 'Usuário(a) Discussão',
			4: 'Wikipédia',
			5: 'Wikipédia Discussão',
			6: 'Arquivo',
			7: 'Arquivo Discussão',
			8: 'MediaWiki',
			9: 'MediaWiki Discussão',
			10: 'Predefinição',
			11: 'Predefinição Discussão',
			12: 'Ajuda',
			13: 'Ajuda Discussão',
			15: 'Categoria Discussão',
			100: 'Portal',
			101: 'Portal Discussão',
			102: 'Anexo',
			103: 'Anexo Discussão',
			104: 'Livro',
			105: 'Livro Discussão',
			710: 'TimedText',
			711: 'TimedText Discussão',
			828: 'Módulo',
			829: 'Módulo Discussão'
		};
 
		fb.changeSubmenu( '<span id="fb-movePage"></span>' );
		$movePage = $( '#fb-movePage' );
 
		$movePage.append(
			$( '<label for="fb-movePage-newTitle">' + fb.message( 'fb-page-move-newTitle' ) + ': </label>' ),
			$( '<select id="fb-movePage-select"></select>' ),
			' ',
			$( '<input type="input" id="fb-movePage-newTitle" size="60" />' ).val( fb.pageName.replace( /_/g, ' ' ) ),
			' ',
			$( '<label for="fb-movePage-reason">' + fb.message( 'fb-page-move-reason' ) + ': </label>' ),
			$( '<input type="input" id="fb-movePage-reason" size="60" />' )
		);
 
		for ( ns in namespaces ) {
			if ( namespaces[ ns ] ) {
				$( '<option></option>' )
					.val( ns )
					.html( namespaces[ ns ] )
					.appendTo( '#fb-movePage-select' );
			}
		}
 
		$( '#fb-movePage-select' ).find( 'option[value="' + mw.config.get( 'wgNamespaceNumber' ) + '"]' ).attr( 'selected', true );
 
		if ( $( '#ca-talk a' ).attr( 'href' ).indexOf( 'redlink=1' ) === -1 ) {
			$movePage.append(
				'<br />',
				$( '<input type="checkbox" id="fb-movePage-talk" checked />' ),
				' ',
				$( '<label for="fb-movePage-talk">' + fb.message( 'fb-page-move-talk' ) + '</label>' )
			);
		}
 
		if ( $.inArray( 'sysop', mw.config.get( 'wgUserGroups' ) ) !== -1
			|| $.inArray( 'eliminator', mw.config.get( 'wgUserGroups' ) ) !== -1
		) {
			$movePage.append(
				!$( '#fb-movePage br' ).length ? '<br />' : ' ',
				$( '<input type="checkbox" id="fb-movePage-redirect" checked />' ),
				' ',
				$( '<label for="fb-movePage-redirect">' + fb.message( 'fb-page-move-redirect' ) + '</label>' )
			);
		}
 
		$newTitle = $( '#fb-movePage-newTitle' );
		$reason = $( '#fb-movePage-reason' );
 
		fb.addButton( $movePage, {
			action: function() {
				if ( $newTitle.val() === '' || $newTitle.val() === fb.title.replace( /_/g, ' ' ) ) {
					$newTitle.addClass( 'fb-fill-field ' );
				} else {
					$newTitle.removeClass( 'fb-fill-field ' );
				}
 
				if ( $movePage.find( '*' ).hasClass( 'fb-fill-field' ) ) {
					return;
				}
 
				params = {
					action: 'move',
					from: fb.pageName,
					to: $newTitle.val(),
					token: mw.user.tokens.get( 'csrfToken' )
				};
 
				if ( $( '#fb-movePage-talk' ).prop( 'checked' ) ) {
					params.movetalk = 1;
				}
 
				if ( !$( '#fb-movePage-redirect' ).prop( 'checked' ) ) {
					params.noredirect = 1;
				}
 
				if ( $reason.val() !== '' ) {
					params.reason = $reason.val() + fb.summaryDefault;
				}
 
				fb.notify( fb.message( 'fb-page-move-moving' ) );
 
				fb.disableAllButtons();
 
				$.post(
					mw.util.wikiScript( 'api' ),
					params
				).done( function() {
					fb.refreshPage( 'move', $newTitle.val() );
				} );
			},
			text: fb.message( 'fb-page-move-buttonName' ),
			title: fb.message( 'fb-page-move-buttonTitle' ),
			type: 'action'
		} );
	}
} );
 
/**
 * @class ProcessAPI
 * Namespace for all Fast Buttons process methods
 * @see "this.callAPI"
 */
fb.ProcessAPI = function( typeRequest ) {
	var
		/**
		 * @private params
		 * Parameters of the requests
		 */
		params = {
			esb: {
				list: 'allpages',
				apnamespace: '10'
			},
 
			PV: {
				list: 'watchlist',
				wlprop: 'user|comment|title|sizes',
				wlshow: '!bot',
				wltype: 'edit',
				wlexcludeuser: mw.config.get( 'wgUserName' )
			},
 
			PN: {
				list: 'recentchanges',
				rctype: 'new',
				rcnamespace: '0',
				rcshow: '!patrolled|!redirect',
				rcprop: 'user|comment|title|sizes|ids'
			},
 
			MR: {
				list: 'recentchanges',
				rctype: 'edit',
				rcnamespace: '0',
				rcshow: 'anon',
				rcprop: 'user|comment|title|sizes'
			},
 
			usu: {
				list: 'allusers',
				aulimit: '1',
				auprop: 'editcount|registration|groups|blockinfo',
				aufrom: fb.userName
			},
 
			anon: {
				list: 'usercontribs',
				uclimit: '500',
				ucprop: 'timestamp',
				ucuser: fb.userName,
				ucdir: 'newer'
			},
 
			deletedEdits: {
				list: 'deletedrevs',
				titles: fb.title,
				drlimit: '500'
			},
 
			backLinks: {
				list: 'backlinks',
				bllimit: '1',
				blfilterredir: 'nonredirects',
				bltitle: fb.pageName
			},
 
			pageQuality: {
				prop: 'categories',
				indexpageids: '1',
				titles: mw.config.get( 'wgFormattedNamespaces' )[ fb.nsNum + 1 ] + ':' + fb.title
			},
 
			patrolPage: {
				action: 'patrol',
				rcid: mw.util.getParamValue(
					'rcid',
					mw.util.$content.find( 'div.patrollink a' ).attr( 'href' )
				),
				token: mw.user.tokens.get( 'patrolToken' )
			},
 
			pageRevisions: {
				prop: 'revisions',
				rvprop: 'user|comment|timestamp',
				rvlimit: '20',
				rvdir: 'newer',
				titles: fb.pageName,
				format: 'json'
			},
 
			pageInfo: {
				prop: 'info|revisions',
				inprop: 'watchers',
				titles: fb.pageName
			},
 
			deletionLogs: {
				list: 'logevents',
				letype: 'delete',
				letitle: fb.pageName
			}
		},
 
		/**
		 * @private callbacks
		 * Callbacks of the requests
		 */
		callbacks = {
			usu: this.userInfo,
			anon: this.userInfo,
			PV: this.recentEdits,
			PN: this.recentEdits,
			MR: this.recentEdits,
			pageInfo: this.pageInfo,
			backLinks: this.backLinks,
			pageQuality: this.pageQuality,
			deletedEdits: this.deletedEdits,
			deletionLogs: this.deletionLogs,
			requestDeletion: this.requestDeletion
		};
 
	/**
	 * @public params
	 * @public callback
	 */
	this.params = params[ typeRequest ];
	this.callback = callbacks[ typeRequest ];
};
 
/**
 * Callback function for the request of recent edits (from watchlist or recent changes)
 *
 * @param {Object} query Query of data JSON content returned by API
 * @param {string} code Code passed through the "fb.callAPI"
 */
fb.ProcessAPI.prototype.recentEdits = function( query, code ) {
	var item, titleItem, length, comment, bytesColor,
		i = 0,
		j = 0,
		charNum = 0,
		pages = [],
		info = {
			MR: {
				listName: 'recentchanges',
				urlParam: 'diff=last',
				noItems: fb.message( 'fb-noRecentChange' ),
				summaryChanges: [
					[ '/*', '?' ],
					[ '*/', ':' ]
				]
			},
			PN: {
				listName: 'recentchanges',
				urlParam: 'redirect=no&rcid=',
				noItems: fb.message( 'fb-noNewPage' ),
				summaryChanges: [
					[ '[[Ajuda:SEA|?]] ', '' ]
				]
			},
			PV: {
				listName: 'watchlist',
				urlParam: 'diff=last',
				noItems: fb.message( 'fb-noRecentChange' ),
				summaryChanges: [
					[ '[[Ajuda:SEA|?]]', '' ],
					[ '/*', '?' ],
					[ '*/', ':' ]
				]
			}
		},
		list = query[ info[ code ].listName ],
		max = ( list.length < 10 ) ? list.length : 10;
 
	while ( i < max ) {
		item = list[ i++ ];
 
		if ( !item ) {
			continue;
		}
 
		titleItem = item.title;
		charNum += titleItem.length;
 
		if ( charNum > 180 ) {
			break;
		}
 
		length = item.newlen - item.oldlen;
 
		if ( length > 0 ) {
			length = '+' + length;
		}
 
		comment = item.comment || '';
 
		while ( j++ < info[ code ].summaryChanges.length ) {
			comment = comment.replace(
				info[ code ].summaryChanges[ 0 ],
				info[ code ].summaryChanges[ 1 ]
			);
		}
 
		if ( comment ) {
			comment = '(' + comment + ')';
		}
 
		if ( code === 'PN' ) {
			info[ code ].urlParam += item.rcid;
		}
 
		if ( parseInt( length ) === 0 ) {
			bytesColor = 'gray';
		} else if ( parseInt( length ) > 0 ) {
			bytesColor = 'green';
		} else {
			bytesColor = 'red';
		}
 
		pages.push(
			'<a href="' + mw.util.getUrl( titleItem ) + '?'
			+ info[ code ].urlParam + '" title="(<span class=\'fb-' + bytesColor + '\'>' + length + '</span>) ' + item.user
			+ ' ' + comment + '">' + titleItem + '</a>'
		);
	}
 
	fb.changeSubmenu( ( pages.join( ' | ' ) || info[ code ].noItems ) );
};
 
/**
 * Works with the page info, and process the backlinks request
 */
fb.ProcessAPI.prototype.backLinks = {
	/**
	 * Executes before request
	 */
	beforeRequest: function() {
		var key,
			$catLine = $( '#mw-normal-catlinks' ),
			info = {
				'cat': {
					condition: $catLine.length
						&& $catLine.html().indexOf( '><a href="' + mw.config.get( 'wgArticlePath' ).replace( '$1', '' ) ) !== -1,
					title: fb.message( 'fb-page-cat' )
				}
			};
 
		if ( $.inArray( fb.nsNum, [ 0, 102 ] ) !== -1 ) {
			$.extend( info, {
				'ref': {
					condition: $( '.references' ).length,
					title: fb.message( 'fb-page-ref' )
				},
 
				'iw': {
					condition: $( '#p-lang' ).find( '.interlanguage-link' ).length,
					title: fb.message( 'fb-page-iw' )
				}
			} );
		}
 
		fb.$pageInfo.append( '(' );
 
		if ( fb.action !== 'history' && ( fb.nsNum % 2 ) === 0 ) {
			for ( key in info ) {
				if ( info[ key ] ) {
					fb.$pageInfo.append( $( '<span></span>', {
						'class': 'fb-' + ( info[ key ].condition ? 'ok' : 'missing' ),
						'title': fb.message( 'fb-page-it' ) + ' '
							+ info[ key ].title.replace( '$1 ', ( info[ key ].condition
								? ''
								: fb.message( 'fb-no' ).replace( 'N', 'n' ) + ' '
							) ),
						'text': key
					} ), ' · ' );
				}
			}
		}
	},
 
	/**
	 * @param {Object} query
	 */
	callback: function( query ) {
		var info = '',
			backlinks = query && query.backlinks;
 
		if ( !backlinks ) {
			return fb.log( fb.message( 'fb-log-backlinksNoData' ) );
		}
 
		if ( backlinks.length ) {
			info += '<a href="'
				+ mw.util.getUrl( 'Especial:Páginas afluentes/' + fb.pageName )
				+ '" title="' + fb.message( 'fb-page-backlinks' ) + '">afl</a>)';
		} else {
			info += '<span class="fb-missing" title="' + fb.message( 'fb-page-noBacklinks' ) + '">afl</span>)';
		}
 
		fb.$pageInfo.append( info );
 
		fb.callAPI( 'requestDeletion' );
	}
};
 
/**
 * Works with page quality of article (or "anexo") and process the request of categories of the discussion page
 */
fb.ProcessAPI.prototype.pageQuality = {
	/**
	 * Executes before request
	 *
	 * @return {boolean} false
	 */
	beforeRequest: function() {
		var $featuredContent = $( '#destaques1' );
 
		if ( !$featuredContent.length ) {
			return fb.callAPI( 'pageQuality', 'noBeforeRequest' );
		}
 
		$featuredContent = $( '#destaques1' ).find( 'img' ).attr( 'alt' );
 
		fb.$pageInfo.append(
			' · <span> ' + fb.message( 'fb-page-quality' ) + ': <b>'
				+ $featuredContent.substring(
					( fb.nsNum === 102 ) ? 16 : 17,
					$featuredContent.indexOf( '.' )
				)
			+ '</b></span>'
		);
 
		fb.callAPI( 'pageInfo' );
 
		return false;
	},
 
	/**
	 * @param {Object} query
	 */
	callback: function( query ) {
		var cats, pageids, cat, quality,
			i = 0;
 
		if ( query ) {
			cats = query.pages;
			pageids = query.pageids;
 
			if ( cats && pageids && pageids.length ) {
				cats = cats[ pageids[ 0 ] ].categories;
			} else {
				fb.log( fb.message( 'fb-log-categoryIncompleteData' ) );
 
				return false;
			}
		} else {
			fb.log( fb.message( 'fb-log-categoryNoData' ) );
 
			return false;
		}
 
		if ( cats ) {
			while ( i < cats.length ) {
				cat = cats[ i++ ].title;
 
				if ( cat && cat.indexOf( '!Artigos de qualidade' ) !== -1 ) {
					// Categoria:!Artigos de qualidade 1 sobre ...
					//				...^
					quality = cat.substr( 32, 1 );
 
					if ( quality === 'd' ) {
						quality = fb.message( 'fb-page-qualityUnknown' );
					}
 
					break;
				}
			}
		}
 
		fb.$pageInfo.append(
			' · <span>' + fb.message( 'fb-page-quality' ) + ': <b>'
				+ ( quality || fb.message( 'fb-page-qualityUnknown' ) )
			+ '</b></span>'
		);
 
		fb.callAPI( 'pageInfo' );
	}
};
 
/**
 * Works with user info and process the request of user editcount
 */
fb.ProcessAPI.prototype.userInfo = {
	/**
	 * Executes before request
	 */
	beforeRequest: function() {
		var item,
			i = 0,
			list = fb.buttons.userInfo;
 
		fb.changeSubmenu( '' );
 
		while ( i < list.length ) {
			item = list[ i++ ];
 
			fb.appendSubmenu( $( '<a></a>', {
				'class': 'fb-button fb-link-button',
				'target': '_blank',
				'href': item.href,
				'title': item.title,
				'text': item.text
			} ) );
 
			if ( item.disable ) {
				fb.$submenu.find( 'a' ).last()
					.addClass( 'fb-disabled-button' ).removeClass( 'fb-link-button' )
					.attr( 'original-title', '' ).removeAttr( 'href target' );
			}
		}
 
		fb.appendSubmenu( ' <span id="fb-editInfo">' + fb.message( 'fb-loading' ) + '</span>' );
	},
 
	/**
	 * Show the data
	 *
	 * @param {object|string} user
	 * @param {string} code
	 * @param {object} data
	 * @param {boolean} [isFallback]
	 */
	showData: function( user, code, data, isFallback ) {
		var groups;
 
		if ( user === 'notExist' ) {
			return $( '#fb-editInfo' ).html( fb.message( 'fb-user-notExist' ) );
		} else if ( !user ) {
			return $( '#fb-editInfo' ).html( fb.message( 'fb-user-error' ) );
		}
 
		groups = {
			'autoconfirmed': 'Autoconfirmado',
			'autoreviewer': 'Autorrevisor',
			'bureaucrat': 'Burocrata',
			'checkuser': 'Verificador de contas',
			'eliminator': 'Eliminador',
			'patroller': 'Patrulhador',
			'reviewer': 'Revisor',
			'rollbacker': 'Reversor',
			'bot': 'Robô',
			'ipblock-exempt': 'Isento de bloqueio de IP',
			'interface_editor': [ 'Editor de interface', 'Editores de interface/Pedidos de aprovação' ],
			'oversight': [ 'Supervisor', 'Oversight/Candidaturas' ],
			'sysop': [ 'Administrador', 'Pedidos de administração' ]
		};
 
		$( '#fb-editInfo' ).html(
			fb.message( 'fb-user-edits' ) + ': <b>'
			+ ( user.editcount ).toLocaleString() + '</b> — ' + ( ( code === 'anon' )
				? fb.message( 'fb-user-anonFirstEdit' )
				: fb.message( 'fb-user-registryDate' )
			) + ': ' + '<b><span id="fb-registryDate"></span></b>'
		);
 
		if ( user.registration ) {
			$( '#fb-registryDate' ).html(
				( data[ 'query-continue' ] && code === 'anon' ? fb.message( 'fb-user-priorTo' ) + ' ' : '' )
				+ fb.formatDate( user.registration, true )
			).after(
				( isFallback ) ? '<sup title="' + fb.message( 'fb-user-userFirstEdit' ) + '">?</sup>' : ''
			);
		} else {
			$( '#fb-registryDate' )
				.text( fb.message( 'fb-user-undefined' ) )
				.attr( 'title', fb.message( 'fb-user-unkownRegisterDate' ) )
				.addClass( 'fb-help' );
		}
 
		if ( code !== 'anon' ) {
			user.groups = user.groups.join( ' ' ).replace( /(\*|\buser|\beditor)\s/g, '' ).split( ' ' );
			user.groups = user.groups.map( function( el ) {
				if ( typeof groups[ el ] === 'object' ) {
					return '<a href="' + mw.util.getUrl( 'Wikipédia:' + groups[ el ][ 1 ] + '/' + user.name ) + '">' + groups[ el ][ 0 ] + '</a>';
				}
 
				return groups[ el ];
			} );
 
			if ( typeof user.blockid === 'string' ) {
				$( '#fb-editInfo' ).prepend( fb.message( 'fb-user-blocked' ) + ' — ' );
			}
 
			fb.appendSubmenu( ' — ' + fb.message( 'fb-user-groups' ) + ': ' + ( user.groups.join( ' · ' ) || '<span class="fb-gray">' + fb.message( 'fb-none' ) + '</span>' ) );
		}
 
		fb.$submenu.find( 'sup' ).tipsy();
	},
 
	/**
	 * @param {Object} query
	 * @param {string} code
	 * @param {Object} data
	 */
	callback: function( query, code, data ) {
		var contribs,
			user = {};
 
		if ( !query ) {
			fb.log( fb.message( 'fb-log-userInfoNoData' ) );
 
			return;
		}
 
		if ( code === 'anon' ) {
			if ( query.usercontribs.length === 0 ) {
				$( '#fb-editInfo' ).text( fb.message( 'fb-user-anonNoEdit' ) );
 
				return;
			}
 
			contribs = query.usercontribs;
			user.name = contribs[ 0 ].user;
			user.editcount = contribs.length;
			user.registration = contribs[ 0 ].timestamp;
 
			if ( data[ 'query-continue' ] ) {
				user.editcount = 'mais de ' + user.editcount;
			}
		} else {
			user = query.allusers && query.allusers[ 0 ];
 
			if ( user.name !== fb.userName.replace( /_/g, ' ' ) ) {
				user = 'notExist';
			} else if ( !user.registration ) {
				// If not possible get the registration date through API call using 'allusers' list
				// Uses 'usercontribs' list to get the first edit, setted in "anon" configs (see fb.ProcessAPI)
				fb.callAPI( 'anon', undefined, true ).done( function( data ) {
					user.registration = data.query.usercontribs[ 0 ] && data.query.usercontribs[ 0 ].timestamp;
 
					this.showData( user, code, data, true );
				}.bind( this ) );
 
				return;
			}
		}
 
		this.showData( user, code, data );
	}
};
 
/**
 * Callback function for the request of deleted contributions
 *
 * @param {object} query Query of data JSON content returned by API
 */
fb.ProcessAPI.prototype.deletedEdits = function( query ) {
	var deletedRevs = query.deletedrevs[ 0 ],
		none = fb.message( 'fb-ucNone' ) + 'a',
		numDeletedRevs = ( !deletedRevs ? 0 : deletedRevs.revisions.length ) || none;
 
	fb.$pageInfo.append(
		' · ',
		$( '<a></a>', {
			'href': mw.util.getUrl( 'Especial:Restaurar/' + fb.title ),
			'title': fb.message( 'fb-page-deletedEdits' ),
			'text': numDeletedRevs
				+ ( ( $.inArray( numDeletedRevs, [ 1, none ] ) !== -1 )
					? ' ' + fb.message( 'fb-page-deletedEdit' )
					: ' ' + fb.message( 'fb-page-deletedEdits' )
				)
		} )
	);
 
	if ( $.inArray( fb.nsNum, [ 0, 102 ] ) !== -1 ) {
		fb.callAPI( 'pageQuality', 'noCallback' );
	} else {
		fb.callAPI( 'pageInfo' );
	}
};
 
 
/**
 * Callback function for the request of page info
 *
 * @param {object} query Query of data JSON content returned by API
 * @param {boolean} [justWatchers] Used by "this.deletionLogs"
 */
fb.ProcessAPI.prototype.pageInfo = function( query, justWatchers ) {
	var info = query.pages[ ( justWatchers === true ) ? -1 : mw.config.get( 'wgArticleId' ) ],
		text = [];
 
	text[ 1 ] = fb.message( 'fb-page-watchers' ) + ': <b>' + ( parseInt( info.watchers ) || fb.message( 'fb-none' ) ).toLocaleString() + '</b>';
 
	if ( justWatchers !== true ) {
		text[ 0 ] = ' · ' + fb.message( 'fb-page-size' ) + ': <b>' +  ( info.length ).toLocaleString() + ' bytes</b>';
		text[ 2 ] = fb.message( 'fb-page-lastEdit' ) + ': <a href="' +  mw.util.getUrl() + '?diff=last">' + fb.formatDate( info.revisions[ 0 ].timestamp ) + '</a>';
	}
 
	text[ text.length ] = '<a href="' +  mw.util.getUrl() + '?action=info">' + fb.message( 'fb-page-moreInfo' ) + '</a>';
 
	if ( !fb.notShowInfo ) {
		fb.$pageInfo.append( text.join( ' · ' ) ).show().html();
		fb.changeSubmenu( fb.$pageInfo );
	} else {
		delete fb.notShowInfo;
	}
};
 
/**
 * Executed if the page isn't exist
 */
fb.ProcessAPI.prototype.deletionLogs = function( query ) {
	var text, getWatchers,
		logevents = query.logevents;
 
	if ( logevents.length ) {
		text = fb.message( 'fb-page-pageDeleteDate', fb.formatDate( logevents[ 0 ].timestamp ) );
		getWatchers = true;
 
	} else {
		text = fb.message( 'fb-page-notExist' );
	}
 
	fb.$pageInfo.append( text );
 
	if ( getWatchers ) {
		fb.callAPI( 'pageInfo', undefined, true ).done( function( data ) {
			fb.ProcessAPI.prototype.pageInfo( data.query, true );
		} );
	} else {
		if ( !fb.notShowInfo ) {
			fb.$pageInfo.show().html();
			fb.changeSubmenu( fb.$pageInfo );
		} else {
			delete fb.notShowInfo;
		}
	}
};
 
/**
 * Checks if the page has already been proposed for deletion
 * @param {boolean} [justVerify] If true, only returns if the proposed exists or not
 */
fb.ProcessAPI.prototype.requestDeletion = function( justVerify ) {
	var tagName,
		apiDeferred = $.Deferred();
 
	api.getCurrentPageText( 'Wikipédia:Páginas para eliminar/' + fb.pageName ).done( function( value ) {
		if ( justVerify ) {
			return apiDeferred.resolve( !!value );
		}
 
		tagName = ( !value ) ? 'span' : 'a';
 
		fb.$pageInfo.append(
			$( '<' + tagName + ' id="fb-requestDeletion"></' + tagName + '>' )
				.html( fb.message( 'fb-page-requestDeletion' ) )
				.before( ' ' )
		);
 
		if ( !value ) {
			$( '#fb-requestDeletion' )
				.attr( 'title', fb.message( 'fb-page-neverProposedElimination' ) )
				.addClass( 'fb-cursorDefault' );
		} else {
			$( '#fb-requestDeletion' ).attr( {
				'title': fb.message( 'fb-page-requestDeletionLink' ),
				'href': mw.util.getUrl( 'Wikipédia:Páginas para eliminar/' + fb.pageName )
			} );
		}
 
		if ( $.inArray( 'sysop', mw.config.get( 'wgUserGroups' ) ) !== -1
			|| $.inArray( 'eliminator', mw.config.get( 'wgUserGroups' ) ) !== -1
		) {
			fb.callAPI( 'deletedEdits' );
		} else if ( $.inArray( fb.nsNum, [ 0, 102 ] ) !== -1 ) {
			fb.callAPI( 'pageQuality', 'noCallback' );
		} else {
			fb.callAPI( 'pageInfo' );
		}
	} );
 
	return apiDeferred.promise();
};
 
/**
 * @class Warn
 * Namespace for all FastButtons warning methods
 * @see "this.sendWarning"
 */
fb.Warn = function( type ) {
	/**
	 * @method process
	 * @return {jQuery.Deferred}
	 */
	this.process = function() {
		var apiDeferred = $.Deferred();
 
		this[ type ].apply( this, arguments ).done( function() {
			apiDeferred.resolve();
		} );
 
		return apiDeferred.promise();
	}.bind( this );
};
 
/**
 * Warn on deleting a page
 *
 * @param {string} code See "FastButtons.prototype.run"
 * @param {string} [warnType] Type of warn. Only if "code" param = 'subst:apagar'
 * @return {jQuery.Deferred}
 */
fb.Warn.prototype.elimination = function( code, warnType ) {
	var revisions, userPageCreator, eliminationType, isPE,
		buttons = {},
		apiDeferred = $.Deferred(),
		callback = function() {
			if ( $.inArray( '1', [ $( '#fb-send-message' ).val(), warnType ] ) !== -1 ) {
				this.info = {
					userName: userPageCreator,
					template: eliminationType,
					summary: fb.message( 'fb-warn-elimination-summary-pageElimination', fb.pageName.replace( /_/g, ' ' ) ),
					isPE: isPE
				};
			} else if ( $.inArray( '2', [ $( '#fb-send-message' ).val(), warnType ] ) !== -1 ) {
				this.info = {
					userName: userPageCreator,
					template: 'não remova',
					summary: fb.message( 'fb-warn-elimination-summary-removeEliminationTag' ),
					isPE: isPE
				};
			} else {
				$( '#fb-dialog' ).dialog( 'close' );
				fb.refreshPage();
			}
 
			apiDeferred.resolve();
		}.bind( this );
 
	switch ( code ) {
		case 'subst:apagar':
			eliminationType = 'PE';
		break;
 
		case 'subst:VDA':
			eliminationType = 'cópia';
		break;
 
		case 'subst:suspeito':
			eliminationType = 'suspeito';
		break;
 
		default:
			eliminationType = 'E' + ( ( code.indexOf( 'ESR' ) !== -1 ) ? 'S' : '' ) + 'R';
	}
 
	eliminationType += '|' + fb.pageName.replace( /_/g, ' ' );
	isPE = eliminationType.indexOf( 'PE' ) !== -1;
 
	fb.callAPI( 'pageRevisions' ).done( function( data ) {
		revisions = data.query.pages[ mw.config.get( 'wgArticleId' ) ].revisions;
		userPageCreator = revisions[ 0 ].user;
 
		if ( userPageCreator === mw.config.get( 'wgUserName' )
			|| ( revisions.length === 1 && /moveu \[\[.+?\]\] para \[\[.+?\]\]/.test( revisions[ 0 ].comment ) )
			|| ( ( mw.util.isIPv4Address( userPageCreator ) || mw.util.isIPv6Address( userPageCreator ) )
				&& ( Date.parse( revisions[ 0 ].timestamp ) + 86400000 ) < new Date().getTime()
			)
		) {
			if ( !isPE ) {
				return fb.refreshPage();
			}
 
			return;
		}
 
		if ( eliminationType.indexOf( 'PE' ) !== -1 ) {
			return callback();
		}
 
		buttons[ fb.message( 'fb-OK' ) ] = callback;
		buttons[ fb.message( 'fb-cancel' ) ] = function() {
			$( this ).dialog( 'close' );
 
			if ( fb.action !== 'edit' ) {
				fb.refreshPage();
			}
		};
 
		fb.dialog( {
			title: fb.message( 'fb-warn-elimination-prompt-title' ),
			width: 'auto',
			height: 'auto',
			content: fb.message( 'fb-warn-elimination-prompt-select' ) + ':<br /><br />'
				+ '<select id="fb-send-message">'
					+ '<option value="1">' + fb.message( 'fb-warn-elimination-prompt-option-1' ) + '</option>'
					+ '<option value="2">' + fb.message( 'fb-warn-elimination-prompt-option-2' ) + '</option>'
					+ '<option>' + fb.message( 'fb-warn-elimination-prompt-option-3' ) + '</option>'
				+ '</select><br /><br />',
			buttons: buttons
		} );
	} );
 
	return apiDeferred.promise();
};
 
/**
 * Warning after a page is tagged with certain maintenance tags.
 *
 * @return {jQuery.Deferred}
 */
fb.Warn.prototype.maintenanceTags = function( code ) {
	var i, revisions, revsUsers, userPageCreator, sameEditor, definitions,
		buttons = {},
		page = fb.pageName.replace( /_/g, ' ' ),
		apiDeferred = $.Deferred();
 
	code = code.replace( 'subst:', '' );
	definitions = {
		's-fontes': {
			name: 'Sem fontes',
			template: 'cite fonte',
			sameEditor: true
		},
		's-fontes-bpv': {
			name: 'Sem fontes-bpv',
			template: 'cite fonte',
			sameEditor: true
		},
		's-cat': {
			name: 'Sem categoria',
			template: 'categoria',
			sameEditor: false
		}
	};
 
	fb.callAPI( 'pageRevisions' ).done( function( data ) {
		revisions = data.query.pages[ mw.config.get( 'wgArticleId' ) ].revisions;
		userPageCreator = revisions[ 0 ].user;
		definitions = definitions[ code ];
 
		if ( definitions.sameEditor ) {
			sameEditor = true;
 
			revsUsers = revisions.map( function( rev ) {
				return rev.user;
			} );
 
			for ( i = 1; i < revsUsers.length - 1; i++ ) {
				if ( !/moveu \[\[.+?\]\] para \[\[.+?\]\]/.test( revisions[ i - 1 ].comment )
					&& revsUsers[ i ] !== revsUsers[ i - 1 ]
				) {
					sameEditor = false;
 
					break;
				}
			}
		}
 
		if ( userPageCreator === mw.config.get( 'wgUserName' )
			|| ( definitions.sameEditor && !sameEditor )
			|| ( ( mw.util.isIPv4Address( userPageCreator ) || mw.util.isIPv6Address( userPageCreator ) )
				&& ( Date.parse( revisions[ 0 ].timestamp ) + 86400000 ) < new Date().getTime()
			)
		) {
			return fb.refreshPage();
		}
 
		buttons[ fb.message( 'fb-yes' ) ] = function() {
			this.info = {
				userName: userPageCreator,
				template: definitions.template + '|' + page,
				summary: fb.message( 'fb-warn-maintenanceTags-summary', page, definitions.name )
			};
 
			apiDeferred.resolve();
		}.bind( this );
 
		buttons[ fb.message( 'fb-no' ) ] = function() {
			fb.refreshPage();
 
			$( this ).dialog( 'close' );
		};
 
		fb.dialog( {
			title: fb.message( 'fb-warn-maintenanceTags-prompt-title', definitions.name ),
			content: fb.message( 'fb-warn-maintenanceTags-prompt-content' ),
			width: 'auto',
			height: 'auto',
			buttons: buttons
		} );
	}.bind( this ) );
 
	return apiDeferred.promise();
};
 
/**
 * @class Prompt
 * Namespace to prompts useds in the gadget
 * @see "this.openPrompt"
 */
fb.Prompt = function( name ) {
	/**
	 * @method open
	 */
	this.open = function() {
		return this[ name ].apply( this, Array.prototype.slice.call( arguments, 1 ) );
	}.bind( this );
};
 
/**
 * Default prompt used in the gadget
 *
 * @param {string} title Title of prompt
 * @param {string} label Labels of inputs
 *     @example
 *     'field1|2=field2[true]|3=field3', results in 3 inputs with the respective labels
 *	Set "[true]" to a label if it's optional
 * @param {Function} callback Function to be called after (...)
 */
fb.Prompt.prototype.defaultPrompt = function( title, label, callback ) {
	if ( !label ) {
		label = fb.message( 'fb-dialog-labelDefault' );
	}
 
	var i,
		buttons = {},
		dialogContent = '',
		multipleLabels = label.indexOf( '|2=' ) !== -1;
 
	if ( multipleLabels ) {
		for ( i = 1, label = label.split( /\|\d+=/ ); i <= label.length; i++ ) {
			dialogContent += '<label for="fb-nprompt-input' + i + '">'
				+ label[ i - 1 ].replace( /\[.+\]/, '' )
				+ ': <input type="text" class="fb-field" id="fb-nprompt-input' + i + '" /></label>';
		}
	} else {
		dialogContent = '<label for="fb-nprompt-input">'
			+ label.replace( /\[.+\]/, '' )
			+ ': <input type="text" class="fb-field" id="fb-nprompt-input" /></label>';
	}
 
	buttons[ fb.message( 'fb-OK' ) ] = function() {
		var awnsers,
			$inputs = $( '#fb-dialog input' );
 
		if ( label !== fb.message( 'fb-dialog-labelDefault' ) && label.length !== 1 ) {
			$inputs.each( function( i ) {
				if ( $( this ).val() === '' && !/\[true\]/.test( label[ i ] ) ) {
					$( this ).addClass( 'fb-fill-field' );
				} else {
					$( this ).removeClass( 'fb-fill-field' );
				}
			} );
		}
 
		if ( $( '.fb-field' ).hasClass( 'fb-fill-field' ) ) {
			return;
		}
 
		if ( !multipleLabels ) {
			awnsers = $( '#fb-nprompt-input' ).val();
		} else {
			for ( i = 1; i <= $inputs.length; i++ ) {
				awnsers = ( i === 1 )
					? $( '#fb-nprompt-input1' ).val()
					: awnsers + '|' + i + '=' + $( '#fb-nprompt-input' + i ).val();
			}
		}
 
		callback( awnsers );
 
		$( this ).dialog( 'close' );
	};
 
	buttons[ fb.message( 'fb-cancel' ) ] = function() {
		$( this ).dialog( 'close' );
	};
 
	fb.dialog( {
		title: title,
		content: dialogContent,
		width: 400,
		height: 'auto',
		buttons: buttons,
		focus: function() {
			$( ':input', this ).keyup( function( event ) {
				if ( event.keyCode === 13 ) {
					$( '.ui-dialog-buttonpane button:first' ).click();
				}
			} );
		}
	} );
};
 
/**
 * ESR (Eliminação semirrápida) prompt
 */
fb.Prompt.prototype.esr = function() {
	var i, subjects, defaultJustifications, $justification,
		buttons = {};
 
	if ( fb.nsNum === 6 ) {
		buttons[ fb.message( 'fb-OK' ) ] = function() {
			$justification = $( '#fb-ESR-justification-field' );
 
			if ( $justification.val() === '' ) {
				return $justification.addClass( 'fb-fill-field' );
			}
 
			fb.run( 'subst:ESR-arquivo', $justification.val() );
 
			$( this ).dialog( 'close' );
		};
 
		buttons[ fb.message( 'fb-cancel' ) ] = function() {
			$( this ).dialog( 'close' );
		};
 
		fb.dialog( {
			title: fb.message( 'fb-dialog-ESR-title-1' ),
			content: '<div id="fb-ESR-justification">'
					+ '<label for="fb-ESR-justification-field">' + fb.message( 'fb-dialog-ESR-reason' ) + ':<br />'
						+ '<textarea id="fb-ESR-justification-field" placeholder="' + fb.message( 'fb-dialog-ESR-placeholder' ) + '"></textarea>'
					+ '</label>'
				+ '</div>',
			buttons: buttons
		} );
 
		return $( '#fb-ESR-justification-field' );
	}
 
	defaultJustifications = window.fastButtons.defaultJustificationsEsrPrompt;
	subjects = [
		'Arte', 'Carnaval', 'Ciência',  'Ciências sociais',
		'Cinema', 'Educação', 'Elementos de ficção', 'Empresas, produtos e serviços',
		'Entretenimento', 'Esporte/Desporto', 'Geografia', 'Ginástica',
		'História e sociedade', 'Medicina', 'Música', 'Países',
		'Pessoas', 'Política', 'Rádio e televisão'
	];
 
	buttons[ fb.message( 'fb-OK' ) ] = function() {
		if ( $( '#fb-ESR-justification-field' ).val() === '' ) {
			$( '#fb-ESR-justification-field' ).addClass( 'fb-fill-field' );
		} else {
			$( '#fb-ESR-justification-field' ).removeClass( 'fb-fill-field' );
		}
 
		if ( $( '#fb-ESR-subject-select' ).val() === ''
			&& !$( '#fb-ESR-subject-other' ).prop( 'checked' )
		) {
			$( '#fb-ESR-subject-select' ).addClass( 'fb-fill-field' );
		} else {
			$( '#fb-ESR-subject-select' ).removeClass( 'fb-fill-field' );
		}
 
		if ( $( '#fb-ESR *' ).hasClass( 'fb-fill-field' ) ) {
			return;
		}
 
		fb.run(
			'subst:ESR|' + $( '#fb-ESR-justification-field' ).val() + ' ~~' + '~~'
				+ ( ( !$( '#fb-ESR-subject-other' ).prop( 'checked' )
					&& $( '#fb-ESR-subject-select' ).val() !== '' )
					? '|assunto=' + $( '#fb-ESR-subject-select' ).val()
					: ''
				)
		);
 
		$( this ).dialog( 'close' );
	};
 
	buttons[ fb.message( 'fb-cancel' ) ] = function() {
		$( this ).dialog( 'close' );
	};
 
	fb.dialog( {
		title: fb.message( 'fb-dialog-ESR-title-2' ) ,
		width: 'auto',
		height: 'auto',
		content: '<div id="fb-ESR">'
				+ '<a id="fb-ESR-matrad" class="fb-button fb-action-button">' + fb.message( 'fb-dialog-ESR-badTranslation' ) + '</a><br /><br />'
				+ '<div id="fb-ESR-justification">'
					+ '<label for="fb-ESR-justification-field">' + fb.message( 'fb-dialog-ESR-reason' ) + ':<br />'
						+ '<textarea id="fb-ESR-justification-field" placeholder="' + fb.message( 'fb-dialog-placeholderDefault' ) + '"></textarea>'
					+ '</label>'
				+ '</div>'
				+ '<div id="fb-ESR-subject">'
					+ '<label for="fb-ESR-subject">' + fb.message( 'fb-dialog-ESR-subject' ) + ':<br />'
						+ '<select id="fb-ESR-subject-select">'
							+ '<option></option>'
						+ '</select>'
					+ '</label><br />'
					+ '<label for="fb-ESR-subject-other">'
						+ '<input type="checkbox" id="fb-ESR-subject-other" /> ' + fb.message( 'fb-dialog-ESR-other' )
					+ '</label>'
				+ '</div>'
			+ '</div>',
		buttons: buttons
	} );
 
	for ( i = 0; i < subjects.length; i++ ) {
		$( '#fb-ESR-subject-select' ).append(
			'<option value="' + subjects[ i ].toLowerCase() + '">' + subjects[ i ] + '</option>'
		);
	}
 
	$( '#fb-ESR-subject-select' ).change( function() {
		if ( defaultJustifications[ $( this ).val() ] ) {
			$( '#fb-ESR-justification-field' ).val( defaultJustifications[ $( this ).val() ] );
		}
	} );
 
	$( '#fb-ESR-matrad' ).click( function() {
		$( '#fb-dialog' ).dialog( 'close' );
 
		fb.openPrompt( 'defaultPrompt',
			fb.message( 'fb-dialog-ESR-whatLang' ),
			fb.message( 'fb-dialog-ESR-lang' ),
			function( lang ) {
				fb.run( 'subst:ESR-matrad', lang.toLowerCase() );
			}
		);
	} );
 
	$( '#fb-ESR-subject-other' ).click( function() {
		if ( $( '#fb-ESR-subject-other' ).attr( 'checked' ) ) {
			$( '#fb-ESR-subject-select' )
				.attr( 'disabled', true )
				.addClass( 'fb-disabled-button' );
		} else {
			$( '#fb-ESR-subject-select' )
				.attr( 'disabled', false )
				.removeClass( 'fb-disabled-button' );
		}
	} );
};
 
/**
 * PE (Páginas para eliminar) prompt
 * @param {boolean} isEditPage
 */
fb.Prompt.prototype.pe = function( isEditPage ) {
	var $justification, $warnType, $sendWarningType, sendWarning, createPE, count,
		buttons = {},
		createPE_callback = function( verifyPE ) {
			if ( verifyPE ) {
				return fb.callAPI( 'requestDeletion', true ).done( function( exists ) {
					if ( !!exists ) {
						archivePE();
					} else {
						createPE_callback();
					}
				} );
			}
 
			fb.notify( fb.message( 'fb-notify-creatingEliminationPage' ) );
 
			api.getCurrentPageText( 'Wikipédia:Páginas_para_eliminar/Novoapagar' ).done( function( value ) {
				value = value
					.replace( /<\/?includeonly>/g, '' )
					.replace( /<!--(.|\n)+canceladas -->/, $justification );
 
				fb.editPage( {
					title: 'Wikipédia:Páginas_para_eliminar/' + fb.pageName,
					watchlist: 'preferences',
					minor: true,
					text: value,
					summary: fb.message( 'fb-summary-creatingEliminationPage' ) + fb.summaryDefault,
					done: function() {
						fb.refreshPage();
					}
				} );
			} );
		},
		archivePE = function() {
			var page;
 
			if ( !count ) {
				fb.notify( fb.message( 'fb-notify-archivingPE' ) );
				count = 1;
			}
 
			page = 'Wikipédia:Páginas para eliminar/' + fb.pageName + '/' + count++;
 
			api.getCurrentPageText( page ).done( function( value ) {
				if ( value === undefined ) {
					api.post( {
						action: 'move',
						from: page.replace( /\/\d*$/, '' ),
						to: page,
						reason: fb.message( 'fb-summary-archivingPE' ) +  fb.summaryDefault,
						token: mw.user.tokens.get( 'csrfToken' )
					} ).done( function() {
						createPE_callback();
					} );
				} else {
					archivePE( count );
				}
			} );
		},
		run = function() {
			if ( sendWarning ) {
				fb.sendWarning( 'elimination', 'subst:apagar', $sendWarningType ).done( function() {
					if ( createPE ) {
						createPE_callback( true );
					} else {
						fb.refreshPage();
					}
				} );
			} else if ( createPE ) {
				createPE_callback( true );
			} else {
				fb.refreshPage();
			}
		};
 
	buttons[ fb.message( 'fb-OK' ) ] = function() {
		sendWarning = $( '#fb-PE-sendWarning' ).attr( 'checked' );
		$sendWarningType = $( 'input[name="fb-PE-sendWarning-type"]' );
		createPE = $( '#fb-PE-createPE' ).attr( 'checked' );
		$justification = $( '#fb-PE-createPE-justification' );
 
		if ( sendWarning && ( !$sendWarningType.eq( 0 ).attr( 'checked' )
			&& !$sendWarningType.eq( 1 ).attr( 'checked' )
		) ) {
			$( '#fb-PE-sendWarning-type' ).addClass( 'fb-fill-field' );
		} else {
			$( '#fb-PE-sendWarning-type' ).removeClass( 'fb-fill-field' );
		}
 
		if ( createPE && $justification.val() === '' ) {
			$justification.addClass( 'fb-fill-field' );
		} else {
			$justification.removeClass( 'fb-fill-field' );
		}
 
		if ( $( '#fb-PE *' ).hasClass( 'fb-fill-field' ) ) {
			return;
		}
 
		$sendWarningType = $( 'input[name="fb-PE-sendWarning-type"]:checked' ).val();
		$justification = $justification.val();
 
		$( this ).dialog( 'close' );
 
		if ( isEditPage ) {
			$( '#editform' ).submit( run );
		}
 
		fb.run( 'subst:apagar', '', fb.message( 'fb-summary-elimination' ) ).done( function() {
			if ( !isEditPage ) {
				run();
			}
		} );
	};
 
	buttons[ fb.message( 'fb-cancel' ) ] = function() {
		$( this ).dialog( 'close' );
	};
 
	fb.dialog( {
		title: fb.message( 'fb-dialog-PE-title' ),
		width: 'auto',
		height: 'auto',
		content: '<div id="fb-PE">'
				+ '<label for="fb-PE-sendWarning">'
					+ '<input type="checkbox" id="fb-PE-sendWarning" /> ' + fb.message( 'fb-dialog-PE-sendWarning' )
				+ '</label>'
				+ '<div id="fb-PE-sendWarning-type">'
					+ '<label>'
						+ '<input type="radio" name="fb-PE-sendWarning-type" value="1" /> ' + fb.message( 'fb-dialog-PE-type-1' )
					+ '</label>'
					+ '<label>'
						+ '<input type="radio" name="fb-PE-sendWarning-type" value="2" /> ' + fb.message( 'fb-dialog-PE-type-2' )
					+ '</label>'
				+ '</div>'
				+ '<label for="fb-PE-createPE">'
					+ '<input type="checkbox" id="fb-PE-createPE" /> ' + fb.message( 'fb-dialog-PE-create' )
					+ '<span id="fb-PE-createPE-warning"><br />' + fb.message( 'fb-dialog-PE-warning' ) + '</span>'
				+ '</label>'
				+ '<textarea id="fb-PE-createPE-justification" placeholder="' + fb.message( 'fb-dialog-PE-reason' ) + '"></textarea>'
			+ '</div>',
		buttons: buttons
	} );
 
	$( '#fb-PE-createPE' ).click( function() {
		$justification = $( '#fb-PE-createPE-justification' );
 
		if ( $justification.css( 'display' ) === 'none' ) {
			$justification.show( 'fast' );
		} else {
			$( '#fb-PE-createPE-warning' ).hide();
			$justification.hide( 'fast' ).removeClass( 'fb-fill-field' ).val( '' );
		}
	} );
 
	$( '#fb-PE-sendWarning' ).click( function() {
		$warnType = $( '#fb-PE-sendWarning-type' );
 
		if ( $warnType.css( 'display' ) === 'none' ) {
			$warnType.show( 'fast' );
		} else {
			$( 'input[name="fb-PE-sendWarning-type"]' ).attr( 'checked', false );
			$warnType.hide( 'fast' ).removeClass( 'fb-fill-field' );
		}
	} );
};
 
/**
 * Prompt to the tag "Em manutenção"
 */
fb.Prompt.prototype.maintenance = function() {
	var $justification,
		button = {};
 
	button[ fb.message( 'fb-OK' ) ] = function() {
		$justification = $( '#fb-maintenance-justification-field' );
 
		if ( $justification.val() === '' ) {
			return $justification.addClass( 'fb-fill-field' );
		}
 
		fb.notify( fb.message( 'fb-notify-editingSomePage', 'Wikipédia:Páginas precisando de manutenção' ) );
 
		fb.editPage( {
			title: 'Wikipédia:Páginas precisando de manutenção',
			section: 'new',
			sectiontitle: '[[' + fb.pageName.replace( /_/g, ' ' ) + ']]',
			watchlist: 'preferences',
			minor: true,
			summary: fb.message( 'fb-summary-maintenance', fb.pageName.replace( /_/g, ' '  ) ) +  fb.summaryDefault,
			text: $justification.val() + ' ~~' + '~~',
			done: function() {
				fb.refreshPage();
			}
		} );
 
		$( this ).dialog( 'close' );
	};
 
	fb.dialog( {
		width: 380,
		content: '<div id="fb-maintenance-justification">'
				+ '<label for="fb-maintenance-justification-field">' + fb.message( 'fb-dialog-pageSituation' ) + ':<br />'
					+ '<textarea id="fb-maintenance-justification-field" placeholder="' + fb.message( 'fb-dialog-placeholderDefault' ) + '"></textarea>'
				+ '</label>'
			+ '</div>',
		buttons: button
	} );
};
 
window.fastButtons = new FastButtons();
 
if ( mw.util.getParamValue( 'printable' ) !== 'yes' ) {
	$.getScript( '//pt.wikipedia.org/w/index.php?title=MediaWiki:Gadget-fastbuttons.js/buttonsList.js&action=raw&ctype=text/javascript&smaxage=21600&maxage=86400' ).done( function() {
		fb.summaryDefault = fb.message( 'fb-summarySufix' );
		fb.buttons = window.fastButtons.buttons;
 
		// Executes the gadget when document is ready
		$( fb.init );
	} );
}
 
}( mediaWiki, jQuery, window ) );