<?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-autocomplete.js</id>
	<title>ميدياويكي:Gadget-autocomplete.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-autocomplete.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-autocomplete.js&amp;action=history"/>
	<updated>2026-04-10T19:13:36Z</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-autocomplete.js&amp;diff=8656&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-autocomplete.js&amp;diff=8656&amp;oldid=prev"/>
		<updated>2021-03-19T00:59:18Z</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;//[[he:MediaWiki:Gadget-autocomplete.js]]&lt;br /&gt;
//http://help.wikia.com/wiki/Help:Link_Suggest&lt;br /&gt;
&lt;br /&gt;
mw.loader.using(['jquery.ui', 'jquery.textSelection'], function() {&lt;br /&gt;
    //extends jquery with autoCompleteWikiText functionality for autocomplete of links and templates&lt;br /&gt;
    $.fn.autoCompleteWikiText = function(options) {&lt;br /&gt;
        var mode = &amp;quot;none&amp;quot;,&lt;br /&gt;
            templateDataCache = {},&lt;br /&gt;
            ctrl = $(this),&lt;br /&gt;
            settings = $.extend(true, {&lt;br /&gt;
            positionMy: &amp;quot;left top&amp;quot; ,&lt;br /&gt;
            positionAt: &amp;quot;left bottom&amp;quot; ,&lt;br /&gt;
            positionOf: ctrl,&lt;br /&gt;
            positionOffset: &amp;quot;0&amp;quot;,&lt;br /&gt;
            filterResponse: function(a) {&lt;br /&gt;
                return a;&lt;br /&gt;
            }, // function that expects array of string and returns array of strings&lt;br /&gt;
            menuCSS: {&lt;br /&gt;
                width: '30%',&lt;br /&gt;
                maxHeight: '30em',&lt;br /&gt;
                'overflow-y': 'auto'&lt;br /&gt;
            },&lt;br /&gt;
            itemCSS: {&lt;br /&gt;
                right: 'inherit'&lt;br /&gt;
            },&lt;br /&gt;
            onselected: function(item) {&lt;br /&gt;
                var pos = ctrl.textSelection('getCaretPosition') - 1,&lt;br /&gt;
                    txt = ctrl.val(),&lt;br /&gt;
                	open, close, caretBackwards;&lt;br /&gt;
&lt;br /&gt;
                switch (mode) {&lt;br /&gt;
                    case &amp;quot;none&amp;quot;:&lt;br /&gt;
                        return;&lt;br /&gt;
                    case &amp;quot;templateValue&amp;quot;:&lt;br /&gt;
                        open = &amp;quot;|&amp;quot;;&lt;br /&gt;
                        close = &amp;quot;&amp;quot;;&lt;br /&gt;
                        caretBackwards = 0;&lt;br /&gt;
                        break;&lt;br /&gt;
                    case &amp;quot;templateParams&amp;quot;:&lt;br /&gt;
                        open = &amp;quot;|&amp;quot;;&lt;br /&gt;
                        close = &amp;quot;=&amp;quot;;&lt;br /&gt;
                        caretBackwards = 0;&lt;br /&gt;
                        break;&lt;br /&gt;
                    case &amp;quot;template&amp;quot;:&lt;br /&gt;
                        item = item.substr(mw.config.get('wgFormattedNamespaces')[10].length + 1);&lt;br /&gt;
                        caretBackwards = 2;&lt;br /&gt;
                        open = &amp;quot;{{&amp;quot;;&lt;br /&gt;
                        close = &amp;quot;|}}&amp;quot;;&lt;br /&gt;
                        break;&lt;br /&gt;
                    case &amp;quot;link&amp;quot;:&lt;br /&gt;
                        open = &amp;quot;[[&amp;quot;;&lt;br /&gt;
                        close = &amp;quot;]]&amp;quot;;&lt;br /&gt;
                        caretBackwards = 0;&lt;br /&gt;
                        if (item[item.length - 1] == ')') item += '|';&lt;br /&gt;
                        break;&lt;br /&gt;
                }&lt;br /&gt;
                var lastbegin = txt.lastIndexOf(open, pos);&lt;br /&gt;
                if (txt[lastbegin + 2] == ':')&lt;br /&gt;
                    item = ':' + item;&lt;br /&gt;
&lt;br /&gt;
                var newTxt = txt.substr(0, lastbegin) + open + item + close + txt.substr(pos + 1);&lt;br /&gt;
                var orgScroll = ctrl.scrollTop();&lt;br /&gt;
                ctrl.val(newTxt);&lt;br /&gt;
                ctrl.textSelection('setSelection', {&lt;br /&gt;
                    start: lastbegin + (open + item + close).length - caretBackwards&lt;br /&gt;
                });&lt;br /&gt;
                ctrl.scrollTop(orgScroll);&lt;br /&gt;
            }&lt;br /&gt;
        }, options);&lt;br /&gt;
&lt;br /&gt;
        function findLinks(res) {&lt;br /&gt;
            var pos = ctrl.textSelection('getCaretPosition') - 1;&lt;br /&gt;
            var txt = ctrl.val();&lt;br /&gt;
&lt;br /&gt;
            var lastbegin = txt.lastIndexOf(&amp;quot;[[&amp;quot;, pos);&lt;br /&gt;
            var lastend = txt.lastIndexOf(&amp;quot;]]&amp;quot;, pos);&lt;br /&gt;
            var isLink = lastbegin &amp;gt; lastend;&lt;br /&gt;
            if (isLink) {&lt;br /&gt;
                mode = 'link';&lt;br /&gt;
                fillLinksList(res, txt.substr(lastbegin + 2, pos - lastbegin));&lt;br /&gt;
            } else {&lt;br /&gt;
                lastbegin = txt.lastIndexOf(&amp;quot;{{&amp;quot;, pos);&lt;br /&gt;
                lastend = txt.lastIndexOf(&amp;quot;}}&amp;quot;, pos);&lt;br /&gt;
                var isTemplate = lastbegin &amp;gt; lastend;&lt;br /&gt;
                if (isTemplate) {&lt;br /&gt;
                    var prefixName = mw.config.get('wgFormattedNamespaces')[10] + ':' + txt.substr(lastbegin + 2, pos - lastbegin - 1);&lt;br /&gt;
                    mode = (prefixName.indexOf('|') &amp;gt; -1) ? 'templateParams' : 'template';&lt;br /&gt;
                    fillLinksList(res, prefixName);&lt;br /&gt;
                } else {&lt;br /&gt;
                    mode = &amp;quot;none&amp;quot;;&lt;br /&gt;
                    res([]);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
        function resolveTempalte(templateName) {&lt;br /&gt;
            var dfd = new jQuery.Deferred();&lt;br /&gt;
            if (!templateName) return dfd.reject().promise();&lt;br /&gt;
            if (templateDataCache[templateName]) return dfd.resolve().promise();&lt;br /&gt;
            var api = new mw.Api();&lt;br /&gt;
            api.get({&lt;br /&gt;
                action: 'templatedata',&lt;br /&gt;
                titles: templateName,&lt;br /&gt;
                redirects: 1&lt;br /&gt;
            }).done(function(data) {&lt;br /&gt;
                if (!data.pages) return dfd.reject();&lt;br /&gt;
                for (var pageid in data.pages) {&lt;br /&gt;
                    templateDataCache[templateName] = data.pages[pageid];&lt;br /&gt;
                    dfd.resolve();&lt;br /&gt;
                }&lt;br /&gt;
                if (!templateDataCache[templateName]) dfd.reject();&lt;br /&gt;
            });&lt;br /&gt;
            return dfd.promise();&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function resolveApi(queryType, queryValue) {&lt;br /&gt;
            var dfd = new jQuery.Deferred(),&lt;br /&gt;
                api = new mw.Api();&lt;br /&gt;
&lt;br /&gt;
            switch (queryType) {&lt;br /&gt;
                case 'users':&lt;br /&gt;
                    api.get({&lt;br /&gt;
                        action: 'query',&lt;br /&gt;
                        list: 'allusers',&lt;br /&gt;
                        auactiveusers: 1,&lt;br /&gt;
                        auprefix: queryValue&lt;br /&gt;
                    }).done(function(data) {&lt;br /&gt;
                        if (data &amp;amp;&amp;amp; data.query &amp;amp;&amp;amp; data.query.allusers) dfd.resolve($.map(data.query.allusers, function(e) {&lt;br /&gt;
                            return e.name;&lt;br /&gt;
                        }));&lt;br /&gt;
                        else dfd.reject();&lt;br /&gt;
                    });&lt;br /&gt;
                    break;&lt;br /&gt;
                case 'pages':&lt;br /&gt;
                    api.get({&lt;br /&gt;
                        action: 'opensearch',&lt;br /&gt;
                        search: queryValue&lt;br /&gt;
                    }).done(function(data) {&lt;br /&gt;
                        if (data[1]) dfd.resolve(settings.filterResponse(data[1]));&lt;br /&gt;
                        else dfd.reject();&lt;br /&gt;
                    });&lt;br /&gt;
                    break;&lt;br /&gt;
                default:&lt;br /&gt;
                    throw 'unexpected queryType';&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            return dfd.promise();&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function fillLinksList(res, txt) {&lt;br /&gt;
            txt = $.trim(txt);&lt;br /&gt;
            if (txt.length &amp;lt;= 1 || (mode != 'templateParams' &amp;amp;&amp;amp; txt.indexOf('|') &amp;gt; -1) || (txt.indexOf('#') &amp;gt; -1 &amp;amp;&amp;amp; mw.config.get('wgNamespaceNumber') === 0)) res([]);&lt;br /&gt;
            else if (mode === 'templateParams') {&lt;br /&gt;
                var templateMatch = /(.+?)\|(?:.*\|)?([^=]+$)/.exec(txt);&lt;br /&gt;
                $.when(resolveTempalte(templateMatch &amp;amp;&amp;amp; templateMatch[1])).done(function() {&lt;br /&gt;
                    var curTemplateData = templateDataCache[templateMatch[1]],&lt;br /&gt;
                    	suggestions = [],&lt;br /&gt;
                    	curParamIndex = txt.split('|').length - 1;&lt;br /&gt;
                    for (var paramName in curTemplateData.params) {&lt;br /&gt;
                        if (paramName == curParamIndex) {&lt;br /&gt;
                            var paramValue = templateMatch[2];&lt;br /&gt;
                            var dfd;&lt;br /&gt;
                            switch (curTemplateData.params[paramName].type) {&lt;br /&gt;
                                case 'wiki-page-name':&lt;br /&gt;
                                    dfd = $.when(resolveApi('pages', paramValue));&lt;br /&gt;
                                    mode = 'templateValue';&lt;br /&gt;
                                    break;&lt;br /&gt;
                                case 'wiki-file-name':&lt;br /&gt;
                                    dfd = $.when(resolveApi('pages', 'File:' + paramValue));&lt;br /&gt;
                                    mode = 'templateValue';&lt;br /&gt;
                                    break;&lt;br /&gt;
                                case 'wiki-template-name':&lt;br /&gt;
                                    dfd = $.when(resolveApi('pages', 'Template:' + paramValue));&lt;br /&gt;
                                    mode = 'templateValue';&lt;br /&gt;
                                    break;                                    &lt;br /&gt;
                                case 'wiki-user-name':&lt;br /&gt;
                                    dfd = $.when(resolveApi('users', paramValue));&lt;br /&gt;
                                    mode = 'templateValue';&lt;br /&gt;
                                    break;&lt;br /&gt;
                                default:&lt;br /&gt;
                                    return res([]); // dont suggest for this indexed param&lt;br /&gt;
                            }&lt;br /&gt;
                            return dfd.done(res).fail(function() {&lt;br /&gt;
                                res([]);&lt;br /&gt;
                            });&lt;br /&gt;
                        }&lt;br /&gt;
                        if (paramName === '1' || txt.indexOf(paramName) &amp;gt; -1) continue; //dont suggest used params&lt;br /&gt;
                        suggestions.push(paramName);&lt;br /&gt;
                    }&lt;br /&gt;
                    res(suggestions);&lt;br /&gt;
                }).fail(res);&lt;br /&gt;
            } else if (txt.indexOf('#') &amp;gt; -1) {&lt;br /&gt;
                var pageTitle = txt.substr(0, txt.indexOf('#'));&lt;br /&gt;
                var sectionPrefix = txt.substr(txt.indexOf('#') + 1);&lt;br /&gt;
                var api = new mw.Api();&lt;br /&gt;
                api.get({&lt;br /&gt;
                    action: 'parse',&lt;br /&gt;
                    page: pageTitle,&lt;br /&gt;
                    prop: 'sections'&lt;br /&gt;
                }).done(function(data) {&lt;br /&gt;
                    if (data &amp;amp;&amp;amp; data.parse &amp;amp;&amp;amp; data.parse.sections) res($(data.parse.sections).map(function() {&lt;br /&gt;
                        return this.line.indexOf(sectionPrefix) == 0 ? (pageTitle + '#' + this.line.replace(/[|\[\]\{\}]/g, escape)) : null;&lt;br /&gt;
                    }));&lt;br /&gt;
                });&lt;br /&gt;
            } else {&lt;br /&gt;
                $.when(resolveApi('pages', txt)).done(res).fail(function() {&lt;br /&gt;
                    res([])&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        ctrl.autocomplete({&lt;br /&gt;
            source: function(request, response) {&lt;br /&gt;
                if (fixArrowsBug(this))&lt;br /&gt;
                    response([]);&lt;br /&gt;
                else&lt;br /&gt;
                    findLinks(response);&lt;br /&gt;
            },&lt;br /&gt;
            focus: function() {&lt;br /&gt;
                return false;&lt;br /&gt;
            },&lt;br /&gt;
            select: function(e, ui) {&lt;br /&gt;
                settings.onselected(ui.item.value);&lt;br /&gt;
                return false;&lt;br /&gt;
            },&lt;br /&gt;
            open: function() {&lt;br /&gt;
                $(&amp;quot;.ui-autocomplete&amp;quot;)&lt;br /&gt;
                    .css(settings.menuCSS)&lt;br /&gt;
                    .position({&lt;br /&gt;
                        my: settings.positionMy,&lt;br /&gt;
                        at: settings.positionAt,&lt;br /&gt;
                        of: settings.positionOf,&lt;br /&gt;
                        offset: settings.positionOffset,&lt;br /&gt;
                        collision: 'none fit'&lt;br /&gt;
                    })&lt;br /&gt;
                    .find('li').css(settings.itemCSS);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
        var fixed, stfu, escapes = 0;&lt;br /&gt;
        //this is hack to prevent known serious bug in autocomplete.js that prevent default of the up and down key which may drive you crazy....&lt;br /&gt;
        function fixArrowsBug(self) {&lt;br /&gt;
            if (fixed) return false;&lt;br /&gt;
            fixed = true;&lt;br /&gt;
&lt;br /&gt;
	   // on click selection may change. close the menu&lt;br /&gt;
            ctrl.on(&amp;quot;click.autocomplete&amp;quot;, function(e){&lt;br /&gt;
		clearTimeout(self.searching);&lt;br /&gt;
		self.close();&lt;br /&gt;
	   });&lt;br /&gt;
            ctrl.off(&amp;quot;keydown.autocomplete&amp;quot;);&lt;br /&gt;
            ctrl.off(&amp;quot;keydown.autocomplete0&amp;quot;);&lt;br /&gt;
            ctrl.on(&amp;quot;keydown.autocomplete&amp;quot;,&lt;br /&gt;
                function(event) {&lt;br /&gt;
                    var keyCode = $.ui.keyCode;&lt;br /&gt;
                    // hack to allow cancelling the gadget: mostly useful when editing templates.&lt;br /&gt;
                    escapes = event.keyCode == keyCode.ESCAPE ? escapes + 1 : 0;&lt;br /&gt;
                    if ( stfu || ( stfu = escapes &amp;gt;= 3 ) ) {&lt;br /&gt;
                        self.close(event);&lt;br /&gt;
                    	return;&lt;br /&gt;
                    }&lt;br /&gt;
                    switch (event.keyCode) {&lt;br /&gt;
                        case keyCode.PAGE_UP:&lt;br /&gt;
                            self._move(&amp;quot;previousPage&amp;quot;, event);&lt;br /&gt;
                            break;&lt;br /&gt;
                        case keyCode.PAGE_DOWN:&lt;br /&gt;
                            self._move(&amp;quot;nextPage&amp;quot;, event);&lt;br /&gt;
                            break;&lt;br /&gt;
                        case keyCode.UP:&lt;br /&gt;
                            if (!self.menu.element.is(&amp;quot;:visible&amp;quot;)) return;&lt;br /&gt;
                            self._move(&amp;quot;previous&amp;quot;, event);&lt;br /&gt;
                            // prevent moving cursor to beginning of text field in some browsers&lt;br /&gt;
                            event.preventDefault();&lt;br /&gt;
                            break;&lt;br /&gt;
                        case keyCode.DOWN:&lt;br /&gt;
                            if (!self.menu.element.is(&amp;quot;:visible&amp;quot;)) return;&lt;br /&gt;
                            self._move(&amp;quot;next&amp;quot;, event);&lt;br /&gt;
                            // prevent moving cursor to end of text field in some browsers&lt;br /&gt;
                            event.preventDefault();&lt;br /&gt;
                            break;&lt;br /&gt;
                        case keyCode.ENTER:&lt;br /&gt;
                        case keyCode.NUMPAD_ENTER:&lt;br /&gt;
                            // when menu is open or has focus&lt;br /&gt;
                            if (self.menu.active) {&lt;br /&gt;
                                event.preventDefault();&lt;br /&gt;
                            }&lt;br /&gt;
                            //passthrough - ENTER and TAB both select the current element&lt;br /&gt;
                        case keyCode.TAB:&lt;br /&gt;
                            if (!self.menu.active) {&lt;br /&gt;
                                return;&lt;br /&gt;
                            }&lt;br /&gt;
                            self.menu.select(event);&lt;br /&gt;
                            break;&lt;br /&gt;
                        case keyCode.ESCAPE:&lt;br /&gt;
                            self.element.val(self.term);&lt;br /&gt;
                            self.close(event);&lt;br /&gt;
                            break;&lt;br /&gt;
&lt;br /&gt;
                        case keyCode.SHIFT:&lt;br /&gt;
                        case keyCode.CONTROL:&lt;br /&gt;
                        case keyCode.ALT:&lt;br /&gt;
                        case keyCode.COMMAND:&lt;br /&gt;
                        case keyCode.COMMAND_RIGHT:&lt;br /&gt;
                        case keyCode.INSERT:&lt;br /&gt;
                        case keyCode.CAPS_LOCK:&lt;br /&gt;
                        case keyCode.END:&lt;br /&gt;
                        case keyCode.HOME:&lt;br /&gt;
                        case keyCode.LEFT:&lt;br /&gt;
                        case keyCode.RIGHT:                        	&lt;br /&gt;
                            // ignore metakeys (shift, ctrl, alt)&lt;br /&gt;
                            break;&lt;br /&gt;
                        default:&lt;br /&gt;
                            // keypress is triggered before the input value is changed&lt;br /&gt;
                            clearTimeout(self.searching);&lt;br /&gt;
                            self.searching = setTimeout(function() {&lt;br /&gt;
                                self.search(null, event);&lt;br /&gt;
                            }, self.options.delay);&lt;br /&gt;
                            break;&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            return true;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
if ($.inArray(mw.config.get('wgAction'), ['edit', 'submit']) + 1)&lt;br /&gt;
    mw.loader.using(['jquery.ui', 'jquery.textSelection'], function() {&lt;br /&gt;
        //enable autocomplete for editbox, relative to editform in an offset of -80 vertical&lt;br /&gt;
        $(&amp;quot;#wpTextbox1&amp;quot;).autoCompleteWikiText({&lt;br /&gt;
            positionAt: &amp;quot;left top&amp;quot;,&lt;br /&gt;
            positionOf: '#editform',&lt;br /&gt;
            positionOffset: &amp;quot;0 0&amp;quot;,&lt;br /&gt;
            menuCSS: {&lt;br /&gt;
                background: '#E0EEF7',&lt;br /&gt;
                opacity: 0.8,&lt;br /&gt;
                left: 0&lt;br /&gt;
            },&lt;br /&gt;
            itemCSS: {&lt;br /&gt;
                padding: 0,&lt;br /&gt;
                margin: 0&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;/div&gt;</summary>
		<author><name>Gerges</name></author>
	</entry>
</feed>