1

入力したテキストを含まないリスト内のすべての行を非表示にする検索ボックスがあります。

これは、リストが10,​​000行になるまでうまく機能しました。1回のキーストロークで問題ありませんが、ユーザーが数文字の単語を入力すると、キーを押すたびに機能が繰り返されます。

私がやりたいのは、新しいキーが押された場合、関数の以前の実行をすべて放棄することです。

関数は次のように非常に単純です。

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

ありがとう

4

3 に答える 3

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);
}
于 2013-03-12T09:19:49.120 に答える
0

直接することはできません。Javascriptはマルチスレッドではないため、関数は実行され、完了するまでキーの押下をブロックします。

ユーザーエクスペリエンスの観点からこれを許容できるようにする方法は、キーイベントですぐに関数をトリガーするのではなく、短時間待機してからイベントを発生させることです。

ユーザーが入力している間、タイムアウト関数は継続的に設定およびリセットされるため、gosearch関数は呼び出されないため、ユーザーは入力を中断することはありません。

ユーザーが入力を一時停止すると、タイムアウトはゼロまでカウントダウンし、検索関数を呼び出します。検索関数は実行され、入力が完了するまで入力をブロックします。ただし、ユーザーが現在入力を試みていない可能性があるため、(1秒程度で完了する限り)問題ありません。

また、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などを格納できるようにすることを強くお勧めします。

于 2013-03-12T08:48:20.023 に答える
0

var keypressCountkeypressイベントハンドラーによって増加しているカウンターを導入します。開始時にgoSearch()その値をバッファに書き込みます。次に、実行するたびに、電流がバッファリングされたものと同じ$(".lplist").each()かどうかを尋ねます。keypressCountそうでない場合は、戻ります。よりもfor()簡単なので、ただしを使用することをお勧めします。break;$.each()

更新:新しいkeypressイベントが発生/受信される時間があることを確認する必要があるため、$。each()の無名関数をタイムアウト内にラップします。

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

于 2013-03-12T08:34:02.107 に答える