【问题标题】:jQuery ui autocomplete when user does not select an option from the dropdown当用户未从下拉列表中选择选项时,jQuery ui 自动完成
【发布时间】:2012-05-01 23:51:36
【问题描述】:

在使用jquery autocomplete plugin 时,如果用户没有选择列表中的某个项目,而是键入了一个有效值并使用制表符离开,你会怎么做?

例如当自动完成列表包含:

Cat
Dog
Fish 

并且用户键入cat,但没有从自动完成的下拉列表中选择Cat,而是选择了选项卡。因为他们没有从列表中选择任何项目,所以不会触发自动完成选择事件,我们失去了响应它的机会:

$('#Animal').autocomplete({
    source: url,
    minlength: 1,
    select: function (event, ui) {
        $("#Animal").val(ui.item.value);
        changeUsersAnimal(ui.item.id);
    }
});

我该如何处理这种情况?

【问题讨论】:

  • 请注意cat 和Cat 不是同一个东西。
  • 使用自动完成的 autoFocus 选项。在下面的答案中查看更多详细信息。

标签: jquery jquery-ui jquery-ui-autocomplete


【解决方案1】:

您可能正在寻找Scott González' autoSelect extension。如果用户输入一个有效值并且不需要您进行任何更改,只需在页面上包含此扩展程序即可触发 select 事件:

/*
 * jQuery UI Autocomplete Auto Select Extension
 *
 * Copyright 2010, Scott González (http://scottgonzalez.com)
 * Dual licensed under the MIT or GPL Version 2 licenses.
 *
 * http://github.com/scottgonzalez/jquery-ui-extensions
 */
(function( $ ) {

$.ui.autocomplete.prototype.options.autoSelect = true;
$( ".ui-autocomplete-input" ).live( "blur", function( event ) {
    var autocomplete = $( this ).data( "autocomplete" );
    if ( !autocomplete.options.autoSelect || autocomplete.selectedItem ) { return; }

    var matcher = new RegExp( "^" + $.ui.autocomplete.escapeRegex( $(this).val() ) + "$", "i" );
    autocomplete.widget().children( ".ui-menu-item" ).each(function() {
        var item = $( this ).data( "item.autocomplete" );
        if ( matcher.test( item.label || item.value || item ) ) {
            autocomplete.selectedItem = item;
            return false;
        }
    });
    if ( autocomplete.selectedItem ) {
        autocomplete._trigger( "select", event, { item: autocomplete.selectedItem } );
    }
});

}( jQuery ));

这是一个使用扩展的示例:http://jsfiddle.net/vFWUt/226/

【讨论】:

  • 有希望..现在看
  • 我在扩展中看到的问题是它使用了live,它将在页面中的每个blur 上触发。为业主竖起大拇指。为你投票...!
  • @gdoron 据我了解,该事件仅应为自动完成触发:$( ".ui-autocomplete-input" ).live("blur" -> 只会触发 ui-autocomplete-input 类的任何内容,还是这种理解不正确?
  • 对于任何寻找这个扩展的人(顺便说一句非常有帮助)。网址已更改为:github.com/scottgonzalez/jquery-ui-extensions/blob/master/src/…
  • @MattBeckman:实际上,autoFocus 选项和这个答案并不等同。如果用户键入一个答案,然后单击 离开autoFocus:true,则该项目将 被选中。使用此扩展,无论用户如何更改焦点,都将选择该项目。我想如果你从字面上理解这个问题,那么是的,autoFocus 满足要求,但我个人觉得它不能处理“点击退出”的情况有点令人沮丧。
【解决方案2】:

对于 jQuery 版本 >= 1.8.11,使用 autoFocus 选项设置为 true

$( ".selector" ).autocomplete({ autoFocus: true });

这具有自动选择列表中的第一项的额外优势,因此用户只需按 Enter 或 Tab 即可选择它,而无需键入所有名称。

【讨论】:

  • 自动对焦不会强制选择项目。所以这不是答案。
  • @ChristophMeißner:问题是:当用户没有选择列表中的某个项目,而是键入一个有效值并跳开时,你会怎么做?如果将 autoFocus 设置为 true,则将选择与用户键入的内容匹配的第一个项目。我认为这是理想的行为。
  • 即使将 autoFocus 设置为 true,用户也可以键入或粘贴有效的项目名称,然后以足够快的速度离开该字段,以至于尚未显示自动完成列表,使该字段没有选定的项目.如果显示自动完成列表,但用户移动鼠标并导致列表中的第一项被取消选择,然后离开字段而不选择项目,也会发生这种情况。这个问题是 Scott González 的自动选择扩展试图纠正的问题,方法是观察字段的模糊事件,然后在匹配时强制选择一个项目。
【解决方案3】:

添加onchange的自定义事件

$('#Animal').change(function(){
    var selectedValue = this.value;
    // Do what you want here:
    ...
});

或者使用小部件内置的change事件:

$('#Animal').autocomplete({
    source: url,
    minlength: 1,
    select: function (event, ui) {
        $("#Animal").val(ui.item.value);
        changeUsersAnimal(ui.item.id);
    }
   change: function(event, ui) { // <=======
       // ... 
       // ...
   }
});

source

【讨论】:

  • 这仅针对一个自动完成功能 - 我有 50 多个自动完成功能需要检查和修复。有没有更通用的方法?
  • @JK.. 给他们一个班级,然后用班级选择器抓住他们。酷吗?
  • 这很尴尬,因为我们在执行 onselected 操作时需要知道 item.id 的值。如果只使用 .change() 那么我们没有 id 并且需要做类似$(selector).change(function(){ var selectedValue = this.value; var id=GetIdFromName(selectedValue); doSelectChangeEvent(id); }); 的事情。所以这意味着要编写一个额外的函数并为每个自动完成进行额外的 ajax 调用。
  • 如果用户没有从菜单中选择项目,autocompletechange 将没有 ui.item 的值。
  • 使用更改事件听起来像是一种改进,但正如@AndrewWhitaker 指出的那样,没有可参考的选定项目
【解决方案4】:

对于 jQuery UI 1.9.2,我不得不在 Andrew Whitaker 的回答中更改一点 Scott González 的 autoSelect 扩展:

var item = $( this ).data( "item.autocomplete" );

成为

var item = $( this ).data( "uiAutocompleteItem" );

然后完美运行。

【讨论】:

    【解决方案5】:

    你可以这样使用

    $("#inputbox").autocomplete({
        source : reuesturl,
        minLength : 1,
        select : function(event, ui) {
            $("#inputbox").attr('rel',ui.item.label);
        },
        open : function() {
            $("#inputbox").attr('rel', 0);
        },
        close : function() {                    
            if ($("#inputbox").attr('rel')=='0')
                $("#inputbox").val('');
        }
    });
    

    【讨论】:

      【解决方案6】:

      对于jQuery UI - v1.11.0,我不得不改变一点Scott González' autoSelect extension,如下所示。

      /*
       * jQuery UI Autocomplete Auto Select Extension
       *
       * Copyright 2010, Scott González (http://scottgonzalez.com)
       * Dual licensed under the MIT or GPL Version 2 licenses.
       *
       * http://github.com/scottgonzalez/jquery-ui-extensions
       */
      $().ready(function () {
          $.ui.autocomplete.prototype.options.autoSelect = true;
          $(".ui-autocomplete-input").change(function (event) {
              var autocomplete = $(this).data("uiAutocomplete");
      
              if (!autocomplete.options.autoSelect || autocomplete.selectedItem) { return; }
      
              var matcher = new RegExp("^" + $.ui.autocomplete.escapeRegex($(this).val()) + "$", "i");
              autocomplete.widget().children(".ui-menu-item").each(function () {
                  var item = $(this).data("uiAutocompleteItem");
                  if (matcher.test(item.label || item.value || item)) {
                      autocomplete.selectedItem = item;
                      return false;
                  }
              });
      
              if (autocomplete.selectedItem) {
                  autocomplete._trigger("select", event, { item: autocomplete.selectedItem });
              }
          });
      });
      

      并且必须在我的自动完成定义中应用扩展的自动完成选项autoSelect: true。

      我从这些答案中提取了一些代码。

      1. trushkevich
      2. gdoron 和
      3. Cagatay Kalan

      编辑

      这是我的自动完成定义,以防有人感兴趣。

      $("your selector").autocomplete({
          // Below filter looks for the values that start with the passed in string
          source: function (request, response) {
              var matches = $.map(yourSourceArray, function (acItem) {
                  if (acItem.toUpperCase().indexOf(request.term.toUpperCase()) === 0) {
                      return acItem;
                  }
              });
              response(matches);
          },
          // one can directly pass the source array instead like,
          // source: yourSourceArray
          autoSelect: true,
          autoFocus: true,
          minLength: 3,
          change: function (event, ui) {
              if (ui.item) {
                  // do whatever you want to when the item is found
              }
              else {
                  // do whatever you want to when the item is not found
              }
          }
      })
      

      【讨论】:

        【解决方案7】:

        以下代码是对 Scott 的扩展以与 jquery ui 1.10.3 版本一起使用的小调整,我仅使用 1.10.3 版本测试了以下代码。

        (function($) {
        
        $.ui.autocomplete.prototype.options.autoSelect = true;
        $( ".ui-autocomplete-input" ).live( "blur", function( event ) {
            var autocomplete = $( this ).data( "ui-autocomplete" );
            if ( ! autocomplete.options.autoSelect || autocomplete.selectedItem ) { return; }
        
            var matcher = new RegExp( "^" + $.ui.autocomplete.escapeRegex( $(this).val() ) + "$", "i" );
            autocomplete.widget().children( ".ui-menu-item" ).each(function() {
                var item = $( this ).data( "ui-autocomplete-item" );
                if ( matcher.test( item.label || item.value || item ) ) {
                    autocomplete.selectedItem = item;
                    return false;
                }
            });
            if ( autocomplete.selectedItem ) {
                autocomplete._trigger( "select", event, { item: autocomplete.selectedItem } );
            }
        });
        }(jQuery));
        

        【讨论】:

          【解决方案8】:

          另一个简单的技巧是使用.autocomplete({ focus: and change: })。 在focus 上将数据放入元素数据属性中,在change 上接受它:

          return $(element).autocomplete({
                      source: get_db_cities,
                      select: function (event, ui) {
                          $(this).attr('tz',ui.item.tz);
                      },
                      autoFocus: true,
                      focus: function (event, ui) {
                          $(this).attr('tz',ui.item.tz);
                          $(this).attr('label',ui.item.label); // put data in attribute
                      },
                      change: function () {
                          $(this).val($(this).attr('label')); // take from attribute and insert as value
                      }
          });
          

          【讨论】:

            【解决方案9】:

            此代码仅自动选择一次。之后的所有其他人什么都不做。有什么想法吗?

            编辑:我注释掉了这一行,它现在可以工作了。不知道为什么。

            if ( !autocomplete.options.autoSelect || autocomplete.selectedItem ) { return; }
            

            【讨论】:

            • 而不是评论该行;在您的自动完成中添加新选项为autoSelect: true。这条线不会给你造成问题。
            【解决方案10】:

            我在使用 jquery 1.9.1 和 jquery-ui 1.10.3 的页面中使用此功能时遇到问题。基于 Scott Gonzalez 的代码和这里的建议以及几个小时的反复思考,我想出了以下内容。请注意,我想要一个解决方案,其中只允许用户输入自动完成建议的值之一——但我想允许用户只输入一个允许的值而不从下拉列表中选择它的情况:

            /*
             * jQuery UI Autocomplete Auto Select Extension
             *
             * v 1.10
             * Jomo Frodo (jomofrodo@gmail.com)
             * 
             * This version requires an autoSelect parameter to be set on the autocomplete widget
             * 
             * e.g.,
             *      $("#autoCompleteID").autocomplete({
                        source:url,
                        minLength:1,
                        autoSelect: true
                    });
             * 
             * Based on an extension by Scott González (http://scottgonzalez.com) 
             * http://blog.jqueryui.com/2010/08/extensible-autocomplete/
             * Dual licensed under the MIT or GPL Version 2 licenses.
             *
             * http://github.com/scottgonzalez/jquery-ui-extensions
             */
            
            $(window).load(
                    function() {
            
                        //$.ui.autocomplete.prototype.options.autoSelect = true; 
                        // Doesn't appear to work in ui 1.10.3
                        // Must set the 'autoSelect' param on the autocomplete widget to get this to work.
            
                        $(".ui-autocomplete-input").bind('autocompleteresponse',
                                function(event, ui) {
                                    $(this).data('menuItems', ui.content);
                                });
            
                        $(".ui-autocomplete-input").on(
                                "blur",
                                null,
                                function(event) {
                                    var autocomplete = $(this).data("uiAutocomplete");
                                    if (!autocomplete.options.autoSelect
                                            || autocomplete.selectedItem) {
                                        return;
                                    }
            
                                    var matcher = new RegExp("^"
                                            + $.ui.autocomplete.escapeRegex($(this).val())
                                            + "$", "i");
                                    var menuItems = $(this).data('menuItems');
                                    for (idx in menuItems) {
                                        var item = menuItems[idx];
                                        if (matcher.test(item.value)) {
                                            autocomplete.selectedItem = item;
                                            break;
                                            // return false;
                                        }
                                    }
                                    if (autocomplete.selectedItem) {
                                        autocomplete._trigger("select", event, {
                                            item : autocomplete.selectedItem
                                        });
                                    } else {
                                        this.value = '';
                                    }
                                });
            
                    });
            

            【讨论】:

              【解决方案11】:

              使用autoFocus: true

              $('#Animal').autocomplete({
                  source: url,
                  **autoFocus: true,**
                  minlength: 1,
                  select: function (event, ui) {
                      $("#Animal").val(ui.item.value);
                      changeUsersAnimal(ui.item.id);
                  }
              });
              

              【讨论】:

                【解决方案12】:

                更新了 Scott Gonzalez 的代码以使用 Jquery-UI 1.12

                (function($) {
                
                    $.ui.autocomplete.prototype.options.autoSelect = true;
                    $('body').on('blur', '.ui-autocomplete-input', function(event) {
                        var autocomplete = $(this).data('ui-autocomplete');
                        if (!autocomplete.options.autoSelect || autocomplete.selectedItem) { return; }
                
                        var matcher = new RegExp($.ui.autocomplete.escapeRegex($(this).val()), 'i');
                        autocomplete.widget().children('.ui-menu-item').each(function(index, item) {
                            var item = $( this ).data('uiAutocompleteItem');
                            if (matcher.test(item.label || item.value || item)) {
                                autocomplete.selectedItem = item;
                                return false;
                            }
                        });
                
                        if (autocomplete.selectedItem) {
                            autocomplete
                            ._trigger('select', event, {item: autocomplete.selectedItem});
                        }
                    });
                
                }(jQuery));
                

                【讨论】:

                  【解决方案13】:

                  我已经尝试了所有这些响应,如果引入的值不在列表中,我的最终解决方案是将 select 设为空:

                              $( "#input" ).autocomplete({
                                  source: source,
                                  minLength: 0,
                                  change: function(event, ui) {
                                      if(!ui.item) {
                                          $(this).val("")
                                      }
                                  }
                              }).focus(function(){            
                                  $(this).data("uiAutocomplete").search($(this).val());
                              });
                  

                  【讨论】:

                    猜你喜欢
                    • 2022-01-21
                    • 2021-11-05
                    • 2020-03-31
                    • 2011-01-13
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    相关资源
                    最近更新 更多