ユーザーがテキストボックスへの入力を完了したら、ajaxリクエストをトリガーしたいのですが。ユーザーが文字を入力するたびにこの関数が実行されるのは望ましくありません。これにより、ajaxリクエストが大量に発生するためです。ただし、Enterボタンを押す必要もありません。
ユーザーが入力を完了したことを検出してajaxリクエストを行う方法はありますか?
ここでjQueryを使用します!デイブ
ユーザーがテキストボックスへの入力を完了したら、ajaxリクエストをトリガーしたいのですが。ユーザーが文字を入力するたびにこの関数が実行されるのは望ましくありません。これにより、ajaxリクエストが大量に発生するためです。ただし、Enterボタンを押す必要もありません。
ユーザーが入力を完了したことを検出してajaxリクエストを行う方法はありますか?
ここでjQueryを使用します!デイブ
回答:
つまり、タイピングを終了するということは、しばらくの間、たとえば5秒間停止することを意味します。それを念頭に置いて、ユーザーがキーを離したときにタイマーを開始し、キーを押したときにそれをクリアしてみましょう。問題の入力は#myInputになると判断しました。
いくつかの仮定をしています...
//setup before functions
var typingTimer; //timer identifier
var doneTypingInterval = 5000; //time in ms, 5 second for example
var $input = $('#myInput');
//on keyup, start the countdown
$input.on('keyup', function () {
clearTimeout(typingTimer);
typingTimer = setTimeout(doneTyping, doneTypingInterval);
});
//on keydown, clear the countdown
$input.on('keydown', function () {
clearTimeout(typingTimer);
});
//user is "finished typing," do something
function doneTyping () {
//do something
}
doneTyping
例では、コールバック関数がすぐに実行されているコメントがいくつか表示されます。これは通常()
、関数名の後に誤って含めた結果です。読むべきではsetTimeout(doneTyping,
ないことに注意してくださいsetTimeout(doneTyping(),
上記の選択した回答は機能しません。
typingTimerは時々複数回設定されるため(高速タイパーでキーダウンがトリガーされる前にキーアップが2回押されるなど)、適切にクリアされません。
以下のソリューションはこの問題を解決し、OPが要求したように、終了してからX秒後に呼び出します。また、冗長なキーダウン機能も不要になりました。入力が空の場合に関数呼び出しが発生しないように、チェックも追加しました。
//setup before functions
var typingTimer; //timer identifier
var doneTypingInterval = 5000; //time in ms (5 seconds)
//on keyup, start the countdown
$('#myInput').keyup(function(){
clearTimeout(typingTimer);
if ($('#myInput').val()) {
typingTimer = setTimeout(doneTyping, doneTypingInterval);
}
});
//user is "finished typing," do something
function doneTyping () {
//do something
}
そして、バニラJavaScriptソリューションの同じコード:
//setup before functions
let typingTimer; //timer identifier
let doneTypingInterval = 5000; //time in ms (5 seconds)
let myInput = document.getElementById('myInput');
//on keyup, start the countdown
myInput.addEventListener('keyup', () => {
clearTimeout(typingTimer);
if (myInput.value) {
typingTimer = setTimeout(doneTyping, doneTypingInterval);
}
});
//user is "finished typing," do something
function doneTyping () {
//do something
}
このソリューションはES6を使用しますが、ここでは必要ありません。ただ、交換するlet
とvar
、定期的な機能を備えた矢印機能。
$('#myInput').on('input', function() {
これをコピーして貼り付ける場合に使用します。入力が空かどうかのチェックポイントがわかりません。彼がタイプしたものを消去したい場合、これはajax呼び出しを行うことに失敗します。
if ($('#myInput').val)
代わりにif ($('#myInput').val())
ですか?.val
関数にする必要がありますか?
これは、underscore.jsデバウンス関数を含む1行にすぎません。
$('#my-input-box').keyup(_.debounce(doSomething , 500));
これは基本的に、入力を停止してから500ミリ秒後にdoSomethingと表示されます。
Uncaught ReferenceError: _ is not defined
はい、Ajaxリクエストを発生させるキーアップイベントごとに、たとえば2秒のタイムアウトを設定できます。XHRメソッドを保存し、後続のキープレスイベントで中止して、帯域幅をさらに節約することもできます。これが私のオートコンプリートスクリプト用に私が書いたものです。
var timer;
var x;
$(".some-input").keyup(function () {
if (x) { x.abort() } // If there is an existing XHR, abort it.
clearTimeout(timer); // Clear the timer so we don't end up with dupes.
timer = setTimeout(function() { // assign timer a new timeout
x = $.getJSON(...); // run ajax request and store in x variable (so we can cancel)
}, 2000); // 2000ms delay, tweak for faster/slower
});
お役に立てれば、
マルコ
var timer;
var timeout = 1000;
$('#in').keyup(function(){
clearTimeout(timer);
if ($('#in').val) {
timer = setTimeout(function(){
//do stuff here e.g ajax call etc....
var v = $("#in").val();
$("#out").html(v);
}, timeout);
}
});
ここに完全な例:http : //jsfiddle.net/ZYXp4/8/
私はSurreal Dreamの答えが好きですが、私の「doneTyping」関数はキーを押すたびに起動することがわかりました。入力を停止したときに1回だけ起動するのではなく、関数は5回起動します。
問題は、javascriptのsetTimeout関数が、設定されている古いタイムアウトを上書きまたは強制終了しないように見えることですが、自分で実行すると機能します。そのため、typingTimerが設定されている場合は、setTimeoutの直前にclearTimeout呼び出しを追加しました。下記参照:
//setup before functions
var typingTimer; //timer identifier
var doneTypingInterval = 5000; //time in ms, 5 second for example
//on keyup, start the countdown
$('#myInput').on("keyup", function(){
if (typingTimer) clearTimeout(typingTimer); // Clear if already set
typingTimer = setTimeout(doneTyping, doneTypingInterval);
});
//on keydown, clear the countdown
$('#myInput').on("keydown", function(){
clearTimeout(typingTimer);
});
//user is "finished typing," do something
function doneTyping () {
//do something
}
注意:これをSurreal Dreamの回答へのコメントとして追加したかったのですが、私は新しいユーザーであり、十分な評判がありません。ごめんなさい!
貼り付けなどの追加のケースを処理するために、受け入れられた回答を変更します。
//setup before functions
var typingTimer; //timer identifier
var doneTypingInterval = 2000; //time in ms, 2 second for example
var $input = $('#myInput');
// updated events
$input.on('input propertychange paste', function () {
clearTimeout(typingTimer);
typingTimer = setTimeout(doneTyping, doneTypingInterval);
});
//user is "finished typing," do something
function doneTyping () {
//do something
}
この場合、keyDownイベントは必要ないと思います(間違っている場合は理由を教えてください)。私の(jquery以外の)スクリプトでは、同様のソリューションは次のようになります。
var _timer, _timeOut = 2000;
function _onKeyUp(e) {
clearTimeout(_timer);
if (e.keyCode == 13) { // close on ENTER key
_onCloseClick();
} else { // send xhr requests
_timer = window.setTimeout(function() {
_onInputChange();
}, _timeOut)
}
}
スタックオーバーフローに対する私の最初の返信です。いつか誰かの役に立つことを願っています:)
次のdelay
関数を宣言します。
var delay = (function () {
var timer = 0;
return function (callback, ms) {
clearTimeout(timer);
timer = setTimeout(callback, ms);
};
})()
そしてそれを使います:
let $filter = $('#item-filter');
$filter.on('keydown', function () {
delay(function () {
console.log('this will hit, once user has not typed for 1 second');
}, 1000);
});
遅い回答ですが、2019年であり、これはかなりのES6を使用して完全に達成可能であり、サードパーティのライブラリは使用できないため、追加します。高評価の回答のほとんどはかさばり、変数が多すぎて圧迫されます。
この優れたブログ投稿から抜粋したエレガントなソリューション。
function debounce(callback, wait) {
let timeout;
return (...args) => {
const context = this;
clearTimeout(timeout);
timeout = setTimeout(() => callback.apply(context, args), wait);
};
}
window.addEventListener('keyup', debounce( () => {
// code you would like to run 1000ms after the keyup event has stopped firing
// further keyup events reset the timer, as expected
}, 1000))
input
イベントの方がソリューションは少しシンプルだと思います:
var typingTimer;
var doneTypingInterval = 500;
$("#myInput").on("input", function () {
window.clearTimeout(typingTimer);
typingTimer = window.setTimeout(doneTyping, doneTypingInterval);
});
function doneTyping () {
// code here
}
@goingの回答に同意します。私のために働いた別の同様の解決策は以下の解決策です。唯一の違いは、キーアップの代わりに.on( "input" ...)を使用していることです。これは、入力の変更のみをキャプチャします。Ctrl、Shiftなどの他のキーは無視されます
var typingTimer; //timer identifier
var doneTypingInterval = 5000; //time in ms (5 seconds)
//on input change, start the countdown
$('#myInput').on("input", function() {
clearTimeout(typingTimer);
typingTimer = setTimeout(function(){
// doSomething...
}, doneTypingInterval);
});
ユーザーが入力を完了するのを待つ簡単なコードを見つけました。
ステップ1.タイムアウトをnullに設定し、ユーザーが入力しているときに現在のタイムアウトをクリアします。
手順2. keyupイベントがトリガーされる前に、タイムアウトを変数defineにクリアします。
ステップ3.上で宣言した変数にタイムアウトを定義します。
<input type="text" id="input" placeholder="please type" style="padding-left:20px;"/>
<div class="data"></div>
JavaScriptコード
var textInput = document.getElementById('input');
var textdata = document.querySelector('.data');
// Init a timeout variable to be used below
var timefired = null;
// Listen for keystroke events
// Init a timeout variable to be used below
var timefired = null;// Listen for keystroke events
textInput.onkeyup = function (event) {
clearTimeout(timefired);
timefired = setTimeout(function () {
textdata.innerHTML = 'Input Value:'+ textInput.value;
}, 600);
};
私は自分のリストで検索を実装していて、それをajaxベースにする必要がありました。つまり、キーを変更するたびに、検索結果を更新して表示する必要があります。これにより、サーバーに送信されるajax呼び出しが非常に多くなり、これは良いことではありません。
いくつかの作業を行った後、ユーザーが入力をやめたときにサーバーにpingを送信する方法を作りました。
この解決策は私にとってうまくいきました:
$(document).ready(function() {
$('#yourtextfield').keyup(function() {
s = $('#yourtextfield').val();
setTimeout(function() {
if($('#yourtextfield').val() == s){ // Check the value searched is the latest one or not. This will help in making the ajax call work when client stops writing.
$.ajax({
type: "POST",
url: "yoururl",
data: 'search=' + s,
cache: false,
beforeSend: function() {
// loading image
},
success: function(data) {
// Your response will come here
}
})
}
}, 1000); // 1 sec delay to check.
}); // End of keyup function
}); // End of document.ready
これを実装している間、タイマーを使用する必要がないことがわかります。
これは私が書いた簡単なJSコードです:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="pt-br" lang="pt-br">
<head><title>Submit after typing finished</title>
<script language="javascript" type="text/javascript">
function DelayedSubmission() {
var date = new Date();
initial_time = date.getTime();
if (typeof setInverval_Variable == 'undefined') {
setInverval_Variable = setInterval(DelayedSubmission_Check, 50);
}
}
function DelayedSubmission_Check() {
var date = new Date();
check_time = date.getTime();
var limit_ms=check_time-initial_time;
if (limit_ms > 800) { //Change value in milliseconds
alert("insert your function"); //Insert your function
clearInterval(setInverval_Variable);
delete setInverval_Variable;
}
}
</script>
</head>
<body>
<input type="search" onkeyup="DelayedSubmission()" id="field_id" style="WIDTH: 100px; HEIGHT: 25px;" />
</body>
</html>
onblurイベントを使用して、テキストボックスがフォーカスを失ったことを検出できます:https : //developer.mozilla.org/en/DOM/element.onblur
これは、ユーザーがたくさんのものを入力してから、テキストボックスにフォーカスしたままそこに座っている場合に気を付ければ、「タイピングを停止する」と同じではありません。
そのため、setTimeoutをonclickイベントに関連付け、キーストロークがない状態でx時間経過した後、ユーザーが入力を停止したと想定します。
なぜonfocusoutを使用しないのですか?
https://www.w3schools.com/jsreF/event_onfocusout.asp
フォームの場合は、送信ボタンをクリックするために常にすべての入力フィールドにフォーカスを置いたままになるので、onfocusoutイベントハンドラーが呼び出されても入力を見逃すことはありません。
ユーザーがフィールドから離れる必要がある場合は、JavaScriptのOnchangeの代わりに「onBlur」を使用できます。
<TextField id="outlined-basic" variant="outlined" defaultValue={CardValue} onBlur={cardTitleFn} />
それが必要ない場合は、タイマーを設定することをお勧めします。
私のニーズが奇妙なものであるかどうかはわかりませんが、私はこれに似たものが必要でした、そしてこれが私が最終的に使用したものです:
$('input.update').bind('sync', function() {
clearTimeout($(this).data('timer'));
$.post($(this).attr('data-url'), {value: $(this).val()}, function(x) {
if(x.success != true) {
triggerError(x.message);
}
}, 'json');
}).keyup(function() {
clearTimeout($(this).data('timer'));
var val = $.trim($(this).val());
if(val) {
var $this = $(this);
var timer = setTimeout(function() {
$this.trigger('sync');
}, 2000);
$(this).data('timer', timer);
}
}).blur(function() {
clearTimeout($(this).data('timer'));
$(this).trigger('sync');
});
これにより、アプリケーションに次のような要素を含めることができます。
<input type="text" data-url="/controller/action/" class="update">
これは、ユーザーが「入力を完了」したとき(2秒間何もしない)または別のフィールドに移動したとき(要素からぼかされる)に更新されます。
ユーザーが入力を完了するまで待つ必要がある場合は、次のように使用します。
$(document).on('change','#PageSize', function () {
//Do something after new value in #PageSize
});
ajax呼び出しを使用した完全な例-これは私のポケットベルで機能します-リストごとの項目数:
$(document).ready(function () {
$(document).on('change','#PageSize', function (e) {
e.preventDefault();
var page = 1;
var pagesize = $("#PageSize").val();
var q = $("#q").val();
$.ajax({
url: '@Url.Action("IndexAjax", "Materials", new { Area = "TenantManage" })',
data: { q: q, pagesize: pagesize, page: page },
type: 'post',
datatype: "json",
success: function (data) {
$('#tablecontainer').html(data);
// toastr.success('Pager has been changed', "Success!");
},
error: function (jqXHR, exception) {
ShowErrorMessage(jqXHR, exception);
}
});
});
});
他のすべての回答は、1つのコントロールに対してのみ機能します(他の回答も含まれています)。ページごとに複数のコントロールがある場合(ショッピングカートなど)、ユーザーが何かを入力した最後のコントロールのみが呼び出されます。私の場合、これは確かに望ましい動作ではありません-各コントロールには独自のタイマーが必要です。
これを解決するには、次のコードのように、IDを関数に渡し、timeoutHandles辞書を維持するだけです。
関数宣言:
var delayUserInput = (function () {
var timeoutHandles = {};
return function (id, callback, ms) {
if (timeoutHandles[id]) {
clearTimeout(timeoutHandles[id]);
}
timeoutHandles[id] = setTimeout(callback, ms);
};
})();
関数の使用:
delayUserInput('yourID', function () {
//do some stuff
}, 1000);
わあ、3件のコメントでもかなり正しいです。
空の入力は、関数呼び出しをスキップする理由ではありません。たとえば、リダイレクトの前にURLから無駄なパラメーターを削除します
.on ('input', function() { ... });
トリガーに使用すべきであるkeyup
、paste
とchange
イベント
間違いなく.val()
または.value
使用する必要があります
複数の入力を処理する$(this)
代わりに、内部イベント関数を使用できます#id
(私の決定)n.4 から簡単にアクセスするにはdoneTyping
、in ではなく匿名関数を使用しますが、最初に次のように保存する必要があります。setTimeout
$(this)
var $currentInput = $(this);
編集一部の人々は、準備ができたコードをコピーして貼り付ける可能性がないと方向性を理解しないことがわかります。ほら
var typingTimer;
// 2
$("#myinput").on('input', function () {
// 4 3
var input = $(this).val();
clearTimeout(typingTimer);
// 5
typingTimer = setTimeout(function() {
// do something with input
alert(input);
}, 5000);
});
paste
していない、使用していないthis
、など(重要だと思いますが、大量のコメントで迷子になりたくありません)