MediaWiki:Gadget-fastbuttons.js: diferenças entre revisões

Origem: Wikipédia, a enciclopédia livre.
Conteúdo apagado Conteúdo adicionado
m Revertidas edições por !Silent para a última versão por Opraco, de 21h24min de 10 de março de 2013 (UTC)
m Repondo patrulhamento automático e já utilizando a API.
Linha 13: Linha 13:


var fb = {
var fb = {
version: /*{{subst:Autossubstituição/Estampa com data e hora|js|.*/ '2013-03-10 23:53:33 (UTC)' /*}}.*/,
version: /*{{subst:Autossubstituição/Estampa com data e hora|js|.*/ '2013-03-12 01:38:10 (UTC)' /*}}.*/,
submenu: {},
submenu: {},
process: {},
process: {},
Linha 649: Linha 649:
}
}
}
}
};

/* Patrol the edit currently displayed
* @param {function()} succes Callback function to be executed after the edit is pattroled
*/
fb.patrolRevision = function( rcid, success ) {
$.getJSON(
mw.util.wikiScript( 'api' ), {
format: 'json',
action: 'query',
list: 'recentchanges',
rctoken: 'patrol',
rcprop: '',
rclimit: '1'
},

function( data ) {
var query = data.query,
rc = query && query.recentchanges,
token = rc && rc[ 0 ] && rc[ 0 ].patroltoken;

if ( !token ) {
mw.log( 'Não foi possível obter um token para patrulhar a edição.' );

return false;
}

if ( !rcid ) {
mw.log( 'Não foi possível identificar a edição a ser patrulhada.' );

return false;
}

$.post(
mw.util.wikiScript( 'api' ), {
action: 'patrol',
format: 'json',
token: token,
rcid: rcid
},

function( data ) {
if ( data.error ) {
mw.log( 'Não foi possível patrulhar a edição: ' + data.error.info );

return false;
}

if ( $.isFunction( success ) ) {
success();
}

mw.log( 'A edição foi marcada como patrulhada.' );

return true;
}
).error( function() {
alert( 'Houve um erro inesperado ao usar a API do MediaWiki.' );

return false;
} );
}
).error( function() {
alert( 'A API retornou um erro ao tentar obter um token para patrulhar a edição.' );

return false;
} );
};
};


Linha 970: Linha 903:
}
}


var $patrol, rcid,
var rcid;
data = {
action: 'edit',
fastb: code
};


switch ( action ) {
switch ( action ) {
case 'view':
case 'view':
rcid = mw.util.getParamValue(
if ( extraText ) {
'rcid',
data.fbtxt = extraText;
mw.util.$content.find( 'div.patrollink a' ).attr( 'href' ) || ''
);

if ( rcid ) {
mw.notify( 'Patrulhando a página...' );
fb.callAPI( 'patrol', rcid );
}
}

$patrol = mw.util.$content.find( 'span.patrollink a' ).first();
rcid = mw.util.getParamValue( 'rcid', $patrol.attr( 'href' ) || '' );


mw.notify( 'Obtendo o conteúdo da página...' );
mw.notify( 'Obtendo o conteúdo da página...' );
Linha 1 027: Linha 959:
* @param {string} code An abreviation such as "esb", "PV",
* @param {string} code An abreviation such as "esb", "PV",
*/
*/
fb.callAPI = function( code ) {
fb.callAPI = function( code, extra ) {
var esb, esbText, esbText2, apiParams, callbacks;
var esb, esbText, esbText2, apiParams, callbacks;


Linha 1 071: Linha 1 003:
ucprop: 'timestamp',
ucprop: 'timestamp',
ucuser: title.split( '/' )[ 0 ]
ucuser: title.split( '/' )[ 0 ]
},

patrol: {
list: 'recentchanges',
rctoken: 'patrol',
rclimit: '1',
rcid: extra,
token: mw.user.tokens.get( 'patrolToken' )
}
}
};
};
Linha 1 100: Linha 1 040:


apiParams[ code ].format = 'json';
apiParams[ code ].format = 'json';
apiParams[ code ].action = 'query';
apiParams[ code ].action = code === 'patrol' ? 'patrol' : 'query';


$.getJSON(
$.post(
mw.util.wikiScript( 'api' ),
mw.util.wikiScript( 'api' ),
apiParams[ code ],
apiParams[ code ],
Linha 1 112: Linha 1 052:
}
}


callbacks[ code ]( data.query, code, data );
if ( code !== 'patrol' ) {
callbacks[ code ]( data.query, code, data );
}
}
}
);
);
Linha 1 716: Linha 1 658:
}
}
] );
] );

// FIXME: Use API to patrol, because pseudo actions may be dangerous
// @see [[commons:Commons:Administrators' noticeboard/Archive 34#MediaWiki:Gadget-autodel.js]]
if ( action === 'markpatrolled' && param !== null ) {
location.href = mw.util.wikiGetlink( pageName )
+ '?action=edit&fastb=' + param;
}


fb.$menu.find( 'a' ).tipsy();
fb.$menu.find( 'a' ).tipsy();

Revisão das 01h38min de 12 de março de 2013

/** 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: Outros editores que aparecem no histórico
 * @source: [[en:User:Macy/FastButtons.js]] ([[en:Special:PermaLink/230473471]])
 * @source: [[es:Special:PrefixIndex/User:Racso/FB]]
 */
/*jslint browser: true, white: true, devel: true, continue: true, regexp: true */
/*global mediaWiki, jQuery */

( function( mw, $ ) {
'use strict';

var	fb = {
		version: /*{{subst:Autossubstituição/Estampa com data e hora|js|.*/ '2013-03-12 01:38:10 (UTC)' /*}}.*/,
		submenu: {},
		process: {},
		$menu: $( '<div id="fb-menu"></div>' ),
		$submenu: $( '<div id="fb-submenu"></div>' )
	},
	nsNum = mw.config.get( 'wgNamespaceNumber' ),
	title = mw.config.get( 'wgTitle' ),
	pageName = mw.config.get( 'wgPageName' ),
	api = new mw.Api(),
	$textBox = $( '#wpTextbox1' ),
	action = mw.config.get( 'wgAction' );

/* 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)
 *			 an Array of this kind of objects
 *		 (Defaults to fb.$menu if the it is not an instance of jQuery)
 * @param {{action: (string|function()), text: string, title: string, prompt: string, label: string, disable: boolean, after: string}=}
 *		 buttons Atributes and other information for the new button
 * @return {boolean} true Not useful so far
 */
fb.addButton = function( $target, buttons ) {
	var	i, comment, props, button,
		doNothing = function( event ) {
			event.preventDefault();
		},
		buttonClick = function( btn ) {
			return function( event ) {
				var	promptCallback = function( comment ) {
						if ( $.isFunction( btn.action ) ) {
							btn.action();
						} else {
							fb.run( btn.action, comment );
						}
					},
					question = ( typeof btn.action === 'string'
						&& btn.action.substr( 0, 2 ) === 'ER' )
						? 'Se necessário, coloque uma observação.'
						: btn.prompt;

				event.preventDefault();

				if ( question ) {
					comment = fb.nicePrompt( question, btn.label, promptCallback );
				} else {
					promptCallback( comment );
				}
			};
		};

	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 ];
	}

	for ( i = 0; i < buttons.length; i += 1 ) {
		button = buttons[ i ];
		props = {
			title: button.title,
			text: button.text
		};

		if ( button.disable ) {
			props[ 'class' ] = 'fb-button fb-disabled-button';
			props.click = doNothing;
		} else {
			props[ 'class' ] = $.isFunction( button.action )
				? 'fb-button fb-menu-button'
				: 'fb-button fb-action-button';
			props.click = buttonClick( button );
		}

		if ( button.after && $( '.fb-button' ).length ) {
			$( '.fb-button' ).eq( button.after ).after( $( '<a></a>', props ) );
		} else {
			$( '<a></a>', props ).appendTo( $target ).after( ' ' );
		}
	}

	return true;
};

fb.addFieldForOtherESROptions = function() {
	var	$otherInput, $okButton;

	$otherInput = $( '<input type="text" id="fb-esr-input" size="55" />' )
		.keypress( function( event ) {
			fb.ok( event, 'ESR', $( this ) );
		} );

	$okButton = $( '<input type="button" value="OK" />' )
		.mousedown( function() {
			fb.ok( 'ok', 'ESR', $( '#fb-esr-input' ) );
		} );

	fb.$submenu.append( 'outra: ', $otherInput, ' ', $okButton );
};

fb.addFieldForStubs = function() {
	var	$stubInput, $okButton;

	$stubInput = $( '<input id="fb-esb-input" size="14" />' )
		.keyup( function() {
			fb.callAPI( 'esb' );
		} )
		.keypress( function( event ) {
			fb.ok( event, 'esb', $( this ) );
		} );

	$okButton = $( '<input type="button" value="OK" />' )
		.mousedown( function() {
			fb.ok( 'ok', 'esb', $( '#fb-esb-input' ) );
		} );

	fb.$submenu.append( ' esboço-', $stubInput, ' ', $okButton );
};

/*** Submenu [ER] ***/
fb.submenu.ER = [ {
		action: 'ER|1',
		text: '1',
		title: 'Marcar subpágina do próprio usuário para eliminação',
		disable: true
	}, {
		action: 'ER|5',
		text: '5',
		title: 'Aparecimento recorrente (se o conteúdo for igual ao eliminado por consenso)'
	}, {
		action: 'ER|6',
		text: '6',
		title: 'Título é SPAM',
		disable: $.inArray( nsNum, [ 0, 102 ] ) === -1
	}, {
		action: 'ER|7',
		text: '7',
		title: 'Próprio criador reconhece que se enganou'
	}, {
		action: 'ER|8',
		text: '8',
		title: 'Eliminações temporárias sem perda de histórico para resolver problemas técnicos',
		disable: $.inArray( 'sysop', mw.config.get( 'wgUserGroups' ) ) === -1
	}, {
		action: 'ER|9',
		text: '9',
		title: 'Eliminar redirect, página sem histórico relevante' +
			' (mover página redirecionada para cá)'
	}, {
		action: 'ER|10',
		text: '10',
		title: 'Namespaces que não existem (WikipÉdia, AjUda)',
		disable: nsNum !== 0
	}, {
		action: 'ER|11',
		text: '11',
		title: 'Má configuração do teclado (Página, Usuário:Sicrano)'
	}, {
		action: 'ER|12',
		text: '12',
		title: 'Imagens, somente por quem a carregou',
		disable: nsNum !== 6
	}, {
		action: 'ER|13',
		text: '13',
		title: 'Páginas sem histórico relevante que são violações flagrantes de' +
			' direitos autorais de outras páginas na internet.',
		disable: $.inArray( nsNum, [ 0, 102 ] ) === -1
	}, {
		action: 'ER|14',
		text: '14',
		title: 'Ficheiros (arquivos) duplicados',
		disable: nsNum !== 6
	}, {
		action: 'ER|17',
		text: '17',
		title: 'Salto de domínio'
	}, {
		action: 'ER|18',
		text: '18',
		title: 'Discussão cujos artigos não existem',
		disable: nsNum !== 1
	}, {
		action: 'ER|19',
		text: '19',
		title: 'Ficheiros (domínio Ficheiro:) que não são som, imagem ou vídeo',
		disable: nsNum !== 6
	}, {
		action: 'ER|20',
		text: '20',
		title: 'Impróprio'
	}, {
		action: 'ER|21',
		text: '21',
		title: 'Página de eliminação de um artigo antes de passados 6 meses da última consenso',
		disable: pageName.indexOf( 'Wikipédia:Páginas_para_eliminar/' ) !== 0
	}, {
		action: 'ER|A1',
		text: 'A1',
		title: 'Páginas com o título malformatado, absurdo, com palavras que não' +
			' o são, com erros devidos à má configuração do teclado, com codificação' +
			' incorreta do sistema ou que expressem domínios que não existem.',
		disable: $.inArray( nsNum, [ 0, 102 ] ) === -1
	}, {
		action: 'ER|C1',
		text: 'C1',
		title: 'Categorias vazias, desnecessárias ou substituídas',
		disable: nsNum !== 14
	}, {
		action: 'ER|D1',
		text: 'D1',
		title: 'Discussões de páginas inexistentes',
		disable: nsNum % 2 === 0
	}, {
		action: 'ER|D2',
		text: 'D2',
		title: 'Discussões de páginas para eliminação ou com histórico irrelevante',
		disable: nsNum % 2 === 0
	}, {
		action: 'ER|U1',
		text: 'U1',
		title: 'Uso impróprio da página de usuário',
		disable: $.inArray( nsNum, [ 2, 3 ] ) === -1
	}, {
		action: 'ER|U2',
		text: 'U2',
		title: 'Página de usuário criada por outro usuário',
		disable: nsNum !== 2
	}, {
		action: 'ER|P1',
		text: 'P1',
		title: 'Predefinições vazias, desnecessárias ou substituídas',
		disable: nsNum !== 10
	}, {
		action: 'ER|R1',
		text: 'R1',
		title: 'Redirecionamento indevido, desnecessário, sem afluentes,' +
			' para páginas inexistente ou eliminadas'
	}, {
		action: 'ER|R2',
		text: 'R2',
		title: 'Redirecionamento de página de discussão sem afluentes',
		disable: nsNum % 2 === 0
	}
];

/*** Submenu [ESR] ***/
fb.submenu.ESR = [ {
		action: 'subst:ESR-banda|1=~~' + '~~',
		text: 'banda',
		title: 'Artigo sobre banda sem fontes e sem notoriedade'
	}, {
		action: 'subst:ESR-bio|1=~~' + '~~',
		text: 'biografia',
		title: 'Biografia sem fontes e sem notoriedade'
	}, {
		action: 'subst:ESR-empresa|1=~~' + '~~',
		text: 'empresa',
		title: 'Empresa sem fontes e sem notoriedade'
	}, {
		action: 'subst:ESR-matrad|1=~~' + '~~|língua=',
		prompt: 'Dados adicionais',
		label: 'Idioma da tradução (apenas a sigla)',
		text: 'má-tradução',
		title: 'Página com má-tradução'
	},

	fb.addFieldForOtherESROptions
];

/*** Submenu [esboço] ***/
fb.submenu.esb = [ {
		action: 'esboço',
		text: 'esboço',
		title: 'Artigo ainda pouco desenvolvido'
	},

	fb.addFieldForStubs
];

/*** Submenu [manuteção] ***/
fb.submenu.man = [ {
		action: 'subst:wkf',
		text: 'wikificar',
		title: 'Não está formatado de acordo com o livro de estilo'
	}, {
		action: 'subst:s-fontes',
		text: 'sem fontes',
		title: 'Página não cita nenhuma fonte ou referência'
	}, {
		action: 'subst:s-cat',
		text: 'sem cat',
		title: 'Página não está em nenhuma categoria'
	}, {
		action: 'subst:rec',
		text: 'reciclagem',
		title: 'Página precisa ser reciclada de acordo com o livro de estilo'
	}, {
		action: 'parcial',
		text: 'parcial',
		title: 'Artigo possui passagens que não respeitam o princípio da imparcialidade'
	}, {
		action: 'subst:ctx',
		text: 'contexto',
		title: 'Página carece de contexto'
	}, {
		action: 'controverso|artigo',
		text: 'controverso',
		title: 'controverso devido às disputas sobre o seu conteúdo'
	}, {
		action: 'subst:f-referências',
		text: 'formatar referências',
		title: 'Artigo contém referências que necessitam de formatação'
	}, {
		action: 'subst:m-notas',
		text: 'mais notas',
		title: 'Página cita fontes fiáveis, mas não cobre todo o texto'
	}, {
		action: 'subst:s-notas',
		text: 'sem notas',
		title: 'Existem fontes no final da página, mas não são citadas no corpo do artigo'
	}, {
		action: 'subst:s-fontes-bpv',
		text: 'bpv sem fontes',
		title: 'Biografia de pessoa viva que não cita nenhuma fonte'
	}, {
		action: 'subst:fpr',
		text: 'fonte primária',
		title: 'Artigo necessita de fontes secundárias fiáveis publicadas por terceiros'
	}, {
		action: 'subst:fu',
		text: 'fusão',
		title: 'Artigo necessita de fusão',
		prompt: 'Com qual página esta deve ser feita fusão?',
		label: 'Página'
	}, {
		action: 'subst:f-de',
		text: 'fusão de',
		title: 'Artigo necessita de fusão',
		prompt: 'De qual página esta deve ser feita fusão?',
		label: 'Página'
	}, {
		action: 'subst:f-com',
		text: 'fusão com',
		title: 'Artigo necessita de fusão',
		prompt: 'Com qual página esta deve ser feita fusão?',
		label: 'Página'
	}
];

/*** Submenu [aviso] ***/
fb.submenu.warn = [ {
		action: 'subst:bem-vindo IP',
		text: 'BV-IP',
		title: 'Boas-vindas para usuário(a) não registrado(a)'
	}, {
		action: 'subst:bem-vindo',
		text: 'BV',
		title: 'Bem-vindo(a) à Wikipédia'
	}, {
		action: 'subst:bem-vinda',
		text: 'BVª',
		title: 'Bem-vinda à Wikipédia'
	}, {
		action: 'subst:bv-av',
		text: 'av-BV-IP',
		title: 'Aviso sobre erro em artigo e boas-vindas para usuário(a) não registrado(a)',
		prompt: 'Aviso sobre qual artigo?',
		label: 'Artigo'
	}, {
		action: 'subst:bv-av-registrado',
		text: 'av-BV',
		title: 'Aviso sobre erro em artigo e boas-vindas para usuário(a) registrado',
		prompt: 'Aviso sobre qual artigo?',
		label: 'Artigo'
	}, {
		action: 'subst:aviso-ER',
		text: 'av-ER',
		title: 'Aviso sobre eliminação rápida',
		prompt: 'Qual página foi proposta para eliminação?',
		label: 'Página'
	}, {
		action: 'subst:av-bv-ER',
		text: 'av-BV-ER',
		title: 'Aviso sobre eliminação rápida + boas-vindas',
		prompt: 'Qual página foi proposta para eliminação?',
		    label: 'Página'
	}, {
		action: 'subst:aviso-ESR',
		text: 'av-ESR',
		title: 'Aviso sobre eliminação semirrápida',
		prompt: 'Qual página foi proposta para eliminação?',
		label: 'Página'
	}, {
		action: 'subst:aviso-PE',
		text: 'av-PE',
		title: 'Aviso sobre eliminação por consenso',
		prompt: 'Qual página foi proposta para eliminação?',
		label: 'Página'
	}, {
		action: 'subst:bv-propaganda',
		text: 'prop-BV',
		title: 'Caro editor,por favor não faça propaganda, [...] Apesar disso, bem-vindo à Wikipédia'
	}, {
		action: 'subst:propaganda',
		text: 'prop',
		title: 'Caro editor, por favor não faça propaganda...',
		prompt: 'Em que página foi feita propaganda?',
		label: 'Página'
	}, {
		action: 'subst:aviso',
		text: 'av',
		title: 'Aviso sobre erro em artigo',
		prompt: 'Aviso sobre qual artigo?',
		label: 'Artigo'
	}, {
		action: 'subst:aviso2',
		text: 'av2',
		title: 'Aviso sobre vandalismo',
		prompt: 'Qual página foi vandalizada?',
		label: 'Página'
	}, {
		action: 'subst:BSRE',
		text: 'BSRE',
		title: 'Aviso de biografia sem relevo enciclopédico',
		prompt: 'Qual artigo?',
		label: 'Artigo'
	}, {
		action: 'subst:cópia',
		text: 'cópia',
		title: 'Aviso sobre artigo copiado de fonte externa/VDA',
		prompt: 'Qual a página da Wikipédia? E qual a URL da página copiada?',
		label: 'Página|2=URL'
	}, {
		action: 'subst:linguagem incorreta',
		text: 'linguagem',
		title: 'Não insulte nem use linguagem inadequada em artigos ou discussões'
	}, {
		action: 'subst:ortografia',
		text: 'ortografia',
		title: 'Não mude a versão da língua',
		prompt: 'Em qual artigo a versão da língua foi alterada?',
		label: 'Artigo'
	}, {
		action: 'subst:mostrar previsão',
		text: 'salvamento sucessivo',
		title: 'Não faça salvamentos sucessivos, utilize o botão \'Mostrar previsão\'',
		prompt: 'Em que artigo foram feitos salvamentos sucessivos?',
		label: 'Página'
	}, {
		action: 'subst:av-boas vindas',
		text: 'aviso-BV',
		title: 'Não dê boas-vindas a usuários que não contribuíram com pelo menos uma edição válida'
	}, {
		action: 'subst:av-página de usuário',
		text: 'av-PU',
		title: 'Considere refazer a página de usuário(a)'
	}, {
		action: 'subst:não remova',
		text: 'não remova',
		title: 'Não remova marcações de eliminação das páginas',
		prompt: 'Qual página em que a marcação de eliminação foi removida?' +
			'Se desejar, pode especificar o tipo de marcação.',
		label: 'Página|2=Tipo de marcação[true]'
	}, {
		action: 'subst:autobiografia',
		text: 'autobiografia',
		title: 'Não crie autobiografias',
		prompt: 'Qual autobiografia foi criada?',
		label: 'Página'
	}, {
		action: 'subst:av-teste',
		text: 'av-teste',
		title: 'Não faça testes nos artigos',
		prompt: 'Qual o nível do aviso? E em que página foram feitos testes?',
		label: 'Nível|2=Página'
	}, {
		action: 'subst:av-data',
		text: 'av-data',
		title: 'Não insira seu nome e data de nascimento em páginas de datas',
		prompt: 'Em que página de data foram inseridos o nome e a data de nascimento?',
		label: 'Página'
	}, {
		action: 'subst:bloqueado',
		text: 'bloqueado',
		title: 'Notificação de bloqueio',
		prompt: 'Especifique o tempo e o motivo do bloqueio.',
		label: 'Tempo|2=Motivo'
	}, {
		action: 'subst:bloqueado-disc',
		text: 'bloqueado-disc',
		title: 'Notificação de bloqueio com discussão',
		prompt: 'Especifique o tempo e o motivo do bloqueio.',
		label: 'Tempo|2=Motivo'
	}, {
		action: 'subst:bloqueado-CPV',
		text: 'bloqueado-CPV',
		title: 'Notificação de bloqueio para contas para vandalismo'
	}, {
		action: 'proxy',
		text: 'proxy',
		title: 'Notificação de proxy bloqueado'
	}, {
		action: 'subst:cite fonte',
		text: 'citar fontes',
		title: 'Faltou citar fontes à página',
		prompt: 'Qual foi a página?',
		label: 'Página'
	}
];

/** Submenu [busca] **/
fb.submenu.search = function() {
	var	i,
		$searchOptions = $( '<span class="plainlinks"></span>' ),
		search = encodeURIComponent(
			title.indexOf( ' ' ) !== -1
				? '"' + title + '"'
				: title
		),
		list = [ {
			text: 'Google',
			desc: 'Pesquisar o título desta página no Google',
			url: '//www.google.com/search?&as_eq=wikipedia&as_epq=',
			after: ' — '
		}, {
			text: 'notícias',
			desc: 'Pesquisar o título desta página no Google Notícias',
			url: '//news.google.com/archivesearch?&as_src=-newswire+-wire+-presswire+-PR+-press+-release&as_epq=',
			after: ', '
		}, {
			text: 'livros',
			desc: 'Pesquisar o título desta página no Google Livros',
			url: '//books.google.com/books?&as_brr=0&as_epq=',
			after: ', '
		}, {
			text: 'acadêmico',
			desc: 'Pesquisar o título desta página no Google Acadêmico',
			url: '//scholar.google.com/scholar?as_epq=',
			after: ' — '
		}, {
			text: 'Scirus',
			desc: 'Pesquisar o título desta página no Scirus',
			url: '//www.scirus.com/srsapp/search?t=all&sort=0&g=s&q='
		} ];

	for ( i = 0; i < list.length; i += 1 ) {
		$searchOptions.append( $( '<a></a>', {
			'class': 'external text',
			'href': list[ i ].url + search,
			'text': list[ i ].text,
			'title': list[ i ].desc
		} ) );

		if ( list[ i ].after ) {
			$searchOptions.append( list[ i ].after );
		}
	}

	fb.$submenu.append( $searchOptions );
};

/** Submenu [CatScan] **/
fb.submenu.cat = function() {
	var	i,
		list = [ {
				text: 'sem fontes',
				desc: 'Procurar páginas desta categoria que precisam de fontes',
				url: 'ts&templates=Sem-fontes'
			}, {
				text: 'revisão',
				desc: 'Procurar páginas desta categoria que precisam de revisão',
				url: 'ts&templates=Revis%C3%A3o'
			}, {
				text: 'wikificação',
				desc: 'Procurar páginas desta categoria que precisam de wikificação',
				url: 'ts&templates=Wikifica%C3%A7%C3%A3o'
			}, {
				text: 'menos de 1 000 bytes ou 4 links',
				desc: 'Procurar páginas desta categoria que possuem menos de 1 000 bytes ou 4 links',
				url: 'ss&size=1000&stubop=or&links=4'
			}, {
				text: 'menos de 500 bytes ou 2 links',
				desc: 'Procurar páginas desta categoria que possuem menos de 500 bytes ou 2 links',
				url: 'ss&size=500&stubop=or&links=2'
		} ],
		catScanUrl = '//toolserver.org/~daniel/WikiSense/CategoryIntersect.php?' +
			$.param( {
				wikilang:  mw.config.get( 'wgContentLanguage' ),
				wikifam: '.wikipedia.org',
				userlang: mw.config.get( 'wgUserLanguage' ),
				basecat: title,
				basedeep: '1',
				go: 'Examinar',
				format: 'html',
				mode: ''
			} );

	fb.$submenu.append( 'Procurar nesta categoria:' );

	for ( i = 0; i < list.length; i += 1 ) {
		fb.$submenu.append( ' ', $('<a></a>', {
			'class': 'fb-button',
			'href': catScanUrl + list[ i ].url,
			'text': list[ i ].text,
			'title': list[ i ].desc
		} ) );
	}
};

// FIXME: Consider using jQuery: $('#target').keypress()
fb.ok = function( event, option, $input ) {
	if ( window.event && window.event.keyCode === 13 ) {
		event = 'ok';
	} else if ( event && event.which === 13 ) {
		event = 'ok';
	}

	if ( event === 'ok' ) {
		if ( $input.val() === '' ) {
			return $input.addClass( 'fb-fill-field' );
		}

		$input.removeClass( 'fb-fill-field' );

		if ( option === 'esb' ) {
			fb.run( 'esboço-' + $( '#fb-esb-input' ).val() );
		} else if ( option === 'ESR' ) {
			fb.run( 'subst:ESR', $( '#fb-esr-input' ).val() + ' ~~' + '~~' );
		}
	}
};

fb.manipulateTextPage = function( code, extraText, value, isEditPage ) {
	var	isEliminationTag = code.search( /ES?R/ ) !== -1
			&& code.search( /ER\|(1|7|8|9|12|18|C1|D1|D2|U1|U2|R1|R2)/ ) === -1,
		// FIXME: Move this to the definition of each button
		summaries = {
			'subst:VDA': 'Página marcada como [[WP:VDA|VDA]]',
			'subst:apagar': 'Página proposta para [[WP:Eliminação' +
				' por consenso|eliminação por consenso]]',
			'subst:s-fontes': 'Página marcada como sem fontes',
			'subst:s-cat': 'Página marcada como sem categoria',
			'subst:wkf': 'Página marcada para [[WP:WKF|wikificação]]',
			'subst:rec': 'Página marcada para [[WP:RECI|reciclagem]]',
			'parcial': 'Página marcada como parcial',
			'subst:ctx': 'Página marcada como sem contexto',
			'controverso|artigo': 'Marcado como controverso',
			'subst:f-referências': 'Marcado que existem referências sem formatação',
			'subst:m-notas': 'Marcado que carece de mais fontes',
			'subst:s-notas': 'Página marcada como sem notas',
			'subst:s-fontes-bpv': 'Marcado como [[WP:BPV|biografia de pessoa viva]] sem fontes',
			'subst:fpr': 'Página marcada como sem fontes secundárias fiáveis',
			'subst:ESR': 'Página proposta para [[WP:ESR|eliminação semirrápida]]',
			'subst:suspeito': 'Página marcada como suspeita de [[WP:VDA|VDA]]',
			'subst:fu': 'Página marcada para [[WP:Fusão|fusão]]',
			'subst:f-de': 'Página marcada para [[WP:Fusão|fusão]]',
			'subst:f-com': 'Página marcada para [[WP:Fusão|fusão]]',
			'não remova': 'Aviso sobre remoção de marcações de eliminação das páginas'
		},
		reloadPage = function() {
			location.href = mw.util.wikiGetlink() + '?fastb=success';
		},
		refreshPage = function() {
			if ( action === 'view' ) {
				reloadPage();
			} else if ( $.inArray( action, [ 'edit', 'submit' ] ) !== -1 ) {
				$( '#editform' )
					.unbind( 'submit' )
					.trigger( 'submit' );
			}
		},
		sendWarn = function( template ) {
			if ( !template ) {
				return refreshPage();
			}

			$.getJSON(
				mw.util.wikiScript( 'api' ),
				'action=query&prop=revisions&rvprop=user|comment|timestamp&rvlimit=2&rvdir=newer&titles=' + pageName + '&format=json'
			).done( function( data ) {
				var	query = data.query.pages[ mw.config.get( 'wgArticleId' ) ].revisions,
					userPageCreator = query[ 0 ].user;

				if ( userPageCreator === mw.config.get( 'wgUserName' )
					|| ( query.length === 1 && query[ 0 ].comment.search( /moveu \[\[.+?\]\] para \[\[.+?\]\]/ ) !== -1 )
					|| ( ( mw.util.isIPv4Address( userPageCreator ) || mw.util.isIPv6Address( userPageCreator ) )
						&& ( Date.parse( query[ 0 ].timestamp ) + 86400000 ) < new Date().getTime()
					)
				) {
					reloadPage();

					return;
				}

				mw.notify( 'Enviando a notificação para o criador...' );

				api.editPage( {
					watchlist: 'preferences',
					minor: true,
					title: 'User talk:' + userPageCreator,
					appendtext: '\n\n{' + '{subst:Aviso-' + template + '}} ~~' + '~~',
					summary: summaries[ template ] || 'Aviso sobre a eliminação da página "[[' + pageName.replace( /_/g, ' ' ) + ']]" (usando [[WP:FB|FastButtons]])',
					done: function() {
						refreshPage();
					}
				} ).fail( function() {
					alert( 'Erro ao tentar enviar a notificação de eliminação.' );
				} );
			} );
		},
		showDialog = function() {
			$( '<div id="fb-nprompt-dialog" class="ui-widget"></div>' )
				.append(
					'<select id="fb-send-message">'
						+ '<option value="1">Enviar um aviso de eliminação</option>'
						+ '<option value="2">Enviar um aviso de remoção de marcações de eliminação nas páginas</option>'
						+ '<option value="3">Não enviar nada</option>'
					+ '</select><br /><br />'
				)
				.dialog( {
					title: 'Selecione uma opção abaixo: ',
					width: 500,
					height: 150,
					open: function() {
						$( '.ui-dialog-titlebar-close' ).hide();
					},
					buttons: {
						'OK': function() {
							switch ( $( '#fb-send-message option:selected' ).index() ) {
								case 0:
									sendWarn( 'E' + ( code.indexOf( 'ESR' ) !== -1 ? 'S' : '' ) + 'R|' + pageName.replace( /_/g, ' ' ) );
								break;

								case 1:
									sendWarn( 'não remova' );
								break;

								case 2:
									sendWarn();
								break;
							}

							$( this ).dialog( 'close' );
						},
						'Cancelar': function() {
							$( this ).dialog( 'close' );
							refreshPage();
						}
					}
				} );
		};

	if ( code !== 'redirect'
		&& value.search( /\{\{(?:subst:)?(?:ER|ESR(?:2?|-banda|-bio|-empresa|-bsre|-organização|-matrad)|VDA|Usuário(?:\(a\))?\:Salebot\/Impróprio)[\|\}]/i ) !== -1
		&& nsNum !== 3
	) {
		alert( 'Já existe uma predefinição de eliminação nesta página.' );

		return false;
	}

	if ( code.indexOf( 'ER' ) === 0 ) {
		extraText = extraText ? '|3=' + extraText : '';
		extraText = '{' + '{' + code + '|2=~~' + '~~' + extraText + '}}\n';
		extraText = nsNum === 10 ? '<noinclude>' + extraText + '</noinclude>' : extraText;

		value = extraText + value;
		fb.save = 'Página proposta para [[WP:ER|eliminação rápida]] (regra '
				+ code.substring( 3 ) + ')';
	} else if ( code.indexOf( 'ESR-matrad' ) !== -1 ) {
		value = '{' + '{' + code + extraText.toLowerCase() + '}}\n';
		fb.save = summaries[ 'subst:ESR' ];
	} else if ( code === 'redirect' ) {
		extraText = extraText.split( '|2=' );

		if ( nsNum === 14 ) {
			if ( extraText ) {
				value = '{' + '{redirecionamento de categoria|' + extraText[ 0 ] + '|2=' + extraText[ 1 ] + '}}';
			}

			fb.save = 'Redirecionando para a [[categoria:' + extraText[ 0 ] + ']] (' + extraText[ 1 ] + ')';
		} else {
			if ( extraText ) {
				value = '#Redirecionamento [[' + extraText[ 0 ] + ']]';
			}

			fb.save = 'Feito redirecionamento para [[' + extraText[ 0 ] + ']]' + ( extraText[ 1 ] !== '' ? ' (' + extraText[ 1 ] + ')' : '' );
		}
	} else {
		extraText = extraText ? '|1=' + extraText : '';
		extraText = '{' + '{' + code + extraText + '}}';

		if ( nsNum === 3 ) {
			value += '\n\n' + extraText + ' ~~' + '~~';
		} else if ( code.indexOf( 'esboço' ) === 0 ) {
			if ( value.match( /\n\n\[\[/ ) ) {
				value = value.substring( 0, value.search( /\n\n\[\[/ ) ) + '\n\n' +
					extraText + value.substring( value.search( /\n\n\[\[/ ) );
			} else {
				value += '\n\n' + extraText;
			}

			fb.save = 'Página marcada como [[WP:EBC|esboço]]';
		} else if ( code.indexOf( 'subst:VDA' ) !== -1 ) {
			value = nsNum === 10 ? '<noinclude>' + extraText + '</noinclude>' : extraText;
		} else {
			value = extraText + '\n' + value;
			value = code.search( /subst:(apagar|ESR)/ ) !== -1 && nsNum === 10
				? '<noinclude>' + value + '</noinclude>'
				: value;
		}

		if ( nsNum === 3 ) {
			fb.save = 'Adicionando mensagem';
		} else {
			if ( code.indexOf( 'subst:ESR' ) === 0 ) {
				code = 'subst:ESR';
			}

			fb.save = summaries[ code ] || 'Adicionando marcação';
		}
	}

	if ( isEditPage ) {
		$textBox.val( value );

		if ( isEliminationTag ) {
			$( '#editform' ).submit( function( e ) {
				e.preventDefault();
				showDialog();
			} );
		}
	} else {
		$( '.fb-button' ).each( function() {
			$( this )
				.addClass( 'fb-disabled-button' )
				.unbind( 'click' );
		} );

		mw.notify( 'Editando a página...' );

		api.editPage( {
			watchlist: 'preferences',
			minor: true,
			summary: fb.save + ' (usando [[WP:FB|FastButtons]])',
			text: value,
			done: {
				success: function() {
					if ( !isEliminationTag ) {
						reloadPage();
					} else {
						showDialog();
					}
				},
				apiError: function( error ) {
					mw.notify(
						'Não foi possível editar a página.<br />A API retornou o código de erro "'
						+ error.code + '": ' + error.info + '.<br />Se o problema persistir,'
						+ ' favor informar no <a href="' + mw.util.wikiGetlink( 'WP:Café dos Programadores' ) + '">Café dos programadores</a>'
						+ ' ou em <a href="' + mw.util.wikiGetlink( 'MediaWiki Discussão:Gadget-fastbuttons.js' ) + '">MediaWiki Discussão:Gadget-fastbuttons.js</a>'
					);
				},
				unknownError: function() {
					mw.notify( 'Não foi possível editar a página devido a um erro desconhecido da API.' );
				}
			}
		} ).fail( function() {
			mw.notify( 'Não foi possível fazer uma requisição com o servidor. Verifique sua conexão com a internet.' );
		} );
	}
};

/* Função de edição
 * @param: {string} code A template name, possibly preceded by "subst:",
 *			 and optionally followed by "|" and some parameter(s)
 * @param {(string|null)=} extraText Extra text for templates and redirects (optional)
 * @return: {boolean} Returns false if the user canceled or the page already has a template
 */
fb.run = function( code, extraText ) {
	if ( extraText === null ) {
		// Do nothing if the user canceled the prompt box
		return false;
	}

	var	rcid;

	switch ( action ) {
		case 'view':
			rcid = mw.util.getParamValue(
				'rcid',
				mw.util.$content.find( 'div.patrollink a' ).attr( 'href' ) || ''
			);

			if ( rcid ) {
				mw.notify( 'Patrulhando a página...' );
				fb.callAPI( 'patrol', rcid );
			}

			mw.notify( 'Obtendo o conteúdo da página...' );

			api.getCurrentPageText().done( function( value ) {
				fb.manipulateTextPage( code, extraText, value );
			} );
		break;

		case 'edit':
		case 'submit':
			fb.manipulateTextPage( code, extraText, $textBox.val(), true );
		break;
	}
};

/* Changes the content of the submenu
 * @param {string} items The new buttons for the new submenu
 */
fb.changeSubmenu = function( items ) {
	var	i;

	fb.$submenu.empty();

	if ( !$.isArray( items ) ) {
		items = [ items ];
	}

	for ( i = 0; i < items.length; i += 1 ) {
		if ( $.isFunction( items[ i ] ) ) {
			items[ i ]();
		} else if ( typeof items[ i ] === 'string' ) {
			fb.$submenu.append( items[ i ] );
		} else {
			fb.addButton( fb.$submenu, items[ i ] );
		}
	}

	fb.$submenu.find( 'a, span' ).tipsy();
};

/* Callback function for API calls
 * @param {string} code An abreviation such as "esb", "PV",
 */
fb.callAPI = function( code, extra ) {
	var	esb, esbText, esbText2, apiParams, callbacks;

	apiParams = {
		esb: {
			list: 'allpages',
			aplimit: '1',
			apnamespace: '10'
		},

		PV: {
			list: 'watchlist',
			wlprop: 'user|comment|title|sizes',
			wlexcludeuser: mw.config.get( 'wgUserName' )
		},

		PN: {
			list: 'recentchanges',
			rctype: 'new',
			rcnamespace: '0',
			rcshow: '!patrolled',
			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',
			aufrom: title.split( '/' )[ 0 ]
		},

		anon: {
			list: 'usercontribs',
			uclimit: '500',
			ucprop: 'timestamp',
			ucuser: title.split( '/' )[ 0 ]
		},

		patrol: {
			list: 'recentchanges',
			rctoken: 'patrol',
			rclimit: '1',
			rcid: extra,
			token: mw.user.tokens.get( 'patrolToken' )
		}
	};

	callbacks = {
		esb: fb.process.stubs,
		PV: fb.process.recentEdits,
		PN: fb.process.recentEdits,
		MR: fb.process.recentEdits,
		usu: fb.process.userInfo,
		anon: fb.process.userInfo
	};

	if ( code === 'esb' ) {
		esb = $( '#fb-esb-input' ).val();

		if ( $.inArray( esb, [ esbText, esbText2 ] ) !== -1 ) {
			return;
		}

		esbText = esb;

		if ( esbText === esb.substr( 0, ( esb.length - 1 ) ) ) {
			return;
		}

		apiParams.esb.apprefix = 'Esboço-' + esb;
	}

	apiParams[ code ].format = 'json';
	apiParams[ code ].action = code === 'patrol' ? 'patrol' : 'query';

	$.post(
		mw.util.wikiScript( 'api' ),
		apiParams[ code ],
		function( data ) {
			if ( !data ) {
				mw.log( 'Não foi possível obter a lista "' + apiParams[ code ].list + '" a partir da API.' );

				return;
			}

			if ( code !== 'patrol' ) {
				callbacks[ code ]( data.query, code, data );
			}
		}
	);
};

/* Callback function for backlinks request
 * @param {Object} data JSON content returned by API
 */
fb.process.backLinks = function( data ) {
	var	backlinks, $hiddenCats, quality,
		catLine = $( '#mw-normal-catlinks' ),
		info = '(';

	info += ( document.getElementById( 'Refer.C3.AAncias' )
			|| document.getElementById( 'Notas_e_refer.C3.AAncias' ) )
		? 'ref'
		: '<span class="fb-missing" title="Esta página ainda não possui referências">ref</span>';

	// FIXME: Use the API (instead of 'screen scraping') to get this information!
	if ( catLine.length && catLine.html().indexOf( '><a href="' + mw.config.get( 'wgArticlePath' ).replace( '$1', '' ) ) !== -1 ) {
		info += ' · cat';
	} else {
		info += ' · <span class="fb-missing" title="Esta página ainda não foi categorizada">cat</span>';
	}

	info += ( $( '#p-lang' ).length ) ?
		' · iw' :
		' · <span class="fb-missing" title="Esta página ainda não'
			+ ' possui links para outros idiomas">iw</span>';

	// Afluentes
	backlinks = data.query && data.query.backlinks;

	if ( !backlinks ) {
		mw.log( 'The backlinks query returned no data.' );
	} else if ( backlinks.length ) {
		info += ' · <a href="'
			+ mw.util.wikiGetlink( 'Especial:Páginas afluentes/' + pageName )
			+ '" title="afluentes">afl</a>)';
	} else {
		info += ' · <span class="fb-missing" title="Esta página ainda não possui afluentes">afl</span>)';
	}

	fb.changeSubmenu( info );

	if ( !$( '#ca-talk' ).hasClass( 'new' ) ) {
		$.getJSON(
			mw.util.wikiScript( 'api' ), {
				format: 'json',
				action: 'query',
				prop: 'categories',
				indexpageids: '1',
				titles: mw.config.get( 'wgFormattedNamespaces' )[ nsNum + 1 ] +
					':' + title
			},
			function( data ) {
				fb.process.pageQuality( data );
			}
		);
	} else {
		$hiddenCats = $( '#mw-hidden-catlinks' );

		if ( $hiddenCats.length ) {
			quality = $hiddenCats.html();

			if ( quality.indexOf( '!Artigos de qualidade' ) !== -1 ) {
				quality = quality.substr( quality.indexOf( '!Artigos de qualidade' ) + 22, 1 );

				if ( quality === 'd' ) {
					quality = '?';
				}

				fb.$submenu.append(
					'<span title="Qualidade do artigo"> Q-<b>' +
					quality + '</b></span>'
				).find( 'a, span' ).tipsy();
			}
		}
	}
};

/* Callback function for the request of talk page categories
 * @param {Object} data JSON content returned by API
 */
fb.process.pageQuality = function( query ) {
	var	cats, pageids, i, cat, quality;

	if ( query ) {
		cats = query.pages;
		pageids = query.pageids;

		if ( cats && pageids && pageids.length ) {
			cats = cats[ pageids[ 0 ] ].categories;

			if ( !cats ) {
				mw.log( 'The categories query returned incomplete data.' );

				return false;
			}
		} else {
			mw.log( 'The categories query returned incomplete data.' );

			return false;
		}
	} else {
		mw.log( 'The categories query returned no data.' );

		return false;
	}

	// Qualidade do artigo
	for ( i = 0; i < cats.length; i += 1 ) {
		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.$submenu.append(
				'<span title="Qualidade do artigo"> Q-<b>' +
					quality + '</b></span>'
			).find( 'a, span' ).tipsy();

			break;
		}
	}
};

/* Callback function for the request of stub templates
 * @param {Object} data JSON content returned by API
 */
fb.process.stubs = function( query ) {
	var	template, start, sel, esbText2,
		esb = document.getElementById( 'fb-esb-input' );

	if ( query ) {
		template = query.allpages && query.allpages[ 0 ] && query.allpages[ 0 ].title;

		if ( !template ) {
			mw.log( 'The categories query returned incomplete data.' );

			return false;
		}

		template = template.replace( /^Predefinição:Esboço-/gi, '' );
	} else {
		mw.log( 'The categories query returned no data.' );

		return false;
	}

	if ( ( esb.setSelectionRange
		|| esb.createTextRange
		|| ( esb.selectionStart !== undefined
			&& esb.selectionEnd !== undefined
		)
	) && esb.value === template.substr( 0, esb.value.length ) ) {
		// Exibe sugestões. Baseado no script do HotCat
		start = esb.value.length;
		esb.value = template;
		esbText2 = template;

		if ( esb.setSelectionRange ) {
			esb.setSelectionRange( start, template.length );
		} else if ( esb.createTextRange ) {
			sel = esb.createTextRange();
			sel.move( 'character', start );
			sel.moveEnd( 'character', template.length - start );
			sel.select();
		} else {
			esb.selectionStart = start;
			esb.selectionEnd = template.length;
		}
	}
};

/* Callback function for the request of recent edits (from watchlist or recent changes)
 * @param {Object} data JSON content returned by API
 */
fb.process.recentEdits = function( query, code ) {
	var	listName, summaryChanges, urlParam, list, max, i,
		item, title, length, comment, j,
		pages = [],
		charnum = 0;

	listName = {
		PV: 'watchlist',
		MR: 'recentchanges',
		PN: 'recentchanges'
	};

	summaryChanges = {
		PV: [
			[ '[[Ajuda:SEA|?]]', '' ],
			[ '/*', '?' ],
			[ '*/', ':' ]
		],

		MR: [
			[ '/*', '?' ],
			[ '*/', ':' ]
		],

		PN: [
			[ '[[Ajuda:SEA|?]] ', '' ]
		]
	};

	urlParam = {
		PV: 'diff=last',
		MR: 'diff=last',
		PN: 'redirect=no&rcid='
	};

	list = query[ listName[ code ] ];
	max = ( list.length < 10 ) ? list.length : 10;

	for ( i = 0; i < max; i += 1 ) {
		item = list[ i ];

		if ( !item ) {
			continue;
		}

		title = item.title;
		charnum += title.length;

		if ( charnum > 180 ) {
			break;
		}

		length = item.newlen - item.oldlen;

		if ( length > 0 ) {
			length = '+' + length;
		}

		comment = item.comment || '';

		for ( j = 0; j < summaryChanges[ code ].length; j += 1 ) {
			comment = comment.replace(
				summaryChanges[ code ][ 0 ],
				summaryChanges[ code ][ 1 ]
			);
		}

		if ( comment ) {
			comment = '(' + comment + ')';
		}

		if ( code === 'PN' ) {
			urlParam[ code ] += item.rcid;
		}

		pages.push(
			'<a href="' + mw.util.wikiGetlink( title ) + '?' +
			urlParam[ code ] + '" title="(' + length + ') ' + item.user +
			' ' + comment + '">' + title + '</a>'
		);
	}

	fb.changeSubmenu( '<div class="horizontal">' + pages.join( ' ' ) + '</div>' );
};

/* Callback function for the request of user info
 * @param {Object} data JSON content returned by API
 */
fb.process.userInfo = function( query, code, data ) {
	var	contribs, regDate, encUser,
		user = {};

	// Informações do(a) usuário(a)
	if ( !query ) {
		mw.log( 'The categories query returned no data.' );

		return false;
	}

	if ( code === 'anon' ) {
		if ( !query.usercontribs ) {
			return;
		}

		contribs = query.usercontribs;
		user.name = contribs[ 0 ].user;
		user.editcount = contribs.length;
		user.registration = contribs[ contribs.length - 1 ].timestamp;

		if ( data[ 'query-continue' ] ) {
			user.editcount = 'mais de ' + user.editcount;
			user.registration = 'antes de ' + user.registration;
		}
	} else {
		user = query.allusers && query.allusers[ 0 ];
	}

	if ( user ) {
		// Ex.: YYYY-MM-DDThh:mm:ssZ
		regDate = user.registration;
		regDate = regDate.substr( 8, 2 ) + '/' + regDate.substr( 5, 2 ) +
			'/' + regDate.substr( 0, 4 );
		encUser = encodeURI( user.name );

		//FIXME: Simplify this!
		fb.changeSubmenu( [
				user.editcount + ' edições desde ' + regDate + '.',
				'<a class="fb-button" href="' +
					mw.util.wikiGetlink( 'Especial:Contribuições/' ) + encUser +
					'" title="Abrir a lista de contribuições deste editor" >contribuições</a>',
				'<a class="fb-button" href="' +
					mw.util.wikiGetlink( 'Especial:Registo/' ) + encUser +
					'" title="Abrir a lista de registros deste editor" >registros</a>',
				'<a class="fb-button" href="' +
					mw.util.wikiGetlink( 'Especial:Registo' ) + '?type=block&page=User%3A' + encUser +
					'" title="Abrir a lista de registros de bloqueio deste editor">registros de bloqueio</a>',
				'<span class="plainlinks"><a class="external text fb-button"' +
					'title="Abrir a contagem de edições deste editor"' +
					' href="//toolserver.org/~river/cgi-bin/count_edits?user=' +
					encUser + '&dbname=' + mw.config.get( 'wgDBname' ) + '_p">contador de edições</a></span>'
			].join( ' ' )
		);
	} else {
		return;
	}
};

fb.nicePrompt = function( title, label, callback ) {
	if ( $( '#fb-nprompt-dialog' ).length ) {
		$( '#fb-nprompt-dialog' ).dialog( 'close' );
	}

	if ( !label ) {
		label = 'Observação';
	}

	var	i,
		multipleQuestions = label.indexOf( '|2=' ),
		$dialog = $( '<div id="fb-nprompt-dialog" class="ui-widget"></div>' );

	if ( multipleQuestions !== -1 ) {
		for ( i = 1, label = label.split( /\|\d+=/ ); i <= label.length; i += 1 ) {
			$dialog.append(
				'<label for="fb-nprompt-input' + i + '">'
				+ label[ i - 1 ].replace( /\[.+\]/, '' )
				+ ': <input type="text" class="fb-field" id="fb-nprompt-input' + i + '" /></label>'
			);
		}
	} else {
		$dialog.append(
			'<label for="fb-nprompt-input">'
			+ label.replace( /\[.+\]/, '' )
			+ ': <input type="text" class="fb-field" id="fb-nprompt-input" /></label>'
		);
	}

	$dialog.dialog( {
		title: title,
		open: function() {
			$( '.ui-dialog-titlebar-close' ).hide();
		},
		close: function() {
			$( '#fb-nprompt-dialog' ).dialog( 'destroy' );
			$( '#fb-nprompt-dialog' ).remove();
		},
		buttons: {
			'OK': function() {
				var	awnsers,
					inputs = $( '#fb-nprompt-dialog input' );

				if ( label !== 'Observação' && label.length !== 1 ) {
					inputs.each( function( i ) {
						if ( $( this ).val() === '' && label[ i ].search( /\[true\]/ ) === -1 ) {
							$( this ).addClass( 'fb-fill-field' );
						} else if ( $( this ).val() !== '' && $( this ).hasClass( 'fb-fill-field' ) ) {
							$( this ).removeClass( 'fb-fill-field' );
						}
					} );
				}

				if ( $( '.fb-field' ).hasClass( 'fb-fill-field' ) ) {
					return;
				}

				if ( multipleQuestions === -1 ) {
					callback( $( '#fb-nprompt-input' ).val() );
				} else {
					for ( i = 1; i <= inputs.length; i += 1 ) {
						awnsers = ( i === 1 )
							? $( '#fb-nprompt-input1' ).val()
							: awnsers + '|' + i + '=' + $( '#fb-nprompt-input' + i ).val();
					}

					callback( awnsers );
				}

				$( this ).dialog( 'close' );
			},

			'Cancelar': function() {
				$( this ).dialog( 'close' );
			}
		},
		focus: function() {
			$( ':input', this ).keyup( function( event ) {
				if ( event.keyCode === 13 ) {
					$( '.ui-dialog-buttonpane button:first' ).click();
				}
			} );
		}
	} );
};

/* Initialize the gadget */
fb.init = function() {
	var	basePageName,
		param = mw.util.getParamValue( 'fastb' );

	if ( mw.util.getParamValue( 'printable' ) === 'yes' ) {
		return;
	}

	if ( param === 'success' ) {
		mw.notify( 'A página foi editada com sucesso.' );
	}

	if ( mw.config.get( 'skin' ) === 'modern' ) {
		$( '#contentSub' ).before( fb.$menu ).before( fb.$submenu );
	} else {
		$( 'h1' ).first().after( fb.$submenu ).after( fb.$menu );
	}

	if ( $.inArray( action, [ 'view', 'edit', 'submit' ] ) !== -1 ) {
		/*** Menu Principal ***/
		if ( nsNum !== -1 ) {
			fb.$menu.empty();

			if ( $.inArray( nsNum, [ 2, 3 ] ) !== -1
				&& 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'
				} );
			} else {
				fb.addButton( {
					action: function() {
						fb.changeSubmenu( fb.submenu.ER );
					},
					text: 'ER',
					title: 'Exibir regras para a eliminação rápida'
				} );
			}
		}

		if ( $.inArray( nsNum, [ 0, 102 ] ) !== -1 ) {
			fb.addButton( [ {
					action: 'subst:VDA',
					prompt: 'Informe o url da página copiada',
					label: 'Url',
					text: 'VDA',
					title: 'Marcar como cópia ou violação de direito autoral'
				}, {
					action: 'subst:suspeito',
					text: 'susp',
					title: 'Marcar como suspeito de violação de direitos autorais'
				}, {
					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[' + ( nsNum !== 14 ) + ']'
				}, {
					action: function() {
						fb.changeSubmenu( fb.submenu.man );
					},
					text: 'manutenção',
					title: 'Exibir predefinições para manutenção'
				}, {
					action: function() {
						fb.changeSubmenu( fb.submenu.esb );
					},
					text: 'esboço',
					title: 'Exibir predefinições para esboços'
				}, {
					action: function() {
						fb.changeSubmenu( fb.submenu.search );
					},
					text: 'busca',
					title: 'Exibir opções para a busca de fontes'
				}
			] );

			if ( action === 'view' ) {
				$.getJSON(
					mw.util.wikiScript( 'api' ), {
						format: 'json',
						action: 'query',
						list: 'backlinks',
						bllimit: '1',
						blfilterredir: 'nonredirects',
						blnamespace: '0',
						bltitle: pageName
					},
					fb.process.backLinks
				);
			}
		} else {
			if ( 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[' + ( nsNum !== 14 ) + ']'
				} );
			}

			if ( nsNum === 14 ) {
				fb.addButton( {
					action: function() {
						fb.changeSubmenu( fb.submenu.cat );
					},
					text: 'CatScan',
					title: 'Exibir opções do CatScan para procurar páginas nesta categoria'
				} );
			}
		}

		if ( $.inArray( nsNum, [ 0, 2, 6, 10, 102 ] ) !== -1 ) {
			fb.addButton( [ {
				action: function() {
					fb.changeSubmenu( fb.submenu.ESR );
				},
				text: 'ESR',
				title: 'Exibir regras para a eliminação semi-rápida',
				disable: nsNum === 2,
				after: '0'
			}, {
				action: 'subst:apagar',
				text: 'PE',
				title: 'Marcar para eliminação por consenso',
				after: '1'
			} ] );
		}

		if ( nsNum === 3 ) {
			fb.addButton( {
				action: function() {
					fb.changeSubmenu( fb.submenu.warn );
				},
				text: 'aviso',
				title: 'Exibir lista de predefinições para avisos'
			} );
		}

		if ( $.inArray( nsNum, [ 2, 3 ] ) !== -1 ) {
			basePageName = title.split( '/' )[ 0 ];

			if ( mw.util.isIPv4Address( basePageName ) || mw.util.isIPv6Address( basePageName ) ) {
				fb.addButton( {
					action: function() {
						fb.callAPI( 'anon' );
					},
					text: 'sobre o IP',
					title: 'Exibir informações sobre este IP'
				} );
			} else {
				fb.addButton( {
					action: function() {
						fb.callAPI( 'usu' );
					},
					text: 'sobre a conta',
					title: 'Exibir informações sobre esta conta'
				} );
			}
		}
	}

	fb.addButton( [ {
			action: function() {
				fb.callAPI( 'PV' );
			},
			text: 'PV',
			title: 'Exibir páginas vigiadas que foram alteradas recentemente'
		}, {
			action: function() {
				fb.callAPI( 'PN' );
			},
			text: 'PN',
			title: 'Exibir páginas novas que ainda não foram patrulhadas'
		}, {
			action: function() {
				fb.callAPI( 'MR' );
			},
			text: 'MR',
			title: 'Exibir mudanças recentes feitas por IPs em páginas do domínio principal'
		}
	] );

	fb.$menu.find( 'a' ).tipsy();
};

window.FastButtons = fb;

/* Executes the gadget when document is ready */
$( fb.init );

}( mediaWiki, jQuery ) );