MediaWiki:Gadget-wikibugs.js/Core.js

Bách khoa toàn thư mở Wikipedia

Chú ý: Sau khi lưu thay đổi trang, bạn phải xóa bộ nhớ đệm của trình duyệt để nhìn thấy các thay đổi. Google Chrome, Firefox, Internet ExplorerSafari: Giữ phím ⇧ Shift và nhấn nút Reload/Tải lại trên thanh công cụ của trình duyệt. Để biết chi tiết và hướng dẫn cho các trình duyệt khác, xem Trợ giúp:Xóa bộ nhớ đệm.

/*
 * Source: [[:pl:MediaWiki:Gadget-wikibugs.js]]
 * @author: [[:pl:User:Dodek]] (idea and text)
 * @author: [[:pl:User:Adziura]] (idea and text)
 * @author: [[:pl:User:Nux]] (implementation)
 * @author: [[:pl:User:Saper]] (implementation)
 * @author: [[:pl:User:Beau]] (implementation)
 * @author: [[:pt:User:Helder.wiki]] (implementation)
 */

/*jslint browser: true, white: true, regexp: true, devel: true, todo: true, sloppy: true*/
/*global mediaWiki, jQuery*/
( function ( mw, $ ) {
// 'use strict';

/* Translatable strings */
mw.messages.set( {
	'wikibugs-dialog-title': 'Báo lỗi',
	'wikibugs-open-form-button': 'Tiếp tục',
	'wikibugs-edit-page-button': 'Tự sửa',
	'wikibugs-cancel-button': 'Hủy',
	'wikibugs-submit-report-button': 'Gửi',
	'wikibugs-ip-address-notice': '<b>Lưu ý:</b> Địa chỉ IP của bạn sẽ được ghi lại trong lịch sử báo lỗi, hãy <a href="' + mw.util.getUrl( 'Wikipedia:Tại sao nên tạo một tài khoản?' ) + '">' +
		'mở một tài khoản</a> để tránh việc này.',
	'wikibugs-page-name-label': 'Tên bài viết:<br/><small>(nếu bạn đang báo lỗi một tập tin, hãy mở đầu bằng "Tập tin:")</small>',
	'wikibugs-report-content-label': 'Nội dung báo lỗi:<br/><small>(nếu có thể, xin kèm theo một url web hoặc tựa sách, báo kèm số trang cụ thể để chứng minh thông tin bạn muốn sửa lại là chính xác)</small>',
	'wikibugs-report-content-placeholder': 'Miêu tả càng chi tiết càng tốt về lỗi mà bạn thấy trong nội dung bài viết. Nếu có thể, hãy kèm theo một nguồn gốc rõ ràng như địa chỉ web (KHÔNG kèm "http://" NẾU bạn chưa đăng nhập) hay tựa sách, báo, v.v... Các biên tập viên Wikipedia thường sẽ nhanh chóng giúp đỡ sửa lại thông tin nếu được cung cấp đầy đủ nguồn dẫn có thể kiểm chứng được.',
	'wikibugs-signature-label': 'Chữ ký:<br/><small>(bốn ký tự <nowiki>~~~~</nowiki> sẽ tự động ký tên thay bạn)</small>',
	'wikibugs-edit-error': '',
	'wikibugs-token-error': '',
	'wikibugs-unknown-token-error': '',
	'wikibugs-ajax-error': 'Đã có lỗi xảy ra trong quá trình xử lý yêu cầu. Xin vui lòng thử lại. Hầu hết nguyên nhân là do bạn đã liên kết trực tiếp đến một trang web, hãy bỏ "http://" ra và thử lại.',
	'wikibugs-incomplete-information': 'Cần miêu tả lỗi cụ thể hơn - miêu tả hiện tại quá ngắn.',
	'wikibugs-invalid-page': 'Tên bài viết không hợp lệ hoặc chưa điền.',
	'wikibugs-reported-by': ' Người báo lỗi: $1',
	'wikibugs-file-section-line': '<!-- Phản hồi lỗi tập tin bên dưới dòng này. Lỗi mới nhất viết ở đầu. -->',
	'wikibugs-page-section-line': '<!-- Phản hồi lỗi bài viết bên dưới dòng này. Lỗi mới nhất viết ở đầu. -->',
	'wikibugs-bad-reports-text': '<p>Mẫu này <b>không dùng</b> để gửi yêu cầu viết thêm thông tin ' +
		'hay thỉnh cầu tạo bài mới. Xin xem trang:</p><ul>' +
		'<li><a href="' + mw.util.getUrl( 'Wikipedia:Bài thỉnh cầu' ) + '">' +
		'Bài thỉnh cầu</a></li></ul><p>Wikipedia không đưa ra lời khuyên nào ' +
		'theo yêu cầu. Nếu bạn có vấn đề cần được tư vấn, <b>đừng viết nó ở đây</b>.</p>' +
		'<p>Thông tin về cách thức liên lạc với Wikipedia có thể tìm thấy tại:</p>' +
		'<ul><li><a href="' + mw.util.getUrl( 'Wikipedia:Liên lạc' ) + '">Liên lạc</a></li></ul>',
	'wikibugs-article-intro': '<p style="margin-top:0px;">Bạn có thể phản hồi một hay nhiều lỗi trong ' +
		'các bài viết Wikipedia, tuy nhiên xin nhớ rằng Wikipedia là một ' +
		'<a href="' + mw.util.getUrl( 'Wiki' ) + '">wiki</a> và bạn ' +
		'luôn được khuyến khích <a href="' + mw.util.getUrl( 'Wikipedia:Táo bạo' ) + '">' +
		'mạnh dạn tự tay sửa lỗi nếu có</a>. ' +
		'Chúng tôi cũng hiểu một thực tế rằng vài độc giả Wikipedia sẽ, ' +
		'vì nhiều lý do, không thể tự tay sửa lỗi cho bài viết. ' +
		'Để lỗi nhanh chóng được sửa, xin vui lòng kèm theo một nguồn bên ngoài từ web hay sách ' +
		'chứng minh thông tin mới là chính xác. </p><p><b>Nếu bạn có thể tự sửa ' +
		'lỗi – xin đừng điền vào mẫu đơn phản hồi này.</b></p><p><b>Những phản hồi của bạn sẽ được công bố công khai – vui lòng không kèm theo bất cứ thông tin liên lạc cá nhân nào vì sự an toàn và riêng tư của bạn!</b></p>',
	'wikibugs-image-intro': '<p style="margin-top:0px;">Bạn có thể phản hồi một tập tin vi phạm bản quyền ' +
		'hoặc tập tin sai phạm ngay cả khi chúng nằm trên Wikimedia Commons.</p>' +
		'<p><b>Nếu bạn có thể tự sửa lỗi - xin đừng điền vào mẫu đơn phản hồi này.</b></p>',
	'wikibugs-already-reported-notice': '<p><b>Lưu ý:</b> Nếu bạn phản hồi xong mà nhìn thấy mục báo lỗi biến mất ' +
		'thì có thể có ai đó đã sửa lỗi này. <ul>' +
		'<li><a href="' + mw.util.getUrl( 'Wikipedia:Báo lỗi bài viết' ) + '">' +
		'Xem danh sách các lỗi vừa phản hồi</a> hoặc</li>' +
		'<li><a href="' + mw.util.getUrl( 'Wikipedia:Báo lỗi bài viết' ) + '?action=history">' +
		'lịch sử của trang báo lỗi.</a></li></ul>' +
                '<p></p> ' +
                '<b>Có thể mất nhiều ngày để lỗi mà bạn phản hồi được sửa lại, xin hãy kiên nhẫn!</b> ' +
		'<p></p> ' +
		'Với việc gửi phản hồi, bạn chấp nhận <a href="' + mw.util.getUrl( 'wmf:Terms_of_Use/vi' ) + '">' +
		'các Điều khoản Sử dụng</a> và bạn đồng ý phát hành, một cách không thể hủy bỏ, ' +
		'phản hồi của mình theo <a href="' + mw.util.getUrl( 'Wikipedia:Nguyên văn Giấy phép Creative Commons Ghi công–Chia sẻ tương tự phiên bản 3.0 Chưa chuyển đổi' ) + '">' +
		' Giấy phép Creative Commons Ghi công–Chia sẻ tương tự 3.0</a> và <a href="' + mw.util.getUrl( 'Wikipedia:Nguyên văn Giấy phép Tài liệu Tự do GNU' ) + '">' +
		' GFDL</a>. ' +
		'Bạn đồng ý rằng một siêu liên kết hoặc URL thỏa mãn điều kiện ghi công trong giấy phép Creative Commons. ' +
		'Bạn nhận thức rằng mọi phản hồi của mình sẽ được xem xét công khai.',
	'wikibugs-footer': '',
	'wikibugs-new-report': 'Phản hồi mới: $1'
} );

$.extend( mw.Api.prototype, {
	/**
	* Convinience method to get the text of the current revision of a page.
	*
	* @param title {String}
	* @param success {Function} callback to which to pass success wikitext
	* @param err {Function} callback if error (optional)
	* @return {jqXHR}
	*/
	getPageText: function( title, success, err ) {
		// TODO Allow passing a "data" object to be merged with default settings
		var params = {
				action: 'query',
				titles: title,
				prop: 'revisions',
				rvprop: 'content',
				indexpageids: ''
			},
			ok = function( data ) {
				var	query = data.query,
					pages = query && query.pages,
					pageid = query && query.pageids && query.pageids[0];
				// Based on https://github.com/Krinkle/mw-gadgets-jsUpdater/commit/b3d96a1a13d72f5022110b05de1a857c9ed64ab5
				// pageid may be -1, in that case 'text' and 'revisions' will be undefined
				if (pageid && Number(pageid) > 0 && pages[pageid]) {
					success( pages[pageid].revisions && pages[pageid].revisions[0] && pages[pageid].revisions[0]['*'] );
				} else {
					err( 'inexistent', mw.msg( 'wikibugs-error-inexistent', title ) );
				}
			};
		return this.get( params ).done( ok ).fail( err );
	},

	/**
	* Convinience method to edit a page.
	*
	* @param title {String}
	* @param ok {Function} callback to which to pass success data
	* @param err {Function} callback if error (optional)
	* @return {jqXHR}
	*/
	editPage: function( data, ok, err ) {
		var	defaultData = {
				action: 'edit',
				minor: false,
				token: mw.user.tokens.get( 'csrfToken' )
			},
			params;
		if ( data === undefined ) {
			data = {};
		}
		params = $.extend( {}, defaultData, data );
		return this.post( params ).done( ok ).fail( err );
	}
} );

var wb = {
	/**
	 * Version number of this gadget.
	 */
	version: 11,
	/**
	 * A name of a page where reports are saved.
	 */
	reportPage: 'Wikipedia:Báo lỗi bài viết',
	/**
	 * Black list of pages which reports should not refer to.
	 */
	badPages: [
		'Wikipedia:Báo lỗi bài viết'
	],
	/**
	 * Message shown on pages in the main namespace.
	 */
	articleIntro: '<div id="wbBadReports">' +
		mw.msg( 'wikibugs-bad-reports-text' ) + '</div>' +
		mw.msg( 'wikibugs-article-intro' ) +
		mw.msg( 'wikibugs-already-reported-notice' ) +
		mw.msg( 'wikibugs-footer' ),
	/**
	 * Message shown on pages in the file namespace.
	 */
	imageIntro: '<div id="wbBadReports">' +
		mw.msg( 'wikibugs-bad-reports-text' ) + '</div>' +
		mw.msg( 'wikibugs-image-intro' ) +
		mw.msg( 'wikibugs-already-reported-notice' ) +
		mw.msg( 'wikibugs-footer' ),

	/**
	 * Checks if a title of the page is valid for a report.
	 * @param title A title of the page.
	 */
	isValidPageName: function( title ) {
		// Empty title is not valid
		if ( title === '' ) {
			return false;
		}
		// Special pages are not valid too
		if ( this.getPageNamespaceNumber( title ) === -1 ) {
			return false;
		}
		// Check black list
		title = this.getRefinedPageName( title );
		return $.inArray( title, this.badPages ) === -1;
	},

	/**
	 * Returns a namespace number of a specifed page.
	 * @param title A title of the page.
	 */
	getPageNamespaceNumber: function( title ) {
		var	matches = title.match( /^([^:]+)/ ),
			key, namespaces, result;
		if ( matches ) {
			key = matches[1].replace( / /g, '_' ).toLowerCase();
			namespaces = mw.config.get( 'wgNamespaceIds' );
			result = namespaces[key];
			if ( result !== null ) {
				return result;
			}
		}
		return 0;
	},

	/**
	 * Redirects to the edit page.
	 */
	goToEditPage: function() {
		var $editLink = $( '#ca-edit' ).find( 'a' );
		window.location = $editLink.attr( 'href' ) || mw.util.getUrl( this.reportPage );
	},

	/**
	 * Shows the dialog window.
	 * @param infoHtml The message content.
	 */
	open: function( infoHtml ) {
		var	that = this,
			buttons = {},
			can_edit = document.getElementById( 'ca-edit' ) ? true : false,
			$dialog = $( '<div id="dialogContent"></div>' ).append( infoHtml );

		if ( mw.user.isAnon() ) {
			$dialog.append( '<p>' + mw.msg( 'wikibugs-ip-address-notice' ) + '</p>' );
		}

		buttons[mw.msg( 'wikibugs-cancel-button' )] = function() {
			$( this ).dialog( 'close' );
		};
		buttons[mw.msg( 'wikibugs-open-form-button' )] = function() {
			that.openForm( this );
		};
		if ( can_edit ) {
			buttons[mw.msg( 'wikibugs-edit-page-button' )] = function() {
				that.goToEditPage();
			};
		}

		$dialog.dialog( {
			width: 700,
			height: 500,
			modal: true,
			resizable: false,
			draggable: true,
			closeOnEscape: true,
			dialogClass: 'reportBugDialog',
			title: mw.msg( 'wikibugs-dialog-title' ),
			close: function() {
				$( this ).dialog( 'destroy' ).remove();
			},
			buttons: buttons
		} );
		$( 'div.reportBugDialog button:last' ).focus();
	},
	/**
	 * Shows the form in the dialog window.
	 */
	openForm: function( dialog ) {
		var	that = this,
			buttons = {},
			author;
		$( '#dialogContent' ).empty().append(
			'<form name="WikibugForm" enctype="multipart/form-data">' +
			'<fieldset>' +
			'<label for="wbPageTitle">' + mw.msg( 'wikibugs-page-name-label' ) + '</label>' +
			'<input id="wbPageTitle" type="text" name="wbPageTitle" class="text ui-widget-content ui-corner-all" />' +
			'<label for="wbText">' + mw.msg( 'wikibugs-report-content-label' ) + '</label>' +
			'<textarea id="wbText" name="wbText" rows="6" class="text ui-widget-content ui-corner-all">' +
			mw.msg( 'wikibugs-report-content-placeholder' ) + '</textarea>' +
			'<label for="wbAuthor">' + mw.msg( 'wikibugs-signature-label' ) + '</label>' +
			'<input id="wbAuthor" type="text" class="text ui-widget-content ui-corner-all"/>' +
			'</fieldset>' +
			'<img id="wikibugs-loading-icon" src="//upload.wikimedia.org/wikipedia/commons/4/49/Linux_Ubuntu_Loader.gif" style="display:none;"/>' +
			'</form>'
		);

		buttons[mw.msg( 'wikibugs-cancel-button' )] = function() {
			$( this ).dialog( 'close' );
		};
		buttons[mw.msg( 'wikibugs-submit-report-button' )] = function() {
			that.submitForm();
		};

		$( dialog ).dialog( 'option', 'buttons', buttons );

		$( '#wbText' ).focus( function() {
			if ( this.value === mw.msg( 'wikibugs-report-content-placeholder' ) ) {
				this.value = '';
			}
		} );

		if ( this.isValidPageName( mw.config.get( 'wgPageName' ) ) ) {
			$( '#wbPageTitle' ).val( this.getRefinedPageName() );
		}

		if ( !mw.user.isAnon() ) {
			author = document.getElementById( 'wbAuthor' );
			author.value = '~~' + '~~';
			author.disabled = 'disabled';
		}
	},

	/**
	 * Indicates wheter submit should be ignored.
	 */
	suppressSubmit: false,
	newText: null,
	reportedPage: null,

	/**
	 * Show an error message to the user
	 */
	informError: function( code, result, tryAgain ){
		var msg = mw.msg( 'wikibugs-error-' + code ) + ' (' + result + ')';
		if ( tryAgain !== undefined && !tryAgain ) {
			alert( msg );
		} else {
			alert( msg + '. ' + mw.msg( 'wikibugs-try-again' ) );
		}
		this.suppressSubmit = false;
		$('#wikibugs-loading-icon').hide();
	},

	/**
	 * Sends the contents of the form.
	 */
	submitForm: function() {
		var	that = this,
			form = document.forms.WikibugForm,
			content = form.wbText.value,
			$captcha = $('#wpCaptchaWord'),
			api = new mw.Api( { ajax: { error: that.informError } } ),
			toInsert, isFile,
			refinedPageName, $loadingIcon;

		function editCallback( res ) {
			var	result = res && res.edit && res.edit.result && res.edit.result,
				$captchaForm;
			if ( res.error !== undefined ) {
				that.informError( 'using-api', res.error.code + ': ' + res.error.info );
			} else if ( result === 'Success' ){
				//saved successfully - go to the report page
				window.location = mw.util.getUrl(that.reportPage) + '#' +
					encodeURIComponent(
						encodeURI(that.reportedPage).replace(/%/g, '.')
					).replace(/%/g, '.').replace(/\.3A/g, ':').
					replace(/\.20/g, '_').
					replace(/\(/g, '.28').replace(/\)/g, '.29');

				if (mw.config.get('wgPageName') === that.reportPage.replace( / /g, '_' )) {
					//we're already there
					window.location.reload();
				}
			} else if ( result === 'Failure' && res.edit.captcha !== undefined ){
				$captchaForm = $('<div id="wikibus-captcha"></div>')
					.append( mw.msg( 'wikibugs-captcha-desc' ) )
					.append('<br /><img src="' + res.edit.captcha.url + '" id="captcha-' + res.edit.captcha.id + '" width="255" height="76" alt="">')
					.append('<input name="wpCaptchaWord" id="wpCaptchaWord" autocorrect="off" autocapitalize="off" tabindex="1">');
					//.append('<input type="submit">');
				$captchaForm.submit(function() {
					return false;
				}).keyup(function(e) {
					if (e.keyCode === $.ui.keyCode.ENTER) {
						that.submitForm();
					}
				});
				$('#wikibugs-loading-icon').after( $captchaForm );
			} else {
				that.informError( 'unexpected-editing' );
			}
		}

		function doEditPage( data ){
			var params = {
				title: that.reportPage,
				text: that.newText,
				summary: mw.msg(
					'wikibugs-new-report',
					'[[:' + that.reportedPage + ']]'
				)
			};
			api.editPage(
				$.extend( {}, params, data ),
				editCallback,
				function( code, result){
					that.informError( 'editing', code + ': ' + result );
				}
			);
		}

		if( $captcha.length ){
			doEditPage( {
				captchaid: $captcha.prev().attr('id').replace( /^captcha-/g, ''),
				captchaword: $captcha.val()
			} );
			return;
		}
		if ( this.suppressSubmit ) {
			return;
		}

		if ( content === mw.msg( 'wikibugs-report-content-placeholder' ) ||
			content.length < 20 ||
			!content.match( ' ' )
		) {
			// Description too short or unchanged
			alert( mw.msg( 'wikibugs-incomplete-information' ) );

			form.wbText.focus();
			return;
		}
		content = $.trim( content );

		// Append a signature to the report
		if ( !mw.user.isAnon() ) {
			content += mw.msg( 'wikibugs-reported-by', '~~' + '~~' );
		} else {
			content += mw.msg( 'wikibugs-reported-by', form.wbAuthor.value + ' ~~' + '~~' );
		}

		that.reportedPage = this.getRefinedPageName( form.wbPageTitle.value.replace( /[\[\]]/g, '' ) );
		isFile = this.getPageNamespaceNumber( that.reportedPage ) === 6;

		if ( !this.isValidPageName( that.reportedPage ) ) {
			alert( mw.msg( 'wikibugs-invalid-page' ) );

			refinedPageName = this.getRefinedPageName();
			if ( this.isValidPageName( refinedPageName ) ) {
				form.wbPageTitle.value = refinedPageName;
			} else {
				form.wbPageTitle.value = '';
				form.wbPageTitle.focus();
			}
			return;
		}

		this.suppressSubmit = true;
		$loadingIcon = $( '#wikibugs-loading-icon' );
		$loadingIcon.show();

		toInsert = '=== [[:' + that.reportedPage + ']] ===\n' + content;

		function processContentOfPage( text ){
			var sectionLine;

			// Process the wikitext of the page
			if(isFile) {
				sectionLine = mw.msg( 'wikibugs-file-section-line' );
			} else {
				sectionLine = mw.msg( 'wikibugs-page-section-line' );
			}
			that.newText = text.replace(sectionLine, sectionLine + '\n\n' + toInsert);
			if (text === that.newText) {
				// Could not find the section line - simply append;
				that.newText = text + '\n\n' + toInsert;
			}
			doEditPage();
		}

		// EDIT THE "REPORT AN ERROR" PAGE
		api.getPageText(
			this.reportPage,
			processContentOfPage,
			function( code, result ){
				that.informError( 'reading-content', code + ': ' + result );
			}
		);
	}
};

$.extend(window.wikiBugsGadget, wb);

}( mediaWiki, jQuery ) );