如何获得 jQuery-UI 自动完成以触发按键

How To Get jQuery-UI Autocomplete To Trigger On Key Press

我不确定ui是否可以实现我想要的。但是我目前有一些代码可以填充自动完成列表。来源由对网络 api 的 ajax 调用处理,return 是数据库中的一组项目(参见下面的代码)。

$(".ItemSearch").on('keypress', function (event, ui) {
    var disabled = true;
    if (event.which === 13) {
        disabled = false;
    }
});

function BindItemNumberSearch(hostItemForm) {        
    if ($(".ItemSearch", hostItemForm).autocomplete({}).data("ui-autocomplete")) {
        $(".ItemSearch", hostItemForm).unbind("autocomplete");
        $(".ItemSearch", hostItemForm).autocomplete({
            close: function () {
                // some logic
            },
            response: function (event, ui) {
                // some logic if the item is empty
            },
            source: function (request, response) {
                // return if the search box is empty or is disabled
                if (request.term.trim().length <= 0 || disabled) {
                    return;
                }

                $.ajax({ 
                    // some ajax call
                });
            },
            delay: 500,
            focus: function (event, ui) {
                return false;
            },
            select: function (event, ui) {
                // return false if no item is selected
                if (ui.item.id != null) {
                    return false;
                }

                // some logic to select the item
            }
        }).data("ui-autocomplete")._renderItem = RenderSearchResultItem;
    }           
}

我们遇到的问题是,有时搜索请求可以在用户输入完搜索字符串之前发送。这曾经是好的,因为搜索会 return quickly,但现在我们有太多数据并且它导致缓慢(我们认为由于用户慢慢键入内容时启动了多个搜索他们正在寻找)。

所以我们想添加一个按键触发(例如回车键)来启动搜索。我找到了这个answer,好像jQuery-ui不支持这个。我尝试了不同的尝试,其中包含的是最新的。但是我似乎无法让它工作。

您可以为 autocomplete 应该开始搜索的时间指定一个标志。

// this will be the flag if autocomplete should begin searching
// should become true when [Enter] key is pressed & input field is not empty
window.BeginSearch = false;

之后,将 DOM 事件附加到您的 autocomplete 元素以检测 Enter

$(document).on("keydown", "#tags", function(e) {
    ...
})

以编程方式指示 autocomplete 在按下 Enter 键时根据需要开始搜索

$("#tags").autocomplete("search");

source 回调中,这时候标志变量就派上用场了。使用它来检测 Enter 键是否被按下,因此将 BeginSearch 设置为 true

$("#tags").autocomplete({
    source: function (request, response) {
        if (window.BeginSearch != true || request.term.trim().length <= 0) {
            response([]);
            window.BeginSearch = false; // reset the flag since searching is finished
            return;
        } else if (window.BeginSearch == true) {
            sample_async_function(request).then(function (return_data) {
                response(return_data);
                window.BeginSearch = false; // reset the flag since searching is finished
            });
        }
    },
    delay: 0 // no need for delay, as you can see
});

示例演示:

// this event will be responsible for tracking [Enter] key press
$(document).on("keydown", "#tags", function(e) {

  // additional checks so that autocomplete search won't occur if conditions are not met
  if (e.key == "Enter" && $("#tags").val().trim().length > 0 && $(".sample-loader:visible").length < 1) {
    window.BeginSearch = true;
    $("#tags").autocomplete("search");
  }
})

$(document).ready(function() {

  // this will be the flag if autocomplete should begin searching
  // should become true when [Enter] key is pressed & input field is not empty
  window.BeginSearch = false;

  $("#tags").autocomplete({
    source: function(request, response) {
      if (window.BeginSearch != true || request.term.trim().length <= 0) {
        response([]);
        window.BeginSearch = false; // reset the flag since searching is finished
        return;
      } else if (window.BeginSearch == true) {
        sample_async_function(request).then(function(return_data) {
          response(return_data);
          window.BeginSearch = false; // reset the flag since searching is finished
        });
      }
    },
    delay: 0 // no need for delay, as you can see
  });

});

// sample asynchronous function. mimics fetching data from server side (e.g., ajax) 
function sample_async_function(some_passed_string) {
  $(".sample-loader").show();
  return new Promise(resolve => setTimeout(() => {
    $(".sample-loader").hide();
    resolve(
      [
        "ActionScript",
        "AppleScript",
        "Asp",
        "BASIC",
        "C",
        "C++",
        "Clojure",
        "COBOL",
        "ColdFusion",
        "Erlang",
        "Fortran",
        "Groovy",
        "Haskell",
        "Java",
        "JavaScript",
        "Lisp",
        "Perl",
        "PHP",
        "Python",
        "Ruby",
        "Scala",
        "Scheme"
      ].filter((val, index) => {
        if (val.toLowerCase().includes(some_passed_string.term.toLowerCase())) {
          return val;
        }
      })
    );
  }, 500)); // arbitrary value. sample speed of the API XHR in unit milliseconds
}
.sample-loader {
  display: none;
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 1053;
  background: #000000dd;
  color: white;
  font-size: 20px;
}
<script src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script>

<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js" integrity="sha256-VazP97ZCwtekAsvgPBSUwPFKdrwD3unUfSGVYrahUqU=" crossorigin="anonymous"></script>

<link rel="stylesheet" href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">

<div class="ui-widget">
  <label for="tags">AutoComplete: </label>
  <input id="tags">
</div>

<div class="sample-loader">Loading...</div>

从用户体验的角度来看,您将想弄清楚如何在搜索过程中暂时禁用与元素的交互。在这个例子中,我使用了一个简单的“正在加载”屏幕。