如果按下另一个键,则放弃挂起/运行键盘功能

时间:2013-03-12 08:26:45

标签: javascript jquery input

我有一个搜索框,隐藏列表中不包含输入文本的所有行。

这项工作很有效,直到该列表变为10,000行。一次击键很好,但如果用户输入多个字母单词,则会为每个按键重复该功能。

如果按下新键,我想要放弃之前执行的任何功能。

该功能非常简单,如下:

    $("#search").keyup(function(e) {
       goSearch();
    });

function goSearch()
{
var searchString = $("#search").val().toLowerCase();
$(".lplist").each(function(index, element) {
    var row = "#row-" + element.id.substr(5);
        if ($(element).text().toLowerCase().indexOf(searchString,0) != -1)
    $(row).show();
    else
    $(row).hide();
});
}

由于

3 个答案:

答案 0 :(得分:0)

引入一个由keypress事件处理程序增加的计数器var keypressCount。在goSearch()的开头将其值写入缓冲区。然后,在$(".lplist").each()的每次运行中,您询问当前keypressCount是否与缓冲的for()相同;如果没有,你就回来了。我建议您使用break;,因为$.each()比{{1}}更容易。

更新: 您必须确保有时间触发/接收新的按键事件,因此将$ .each()的匿名函数包装在超时内。

参考:http://www.garrickcheung.com/javascript/what-i-learned-about-multi-threading-in-javascript/

答案 1 :(得分:0)

你不能直接。 Javascript不是多线程的,因此您的函数将运行并阻止任何按键操作直到完成。

从用户体验的角度来看,这是可以容忍的方式是不会立即触发关键事件的功能,而是等待一小段时间然后触发事件。

当用户正在键入时,将不断设置和重置超时功能,因此不会调用gosearch函数,因此用户不会中断其输入。

当用户暂停键入时,超时将倒计时到零并调用搜索功能,该功能将运行并阻止键入直到完成。但这没关系(只要它在一秒左右内完成),因为用户可能当前没有尝试输入。

您也可以通过将gosearch函数分解为块来执行您实际要求的操作,其中每次调用函数:*读取到目前为止处理的行数的计数器,然后处理另外500行并递增计数器。 *使用setTimeout调用另一个gosearch,其值为零。这会将事件发送到其他“线程”,并允许快速更改搜索项。

var goSearchTimeout = null;
var linesSearched = 0;

function keySearch(e){
    if(goSearchTimeout != null){
        clearTimeout(goSearchTimeout);
        linesSearched = 0;
    }
    goSearchTimeout = setTimeout(goSearch, 500);
}

$("#search").keyup(keySearch);

function highLight(index, element) {

    if(index >= linesSearched){
        var row = "#row-" + element.id.substr(5);
        if ($(element).text().toLowerCase().indexOf(searchString,0) != -1){
        $(row).show();
    else{
        $(row).hide();
    }
    if(index > linesSearched + 500){
        linesSearched = index;
        goSearchTimeout = setTimeout(goSearch);
        return;
    }
}

function goSearch(){
    goSearchTimeout = null;
    var searchString = $("#search").val().toLowerCase();
    $(".lplist").each(highLight);
}

如果您打算使用这样的超时回调,我强烈建议将代码包装到jQuery小部件中,这样您就可以使用对象上的变量来存储变量goSearchTimeout等,而不是让它们浮动为全局变量。

答案 2 :(得分:0)

您可以使用全局变量来保存搜索字符串,并在搜索字符串更改时停止执行。

重要:您必须在每次迭代中设置超时,以便暂停函数执行并更新全局变量,因为JavaScript是单线程的。

您的代码如下所示:

var searchString;

$("#search").keyup(function(e) {
    // Update search string
    searchString = $("#search").val().toLowerCase();

    // Get items to be searched
    var items = $(".lplist");

    // Start searching!
    goSearch(items, searchString, 0);
});

function goSearch(items, filter, iterator)
{
    // Exit if search changed
    if (searchString != filter) {
        return;
    }

    // Exit if there are no items left
    if (iterator >= items.length) {
        return;
    }

    // Main logic goes here
    var element = items[iterator];
    var row = "#row-" + element.id.substr(5);
    if ($(element).text().toLowerCase().indexOf(filter, 0) != -1)
        $(row).show();
    else
        $(row).hide();

    // Schedule next iteration in 5 ms (tune time for better performance)
    setTimeout(function() {
        goSearch(items, filter, iterator + 1);
    }, 5);
}