如何在jQuery UI自动完成中实现“mustMatch”和“selectFirst”?

时间:2022-10-19 14:29:56

I recently migrated a few of my Autocomplete plugins from the one produced by bassistance to the jQuery UI autocomplete.

我最近将一些自动完成插件从bassistance生成的插件迁移到了jQuery UI自动完成。

How can the "mustMatch" and "selectFirst" be implemented with just callbacks and other options without modifying the core autocomplete code itself?

如何在不修改核心自动完成代码本身的情况下,仅使用回调和其他选项实现“mustMatch”和“selectFirst”?

12 个解决方案

#1


40  

I think I solved both features...

我想我解决了这两个问题......

To make things easier, I used a common custom selector:

为了简化操作,我使用了一个常见的自定义选择器:

$.expr[':'].textEquals = function (a, i, m) {
    return $(a).text().match("^" + m[3] + "$");
};

The rest of the code:

其余代码:

$(function () {
    $("#tags").autocomplete({
        source: '/get_my_data/',
        change: function (event, ui) {
            //if the value of the textbox does not match a suggestion, clear its value
            if ($(".ui-autocomplete li:textEquals('" + $(this).val() + "')").size() == 0) {
                $(this).val('');
            }
        }
    }).live('keydown', function (e) {
        var keyCode = e.keyCode || e.which;
        //if TAB or RETURN is pressed and the text in the textbox does not match a suggestion, set the value of the textbox to the text of the first suggestion
        if((keyCode == 9 || keyCode == 13) && ($(".ui-autocomplete li:textEquals('" + $(this).val() + "')").size() == 0)) {
            $(this).val($(".ui-autocomplete li:visible:first").text());
        }
    });
});

If any of your autocomplete suggestions contain any 'special' characters used by regexp, you must escape those characters within m[3] in the custom selector:

如果您的任何自动填充建议包含regexp使用的任何“特殊”字符,则必须在自定义选择器中的m [3]中转义这些字符:

function escape_regexp(text) {
  return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
}

and change the custom selector:

并更改自定义选择器:

$.expr[':'].textEquals = function (a, i, m) {
  return $(a).text().match("^" + escape_regexp(m[3]) + "$");
};

#2


32  

I used something as simple as this for mustMatch and it works. I hope it helps someone.

对于mustMatch,我使用了一些简单的东西,它可以工作。我希望它对某人有帮助。

        change: function (event, ui) {
            if (!ui.item) {
                 $(this).val('');
             }
        }

#3


3  

I think I got the mustMatch working with this code... need throughly test though:

我想我的mustMatch正在使用这段代码......需要彻底测试:

<script type="text/javascript">
    $(function() {
        $("#my_input_id").autocomplete({
            source: '/get_my_data/',
            minChars: 3,
            change: function(event, ui) {
                // provide must match checking if what is in the input
                // is in the list of results. HACK!
                var source = $(this).val();
                var found = $('.ui-autocomplete li').text().search(source);
                console.debug('found:' + found);
                if(found < 0) {
                    $(this).val('');
                }
            }
        });
    });
</script>

#4


2  

I found this question to be useful.

我发现这个问题很有用。

I thought I'd post up the code I'm now using (adapted from Esteban Feldman's answer).

我以为我会发布我现在正在使用的代码(改编自Esteban Feldman的答案)。

I've added my own mustMatch option, and a CSS class to highlight the issue before resetting the textbox value.

我添加了自己的mustMatch选项和一个CSS类,以在重置文本框值之前突出显示该问题。

       change: function (event, ui) {
          if (options.mustMatch) {
            var found = $('.ui-autocomplete li').text().search($(this).val());

            if (found < 0) {
              $(this).addClass('ui-autocomplete-nomatch').val('');
              $(this).delay(1500).removeClass('ui-autocomplete-nomatch', 500);
            }
          }
        }

CSS

CSS

.ui-autocomplete-nomatch { background: white url('../Images/AutocompleteError.gif') right center no-repeat; }

#5


1  

The solution I've used to implement 'mustMatch':

我用来实现'mustMatch'的解决方案:

<script type="text/javascript">
...

$('#recipient_name').autocomplete({
    source: friends,
    change: function (event, ui) {
        if ($('#message_recipient_id').attr('rel') != $(this).val()) {
            $(this).val('');
            $('#message_recipient_id').val('');
            $('#message_recipient_id').attr('rel', '');
        }
    },
    select: function(event, ui) {
        $('#message_recipient_id').val(ui.item.user_id);
        $('#message_recipient_id').attr('rel', ui.item.label);
    }
}); 

...
</script>

#6


1  

I discovered one issue. While the suggestion list is active you can submit your form even if the value doesn't match the suggestion. To dissallow this I added:

我发现了一个问题。当建议列表处于活动状态时,即使该值与建议不符,您也可以提交表单。为了解除这个,我补充道:

$('form').submit(function() {
        if ($(".ui-autocomplete li:textEquals('" + $(this).val() + "')").size() == 0) {
            $(this).val('');
            $("span").text("Select a valid city").show();
            return false;
        }
});

This prevents the form from being submitted and displays a message.

这可以防止提交表单并显示消息。

#7


1  

This JQuery-UI official demo has mustMatch, amongst other cool stuff: http://jqueryui.com/demos/autocomplete/#combobox

这个JQuery-UI官方演示有mustMatch,还有其他很酷的东西:http://jqueryui.com/demos/autocomplete/#combobox

I've updated it to add autoFill, and a few other things.

我已经更新它以添加autoFill和其他一些东西。

Javascript:

使用Javascript:



/* stolen from http://jqueryui.com/demos/autocomplete/#combobox
 *
 * and these options added.
 *
 * - autoFill (default: true):  select first value rather than clearing if there's a match
 *
 * - clearButton (default: true): add a "clear" button
 *
 * - adjustWidth (default: true): if true, will set the autocomplete width the same as
 *    the old select.  (requires jQuery 1.4.4 to work on IE8)
 *
 * - uiStyle (default: false): if true, will add classes so that the autocomplete input
 *    takes a jQuery-UI style
 */
(function( $ ) {
    $.widget( "ui.combobox", {
        options: {
            autoFill: true,
            clearButton: true,
            adjustWidth: true,
            uiStyle: false,
            selected: null,
        },
    _create: function() {
        var self = this,
          select = this.element.hide(),
          selected = select.children( ":selected" ),
          value = selected.val() ? selected.text() : "",
              found = false;
        var input = this.input = $( "" )
                .attr('title', '' + select.attr("title") + '')
        .insertAfter( select )
        .val( value )
        .autocomplete({
            delay: 0,
            minLength: 0,
            source: function( request, response ) {
                var matcher = new RegExp( $.ui.autocomplete.escapeRegex(request.term), "i" );
                        var resp = select.children( "option" ).map(function() {
                    var text = $( this ).text();
                    if ( this.value && ( !request.term || matcher.test(text) ) )
                    return {
                        label: text.replace(
                        new RegExp(
                            "(?![^&;]+;)(?!]*)(" +
                            $.ui.autocomplete.escapeRegex(request.term) +
                            ")(?![^]*>)(?![^&;]+;)", "gi"
                        ), "$1" ),
                        value: text,
                        option: this
                    };
                });
                        found = resp.length > 0;
                response( resp );
            },
            select: function( event, ui ) {
                ui.item.option.selected = true;
                self._trigger( "selected", event, {
                    item: ui.item.option
                });
            },
            change: function( event, ui ) {
                if ( !ui.item ) {
                    var matcher = new RegExp( "^" + $.ui.autocomplete.escapeRegex( $(this).val() ) + "$", "i" ),
                    valid = false;
                    select.children( "option" ).each(function() {
                    if ( $( this ).text().match( matcher ) ) {
                        this.selected = valid = true;
                        return false;
                    }
                    });
                    if ( !valid || input.data("autocomplete").term=="" ) {
                    // set to first suggestion, unless blank or autoFill is turned off
                                var suggestion;
                                if(!self.options.autoFill || input.data("autocomplete").term=="") found=false;
                                if(found) {
                                    suggestion = jQuery(input.data("autocomplete").widget()).find("li:first")[0];
                                    var option = select.find("option[text="+suggestion.innerText+"]").attr('selected', true);
                                    $(this).val(suggestion.innerText);
                        input.data("autocomplete").term = suggestion.innerText;
                            self._trigger( "selected", event, { item: option[0] });
                                } else {
                                    suggestion={innerText: ''};
                                    select.find("option:selected").removeAttr("selected");
                                    $(this).val('');
                        input.data( "autocomplete" ).term = '';
                                    self._trigger( "selected", event, { item: null });
                                }
                    return found;
                    }
                }
            }
        });

            if( self.options.adjustWidth ) { input.width(select.width()); }

            if( self.options.uiStyle ) {
                input.addClass( "ui-widget ui-widget-content ui-corner-left" );
            }


        input.data( "autocomplete" )._renderItem = function( ul, item ) {
            return $( "
  • " ) .data( "item.autocomplete", item ) .append( "" + item.label + "" ) .appendTo( ul ); }; this.button = $( " " ) .attr( "tabIndex", -1 ) .attr( "title", "Show All Items" ) .insertAfter( input ) .button({ icons: { primary: "ui-icon-triangle-1-s" }, text: false }) .removeClass( "ui-corner-all" ) .addClass( "ui-corner-right ui-button-icon" ) .click(function() { // close if already visible if ( input.autocomplete( "widget" ).is( ":visible" ) ) { input.autocomplete( "close" ); return; } // work around a bug (likely same cause as #5265) $( this ).blur(); // pass empty string as value to search for, displaying all results input.autocomplete( "search", "" ); input.focus(); }); if( self.options.clearButton ) { this.clear_button = $( " " ) .attr( "tabIndex", -1 ) .attr( "title", "Clear Entry" ) .insertAfter( input ) .button({ icons: { primary: "ui-icon-close" }, text: false }) .removeClass( "ui-corner-all" ) .click(function(event, ui) { select.find("option:selected").removeAttr("selected"); input.val( "" ); input.data( "autocomplete" ).term = ""; self._trigger( "selected", event, { item: null }); // work around a bug (likely same cause as #5265) $( this ).blur(); }); } }, destroy: function() { this.input.remove(); this.button.remove(); this.element.show(); $.Widget.prototype.destroy.call( this ); } }); })( jQuery );

    CSS (.hjq-combobox is a wrapping span)

    CSS(.hjq-combobox是一个包装范围)

    .hjq-combobox .ui-button { margin-left: -1px; }
    .hjq-combobox .ui-button-icon-only .ui-button-text { padding: 0; }
    .hjq-combobox button.ui-button-icon-only { width: 20px; }
    .hjq-combobox .ui-autocomplete-input { margin-right: 0; }
    .hjq-combobox {white-space: nowrap;}
    

    Note: this code is being updated and maintained here: https://github.com/tablatom/hobo/blob/master/hobo_jquery_ui/vendor/assets/javascripts/combobox.js

    注意:此代码正在更新和维护:https://github.com/tablatom/hobo/blob/master/hobo_jquery_ui/vendor/assets/javascripts/combobox.js

  • #8


    1  

    Maybe it's just because this is an old issue, but I found that the easiest solution is already there in the plugin, you just need to use the proper functions to access it.

    也许只是因为这是一个老问题,但我发现插件中已经存在最简单的解决方案,你只需要使用适当的函数来访问它。

    This code will handle the cases when the autocomplete loses focus with an invalid value:

    此代码将处理自动完成失去焦点且无效值的情况:

    change: function(e, ui) {
        if (!ui.item) {
            $(this).val("");
        }
    }
    

    And this code, much like the original functionality from bassistance, will handle the cases when there are no matches while typing in the autocomplete:

    这段代码与bassistance的原始功能非常相似,可以在输入自动完成时输入没有匹配项的情况:

    response: function(e, ui) {
        if (ui.content.length == 0) {
            $(this).val("");
        }
    }
    

    This works well with either a static array source, or a JSON data source. Combined with the autoFocus: true option, it seems to do everything needed in an efficient manner.

    这适用于静态数组源或JSON数据源。结合autoFocus:true选项,它似乎以高效的方式完成所需的一切。

    The last case that you may want to handle is what to do when the ESCAPE key is pressed with an invalid value in the textbox. What I do is use the value of the first matched result. And this is how I do that...

    您可能想要处理的最后一种情况是在文本框中按下ESCAPE键并使用无效值时要执行的操作。我所做的是使用第一个匹配结果的值。这就是我这样做的方式......

    First, declare a variable to hold the best match. Do this outside of your autocomplete plugin.

    首先,声明一个变量以保持最佳匹配。在您的自动完成插件之外执行此操作。

    var bestMatch = "";
    

    Then use the following option:

    然后使用以下选项:

    open: function(e, ui) {
        bestMatch = "";
    
        var acData = $(this).data('uiAutocomplete');
        acData.menu.element.find("A").each(function () {
            var me = $(this);
    
            if (me.parent().index() == 0) {
                bestMatch = me.text();
            }
        });
    }
    

    Lastly, add the following event to your autocomplete:

    最后,将以下事件添加到您的自动填充中:

    .on("keydown", function(e) {
        if (e.keyCode == 27)        // ESCAPE key
        {
            $(this).val(bestMatch);
        }
    })
    

    You can just as easily force the field to be empty when the escape key is pressed. All you have to do is set the value to an empty string when the key is pressed instead of the bestMatch variable (which isn't needed at all if you choose to empty the field).

    按下退出键时,您可以轻松地强制字段为空。您只需在按下键时将值设置为空字符串而不是bestMatch变量(如果您选择清空该字段,则根本不需要该变量)。

    #9


    0  

    I'm doing it a little differently, caching the results and clearing the text field if the number of results for a certain term is zero:

    我的做法有所不同,如果某个术语的结果数为零,则缓存结果并清除文本字段:

    <script type='text/javascript'>
    function init_autocomplete( args )
    {
         var resultCache = {};
         var currentRequestTerm = null;
    
         var closeCallback = function()
         {
             // Clear text field if current request has no results
             if( resultCache[currentRequestTerm].length == 0 )
                 $(args.selector).val('');
         };
    
         var sourceCallback = function( request, responseCallback )
         {
             // Save request term
             currentRequestTerm = request.term;
    
             // Check for cache hit
             // ...
             // If no cache hit, fetch remote data
             $.post(
                 dataSourceUrl,
                 { ...  }, // post data
                 function( response )
                 {
                     // Store cache
                     resultCache[request.term] = response;
    
                     responseCallback( response );
                 }
         };
    
         $(args.selector).autocomplete({
             close:  closeCallback,
             source: sourceCallback
         });
    }
    </script>
    

    #10


    0  

    Scott Gonzalez has written a selectFirst extension (as well as several others) for jQueryUI AutoComplete.

    Scott Gonzalez为jQueryUI AutoComplete编写了一个selectFirst扩展(以及其他几个扩展)。

    #11


    0  

    Based on the accepted answer:

    根据接受的答案:

    My additional requirements: multiple autocompletes, unobtrusive error validation.

    我的附加要求:多个自动完成,不显眼的错误验证。

    change: function () {
        var target = $(this),
            widget = target.autocomplete('widget'),
            cond = widget.find('li:textEquals("' + target.val() + '")').length === 0;
    
        target.toggleClass('input-validation-error', cond);
    }
    

    #12


    0  

    Late reply but might help someone!

    迟到的回复但可能会帮助别人!

    Considering the two events in autocomplete widget

    考虑自动完成小部件中的两个事件

    1) change - triggered when field is blurred and value is changed.

    1)更改 - 当字段模糊且值更改时触发。

    2) response - triggered when the search completes and the menu is shown.

    2)响应 - 在搜索完成并显示菜单时触发。

    Modify the change and response events as follows:

    修改更改和响应事件,如下所示:

    change : function(event,ui)
    {  
    if(!ui.item){
    $("selector").val("");
    }
    },
    
    response : function(event,ui){
    if(ui.content.length==0){
      $("selector").val("");
    }
    }
    

    Hope this helps!

    希望这可以帮助!

    #1


    40  

    I think I solved both features...

    我想我解决了这两个问题......

    To make things easier, I used a common custom selector:

    为了简化操作,我使用了一个常见的自定义选择器:

    $.expr[':'].textEquals = function (a, i, m) {
        return $(a).text().match("^" + m[3] + "$");
    };
    

    The rest of the code:

    其余代码:

    $(function () {
        $("#tags").autocomplete({
            source: '/get_my_data/',
            change: function (event, ui) {
                //if the value of the textbox does not match a suggestion, clear its value
                if ($(".ui-autocomplete li:textEquals('" + $(this).val() + "')").size() == 0) {
                    $(this).val('');
                }
            }
        }).live('keydown', function (e) {
            var keyCode = e.keyCode || e.which;
            //if TAB or RETURN is pressed and the text in the textbox does not match a suggestion, set the value of the textbox to the text of the first suggestion
            if((keyCode == 9 || keyCode == 13) && ($(".ui-autocomplete li:textEquals('" + $(this).val() + "')").size() == 0)) {
                $(this).val($(".ui-autocomplete li:visible:first").text());
            }
        });
    });
    

    If any of your autocomplete suggestions contain any 'special' characters used by regexp, you must escape those characters within m[3] in the custom selector:

    如果您的任何自动填充建议包含regexp使用的任何“特殊”字符,则必须在自定义选择器中的m [3]中转义这些字符:

    function escape_regexp(text) {
      return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
    }
    

    and change the custom selector:

    并更改自定义选择器:

    $.expr[':'].textEquals = function (a, i, m) {
      return $(a).text().match("^" + escape_regexp(m[3]) + "$");
    };
    

    #2


    32  

    I used something as simple as this for mustMatch and it works. I hope it helps someone.

    对于mustMatch,我使用了一些简单的东西,它可以工作。我希望它对某人有帮助。

            change: function (event, ui) {
                if (!ui.item) {
                     $(this).val('');
                 }
            }
    

    #3


    3  

    I think I got the mustMatch working with this code... need throughly test though:

    我想我的mustMatch正在使用这段代码......需要彻底测试:

    <script type="text/javascript">
        $(function() {
            $("#my_input_id").autocomplete({
                source: '/get_my_data/',
                minChars: 3,
                change: function(event, ui) {
                    // provide must match checking if what is in the input
                    // is in the list of results. HACK!
                    var source = $(this).val();
                    var found = $('.ui-autocomplete li').text().search(source);
                    console.debug('found:' + found);
                    if(found < 0) {
                        $(this).val('');
                    }
                }
            });
        });
    </script>
    

    #4


    2  

    I found this question to be useful.

    我发现这个问题很有用。

    I thought I'd post up the code I'm now using (adapted from Esteban Feldman's answer).

    我以为我会发布我现在正在使用的代码(改编自Esteban Feldman的答案)。

    I've added my own mustMatch option, and a CSS class to highlight the issue before resetting the textbox value.

    我添加了自己的mustMatch选项和一个CSS类,以在重置文本框值之前突出显示该问题。

           change: function (event, ui) {
              if (options.mustMatch) {
                var found = $('.ui-autocomplete li').text().search($(this).val());
    
                if (found < 0) {
                  $(this).addClass('ui-autocomplete-nomatch').val('');
                  $(this).delay(1500).removeClass('ui-autocomplete-nomatch', 500);
                }
              }
            }
    

    CSS

    CSS

    .ui-autocomplete-nomatch { background: white url('../Images/AutocompleteError.gif') right center no-repeat; }
    

    #5


    1  

    The solution I've used to implement 'mustMatch':

    我用来实现'mustMatch'的解决方案:

    <script type="text/javascript">
    ...
    
    $('#recipient_name').autocomplete({
        source: friends,
        change: function (event, ui) {
            if ($('#message_recipient_id').attr('rel') != $(this).val()) {
                $(this).val('');
                $('#message_recipient_id').val('');
                $('#message_recipient_id').attr('rel', '');
            }
        },
        select: function(event, ui) {
            $('#message_recipient_id').val(ui.item.user_id);
            $('#message_recipient_id').attr('rel', ui.item.label);
        }
    }); 
    
    ...
    </script>
    

    #6


    1  

    I discovered one issue. While the suggestion list is active you can submit your form even if the value doesn't match the suggestion. To dissallow this I added:

    我发现了一个问题。当建议列表处于活动状态时,即使该值与建议不符,您也可以提交表单。为了解除这个,我补充道:

    $('form').submit(function() {
            if ($(".ui-autocomplete li:textEquals('" + $(this).val() + "')").size() == 0) {
                $(this).val('');
                $("span").text("Select a valid city").show();
                return false;
            }
    });
    

    This prevents the form from being submitted and displays a message.

    这可以防止提交表单并显示消息。

    #7


    1  

    This JQuery-UI official demo has mustMatch, amongst other cool stuff: http://jqueryui.com/demos/autocomplete/#combobox

    这个JQuery-UI官方演示有mustMatch,还有其他很酷的东西:http://jqueryui.com/demos/autocomplete/#combobox

    I've updated it to add autoFill, and a few other things.

    我已经更新它以添加autoFill和其他一些东西。

    Javascript:

    使用Javascript:

    
    
    /* stolen from http://jqueryui.com/demos/autocomplete/#combobox
     *
     * and these options added.
     *
     * - autoFill (default: true):  select first value rather than clearing if there's a match
     *
     * - clearButton (default: true): add a "clear" button
     *
     * - adjustWidth (default: true): if true, will set the autocomplete width the same as
     *    the old select.  (requires jQuery 1.4.4 to work on IE8)
     *
     * - uiStyle (default: false): if true, will add classes so that the autocomplete input
     *    takes a jQuery-UI style
     */
    (function( $ ) {
        $.widget( "ui.combobox", {
            options: {
                autoFill: true,
                clearButton: true,
                adjustWidth: true,
                uiStyle: false,
                selected: null,
            },
        _create: function() {
            var self = this,
              select = this.element.hide(),
              selected = select.children( ":selected" ),
              value = selected.val() ? selected.text() : "",
                  found = false;
            var input = this.input = $( "" )
                    .attr('title', '' + select.attr("title") + '')
            .insertAfter( select )
            .val( value )
            .autocomplete({
                delay: 0,
                minLength: 0,
                source: function( request, response ) {
                    var matcher = new RegExp( $.ui.autocomplete.escapeRegex(request.term), "i" );
                            var resp = select.children( "option" ).map(function() {
                        var text = $( this ).text();
                        if ( this.value && ( !request.term || matcher.test(text) ) )
                        return {
                            label: text.replace(
                            new RegExp(
                                "(?![^&;]+;)(?!]*)(" +
                                $.ui.autocomplete.escapeRegex(request.term) +
                                ")(?![^]*>)(?![^&;]+;)", "gi"
                            ), "$1" ),
                            value: text,
                            option: this
                        };
                    });
                            found = resp.length > 0;
                    response( resp );
                },
                select: function( event, ui ) {
                    ui.item.option.selected = true;
                    self._trigger( "selected", event, {
                        item: ui.item.option
                    });
                },
                change: function( event, ui ) {
                    if ( !ui.item ) {
                        var matcher = new RegExp( "^" + $.ui.autocomplete.escapeRegex( $(this).val() ) + "$", "i" ),
                        valid = false;
                        select.children( "option" ).each(function() {
                        if ( $( this ).text().match( matcher ) ) {
                            this.selected = valid = true;
                            return false;
                        }
                        });
                        if ( !valid || input.data("autocomplete").term=="" ) {
                        // set to first suggestion, unless blank or autoFill is turned off
                                    var suggestion;
                                    if(!self.options.autoFill || input.data("autocomplete").term=="") found=false;
                                    if(found) {
                                        suggestion = jQuery(input.data("autocomplete").widget()).find("li:first")[0];
                                        var option = select.find("option[text="+suggestion.innerText+"]").attr('selected', true);
                                        $(this).val(suggestion.innerText);
                            input.data("autocomplete").term = suggestion.innerText;
                                self._trigger( "selected", event, { item: option[0] });
                                    } else {
                                        suggestion={innerText: ''};
                                        select.find("option:selected").removeAttr("selected");
                                        $(this).val('');
                            input.data( "autocomplete" ).term = '';
                                        self._trigger( "selected", event, { item: null });
                                    }
                        return found;
                        }
                    }
                }
            });
    
                if( self.options.adjustWidth ) { input.width(select.width()); }
    
                if( self.options.uiStyle ) {
                    input.addClass( "ui-widget ui-widget-content ui-corner-left" );
                }
    
    
            input.data( "autocomplete" )._renderItem = function( ul, item ) {
                return $( "
  • " ) .data( "item.autocomplete", item ) .append( "" + item.label + "" ) .appendTo( ul ); }; this.button = $( " " ) .attr( "tabIndex", -1 ) .attr( "title", "Show All Items" ) .insertAfter( input ) .button({ icons: { primary: "ui-icon-triangle-1-s" }, text: false }) .removeClass( "ui-corner-all" ) .addClass( "ui-corner-right ui-button-icon" ) .click(function() { // close if already visible if ( input.autocomplete( "widget" ).is( ":visible" ) ) { input.autocomplete( "close" ); return; } // work around a bug (likely same cause as #5265) $( this ).blur(); // pass empty string as value to search for, displaying all results input.autocomplete( "search", "" ); input.focus(); }); if( self.options.clearButton ) { this.clear_button = $( " " ) .attr( "tabIndex", -1 ) .attr( "title", "Clear Entry" ) .insertAfter( input ) .button({ icons: { primary: "ui-icon-close" }, text: false }) .removeClass( "ui-corner-all" ) .click(function(event, ui) { select.find("option:selected").removeAttr("selected"); input.val( "" ); input.data( "autocomplete" ).term = ""; self._trigger( "selected", event, { item: null }); // work around a bug (likely same cause as #5265) $( this ).blur(); }); } }, destroy: function() { this.input.remove(); this.button.remove(); this.element.show(); $.Widget.prototype.destroy.call( this ); } }); })( jQuery );

    CSS (.hjq-combobox is a wrapping span)

    CSS(.hjq-combobox是一个包装范围)

    .hjq-combobox .ui-button { margin-left: -1px; }
    .hjq-combobox .ui-button-icon-only .ui-button-text { padding: 0; }
    .hjq-combobox button.ui-button-icon-only { width: 20px; }
    .hjq-combobox .ui-autocomplete-input { margin-right: 0; }
    .hjq-combobox {white-space: nowrap;}
    

    Note: this code is being updated and maintained here: https://github.com/tablatom/hobo/blob/master/hobo_jquery_ui/vendor/assets/javascripts/combobox.js

    注意:此代码正在更新和维护:https://github.com/tablatom/hobo/blob/master/hobo_jquery_ui/vendor/assets/javascripts/combobox.js

  • #8


    1  

    Maybe it's just because this is an old issue, but I found that the easiest solution is already there in the plugin, you just need to use the proper functions to access it.

    也许只是因为这是一个老问题,但我发现插件中已经存在最简单的解决方案,你只需要使用适当的函数来访问它。

    This code will handle the cases when the autocomplete loses focus with an invalid value:

    此代码将处理自动完成失去焦点且无效值的情况:

    change: function(e, ui) {
        if (!ui.item) {
            $(this).val("");
        }
    }
    

    And this code, much like the original functionality from bassistance, will handle the cases when there are no matches while typing in the autocomplete:

    这段代码与bassistance的原始功能非常相似,可以在输入自动完成时输入没有匹配项的情况:

    response: function(e, ui) {
        if (ui.content.length == 0) {
            $(this).val("");
        }
    }
    

    This works well with either a static array source, or a JSON data source. Combined with the autoFocus: true option, it seems to do everything needed in an efficient manner.

    这适用于静态数组源或JSON数据源。结合autoFocus:true选项,它似乎以高效的方式完成所需的一切。

    The last case that you may want to handle is what to do when the ESCAPE key is pressed with an invalid value in the textbox. What I do is use the value of the first matched result. And this is how I do that...

    您可能想要处理的最后一种情况是在文本框中按下ESCAPE键并使用无效值时要执行的操作。我所做的是使用第一个匹配结果的值。这就是我这样做的方式......

    First, declare a variable to hold the best match. Do this outside of your autocomplete plugin.

    首先,声明一个变量以保持最佳匹配。在您的自动完成插件之外执行此操作。

    var bestMatch = "";
    

    Then use the following option:

    然后使用以下选项:

    open: function(e, ui) {
        bestMatch = "";
    
        var acData = $(this).data('uiAutocomplete');
        acData.menu.element.find("A").each(function () {
            var me = $(this);
    
            if (me.parent().index() == 0) {
                bestMatch = me.text();
            }
        });
    }
    

    Lastly, add the following event to your autocomplete:

    最后,将以下事件添加到您的自动填充中:

    .on("keydown", function(e) {
        if (e.keyCode == 27)        // ESCAPE key
        {
            $(this).val(bestMatch);
        }
    })
    

    You can just as easily force the field to be empty when the escape key is pressed. All you have to do is set the value to an empty string when the key is pressed instead of the bestMatch variable (which isn't needed at all if you choose to empty the field).

    按下退出键时,您可以轻松地强制字段为空。您只需在按下键时将值设置为空字符串而不是bestMatch变量(如果您选择清空该字段,则根本不需要该变量)。

    #9


    0  

    I'm doing it a little differently, caching the results and clearing the text field if the number of results for a certain term is zero:

    我的做法有所不同,如果某个术语的结果数为零,则缓存结果并清除文本字段:

    <script type='text/javascript'>
    function init_autocomplete( args )
    {
         var resultCache = {};
         var currentRequestTerm = null;
    
         var closeCallback = function()
         {
             // Clear text field if current request has no results
             if( resultCache[currentRequestTerm].length == 0 )
                 $(args.selector).val('');
         };
    
         var sourceCallback = function( request, responseCallback )
         {
             // Save request term
             currentRequestTerm = request.term;
    
             // Check for cache hit
             // ...
             // If no cache hit, fetch remote data
             $.post(
                 dataSourceUrl,
                 { ...  }, // post data
                 function( response )
                 {
                     // Store cache
                     resultCache[request.term] = response;
    
                     responseCallback( response );
                 }
         };
    
         $(args.selector).autocomplete({
             close:  closeCallback,
             source: sourceCallback
         });
    }
    </script>
    

    #10


    0  

    Scott Gonzalez has written a selectFirst extension (as well as several others) for jQueryUI AutoComplete.

    Scott Gonzalez为jQueryUI AutoComplete编写了一个selectFirst扩展(以及其他几个扩展)。

    #11


    0  

    Based on the accepted answer:

    根据接受的答案:

    My additional requirements: multiple autocompletes, unobtrusive error validation.

    我的附加要求:多个自动完成,不显眼的错误验证。

    change: function () {
        var target = $(this),
            widget = target.autocomplete('widget'),
            cond = widget.find('li:textEquals("' + target.val() + '")').length === 0;
    
        target.toggleClass('input-validation-error', cond);
    }
    

    #12


    0  

    Late reply but might help someone!

    迟到的回复但可能会帮助别人!

    Considering the two events in autocomplete widget

    考虑自动完成小部件中的两个事件

    1) change - triggered when field is blurred and value is changed.

    1)更改 - 当字段模糊且值更改时触发。

    2) response - triggered when the search completes and the menu is shown.

    2)响应 - 在搜索完成并显示菜单时触发。

    Modify the change and response events as follows:

    修改更改和响应事件,如下所示:

    change : function(event,ui)
    {  
    if(!ui.item){
    $("selector").val("");
    }
    },
    
    response : function(event,ui){
    if(ui.content.length==0){
      $("selector").val("");
    }
    }
    

    Hope this helps!

    希望这可以帮助!