【问题标题】:How to implement "mustMatch" and "selectFirst" in jQuery UI Autocomplete?如何在 jQuery UI 自动完成中实现“mustMatch”和“selectFirst”?
【发布时间】:2011-02-04 22:53:56
【问题描述】:

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

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

【问题讨论】:

    标签: jquery jquery-ui autocomplete


    【解决方案1】:

    我想我解决了这两个功能......

    为了方便起见,我使用了一个通用的自定义选择器:

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

    其余代码:

    $(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());
            }
        });
    });
    

    如果您的任何自动完成建议包含正则表达式使用的任何“特殊”字符,您必须在自定义选择器中转义 m[3] 内的这些字符:

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

    并更改自定义选择器:

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

    【讨论】:

    • 您是否也能够让“自动填充”工作?我在stackoverflow.com/questions/2933713/… 有一个问题,但我一辈子都无法让自动填充工作。
    • 如何自定义它以使用在插件的焦点、选择等事件参数旁边传递的 ui 对象?
    • 我几乎让它工作(只是必须匹配的东西),但无论是否建议,它似乎都清除了值。有任何想法吗? ://
    • 更新:我做了一些调试,看起来好像每个建议的自动完成值都调用了表达式,并且由于建议列表中的最后一个与它返回的所选值不匹配false 并从输入框中清空选定的值。有什么想法为什么要遍历所有这些吗?也许我搞砸了!
    • Update2:看起来即使事情相同,正则表达式也会返回 null,因此可能存在问题。认为这可能是因为我的字符串实际上有方括号,其中可能会搞砸正则表达式。
    【解决方案2】:

    我在 mustMatch 中使用了像这样简单的东西,它可以工作。我希望它可以帮助某人。

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

    【讨论】:

    • 完美,谢谢!你实现了自动填充吗?也在找那个:)
    • 请注意,您应该确保您拥有autoFocus: true
    • 这就是我要找的
    【解决方案3】:

    我想我已经让 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>
    

    【讨论】:

    • 很好,但我可以在退货时提交一个空值。我认为你必须实现一个 keydown 功能。
    【解决方案4】:

    我发现这个问题很有用。

    我想我会发布我现在使用的代码(改编自 Esteban Feldman's answer)。

    我添加了我自己的 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

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

    【讨论】:

    • @GordonB - 你有没有任何地方的图像 autocompleteerror.gif
    【解决方案5】:

    我用来实现“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】:

      我发现了一个问题。当建议列表处于活动状态时,即使值与建议不匹配,您也可以提交表单。为了禁止这一点,我添加了:

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

      这会阻止提交表单并显示一条消息。

      【讨论】:

      • 注意:这似乎是对 Doc Hoffiday 接受的答案的评论。
      【解决方案7】:

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

      我已对其进行了更新以添加自动填充和其他一些内容。

      Javascript:

      /* 从 http://jqueryui.com/demos/autocomplete/#combobox 窃取 * * 并添加了这些选项。 * * - 自动填充(默认值:true):选择第一个值而不是在匹配时清除 * * - clearButton(默认值:true):添加一个“清除”按钮 * * - adjustWidth(默认值:true):如果为true,将自动完成宽度设置为相同 * 旧选择。 (需要 jQuery 1.4.4 才能在 IE8 上工作) * * - uiStyle(默认:false):如果为true,将添加类以便自动完成输入 * 采用 jQuery-UI 样式 */ (函数($){ $.widget("ui.combobox", { 选项: { 自动填充:真, 清除按钮:真, 调整宽度:真, uiStyle:假, 选择:空, }, _创建:函数(){ var self = 这个, 选择 = this.element.hide(), selected = select.children(":selected"), 值 = selected.val() ? selected.text() : "", 找到=假; var input = this.input = $( "" ) .attr('title', '' + select.attr("title") + '') .insertAfter(选择) .val(值) .自动完成({ 延迟:0, 最小长度:0, 来源:功能(请求,响应){ 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) ) ) 返回 { 标签:文本。替换( 新的正则表达式( "(?![^&;]+;)(?!]*)(" + $.ui.autocomplete.escapeRegex(request.term) + ")(?![^]*>)(?![^&;]+;)", "gi" ), "$1" ), 值:文本, 选项:这个 }; }); 找到 = resp.length > 0; 响应(响应); }, 选择:函数(事件,用户界面){ ui.item.option.selected = true; self._trigger(“选择”,事件,{ 项目:ui.item.option }); }, 改变:函数(事件,用户界面){ 如果(!ui.item){ var matcher = new RegExp( "^" + $.ui.autocomplete.escapeRegex( $(this).val() ) + "$", "i" ), 有效=假; select.children("option").each(function(){ if ( $( this ).text().match( matcher ) ) { this.selected = 有效 = true; 返回假; } }); if ( !valid || input.data("autocomplete").term=="" ) { // 设置为第一个建议,除非空白或自动填充已关闭 var 建议; if(!self.options.autoFill || input.data("autocomplete").term=="") found=false; 如果(找到){ 建议 = 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("自动完成").term =Suggestion.innerText; self._trigger("选中", 事件, { item: option[0] }); } 别的 { 建议={innerText:''}; select.find("option:selected").removeAttr("selected"); $(this).val(''); input.data("自动完成").term = ''; self._trigger("选中", 事件, { item: null }); } 发现退货; } } } }); if(self.options.adjustWidth) { input.width(select.width()); } 如果(self.options.uiStyle){ input.addClass("ui-widget ui-widget-content ui-corner-left"); } input.data("自动完成")._renderItem = function(ul, item) { 返回 $("
    • ") .data("item.autocomplete", item) .append("" + item.label + "") .appendTo(ul); }; this.button = $( " " ) .attr("tabIndex", -1) .attr("title", "显示所有项目") .insertAfter(输入) 。按钮({ 图标:{ 主要:“ui-icon-triangle-1-s” }, 文字:假 }) .removeClass("ui-corner-all") .addClass("ui-corner-right ui-button-icon") .click(函数(){ // 如果已经可见则关闭 if ( input.autocomplete( "widget" ).is( ":visible" ) ) { 输入.自动完成(“关闭”); 返回; } // 解决一个错误(可能与 #5265 相同的原因) $( 这个 ).blur(); // 传递空字符串作为要搜索的值,显示所有结果 input.autocomplete("搜索", ""); 输入.焦点(); }); 如果(self.options.clearButton){ this.clear_button = $( " " ) .attr("tabIndex", -1) .attr("标题", "清除条目") .insertAfter(输入) 。按钮({ 图标:{ 主要:“ui-icon-close” }, 文字:假 }) .removeClass("ui-corner-all") .click(函数(事件,用户界面){ select.find("option:selected").removeAttr("selected"); 输入.val(""); input.data("自动完成").term = ""; self._trigger("选中", 事件, { item: null }); // 解决一个错误(可能与 #5265 相同的原因) $( 这个 ).blur(); }); } }, 销毁:函数(){ this.input.remove(); this.button.remove(); this.element.show(); $.Widget.prototype.destroy.call(this); } }); })( jQuery );

      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 { 宽度:20px; } .hjq-combobox .ui-autocomplete-input { margin-right: 0; } .hjq-combobox {空白:nowrap;}

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

    • 【讨论】:

        【解决方案8】:

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

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

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

        这段代码,很像 bassistance 的原始功能,将处理在输入自动完成时没有匹配项的情况:

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

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

        您可能要处理的最后一种情况是当文本框中的值无效时按下 ESCAPE 键时该怎么办。我所做的是使用第一个匹配结果的值。我就是这样做的……

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

        var bestMatch = "";
        

        然后使用以下选项:

        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();
                }
            });
        }
        

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

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

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

        【讨论】:

          【解决方案9】:

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

          <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】:

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

            【讨论】:

              【解决方案11】:

              根据接受的答案:

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

              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】:

                回复较晚,但可能对某人有所帮助!

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

                1) 变化 - 当字段模糊且值发生变化时触发。

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

                修改change和response事件如下:

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

                希望这会有所帮助!

                【讨论】:

                  【解决方案13】:

                  这里是“mustMatch”要求的简单确定解决方案:

                  <script type="text/javascript">
                      $(function() {
                          $("#my_input_id").autocomplete({
                              source: '/get_my_data/',
                              minChars: 3,
                              select: function(event, ui) {
                                  // custom code
                                  $(this).data("pre-ui-autocomplete-value", $(this).val());
                              }
                          }).on("focus", function () {
                              $(this).data("pre-ui-autocomplete-value", $(this).val());
                          }).on("blur", function () {
                              $(this).val($(this).data("pre-ui-autocomplete-value"));
                          });
                      });
                  </script>
                  

                  【讨论】:

                    猜你喜欢
                    • 2011-06-26
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2013-04-05
                    • 2013-07-12
                    相关资源
                    最近更新 更多