如何使用setTimeout / .delay()等待字符间的输入

时间:2010-05-26 13:43:37

标签: javascript jquery listbox delay settimeout

我正在创建一个简单的列表框过滤器,它接受用户输入并通过javascript / jquery(列表框中大约5000多个项目)在列表框中返回匹配结果。以下是代码段:

var Listbox1 = $('#Listbox1');
var commands = document.getElementById('DatabaseCommandsHidden'); //using js for speed

$('#CommandsFilter').bind('keyup', function() {

Listbox1.children().remove();


for (var i = 0; i < commands.options.length; i++) {
    if (commands.options[i].text.toLowerCase().match($(this).val().toLowerCase())) {
        Listbox1.append($('<option></option>').val(i).html(commands.options[i].text));
    }
}
});

这很好用,但是当输入第一个/第二个字符时会有所减慢,因为项目很多。

我认为我可以使用的解决方案是在文本框中添加延迟,以防止在用户停止输入之前调用“keyup”事件。问题是,我不知道该怎么做,或者它是否是一个好主意。

非常感谢任何建议/帮助。

2 个答案:

答案 0 :(得分:6)

你可以这样做延迟:

$('#CommandsFilter').keyup(function() {
  clearTimeout($.data(this, 'timer'));
  var wait = setTimeout(search, 500);
  $(this).data('timer', wait);
});

function search() {
  var temp = $("<select />");
  for (var i = 0; i < commands.options.length; i++) {
    if (commands.options[i].text.toLowerCase().match($(this).val().toLowerCase())) {
      $('<option></option>', { val: i, html: commands.options[i].text }).appendTo(temp);
    }
  }
  Listbox1.empty().append(temp.children());
}

这会在您键入的元素上存储超时,如果在击键之间传递500毫秒(根据需要调整),则执行搜索。此外,这会将文档片段中的元素附加到DOM中(仍然保留编码等)。根据项目的数量,这也可能是一个不错的性能提升。

答案 1 :(得分:2)

如果命令下拉列表没有改变,我建议如下(注意我已经删除了jQuery以获得更好的性能和兼容性)。有几项改进:

  • 自上次按键后半秒钟,计时器延迟更新已过滤的列表
  • 预先缓存命令文本列表
  • 不必要地使用match替换为indexOf
  • 使用自20世纪90年代以来适用于所有可编写脚本的浏览器的快速原生DOM操作

快速测试表明,对于包含短字符串的5000个选项的下拉列表,它比大多数浏览器中的jQuery等效值快10到30倍。

代码:

var commands = document.getElementById("DatabaseCommandsHidden");
var filteredDropDown = document.getElementById("Listbox1");
var filterInput = document.getElementById("CommandsFilter");
var timer;

// Create a cached list of the lower case text of the commands drop-down
var commandTexts = [], commandText;
for (var i = 0, len = commands.options.length; i < len; ++i) {
    commandText = commands.options[i].text;
    commandTexts.push({original: commandText, lower: commandText.toLowerCase()});
}

function populateFilteredDropDown() {
    timer = null;
    var val = filterInput.value.toLowerCase(), commandText;
    var opts = filteredDropDown.options;
    filteredDropDown.length = 0;
    for (var i = 0, len = commandTexts.length; i < len; ++i) {
        commandText = commandTexts[i];
        if (commandText.lower.indexOf(val) > -1) {
            opts[opts.length] = new Option(commandText.original);
        }
    }
}

filterInput.onkeyup = function() {
    if (timer) {
        window.clearTimeout(timer);
    }
    timer = window.setTimeout(populateFilteredDropDown, 500);
};