ميدياويكي:Gadget-autocompleter.js

من كوبتيكبيديا
اذهب إلى التنقلاذهب الى البحث
لم تعد النسخة القابلة للطباعة مدعومة وقد تحتوي على أخطاء في العرض. يرجى تحديث علامات متصفحك المرجعية واستخدام وظيفة الطباعة الافتراضية في متصفحك بدلا منها.

ملاحظة: بعد النشر، أنت قد تحتاج إلى إفراغ الكاش الخاص بمتصفحك لرؤية التغييرات.

  • فايرفوكس / سافاري: أمسك Shift أثناء ضغط Reload، أو اضغط على إما Ctrl-F5 أو Ctrl-R (⌘-R على ماك)
  • جوجل كروم: اضغط Ctrl-Shift-R (⌘-Shift-R على ماك)
  • إنترنت إكسبلورر/إيدج: أمسك Ctrl أثناء ضغط Refresh، أو اضغط Ctrl-F5
  • أوبرا: اضغط Ctrl-F5.
//[[en:User:Theopolisme/Scripts/autocompleter]]
 /**
 * autocompleter.js
 * Bringing tab-based autocompletion to the mediawiki edit interface!
 *
 * @see [[User:Theopolisme/Scripts/autocompleter]]
 * @author Theopolisme
 */
/* global jQuery, mediaWiki */
mw.loader.using('mediawiki.util').then(function () {
	'use strict';

	var DELIMTER = /[\[\:\s|]/,
		MATCHERS = [
			// Usernames: [[User (talk):$$$]], {{ping|$$$}}, {{u|$$$}}
			/(?:\[\[user(?:[_ ]talk)?:(.*?)[\|\]#]|\{\{(?:ping|u)\|(.*?)\}\})/gi,
			// Wikipages: [[Xyz]], [[Wikipedia:Xyz]], [[Talk:Foo|Bar]]
			/\[\[(.*?)(?:\||\]\])/g
		];

	function log () {
		var args = Array.prototype.slice.call( arguments );
		if ( console && console.log ) {
			args.unshift( '[autocompleter]' );
			console.log.apply( console, args );
		}
	}

	function Autocompleter ( $textarea ) {
		this.$textarea = $textarea;
		this.isListening = false;
		this.cache = [];
		this.updateCache();
	}

	Autocompleter.prototype.updateCache = function () {
		var i, j, matcher, match, value,
			cache = this.cache,
			content = this.$textarea.val();

		for ( i = 0; i < MATCHERS.length; i++ ) {
			matcher = MATCHERS[i];
			match =	matcher.exec( content );

			while ( match !== null ) {
				j = match.length - 1;
				do {
					value = match[j];
					j--;
				} while ( value === undefined );

				if ( cache.indexOf( value ) === -1 ) {
					cache.push( value );
				}

				match =	matcher.exec( content );
			}
		}
		
		this.cache = cache;
		log( 'cache updated', this.cache );
	};

	Autocompleter.prototype.autocomplete = function () {
		var ac = this,
			pattern, completions, currentCompletion,
			content = this.$textarea.val(),
			caretPosition = this.$textarea.textSelection( 'getCaretPosition' );

		function findPattern( content, caretPosition ) {
			var piece = content.substring( 0, caretPosition ),
				i = piece.length;

			while ( i >= 0 ) {
				if ( DELIMTER.test( piece[i] ) ) {
					return piece.substring( i + 1 ).toLowerCase();
				}
				i--;
			}

			log( 'could not find a delimeter' );
			return false;
		}

		function complete( pattern ) {
			var i, cache = ac.cache,
				completions = [];

			for (  i = 0; i < cache.length; i++ ) {
				if ( cache[i].toLowerCase().indexOf( pattern ) === 0 ) {
					completions.push( cache[i] );
				}
			}

			return completions;
		}

		function updateTextarea ( content, caretPosition, pattern, completion ) {
			var start = caretPosition - pattern.length,
				end = start + completion.length,
				newContent = content.substring( 0, start ) + completion + content.substring( caretPosition );

			ac.$textarea.val( newContent );

			ac.$textarea.textSelection( 'setSelection', {
				start: start,
				end: end
			} );
		}

		pattern = findPattern( content, caretPosition );
		completions = complete( pattern );
		currentCompletion = 0;

		log( 'pattern', pattern );
		log( 'completions', completions );

		if ( !completions.length ) {
			log( 'could not find a match' );
			return;
		}

		updateTextarea( content, caretPosition, pattern, completions[ currentCompletion ] );

		// Allow the user to "scroll" through matches
		function keydownHandler ( e ) {
			switch ( e.which ) {
				case 38: // up arrow
					currentCompletion += 1;
					if ( currentCompletion > completions.length - 1 ) {
						currentCompletion = 0;
					}
					break;
				case 40: // down arrow
					currentCompletion -= 1;
					if ( currentCompletion < 0 ) {
						currentCompletion = completions.length - 1;
					}
					break;
				default:
					ac.$textarea.off( 'keydown', keydownHandler );
					return;
			}

			updateTextarea( content, caretPosition, pattern, completions[ currentCompletion ] );

			e.preventDefault();
			return false;
		}

		this.$textarea.on( 'keydown', keydownHandler );
	};

	Autocompleter.prototype.listen = function () {
		var ac = this;

		if ( this.isListening ) {
			return;
		}

		this.$textarea.on( 'keydown', function ( e ) {
			if ( e.which === 9 ) { // tab
				e.preventDefault();
				ac.autocomplete();
				return false;
			}
		} );

		this.isListening = true;
	};

	$( document ).ready( function () {
		if ( [ 'edit', 'submit' ].indexOf( mw.util.getParamValue( 'action' ) ) !== -1 ) {
			mw.loader.using( 'jquery.textSelection', function () {
				var autocompleter = new Autocompleter( $( '#wpTextbox1' ) );
				autocompleter.listen();
			} );
		}
	} );

});