I have a working javascript block that basically takes user input, and upon each keystroke makes an Ajax POST call.
This works perfectly but I'd like to change it to only fire the ajax 3 seconds after the user starts typing, as opposed to every keystroke. Ideally I'd like to fire it after 3 seconds and if they start typing again it would start over, but the initial delay is most important.
I tried to do a set interval around it but it's didn't make the ajax call, so I'm wondering if there's different approach I need to take.
how can I make this ajax only call 3 seconds after typing in the input starts?
$('#productInput').on('input', function() {
let _this = $(this);
let optSelector = `option[value='${_this.val()}']`;
if (_this.val() === '') {
return;
} else if ($('#returnedProducts').find(optSelector).length) {
//html stuff
} else {
const searchResult = $(this).val();
$.ajax({ url: '/account/autocomplete',
data: {
search_result:searchResult
},
"_token": "{{ csrf_token() }}",
type: "POST",
success: function (response) {
$("#returnedProducts").empty();
var result = response.hits.hits;
for (let i = 0; i < result.length; i++) {
$("#returnedProducts").append($("<option/>",
{
//option stuff
}
));
}
}
});
}
});
Have a persistent variable that holds a setTimeout. On input, clear the current timeout (if there is one), and set another timeout to trigger in 3 seconds (unless another input event occurs). You may also consider putting the ajax call (at least) into its own function, for the sake of less indentation hell:
let timeout;
$('input').on('input', () => {
clearTimeout(timeout);
console.log('timeout set');
timeout = setTimeout(() => console.log('action running'), 3000);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input>
let timeout;
$('#productInput').on('input', function() {
clearTimeout(timeout);
let _this = $(this);
let optSelector = `option[value='${_this.val()}']`;
if (_this.val() === '') {
return;
} else if ($('#returnedProducts').find(optSelector).length) {
//html stuff
} else {
const searchResult = $(this).val();
timeout = setTimeout(ajaxCall, 3000, searchResult);
}
});
function ajaxCall(search_result) {
$.ajax({
url: '/account/autocomplete',
data: { search_result },
"_token": "{{ csrf_token() }}",
type: "POST",
success: successHandler
});
}
function successHandler(response) {
$("#returnedProducts").empty();
var result = response.hits.hits;
for (let i = 0; i < result.length; i++) {
$("#returnedProducts").append($("<option/>", {
//option stuff
}));
}
}
Related
I'm trying to make a search bar which is loading dynamicly content.
However I wish the real content loading start after the user end typing.
I tried this version but it does not work because it does not take into count each event "keyup".
let old_search = ""
let search = ""
$("#search_input").on('keyup paste',function(){
$("#loader_active").show()
$('#videos').empty()
let old_search = $("#recherche").val()
setTimeout(function (){
search = $("#search_input").val()
console.log(old_search + ">" + search)
if (search == old_search){
console.log("loading")
start = 0;
limit = 20;
load(search, start, limit);
start += limit;
}
}, 1000);
});
function load(search, start=0, limit=20) {
$("#loader_active").show()
let form_data = new FormData();
form_data.append('search', search);
form_data.append('start', start);
form_data.append('limit', limit);
$.ajax({
url: "http://website.com/ajax/videos.php",
contentType: false,
dataType: "json",
processData: false,
cache: false,
data: form_data,
type: 'POST',
success: function (data) {
$(data).each(function(index, value) {
showVideo(value) // show video creates divs with jquery containing the data from the json received by the ajax call
})
$("#loader_active").hide()
}
})
}
Does any body know any solution ?
What you can do is to make your function reset a trigger that will fire after x amount of time. Something like:
function myCoolFunction(myParameters) {
//Clear the timeout every time this happens
clearTimeout(window.myTimeout);
//Create a new timeout
window.myTimeout = setTimeout(function() {
//Do Something after 1 second
}, 1000);
}
$(".selector").on('keyup paste', function (){
myCoolFunction(myParameters);
});
This will execute 1 second after the last 'keyup/paste'. :D
I list of users in a html table that is dynamically created on page load. Each row has an inline button and each button has onclick="functionName(userId)", calls the following functions:On click show the bootstrap model pop up and then after starts calling ajax. The problem is stopping the ajax calls after user has closed model,and if user clicks on another row/user pass the current userId. for some reason, sometimes ajax calls stop and sometimes dont. Previous userId is also being saved somewhere which is resulting double or triple calls in a given interval. Thank you for your insights.
//This function gets called from each row passing its userId:
var timer = null;
function RTLS(id) {
$('#RTLSModal').modal('show');
window.clearTimeout(timer);
$('#RTLSModal').on('hidden.bs.modal',
function() {
window.clearTimeout(timer);
timer = 0;
$('#RTLSModal .modal-body').html("");
$('#RTLSModal').data('bs.modal', null);
});
$('#RTLSModal').on('shown.bs.modal',
function () {
GetRealTimeScans(id);
});
}
function GetRealTimeScans(id) {
var html = '';
$.ajax({
url: '/api/v1/computers/GetRealTimeKeys?computerId=' + id,
typr: "GET",
contentType: "application/json;charset=UTF-8",
dataType: "json",
success: function (scans) {
if (scans.length > 0) {
$.each(scans,
function (index, value) {
//create html
});
$('#RTLSModal .modal-body').html(html);
} else {
html += '<div class=""><h3 style="text-align: center;">No one around</h3></div>';
$('#RTLSModal .modal-body').html(html);
}
},
complete: function () {
timer = setTimeout('GetRealTimeScans('+id+')', 10000);
}
});
}
So abort the Ajax call so it stops
var timer = null;
var ajaxCall;
function cleanUp () {
if (timer) window.clearTimeout(timer);
if (ajaxCall) ajaxCall.abort()
}
and when you make the call
cleanUp()
ajaxCall = $.ajax({})
.done( function () {
ajaxCall = null
timer = window.setTimeout(function(){}, 10000)
});
And when you bind the events to the modal, you need to remove the previous event handler.
$('#RTLSModal')
.off('hidden.bs.modal shown.bs.modal')
.on('hidden.bs.modal', function() {})
.on('shown.bs.modal', function() {});
<script type="text/javascript">
var timeOutID = 0;
var checkScores = function() {
$.ajax({
url: "<?php echo 'http://127.0.0.1/ProgVsProg/main/countScoreCh'?>",
success:function(response){
if (response !=' ') {
$('#scoreCh').html(response);
clearTimeout(timeOutID);
} else{
timeOutID = setTimeout(checkScores, 3000);
}
});
}
timeOutID = setTimeout(checkScores,1000);
</script>
I am using setTimeout if there is a change in the database. If there is a change..it will output the change.
My problem is setTimeout will only display the first call.and never checks again if there is another change in the database.
I don't know if setTimeout is the correct way of doing it.
Yeah, setTimeout only runs once though. You're looking for setInterval.
<script type="text/javascript">
var timeOutID = 0;
var checkScores = function() {
$.ajax({
url: "<?php echo 'http://127.0.0.1/ProgVsProg/main/countScoreCh'?>",
success: function(response) {
if(response !== '') {
$('#scoreCh').html(response);
}
}
});
};
timeOutID = setInterval(checkScores, 1000);
</script>
You could also get it working by just getting rid of that else in your success function:
success: function(response) {
if(response !== '') {
$('#scoreCh').html(response);
}
timeOutID = setTimeout(checkScores, 3000);
},
error: function() {
timeOutID = setTimeout(checkScores, 3000);
}
You are making these mistakes
If you want to poll for database changes, don't use setTimeout. Instead use setInterval and clear this interval depending upon your logic like after 50times or something else.
Use a busyFlag because you are making an asynchronous call. (As suggested by #mike)
Try this
var intervalId = null;
var IS_BUSY_FETCHING_UPDATES = false;
var checkScores = function() {
if (!IS_BUSY_FETCHING_UPDTAES) {
IS_BUSY_FETCHING_UPDTAES = true;
$.ajax({
url: "http://127.0.0.1/ProgVsProg/main/countScoreCh"
}).done(function(response){
if (response) {
$('#scoreCh').html(response);
}
}).fail(function(e) {
console.error(e);
}).always(function() {
IS_BUSY_FETCHING_UPDATES = false; // This will be executed when AJAX gets complete
});
}
intervalID = setInterval(checkScores,1000);
So I am retrieving some data via POST using ajax, every 5 seconds, what I am trying to achieve is if the php file ouputs something, then stop the setInterval somehow or set it to 9999999.
Here is what I've tried:
var interval = DEFINEDFROMMYQL;
$(function() {
setInterval(function() {
$.ajax({
type: "POST",
url: "url/file.php",
data: "whatever=2",
success: function(html) {
$("#new").html(html);
if(html.lenght > 0) {
var interval = 99999999999999;
}
}
});
}, interval);
});
I'm a newbie, so any help will be appreciated.
You can use clearInterval() to stop the timer started by setInterval and correct the typo html.lenght to html.length
// var interval = DEFINEDFROMMYQL;
$(function() {
yourInterval = setInterval(function() {
$.ajax({
type: "POST",
url: "url/file.php",
data: "whatever=2",
success: function(html) {
$("#new").html(html);
if(html.length > 0) {
///var interval = 99999999999999;
clearInterval(yourInterval);
}
}
});
}, interval);
});
You can handle this a couple of different ways, but based on your question ("stop the setinterval somehow") let's switch the implementation to a setTimeout and also refactor the code in to a function we can recall. So...
var interval = DEFINEDFROMMYQL;
$(function() {
// establish a function we can recall
function getDataFromServer(){
// this encapsulates the original code in a function we can re-call
// in a setTimeout later on (when applicable)
$.ajax({
type: "POST",
url: "url/file.php",
data: "whatever=2",
success: function(html) {
$("#new").html(html);
// only if the length is 0 do we re-queue the function
// otherwise (becase it's setTimeout) it will just die
// off and stop.
if(html.lenght == 0) {
setTimeout(getDataFromServer, interval);
}
}
});
}
// make an initial call to the function to get the ball rolling
setTimeout(getDataFromServer, interval);
// if you want it to execute immediately instead of wait out the interval,
// replace the above line to simply:
//getDataFromServer();
});
I use the function below to check on the status of a JSON file. It runs every 8 seconds (using setTimeout) to check if the file has changed. Once the JSON's status becomes 'success' I no longer want to keep calling the function. Can someone please show me how to do this? I suspect it involves the use of clearTimeout, but I'm unsure how to implement this.
Cheers!
$(function() {
var checkBookStatus = function() {
var job_id = "#{#job.job_id}";
var msg = $('.msg');
var msgBuilding = $('#msg-building');
var msgQueuing = $('#msg-in-queue');
var msgSuccessful = $('#msg-successful-build');
var msgError = $('#msg-error');
$.ajax({
url: '/jobs/'+job_id+'/status.json',
datatype: 'JSON',
success:function(data){
if (data.status == "failure") {
msg.hide();
msgError.show();
}
else if (data.status == "#{Job.queue}") {
msg.hide();
msgQueuing.show();
}
else if (data.status == "#{Job.building}") {
msg.hide();
msgBuilding.show();
}
else if (data.status == "#{Job.failure}") {
msg.hide();
msgError.show();
}
else if (data.status == "#{Job.success}") {
msg.hide();
msgSuccessful.show();
}
},
}).always(function () {
setTimeout(checkBookStatus, 8000);
});
};
checkBookStatus();
});
t = setTimeout(checkBookStatus, 8000); when you decide to stop the timeout use this clearTimeout(t);.
use clearTimeout
e.g. you defined :
id = setTimeout(checkBookStatus, 8000);
then you can remove this function by :
clearTimeout(id)
Before your call of checkBookStatus() at the end, put another call: var interval = setInterval(checkBookStatus, 8000);. Then on success you can clearInterval(interval).
Do not use setTimeout for iteration.
A lot of answers are suggesting just to use clearTimeout() however, you are checking the status after the timeout has expired, there is no timeout to clear. You need to not call setTimeout() in your always() function rather than to clear anything. So you could re-inspect the status inside your always() function I suppose, but your data object isn't in scope there. It would be preferable to just use setInterval() outside of your checkBookStatus() function.
$(function() {
var checkBookStatus = function() {
var job_id = "#{#job.job_id}";
var msg = $('.msg');
var msgBuilding = $('#msg-building');
var msgQueuing = $('#msg-in-queue');
var msgSuccessful = $('#msg-successful-build');
var msgError = $('#msg-error');
$.ajax({
url: '/jobs/'+job_id+'/status.json',
datatype: 'JSON',
success:function(data){
if (data.status == "failure") {
msg.hide();
msgError.show();
}
else if (data.status == "#{Job.queue}") {
msg.hide();
msgQueuing.show();
}
else if (data.status == "#{Job.building}") {
msg.hide();
msgBuilding.show();
}
else if (data.status == "#{Job.failure}") {
msg.hide();
msgError.show();
}
else if (data.status == "#{Job.success}") {
msg.hide();
msgSuccessful.show();
clearInterval(interval);
}
}
});
};
var interval = setInterval(checkBookStatus, 8000);
checkBookStatus();
});
Call clearTimeout with the value previously returned by setTimeout. This would give you something like:
$(function() {
var timeoutID;
var checkBookStatus = function () {
[…]
else if (data.status == "#{Job.success}") {
clearTimeout(timeoutID);
[…]
}).always(function () {
timeoutID = setTimeout(checkBookStatus, 8000);
[…]
When you use setTimeout, use like this:
var myTime = setTimeout(checkBookStatus, 8000);
to clear it just:
clearTimeout(myTime);
the following should work...
the setTimeout function return an instance of the setTimeout function. Keep this value in a variable and pass it to the function clearTimeout when you want to prevent the event from firing again.
i.e.
var t = setTimeout(1000, someFunction);
...
//after you no longer need the timeout to fire, call
clearTimeout(t);