【问题标题】:jQuery UI Autocomplete disable Select & Close eventsjQuery UI 自动完成禁用选择和关闭事件
【发布时间】:2011-05-18 10:52:12
【问题描述】:

我使用 jQuery UI 的自动完成功能与它可能创建的用途略有不同。

基本上我想保留所有相同的功能,唯一的区别是当建议框出现时,我不会在用户进行选择时隐藏建议框,我也不希望填充该选择.autocomplete 附加到的输入框。

所以,我一直在阅读 jQuery UI 文档,似乎有一种方法可以禁用 Select: 和 Close: 事件,但我发现他们解释它的方式非常令人困惑,因此,这这就是我在这里寻求帮助的原因。

我的 jQuery

$( "#comment" ).autocomplete({
    source: "comments.php",
    minLength: 4,

    // Attempt to remove click/select functionality - may be a better way to do this        
    select: function( event, ui ) {
        return false;
    },
    // Attempt to add custom Class to the open Suggestion box - may be a better way
    open : function (event, ui) {
        $(this).addClass("suggestion-box");
    },
    // Attempt to cancel the Close event, so when someone makes a selection, the box does not close
    close : function (event, ui) {
        return false;   
    }
});

jQuery UI 官方文档

从菜单中选择项目时触发; ui.item 是指选中的项目。 select 的默认操作是将文本字段的值替换为 选定的项目。取消此事件可防止值被更新,但不会 防止菜单关闭。

代码示例

Supply a callback function to handle the select event as an init option.
$( ".selector" ).autocomplete({
   select: function(event, ui) { ... }
});
Bind to the select event by type: autocompleteselect.
$( ".selector" ).bind( "autocompleteselect", function(event, ui) {
  ...
});

混乱

让我感到困惑的是,他们似乎建议删除 .autocomplete 并替换为 .bind("autocompleteselect") - 这将完全禁用自动完成功能?

非常感谢您提供的任何帮助。

【问题讨论】:

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


    【解决方案1】:

    从 Andrews 解决方案中汲取灵感,我找到了一种在选择时保持自动完成功能打开且对核心功能影响较小的方法:

    var selected;  //flag indicating a selection has taken place
    
    var $input = $("input").autocomplete({
        source: ['Hello', 'Goodbye', 'Foo', 'Bar'],
        select: function( event, ui ) {
            selected = true;
        }
    });
    
    //Override close method - see link below for details
    (function(){
       var originalCloseMethod = $input.data("autocomplete").close;
        $input.data("autocomplete").close = function(event) {
            if (!selected){
                //close requested by someone else, let it pass
                originalCloseMethod.apply( this, arguments );
            }
            selected = false;
        };
    })();
    

    所以想法是在适当的时候中性关闭方法,如选定的标志所示。在全局名称空间中选择标志可能不是最好的主意,但这是为了让其他人改进:-)。

    More about overriding methods

    【讨论】:

    • 太棒了,这对我帮助很大
    • 重写内置方法的好主意。谢谢。
    • +1,您的解决方案有所帮助。以这种方式修补 jQuery UI(和类似的小部件)的方法通常很有帮助。
    • 工作正常。但在 2019 年(对于实际的 jQuery 版本),您需要使用 $input.data("uiAutocomplete") 而不是 $input.data("autocomplete") 才能使其工作。
    • .data("ui-autocomplete")
    【解决方案2】:

    使用.bind() 的第二种语法只是将事件处理程序附加到jQueryUI 的自定义事件的另一种方式。这与在小部件选项中定义事件处理程序完全相同(使用select: function(event, ui) { }

    想象一下,如果您的页面上有多个自动完成小部件,并且您希望在其中任何一个引发“选择”事件时执行相同的功能,例如:

    $(".autocomplete").bind("autocompleteselect", function(event, ui) {
        /* Will occur when any element with an autocomplete widget fires the
         * autocomplete select event.
         */
    });
    

    关于取消select 事件,你说得对。但是,取消close 事件有点困难;看起来从事件处理程序返回 false 将不起作用(在菜单实际关闭后触发close)。您可以执行一些小技巧,然后将 select 函数替换为您自己的函数:

    var $input = $("input").autocomplete({
        source: ['Hello', 'Goodbye', 'Foo', 'Bar']
    });
    $input.data("autocomplete").menu.options.selected = function(event, ui) { 
        var item = ui.item.data( "item.autocomplete" );
        $input.focus();
    };
    

    这是一个工作示例:http://jsfiddle.net/ZGmyp/

    我不确定覆盖关闭事件的后果是什么,但在这个简单的示例中看起来并没有发生任何疯狂的事情。我会说这是对小部件的一种不自然的使用,因此可能会产生意想不到的后果。

    【讨论】:

    • 非常感谢@Andrew,您能想出一种方法来取消单击/选择功能,但在输入更改和/或用户取消选择输入时仍然更改建议框盒子?
    • @thathurtabit:因为当您输入建议时,菜单仍应更新。但是,当取消选择输入时更改建议框是什么意思?
    • @AndrewWhitaker 感谢您回复我,是的,我正在寻找在输入建议时仍会更新的菜单。我刚刚再次尝试了您的演示,如果您会更新输入它识别的另一个建议,但是如果您输入完全不同的人(并且它不识别),它仍然保留其先前不相关的建议。此外,当您在输入框外部单击(以摆脱其焦点)时,建议框保持打开状态。
    • @thathurtabit:我明白了——我再看看
    • 感谢安德鲁,非常感谢您的帮助!
    【解决方案3】:

    我尝试了其他人在这里提出的各种想法,但没有成功。

    我正在使用带有 UI 1.11.4 的 Jquery 2.1.4,这就是我让它工作的方式:

    Javascript:

    
    <script>
    var lookup_selectable = false;
    var lookup_term = '';
    
    $(function() {
    
        $( "#lookup" ).autocomplete({
            source: "lookup_processor.php",
            minLength: 3,
            renderItem: function( ul, item ) {
    
                // This function is called for each item returned from the 'source:'
                // It is up to you to ensure that a list item element is returned.
    
                // do whatever logic on the item data to determine if it should not be slectable..
    
    
                //Example:
                // The backend "source" has handled the logic of what is selectable or not
                // and has set a 'selectable' parameter that we can use
                if(item.selectable){                  
                    // return the item unchanged from autocompletes default behavior
                    return $("<li></li>").data("item.autocomplete", item).append("<a>" + item.label + "</a>").appendTo(ul);              
                }else{
                    // this item is not selectable so lets apply a class named 'item-disabled' to give a visual queue. 
                    // We are also wrapping the label in a span instead of an anchor just to show that the item is still clickable,  darn!
                    return $('<li class="ui-menu-item item-disabled"></li>').data("item.autocomplete", item).append('<span>'+item.label+'</span>').appendTo(ul);                  
                }
    
            },
    
            select: function( event, ui ) {                                  
    
                // This item was clicked ..
    
                // save the item.clickable value to our own external variable
                // Note: We have to do this because the item object is not available in the 'close' function :-(
                lookup_selectable = ui.item.selectable;  // the item object is available inside the ui parameter
    
                // store the current search term
                lookup_term = $('#lookup').val();
    
                // do any additional stuff based on the item selected, if needed...
    
    
            },
    
            close: function(event, ui){
    
                // This function fires after select: and after autocomplete has already "closed" everything.  This is why event.preventDefault() won't work.               
                // ** ui is an empty object here so we have to use our own variable to check if the selected item is "selectable" or not..                              
                if (! lookup_selectable){
                    // We need to undo what autocomplete has already done..                                                       
                    $('#lookup').val(lookup_term); // Restore the search term value
                    $('#'+event.currentTarget.id).show(); // Keep the selection window open
                    // ta-da!  To the end user, nothing changes when clicking on an item that was not selectable.
                }    
            }
    
        });
    });
    </script>  
    

    CSS:

    
    <style>
    li.ui-menu-item.item-disabled {
        text-decoration: none;    
        line-height: 1.5;    
        color: #ccc;
    }
    </style>
    

    后端源“lookup_processor.php”:

    
    <?php
    
            $search_results = array();
    
        // ..do whatever to get the data for each item
        $item_data = getting_item_data();
    
        foreach ($item_data as $data){
            // The id, label, and value keys are the typical keys that autocomplete expects,  but you can add ass many others as you want..
            // For our example we are setting the 'selectable' key to true or false based on some simple example logic
            $search_results[] = array(
                'id'=>$data['id'], 
                'label'=>$data['label'], 
                'value'=>$data['value'], 
                'selectable'=>$data['some_thing_to_check']>0?true:false, // This is the parameter our 'select:' function is looking for
                'send_it_all_if_you_want'=>json_encode($data)); // this is just an example of how you can send back anything you want 
             );
         }
    
        // send the results back to autocomplete
        echo json_encode($search_results);
        exit;
    
    ?>
    

    【讨论】:

      【解决方案4】:

      为此我走了一条稍微不同的路线,并扩展了 Andrew 的 fiddle

      目的是我一直希望在某个输入具有焦点时显示自动完成功能 - 允许进行多项选择。

      $("#myInput").autocomplete({
          source: ["Test", "This", "Doesnt", "Close"],
          minLength: 0,
          select: function (event, ui) {
              // Add your own custom login to manipulate ui.item.label and add what you need the input field (and ui.item.value if required.)
              // We've customised how we want the select to "work" so prevent the default
              // of auto clearing the input.    
              event.preventDefault();
          },
          close : function(event)
          {
              // We're closing the autocomplete - check if the input still has focus...
              if ($("#myInput").is(":focus"))
              {
                  // Prevent the auto complete from closing.
                  event.preventDefault();
      
                  // Make sure we're reshowing the autcomplete - since the input would have momentarily
                  // lost focus when we selected an item.
                  $("#myInput").autocomplete("search", "")
              }        
          }
      });
      
      $("#myInput").focus(function () {
          // We're not taking any filtering into account for this example.
          $(this).autocomplete("search", "")
      });
      

      【讨论】:

      • 这真的帮助我创建了一个动态的多级选择,我需要的是,如果你选择某个项目,你会得到一个新的项目列表。花了几个小时试图弄清楚这一点。每个人都做简单的选择,但不演示这个功能。很快就会为此功能写一个页面。
      【解决方案5】:

      使用 $input.data("autocomplete").menu.options.selected = function(){} 选择不同的项目后导致值不保持(我们的实现需要附加到末尾。可能只需要添加 e.preventDefault() 或在附加代码之前返回 false )。所以我只是在关闭事件中进行了切换。 放置外部变量并编写自己的方法的示例更好,但也不喜欢它。当需要手动关闭自动完成时,我首先通过传递参数手动调用方法。 (在我们的实现中,客户要求列表在单击项目时打开,但在鼠标离开文本框容器时关闭。

      所以我只是将自动完成附加到文本框的元素容器并附加了 mouseenter 和 mouseleave。为了确定它是否应该关闭,我使用了 jQuery(this).data("canClose") 自定义变量。基本上,它所做的只是在变量为“false”时使用搜索方法重新打开自动完成。

      这是最终代码:

      element.autocomplete({
                      minLength:0,
                      source: source,
                      appendTo: element.parent(),
                      close: function () {
                          if (!jQuery(this).data("canClose")) {
                              jQuery(this).autocomplete('search', '');
                          }
                          return false;
                      }
                  });
                  element.mouseenter(function () {
                      element.data("canClose", false);
                      jQuery(this).autocomplete('search', '');
                  });
                  element.parent().mouseleave(function () {
                      element.data("canClose", true);
                      element.delay(2000).autocomplete("close");
                  });
      

      如果您需要追加而不是替换值,请在构造函数中添加选择处理程序:

       select: function (event, ui) {
                          var text = element.text().trim();
                          if (text.length > 0 && !text.endsWith(",")) {
                              text += ", ";
                          }
                          jQuery(this).text((text + ui.item.label));
                          jQuery(this).focus();
                          return false;
                      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-12-05
        • 2014-11-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-06-17
        • 2011-05-13
        相关资源
        最近更新 更多