מדיה ויקי:Gadget-autocomplete.js: הבדלים בין גרסאות בדף

החלפת הדף בתוכן "mw.loader.load('//he.wikipedia.org/w/load.php?modules=ext.gadget.autocomplete');"
תגיות: החלפה שוחזרה
אין תקציר עריכה
תגית: שוחזרה
(גרסת ביניים אחת של אותו משתמש אינה מוצגת)
שורה 1: שורה 1:
mw.loader.load('//he.wikipedia.org/w/load.php?modules=ext.gadget.autocomplete');
/*
Autocomplete for links and templates
Written by [[משתמש:ערן]]
*/
 
mw.loader.using(['jquery.ui', 'jquery.textSelection'], function() {
    $.fn.autoCompleteWikiText = function(options) {
        var mode = "none",
            templateDataCache = {},
            ctrl = $(this),
            settings = $.extend(true, {
                positionMy: $('body').is('.rtl') ? "left top" : "right top",
                positionAt: $('body').is('.rtl') ? "left bottom" : "right bottom",
                positionOf: ctrl,
                positionOffset: "0",
                filterResponse: function(a) {
                    return a;
                },
                menuCSS: {
                    width: 'auto',
                    maxHeight: '30em',
                    'overflow-y': 'auto'
                },
                itemCSS: {
                    right: 'inherit'
                },
                onselected: function(item) {
                    var pos = ctrl.textSelection('getCaretPosition') - 1,
                        txt = ctrl.val(),
                        open, close, caretBackwards;
 
                    switch (mode) {
                        case "none":
                            return;
                        case "templateValue":
                            open = "|";
                            close = "";
                            caretBackwards = 0;
                            break;
                        case "templateParams":
                            open = "|";
                            close = "=";
                            caretBackwards = 0;
                            break;
                        case "template":
                            item = item.substr(mw.config.get('wgFormattedNamespaces')[10].length + 1);
                            caretBackwards = 2;
                            open = "{{";
                            close = "|}}";
                            break;
                        case "link":
                            open = "[[";
                            close = "]]";
                            caretBackwards = 0;
                            if (item[item.length - 1] == ')') item += '|';
                            break;
                    }
                    var lastbegin = txt.lastIndexOf(open, pos);
                    if (txt[lastbegin + 2] == ':')
                        item = ':' + item;
 
                    var newTxt = txt.substr(0, lastbegin) + open + item + close + txt.substr(pos + 1);
                    var orgScroll = ctrl.scrollTop();
                    ctrl.val(newTxt);
                    ctrl.textSelection('setSelection', {
                        start: lastbegin + (open + item + close).length - caretBackwards
                    });
                    ctrl.scrollTop(orgScroll);
                }
            }, options);
 
        function findLinks(res) {
            var pos = ctrl.textSelection('getCaretPosition') - 1;
            var txt = ctrl.val();
 
            var lastbegin = txt.lastIndexOf("[[", pos);
            var lastend = txt.lastIndexOf("]]", pos);
            var isLink = lastbegin > lastend;
            if (isLink) {
                mode = 'link';
                fillLinksList(res, txt.substr(lastbegin + 2, pos - lastbegin));
            } else {
                lastbegin = txt.lastIndexOf("{{", pos);
                lastend = txt.lastIndexOf("}}", pos);
                var isTemplate = lastbegin > lastend;
                if (isTemplate) {
                    var prefixName = mw.config.get('wgFormattedNamespaces')[10] + ':' + txt.substr(lastbegin + 2, pos - lastbegin - 1);
                    mode = (prefixName.indexOf('|') > -1) ? 'templateParams' : 'template';
                    fillLinksList(res, prefixName);
                } else {
                    mode = "none";
                    res([]);
                }
            }
        }
 
        function resolveTemplate(templateName) {
            var dfd = new jQuery.Deferred();
            if (!templateName) return dfd.reject().promise();
            if (templateDataCache[templateName]) return dfd.resolve(templateDataCache[templateName]).promise();
            var api = new mw.Api();
            api.get({
                action: 'templatedata',
                titles: templateName,
                redirects: 1
            }).done(function(data) {
                if (!data.pages) return dfd.reject();
                for (var pageid in data.pages) {
                    templateDataCache[templateName] = data.pages[pageid];
                    dfd.resolve(templateDataCache[templateName]);
                }
                if (!templateDataCache[templateName]) dfd.reject();
            });
            return dfd.promise();
        }
 
        function resolveApi(queryType, queryValue) {
            var dfd = new jQuery.Deferred(),
                api = new mw.Api();
 
            switch (queryType) {
                case 'users':
                    api.get({
                        action: 'query',
                        list: 'allusers',
                        auactiveusers: 1,
                        auprefix: queryValue
                    }).done(function(data) {
                        if (data && data.query && data.query.allusers) dfd.resolve($.map(data.query.allusers, function(e) {
                            return e.name;
                        }));
                        else dfd.reject();
                    });
                    break;
                case 'pages':
                    api.get({
                        action: 'opensearch',
                        search: queryValue
                    }).done(function(data) {
                        if (data[1]) dfd.resolve(settings.filterResponse(data[1]));
                        else dfd.reject();
                    });
                    break;
                default:
                    throw 'unexpected queryType';
            }
 
            return dfd.promise();
        }
 
        function fillLinksList(res, txt) {
            txt = $.trim(txt);
            if (txt.length <= 1 || (mode != 'templateParams' && txt.indexOf('|') > -1) || (txt.indexOf('#') > -1 && mw.config.get('wgNamespaceNumber') === 0)) res([]);
            else if (mode === 'templateParams') {
                var templateMatch = /(.+?)\|(?:.*\|)?([^=]+$)/.exec(txt);
                var templateParamMatch = /(.+?)\|(?:.*\|)?([^=]+=[^=]+$)/.exec(txt);
 
                $.when(resolveTemplate((templateMatch && templateMatch[1]) || (templateParamMatch && templateParamMatch[1]))).done(function(td) {
 
                    var curTemplateData = td,
                        suggestions = [],
                        curParamIndex = txt.split('|').length - 1;
                    if (templateParamMatch && !templateMatch) {
                        var paramNameVal = templateParamMatch[2].split('=');
                        if (paramNameVal[0] in curTemplateData.params && 'suggestedvalues' in curTemplateData.params[paramNameVal[0]]) {
                            mode = 'templateValue';
                            var suggestedValues = curTemplateData.params[paramNameVal[0]].suggestedvalues;
                            for (var i = 0; i < suggestedValues.length; i++) {
                                var suggestedVal = suggestedValues[i];
                                if (suggestedVal.indexOf(paramNameVal[1]) === 0) {
                                    suggestions.push(paramNameVal[0] + '=' + suggestedVal);
                                }
                            }
                        }
                    } else {
                        for (var paramName in curTemplateData.params) {
                            if (paramName == curParamIndex) {
                                var paramValue = templateMatch[2];
                                var dfd;
                                switch (curTemplateData.params[paramName].type) {
                                    case 'wiki-page-name':
                                        dfd = $.when(resolveApi('pages', paramValue));
                                        mode = 'templateValue';
                                        break;
                                    case 'wiki-file-name':
                                        dfd = $.when(resolveApi('pages', 'File:' + paramValue));
                                        mode = 'templateValue';
                                        break;
                                    case 'wiki-template-name':
                                        dfd = $.when(resolveApi('pages', 'Template:' + paramValue));
                                        mode = 'templateValue';
                                        break;
                                    case 'wiki-user-name':
                                        dfd = $.when(resolveApi('users', paramValue));
                                        mode = 'templateValue';
                                        break;
                                    case 'string':
                                        if ('suggestedvalues' in curTemplateData.params[paramName]) {
                                            mode = 'templateValue';
                                            var suggestedValues = curTemplateData.params[paramName].suggestedvalues;
                                            for (var i = 0; i < suggestedValues.length; i++) {
                                                var suggestedVal = suggestedValues[i];
                                                if (suggestedVal.indexOf(paramValue) === 0) {
                                                    suggestions.push(suggestedVal);
                                                }
                                            }
                                            return res(suggestions);
                                        } else
                                            return res([]);
                                    default:
                                        return res([]);
                                }
                                return dfd.done(res).fail(function() {
                                    res([]);
                                });
                            }
                            if (paramName === '1' || txt.indexOf(paramName) > -1) continue;
                            suggestions.push(paramName);
                        }
                    }
                    res(suggestions);
                }).fail(res);
            } else if (txt.indexOf('#') > -1) {
                var pageTitle = txt.substr(0, txt.indexOf('#'));
                var sectionPrefix = txt.substr(txt.indexOf('#') + 1);
                var api = new mw.Api();
                api.get({
                    action: 'parse',
                    page: pageTitle,
                    prop: 'sections'
                }).done(function(data) {
                    if (data && data.parse && data.parse.sections) res($(data.parse.sections).map(function() {
                        return this.line.indexOf(sectionPrefix) == 0 ? (pageTitle + '#' + this.line.replace(/[|\[\]\{\}]/g, escape)) : null;
                    }));
                });
            } else {
                $.when(resolveApi('pages', txt)).done(res).fail(function() {
                    res([]);
                });
            }
        }
 
        ctrl.autocomplete({
            source: function(request, response) {
                if (fixArrowsBug(this))
                    response([]);
                else
                    findLinks(response);
            },
            focus: function() {
                return false;
            },
            select: function(e, ui) {
                settings.onselected(ui.item.value);
                return false;
            },
            open: function() {
                $(".ui-autocomplete")
                    .css(settings.menuCSS)
                    .position({
                        my: settings.positionMy,
                        at: settings.positionAt,
                        of: settings.positionOf,
                        offset: settings.positionOffset,
                        collision: 'none fit'
                    })
                    .find('li').css(settings.itemCSS);
            }
        });
 
        var fixed, stfu, escapes = 0;
 
        function fixArrowsBug(self) {
            if (fixed) return false;
            fixed = true;
 
            ctrl.on("click.autocomplete", function(e)
::contentReference[oaicite:12]{index=12}