<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ar">
	<id>https://www.copticpedia.org/index.php?action=history&amp;feed=atom&amp;title=%D9%85%D9%8A%D8%AF%D9%8A%D8%A7%D9%88%D9%8A%D9%83%D9%8A%3AGadget-autocompleter.js</id>
	<title>ميدياويكي:Gadget-autocompleter.js - تاريخ المراجعة</title>
	<link rel="self" type="application/atom+xml" href="https://www.copticpedia.org/index.php?action=history&amp;feed=atom&amp;title=%D9%85%D9%8A%D8%AF%D9%8A%D8%A7%D9%88%D9%8A%D9%83%D9%8A%3AGadget-autocompleter.js"/>
	<link rel="alternate" type="text/html" href="https://www.copticpedia.org/index.php?title=%D9%85%D9%8A%D8%AF%D9%8A%D8%A7%D9%88%D9%8A%D9%83%D9%8A:Gadget-autocompleter.js&amp;action=history"/>
	<updated>2026-05-19T05:31:41Z</updated>
	<subtitle>تاريخ التعديل لهذه الصفحة في الويكي</subtitle>
	<generator>MediaWiki 1.41.1</generator>
	<entry>
		<id>https://www.copticpedia.org/index.php?title=%D9%85%D9%8A%D8%AF%D9%8A%D8%A7%D9%88%D9%8A%D9%83%D9%8A:Gadget-autocompleter.js&amp;diff=8636&amp;oldid=prev</id>
		<title>Gerges: مراجعة واحدة</title>
		<link rel="alternate" type="text/html" href="https://www.copticpedia.org/index.php?title=%D9%85%D9%8A%D8%AF%D9%8A%D8%A7%D9%88%D9%8A%D9%83%D9%8A:Gadget-autocompleter.js&amp;diff=8636&amp;oldid=prev"/>
		<updated>2021-03-19T00:58:59Z</updated>

		<summary type="html">&lt;p&gt;مراجعة واحدة&lt;/p&gt;
&lt;p&gt;&lt;b&gt;صفحة جديدة&lt;/b&gt;&lt;/p&gt;&lt;div&gt;//[[en:User:Theopolisme/Scripts/autocompleter]]&lt;br /&gt;
 /**&lt;br /&gt;
 * autocompleter.js&lt;br /&gt;
 * Bringing tab-based autocompletion to the mediawiki edit interface!&lt;br /&gt;
 *&lt;br /&gt;
 * @see [[User:Theopolisme/Scripts/autocompleter]]&lt;br /&gt;
 * @author Theopolisme&lt;br /&gt;
 */&lt;br /&gt;
/* global jQuery, mediaWiki */&lt;br /&gt;
mw.loader.using('mediawiki.util').then(function () {&lt;br /&gt;
	'use strict';&lt;br /&gt;
&lt;br /&gt;
	var DELIMTER = /[\[\:\s|]/,&lt;br /&gt;
		MATCHERS = [&lt;br /&gt;
			// Usernames: [[User (talk):$$$]], {{ping|$$$}}, {{u|$$$}}&lt;br /&gt;
			/(?:\[\[user(?:[_ ]talk)?:(.*?)[\|\]#]|\{\{(?:ping|u)\|(.*?)\}\})/gi,&lt;br /&gt;
			// Wikipages: [[Xyz]], [[Wikipedia:Xyz]], [[Talk:Foo|Bar]]&lt;br /&gt;
			/\[\[(.*?)(?:\||\]\])/g&lt;br /&gt;
		];&lt;br /&gt;
&lt;br /&gt;
	function log () {&lt;br /&gt;
		var args = Array.prototype.slice.call( arguments );&lt;br /&gt;
		if ( console &amp;amp;&amp;amp; console.log ) {&lt;br /&gt;
			args.unshift( '[autocompleter]' );&lt;br /&gt;
			console.log.apply( console, args );&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function Autocompleter ( $textarea ) {&lt;br /&gt;
		this.$textarea = $textarea;&lt;br /&gt;
		this.isListening = false;&lt;br /&gt;
		this.cache = [];&lt;br /&gt;
		this.updateCache();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	Autocompleter.prototype.updateCache = function () {&lt;br /&gt;
		var i, j, matcher, match, value,&lt;br /&gt;
			cache = this.cache,&lt;br /&gt;
			content = this.$textarea.val();&lt;br /&gt;
&lt;br /&gt;
		for ( i = 0; i &amp;lt; MATCHERS.length; i++ ) {&lt;br /&gt;
			matcher = MATCHERS[i];&lt;br /&gt;
			match =	matcher.exec( content );&lt;br /&gt;
&lt;br /&gt;
			while ( match !== null ) {&lt;br /&gt;
				j = match.length - 1;&lt;br /&gt;
				do {&lt;br /&gt;
					value = match[j];&lt;br /&gt;
					j--;&lt;br /&gt;
				} while ( value === undefined );&lt;br /&gt;
&lt;br /&gt;
				if ( cache.indexOf( value ) === -1 ) {&lt;br /&gt;
					cache.push( value );&lt;br /&gt;
				}&lt;br /&gt;
&lt;br /&gt;
				match =	matcher.exec( content );&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		&lt;br /&gt;
		this.cache = cache;&lt;br /&gt;
		log( 'cache updated', this.cache );&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	Autocompleter.prototype.autocomplete = function () {&lt;br /&gt;
		var ac = this,&lt;br /&gt;
			pattern, completions, currentCompletion,&lt;br /&gt;
			content = this.$textarea.val(),&lt;br /&gt;
			caretPosition = this.$textarea.textSelection( 'getCaretPosition' );&lt;br /&gt;
&lt;br /&gt;
		function findPattern( content, caretPosition ) {&lt;br /&gt;
			var piece = content.substring( 0, caretPosition ),&lt;br /&gt;
				i = piece.length;&lt;br /&gt;
&lt;br /&gt;
			while ( i &amp;gt;= 0 ) {&lt;br /&gt;
				if ( DELIMTER.test( piece[i] ) ) {&lt;br /&gt;
					return piece.substring( i + 1 ).toLowerCase();&lt;br /&gt;
				}&lt;br /&gt;
				i--;&lt;br /&gt;
			}&lt;br /&gt;
&lt;br /&gt;
			log( 'could not find a delimeter' );&lt;br /&gt;
			return false;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		function complete( pattern ) {&lt;br /&gt;
			var i, cache = ac.cache,&lt;br /&gt;
				completions = [];&lt;br /&gt;
&lt;br /&gt;
			for (  i = 0; i &amp;lt; cache.length; i++ ) {&lt;br /&gt;
				if ( cache[i].toLowerCase().indexOf( pattern ) === 0 ) {&lt;br /&gt;
					completions.push( cache[i] );&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
&lt;br /&gt;
			return completions;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		function updateTextarea ( content, caretPosition, pattern, completion ) {&lt;br /&gt;
			var start = caretPosition - pattern.length,&lt;br /&gt;
				end = start + completion.length,&lt;br /&gt;
				newContent = content.substring( 0, start ) + completion + content.substring( caretPosition );&lt;br /&gt;
&lt;br /&gt;
			ac.$textarea.val( newContent );&lt;br /&gt;
&lt;br /&gt;
			ac.$textarea.textSelection( 'setSelection', {&lt;br /&gt;
				start: start,&lt;br /&gt;
				end: end&lt;br /&gt;
			} );&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		pattern = findPattern( content, caretPosition );&lt;br /&gt;
		completions = complete( pattern );&lt;br /&gt;
		currentCompletion = 0;&lt;br /&gt;
&lt;br /&gt;
		log( 'pattern', pattern );&lt;br /&gt;
		log( 'completions', completions );&lt;br /&gt;
&lt;br /&gt;
		if ( !completions.length ) {&lt;br /&gt;
			log( 'could not find a match' );&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		updateTextarea( content, caretPosition, pattern, completions[ currentCompletion ] );&lt;br /&gt;
&lt;br /&gt;
		// Allow the user to &amp;quot;scroll&amp;quot; through matches&lt;br /&gt;
		function keydownHandler ( e ) {&lt;br /&gt;
			switch ( e.which ) {&lt;br /&gt;
				case 38: // up arrow&lt;br /&gt;
					currentCompletion += 1;&lt;br /&gt;
					if ( currentCompletion &amp;gt; completions.length - 1 ) {&lt;br /&gt;
						currentCompletion = 0;&lt;br /&gt;
					}&lt;br /&gt;
					break;&lt;br /&gt;
				case 40: // down arrow&lt;br /&gt;
					currentCompletion -= 1;&lt;br /&gt;
					if ( currentCompletion &amp;lt; 0 ) {&lt;br /&gt;
						currentCompletion = completions.length - 1;&lt;br /&gt;
					}&lt;br /&gt;
					break;&lt;br /&gt;
				default:&lt;br /&gt;
					ac.$textarea.off( 'keydown', keydownHandler );&lt;br /&gt;
					return;&lt;br /&gt;
			}&lt;br /&gt;
&lt;br /&gt;
			updateTextarea( content, caretPosition, pattern, completions[ currentCompletion ] );&lt;br /&gt;
&lt;br /&gt;
			e.preventDefault();&lt;br /&gt;
			return false;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		this.$textarea.on( 'keydown', keydownHandler );&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	Autocompleter.prototype.listen = function () {&lt;br /&gt;
		var ac = this;&lt;br /&gt;
&lt;br /&gt;
		if ( this.isListening ) {&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		this.$textarea.on( 'keydown', function ( e ) {&lt;br /&gt;
			if ( e.which === 9 ) { // tab&lt;br /&gt;
				e.preventDefault();&lt;br /&gt;
				ac.autocomplete();&lt;br /&gt;
				return false;&lt;br /&gt;
			}&lt;br /&gt;
		} );&lt;br /&gt;
&lt;br /&gt;
		this.isListening = true;&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	$( document ).ready( function () {&lt;br /&gt;
		if ( [ 'edit', 'submit' ].indexOf( mw.util.getParamValue( 'action' ) ) !== -1 ) {&lt;br /&gt;
			mw.loader.using( 'jquery.textSelection', function () {&lt;br /&gt;
				var autocompleter = new Autocompleter( $( '#wpTextbox1' ) );&lt;br /&gt;
				autocompleter.listen();&lt;br /&gt;
			} );&lt;br /&gt;
		}&lt;br /&gt;
	} );&lt;br /&gt;
&lt;br /&gt;
});&lt;/div&gt;</summary>
		<author><name>Gerges</name></author>
	</entry>
</feed>