如何让jQuery自动完成插件在字段聚焦时弹出?

9
4个回答

25

抱歉,我没有保存分支...现在已经修复了。 - Pierre
2
能够正常工作,但是使用鼠标选择项目后会再次弹出(我猜测它可能是再次将焦点返回到元素上)。 - mpen
Firefox 3.6.13。编辑:在您的jsfiddle上运行正常,但在我的网站上却不行。奇怪..我稍后会再回来看看。http://jsfiddle.net/q9ERL/ - mpen
(请注意,现在,为了弹出焦点猜测,字段必须为空。) - Pierre
1
直到我从jsfiddle中添加了“minLength: 0”,这个(stackoverflow的答案)对我才起作用,然后它完美地工作了。 - HoldOffHunger
显示剩余5条评论

2
我认为您正在破坏“自动完成”实用程序,只是为了制作一个样式化的选择框,这就是等待按键才能完成的原因。
我知道这不是您要找的答案,但请记住,您正在尝试处理少量选项,如果有许多选项,您将很难在前几个字母中加载自动完成div。
或者,如果您从此处查询,则可以在sql查询中拥有10个结果记录,如果是这样,则可以快速获得结果,而无需加载所有类型的结果。
--- 我测试了ie8上的焦点绑定,它失败了,顺便说一下,它并没有失败,它正好做到了您想要的,在焦点事件中,IE使用jquery焦点事件而不是像其他浏览器那样触发onFocus事件,因此您必须在焦点事件中评估字段是否为空,如果是则启动搜索,如果不是则什么都不做..希望这有所帮助。
$("#yourField").bind('focus', function(){
  if($(this).val()!=""){ 
     $(this).autocomplete("search");
  } 
});

这不仅是一个样式化的选择框,因为用户仍然可以在框中输入,并输入列表中没有的内容。更像一个组合框。我已经限制了结果,所以这不是问题。 - mpen
好的,Mark,你是对的,但我编辑了我的答案,修复了IE存在的问题,请看一下。 - Camilo Lizarazo
3
应该使用“==”而不是“!=”,但你的想法是正确的。那样能行 :) 谢谢。 - mpen

0

这是我的完整解决方案(它还做了一些其他的事情):

$.fn.ajaxselect = function(options) {
    var settings = {
        delay: 300,
        sourceData: function(term) {
            return {term:term};
        },
        sourceUrl: null,
        select: function(item) {},
        html: true,
        minLength: 0,
        autoSelect: true,
        autoFocus: true,
        showOnClick: null
    };

    if(options) $.extend(settings, options);
    if(settings.showOnClick === null) settings.showOnClick = settings.minLength === 0;

    $(this).autocomplete({
        source: function(request, response) {
            var data = settings.sourceData.call(this.element[0], request.term);
            if(data === false) {
                response([]);
                return;
            }
            $.ajax({
                url: settings.sourceUrl,
                dataType: 'json',
                data: data,
                success: function(data, textStatus, $xhr) {
                    response(data);
                },
                error: function($xhr, textStatus) {
                    response([]);
                }
            });
        },
        focus: function(e, ui) {
            return false; // don't fill input with highlighted value
        },
        search: function(e, ui) {
            if(settings.minLength < 0 && e.hasOwnProperty('originalEvent')) return false;  // don't search on keypress if minLength < 0 (use with showOnClick)
            $(this).data('lastSearch', this.value);
            return true;
        },
        select: function(e, ui) {
            if(!settings.autoSelect && e.keyCode === 9) return false; // don't select highlighted item on tab unless autoSelect is enabled
            if($(this).val() === $(this).data('lastSearch')) {
                if(settings.select.call(this, ui.item) !== false) {
                    $(this).val(ui.item.value);
                }
                $(this).data('selectedValue',$(this).val()).trigger('change');
            } 
            return false;
        },
        open: function(e, ui) {
            $(this).data('isOpen', true);
        },
        close: function(e, ui) {
            $(this).data('isOpen', false);
        },
        minLength: settings.minLength,
        autoFocus: settings.autoFocus,
        delay: settings.delay,
        html: settings.html
    }).bind('change.ajaxselect', function() {
        $(this).toggleClass('ajax-selected', $(this).val() === $(this).data('selectedValue'));
    });

    if(settings.autoSelect) {
        $(this).bind('autocompletechange.ajaxselect', function(event, ui) {
            if($(this).val() !== $(this).data('selectedValue') && this.value.length > 0) {
                var self = this;
                var data = $.extend({autoSelect:1},settings.sourceData.call(this, this.value));
                $(this).addClass('.ui-autocomplete-loading');
                $.ajax({
                    url: settings.sourceUrl,
                    dataType: 'json',
                    data: data,
                    success: function(data, textStatus, $xhr) {
                        if(data.length >= 1) {
                            var item = $.ui.autocomplete.prototype._normalize(data)[0];
                            if(settings.select.call(self, item) !== false) {
                                $(self).val(item.value);
                            }
                            $(self).data('selectedValue',$(self).val()).trigger('change');
                        }
                    },
                    complete: function($xhr, textStatus) {
                        $(self).removeClass('.ui-autocomplete-loading');
                    }
                });
            }
        });
    }

    if(settings.showOnClick) {
        $(this).bind('click.ajaxselect', function(e) {
            if(!$(this).data('clickHandled') && !$(this).data('isOpen')) {
                $(this).data('clickHandled',true);
                $(this).autocomplete('search','');
            } else {
                $(this).data('clickHandled',false);
            }
        }).bind('focus.ajaxselect', function(e) {
            if(!$(this).data('clickHandled') && e.hasOwnProperty('originalEvent') && $(this).val() === this.defaultValue && !$(this).data('isOpen')) {
                $(this).data('clickHandled',true);
                $(this).autocomplete('search','');
            } else {
                $(this).data('clickHandled',false);
            }
        })
    }

    return $(this);
};

0

那个解决方案有点像是一个hack。它依赖于300毫秒的延迟。 - mpen
虽然不是最理想的解决方案,但它能够工作 - 我愿意听取更好的建议? - Dunc
你可以查看我的解决方案。虽然它比简单地弹出搜索结果更复杂。它在点击或选项卡下打开,但仅在特定条件下,例如不是被程序自动触发的情况下。我认为防止双重打开的关键是在打开和关闭事件中使用$(this).data('isOpen', true)这一部分代码,将变量存储在元素本身上,而不是使用全局变量,这还允许您在页面上拥有多个此类元素。 - mpen
感谢您的发布 - 我无法轻松地将您的代码集成到我的解决方案中,但正如您所说,它似乎更加优雅,希望有人会发现它有用。 - Dunc

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接