AutoComplete由两个特殊字符和两个数据源触发

时间:2012-02-06 08:21:40

标签: c# javascript jquery asp.net-mvc

我玩过:

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”的东西时,它应该过滤结果但它不会!

知道为什么这不起作用?

1 个答案:

答案 0 :(得分:1)

您似乎正在使用LookupSec操作来过滤@字符,但在您的问题中,您只显示了LookupFirst#相关联的操作1}}过滤字符。我已经测试了您的代码,它适用于#而不适用于@,因为LookupSec不存在。

一旦我定义了LookupSec控制器动作,它就可以用于两者。请注意,现在您已在窗口小部件中对这些操作名称进行了硬编码,因此sourceOption1sourceOption2参数将被完全忽略。

jquery自动完成使用的查询字符串参数称为term,而不是q,因此请立即修复您的控制器操作,不要过滤任何内容:

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