自动完成由两个特殊字符和两个数据源触发

AutoComplete triggered with two Special characters and two datasources

本文关键字:两个 数据源 特殊字符      更新时间:2023-09-26

我玩过:

https://github.com/experteer/autocompleteTrigger/

如下所示:

(function ($, window, document, undefined) {
$.widget("ui.autocompleteTrigger", {
    //Options to be used as defaults
    options: {
        triggerStart: "%{",
        triggerEnd: "}"
    },

    _create: function () {
        this.triggered = false;
        this.triggered2 = false;
        this.element.autocomplete($.extend({
            search: function () {
                /**
                * @description only make a request and suggest items if acTrigger.triggered is true
                */
                var acTrigger = $(this).data("autocompleteTrigger");
                if (acTrigger.triggered == true || acTrigger.triggered2 == true) {
                    return true;
                } else {
                    return false;
                }
             },
            select: function (event, ui) {
                /**
                * @description if a item is selected, insert the value between triggerStart and triggerEnd
                */
                var acTrigger = $(this).data("autocompleteTrigger");
                var text = this.value;
                var trigger = acTrigger.options.triggerStart;
                var trigger2 = acTrigger.options.triggerStart2;
                var cursorPosition = acTrigger.getCursorPosition();
                var lastTrigger1Position = text.substring(0, cursorPosition).lastIndexOf(trigger);
                var lastTrigger2Position = text.substring(0, cursorPosition).lastIndexOf(trigger2);
                var lastTriggerPosition;
                if (lastTrigger1Position > lastTrigger2Position) {
                    lastTriggerPosition = lastTrigger1Position;
                } else {
                    lastTriggerPosition = lastTrigger2Position;
                }
                var firstTextPart = text.substring(0, lastTriggerPosition + trigger.length) + ui.item.value +
                    acTrigger.options.triggerEnd;
                this.value = firstTextPart + text.substring(cursorPosition, text.length);
                acTrigger.triggered = false;
                acTrigger.triggered2 = false;
                // set cursor position after the autocompleted text
                this.selectionStart = firstTextPart.length;
                this.selectionEnd = firstTextPart.length;
                return false;
            },
            focus: function () {
                /**
                * @description prevent to replace the hole text, if a item is hovered
                */
                return false;
            },
            minLength: 0
        }, this.options))
    .bind("keyup", function (event) {
        /**
        * @description Bind to keyup-events to detect text changes.
        * If the trigger is found before the cursor, autocomplete will be called
        */
        var acTrigger = $(this).data("autocompleteTrigger");
        if (event.keyCode != $.ui.keyCode.UP && event.keyCode != $.ui.keyCode.DOWN) {
            var text = this.value;
            var textLength = text.length;
            var cursorPosition = acTrigger.getCursorPosition();
            var lastString;
            var query;
            var lastTriggerPosition;
            var lastTriggerPosition2;
            var trigger = acTrigger.options.triggerStart;
            var trigger2 = acTrigger.options.triggerStart2;
            if (acTrigger.triggered && text != "") {
                // call autocomplete with the string after the trigger
                // Example: triggerStart = @, string is '@foo' -> query string is 'foo'
                $(this).autocomplete("option", "source", '/UITests/LookupFirst');
                lastTriggerPosition = text.substring(0, cursorPosition).lastIndexOf(trigger);
                query = text.substring(lastTriggerPosition + trigger.length, cursorPosition);
                $(this).autocomplete("search", query);

            }
            if (acTrigger.triggered2 && text != "") {
                // call autocomplete with the string after the trigger
                // Example: triggerStart = @, string is '@foo' -> query string is 'foo'
                $(this).autocomplete("option", "source", '/UITests/LookupSec');
                lastTriggerPosition2 = text.substring(0, cursorPosition).lastIndexOf(trigger2);
                query = text.substring(lastTriggerPosition2 + trigger2.length, cursorPosition);
                $(this).autocomplete("search", query);
            }
            else if (textLength >= trigger.length) {
                // set trigged to true, if the string before the cursor is triggerStart
                lastString = text.substring(cursorPosition - trigger.length, cursorPosition);
                acTrigger.triggered = (lastString === trigger);
                acTrigger.triggered2 = (lastString === trigger2);
            }
        }
    });
    },
    /**
    * @description Destroy an instantiated plugin and clean up modifications the widget has made to the DOM
    */
    destroy: function () {
        // this.element.removeStuff();
        // For UI 1.8, destroy must be invoked from the
        // base widget
        $.Widget.prototype.destroy.call(this);
        // For UI 1.9, define _destroy instead and don't
        // worry about
        // calling the base widget
    },

    /**
    * @description calculates the the current cursor position in the bound textfield, area,...
    * @returns {int}  the position of the cursor.
    */
    getCursorPosition: function () {
        var elem = this.element[0];
        var position = 0;
        // dom 3
        if (elem.selectionStart >= 0) {
            position = elem.selectionStart;
            // IE
        } else if (elem.ownerDocument.selection) {
            var r = elem.ownerDocument.selection.createRange();
            if (!r) return data;
            var tr = elem.createTextRange(), ctr = tr.duplicate();
            tr.moveToBookmark(r.getBookmark());
            ctr.setEndPoint('EndToStart', tr);
            position = ctr.text.length;
        }
        return position;
    }
});
})(jQuery, window, document);

在视图中:

    $('input,textarea').autocompleteTrigger({
    triggerStart: '#',
    triggerEnd: '',
    triggerStart2: '@@',
    sourceOption1: '/UITests/LookupFirst',
    sourceOption2: '/UITests/LookupSec'
});

控制器操作方法(LookupSec相同)为:

 public ActionResult LookupFirst(string q)
    {
        var list = new List<string>()
                                {
                                    "Asp",
                                    "BASIC",
                                    "COBOL",
                                    "ColdFusion",
                                    "Erlang",
                                    "Fortran",
                                    "Groovy",
                                    "Java",
                                    "JavaScript",
                                    "Lisp",
                                    "Perl",
                                    "PHP",
                                    "Python",
                                    "Ruby",
                                    "Scala",
                                    "Scheme"
                                };
        IEnumerable<string> data;
        if (q != null)
        {
            data = list.Where(x => x.StartsWith(q));
        }
        else
            data = list;
        return Json(data, JsonRequestBehavior.AllowGet);
    }

现在它支持两个触发器@和#,每个触发器支持两个数据源。。。

问题是搜索已经不起作用了,一切都如预期的那样"几乎",但当我键入"@as"之类的内容时,它应该过滤结果,但它没有!

知道为什么不起作用吗?

您似乎在使用LookupSec操作来使用@字符进行筛选,但在您的问题中,您只显示了与#筛选字符相关的LookupFirst操作。我已经测试了您的代码,它适用于#,而不适用于@,因为LookupSec不存在。

一旦我定义了LookupSec控制器动作,它对两者都有效。只是要小心,因为现在您已经在小部件本身中硬编码了这些操作名称,所以sourceOption1sourceOption2参数将被完全忽略

jquery autocomplete使用的查询字符串参数被称为term,而不是q,所以修复您的控制器操作,因为现在它没有过滤任何内容:

public ActionResult LookupFirst(string term)
{
    ...
}