私が仕事のために構築しているWebサイトには、ユーザーが入力して一連の要素のデータに格納されているさまざまなフィールドを検索できる検索バーがあります。問題は、ブラウザが遅くなり、入力を開始したときに発生します。
私がやろうとしていたのは、jQuery Deferredオブジェクトを使用して、次のことです。入力ボックスにキーアップハンドラーを追加します。キーアップがトリガーされたら、まだ「保留中」である以前にトリガーされたキーアップを解決します。次に、現在のキーアップイベントの使用を続行します。入力値に基づいてすべてのマッチングを実行するkeyupイベント自体の内部では、現在のイベントがまだ保留中であるかどうかを常にチェックし、保留中でない場合は、そのイベントの残りをスキップすることになっています。
問題は、IE7のような遅いブラウザでも、各キーアップイベントがブロックされていることだと思われます。したがって、ユーザーが「テスト」と入力すると、「te」のキーアップイベントが表示される前に、「t」文字のイベント全体を終了しようとします。
問題は、どうすればキーアップイベントを非同期/非ブロッキングにすることができるのか、それともこれはほとんど不可能なのかということです。
例:
var search_values = new Array();
var deferred_searches = {};
function filterSearchResults(event) {
var input_element = jq(event.target);
var search_value = input_element.val();
console.log('user just typed final letter in :' + search_value);
for (var svi = 0; svi < search_values.length-1; svi++) {
if (deferred_searches[search_values[svi]] !== undefined &&
deferred_searches[search_values[svi]].state() == 'pending') {
console.log('resolving ' + search_values[svi])
deferred_searches[search_values[svi]].resolve(search_values[svi]);
}
}
var result_list = jq('div#header_project_selection_result_list');
var all_project_results = result_list.find('div.header_project_result');
console.log('beginning search for "'+search_value+'"');
if (search_value == '') {
// Blank input value means show all results
}
else {
// Non-blank value means search
if (! startSearchFilter(search_value, all_project_results)) {
return false; // this should return out of this current event handler
}
}
console.log('ending search for "'+search_value+'"');
},
/**
* Helper function that actually handles finding and hiding/showing results,
* and highlighting found text.
*
* Uses jQuery for this functionality.
*
* @param search_value string The text the user has input
* @param all_project_results jQuery A jQuery extended array of all project results to filter
*
* @return tbr boolean Flag indicating whether the search was short circuited
*/
function startSearchFilter(search_value, all_project_results) {
var tbr = true;
search_values.push(search_value);
deferred_searches[search_value] = jq.Deferred();
deferred_searches[search_value].done(function(sv) {
search_values = search_values.without(sv);
console.log('done deferred search for "'+sv+'" - disabling');
});
var number_of_results_found = 0;
var pr_count = all_project_results.length - 1;
var regexp = new RegExp(search_value, 'im');
for (var index = 0; index <= pr_count; index++) {
if (deferred_searches[search_value].state() == 'pending') {
// KEEP GOING
var ext_project_result = all_project_results.eq(index);
var result_data = ext_project_result.data();
//console.log(search_value+" is in state '"+deferred_searches[search_value].state()+"'.....' all_project_results.each() [inside]");
if (result_shown) {
number_of_results_found++;
// The input text has been found on data for the current project, so make sure we show that result row
ext_project_result.addClass('filtered');
}
else if (ext_project_result.hasClass('filtered')) {
// The input text has not been found, or the user is not an admin and can't view it, so hide that row
ext_project_result.removeClass('filtered');
}
continue; // keep going to the next result element
}
else {
tbr = false;
break; // break when short circuited
}
}
if (deferred_searches[search_value].state() == 'pending') {
deferred_searches[search_value].resolve(search_value); // explicitly resolve this finalized one
}
return tbr;
}
理論的にはこれは機能するはずですが、前述したように、常にブロックされているようです。