jQuery event only every time interval - javascript

$(document).ready(function() {
$('#domain').change(function() {
//
});
});
The code inside the change function will basically send ajax request to run a PHP script. The #domain is a text input field. So basically what I want to do is to send ajax requests as user types in some text inside the text field (for example search suggestions).
However, I would like to set a time interval in order to lessen the load of PHP server. Because if jQuery sends AJAX request every time user adds another letter to the text field it would consume lots of bandwidth.
So I would like to set let's say 2 seconds as an interval. The AJAX request will be fired every time the user types a letter but with maximum frequency of 2 seconds.
How can I do that?

$(function() {
var timer = 0;
$("#domain").change(function() {
clearTimeout(timer);
timer = setTimeout(function(){
// Do stuff here
}, 2000);
});
});

$(document).ready(function() {
var ajaxQueue;
$('#domain').change(function() {
if(!ajaxQueue) {
ajaxQueue = setTimeout(function() {
/* your stuff */
ajaxQueue = null;
}, 2000);
}
});
});

What you really want to do is check how long since the last change event so you keep track of the number of milliseconds between events rather than make a call every 2 seconds.
$(document).ready(function() {
var lastreq = 0; //0 means there were never any requests sent
$('#domain').change(function() {
var d = new Date();
var currenttime = d.getTime(); //get the time of this change event
var interval = currenttime - lastreq; //how many milliseconds since the last request
if(interval >= 2000){ //more than 2 seconds
lastreq = currenttime; //set lastreq for next change event
//perform AJAX call
}
});
});

Off the top of my head without trying this in a browser. Something like this:
$('#domain').change(function() {
if (!this.sendToServer) { // some expando property I made up
var that = this;
this.sendToServer = setTimeout(function(that) {
// use "that" as a reference to your element that fired the onchange.
// Do your AJAX call here
that.sendToServer = undefined;
}, yourTimeoutTimeInMillis)
}
else {
clearTimeout(this.sendToServer);
}
});

two variables, charBuffer, sendFlag
Use a setTimeout to have a function be called every two seconds.
This function checks if the buffer has stuff in it.
If it does, it sends/empties the stuff and clears the sent flag (to false).
and It should also clear the timeout, and set it again
else it sets the flag (to true).
Everytime the user hits a key, store it in the buffer.
if the sent flag is clear (it's false), do nothing.
else (it's true) send/empty the stuff currently in the buffer and clear the flag (to false),
and It should also clear the timeout, and set it again
This will make it so that the first time you press a key, it is sent, and a minimum of 2 seconds must pass before it can send again.
Could use some tweaking, but i use this setup to do something similar.

I am coming across this problem more and more (the more i do UI ajax stuff) so i packaged this up into a plugin available here

Related

onkeyup activates many ajax requests

In an entry I use the onkeyup function so that every time I type it, I activate a javascript function, which makes requests to the server using ajax, the problem arises when the user types quickly, so with each key that he / she touches, activates an ajax request which causes me many requests, and also brings me bad results.
I do not know if it is understood, I hope someone can give me an idea of ​​how to change this.
Thank you
This kind of ajax call is not good idea.
Anyhow,
You should do ajax call when user has typed at least 3-4 letters.
You can also add some a check to see if user has typed something and stopped writing then do the ajax.
If you still want to do ajax on each character then try to do very light ajax means get very small data from server.
Check if input length is > 3:
var userInput = $('#inputFiled').val(); // get user input and save into js variable
if(userInput.length > 3){ //if user input is at least 3 characters
//do ajax here
}
To check if user has stopped writing
To do so you will have to use underscore.js
$('#userInout').keyup(_.debounce(yourAjaxCallFunctionHere , 500));
underscorejs.org/#debounce
You can also achieve this using jQuery
var delayInAjaxCall = (function(){
var timer = 0;
return function(callback, milliseconds){
clearTimeout (timer);
timer = setTimeout(callback, milliseconds);
};
})();
Usage Of Above Function
$('input').keyup(function() {
delayInAjaxCall(function(){
alert('Hi, func called');
}, 1000 );
});
You can utilize the below JS code and achieve with few lines of codes,
let timer = null;
on_key_up(){
//if input length < 3 return it
if(timer){
window.clearTimeout(timer);
timer = null;
}
timer = window.setTimeout( ()=>{
FireMyEvent()
}, 1000);
}

setTimeout() function being called twice in a row

I am writing a bot that sends alerts at variable intervals. I am using setTimeout() and I have an issue I can't seem to be able to figure out. The (simplified) code is:
//Original call to setTimeout():
timeout = setTimeout(issueAlarm, 2147483647); // highest possible interval setTimeout() will accept.
//In bot:
// dh is a priority queue that keeps timestamps sorted from smaller to larger as the user requests alerts.
//'mom' is a moment.js variable that holds the most recent request.
//This block of code checks the PQ and if what the user just entered is smaller than what is already stored, it updates the timeout.
//This seems to work fine
// First get input from user and store the desired time of first alert in 'mom'. Then:
var nextD = dh.peekNext();
if (nextD.timestamp >= mom.valueOf() ){
var now = new Date();
clearTimeout(timeout);
timeout = mom.valueOf() - now;
setTimeout(issueAlarm, timeout);
}
//issueAlarm function:
function issueAlarm() {
var next = dh.getNext(); // this pops the first alarm from the queue
// here goes some code that issues message. Then:
var peek = dh.peekNext(); // this looks at the next element in the queue without popping it
if (peek) {
var now = new Date();
timeout = peek.timestamp - now;
setTimeout(issueAlarm, timeout);
}
}
The example inputs are:
First input entered: Set an alert every 8 hours starting 5 minutes from now ("call Bob")
Second input entered: Set an alert every 8 hours starting 4 minutes from now ("call Jane")
In 4 minutes, i correctly get "call Jane" (this one gets set from the bot code)
One minute later, I correctly get "call Bob", but also i get "call Jane" (which should not happen until 8 hours later)
I printed all the timeout values and they seem correct. I also am printing the return of the setTimeout() function inside the issueAlarm() function.
Inside the first call: _idleTimeout: 59994 (this is correct, the next call is in one minute)
Inside the second call: _idleTimeout: 28739994 (this looks correct, it's approximately 8 hours, but still i get a third call right away)
Inside the third call: _idleTimeout: 28799991 (this timeout looks correct but this function call shouldn't have happened)
I'm using botFramework. My knowledge of JavaScript and node.js is far from extensive. I have printed out everything I could think of, but I can't figure out why that third call is being made right away.
This happens only if the first input entered requests an alert that starts later than the one entered in the second input. But I can't possibly understand why.
I thought you could have a problem with the Next function that returns you the data, take a look to my example. If your function is returning the next element as they were saved, you could not use that function, you need to build a function that return the first alarm to call. Hope it helps!
var dh = {};
dh.alarms = [{time: 1000, name:"Jane"},{time:5000, name:"Jane"},{time: 3000, name:"Bob"}];
dh.first = function(){
dh.alarms = dh.alarms.sort(function(a,b){return a.time - b.time});
next = dh.alarms.slice(0,1);
dh.alarms = dh.alarms.slice(1);
return next[0]
}
dh.next = function(){
next = dh.alarms.slice(0,1);
dh.alarms = dh.alarms.slice(1);
return next[0]
}
var timeout = setTimeout(executeAlarm, 2999999);
function start(){
var next = dh.first(); // dh.next(); I thought this is your problem!!
if(next && next.name){
clearInterval(timeout);
timeout = setTimeout(function(){executeAlarm(next)},next.time);
}
}
function executeAlarm(next){
if(!next || !next.name) clearInterval(timeout)
document.getElementById("alarms").innerHTML += "<span> Alarm for " + next.name + "</span>";
start();
}
document.addEventListener( "DOMContentLoaded", start, false );
<div id="alarms"></div>
(Posted on behalf of the OP).
The problem was here, in the bot code:
if (nextD.timestamp >= mom.valueOf() ){
var now = new Date();
clearTimeout(timeout);
timeout = mom.valueOf() - now;
setTimeout(issueAlarm, timeout);
}
I was clearing the timeout correctly the first time (when i cleared the original timeout of 2^31 - 1), but not afterwards. The issue is that the line in which i call setTimeout should be
timeout = setTimeout(issueAlarm, timeout);
So that the return is stored in a timeout object. I was making subsequent calls to clearTimeout() by passing a value, not an object, and therefore the timeout stored first (5 minutes, 'call Bob') was never cleared.
Thanks to #guest271314 and to #damianfabian for helping me get to the correct answer.

How to have a timer which cannot be modified in javascript?

Basically, I am designing a quiz application with limited time. Use selects answer to a question and the next question loads using an Ajax request. All questions must be answered within a time frame of, say 2 minutes.
A clock ticks away to show how much time is left and as soon as it hits 0, results are shown. Now since the timer will be implemented using window.setTimeout(), it is possible that the value of timer variable be modified using an external bookmarklet or something like that. Anyway I can prevent this? I think this is implemented on file sharing sites like megaupload. Any forgery on the timer variable results in request for file being rejected.
Have .setTimeout() call an AJAX method on your server to synch time. Don't rely on the client time. You could also store the start time on the server for a quiz, and then check the end time when the quiz is posted.
You need to add a validation in your server side. When the client want to load the next question using an Ajax request, check whether deadline arrived.
The timer in client side js just a presention layer.
If the function runs as a immediately called function expression, then there are no global variables and nothing for a local script to subvert. Of course there's nothing to stop a user from reading your code and formulating a spoof, but anything to do with javascript is open to such attacks.
As others have said, use the server to validate requests based on the clock, do not rely on it to guarantee anything. Here's a simple count down that works from a start time so attempts to dealy execution won't work. There are no global variables to reset or modify either.
e.g.
(function (){
// Place to write count down
var el = document.getElementById('secondsLeft');
var starttime,
timeout,
limit = 20; // Timelimit in seconds
// Function to run about every second
function nextTick() {
var d = new Date();
// Set start time the first time
if (!starttime) starttime = d.getTime();
var diff = d.getTime() - starttime;
// Only run for period
if (diff < (limit * 1000)) {
el.innerHTML = limit - (diff/1000 | 0);
} else {
// Time's up
el.innerHTML = 0;
clearTimeout(timeout);
}
}
// Kick it off
timeout = window.setInterval(nextTick, 1000);
}());

How to check the status each 10 seconds with JavaScript?

I have a server (mysite.com/status), which returns number of active tasks (just a single integer).
How can I check number of active tasks each 10 seconds with JavaScript and show user something like:
Number of remaining tasks: XXX
And, if number of tasks is 0, then I should load another page.
Make a function set a new timeout calling itself.
function checkTasks(){
// Make AJAX request
setTimeout(checkTasks, 10000);
}
checkTasks(); // Start task checking
with jQuery for AJAX functions... (untested code)
setInterval(function(){
$.get('http://example.com/status',function(d){
// where there is html element with id 'status' to contain message
$('#status').text('Number of remaining tasks: '+d)
if(d == 0){
window.location = '/another/page'
}
})
},10000)
I have thought of different approach, without any AJAX. As you just need to show simple plain data, just use <iframe> to show that dynamic data then with simple JS "reload" the frame every 10 seconds.
HTML would be:
Number of remaining tasks: <iframe id="myFrame" src="mysite.com/status"></iframe>
And the JavaScript:
window.onload = function() {
window.setTimeout(ReloadTime, 10000);
};
function ReloadTime() {
var oFrame = document.getElementById("myFrame");
oFrame.src = oFrame.src;
window.setTimeout(ReloadTime, 10000);
}
Live test case, using time for the same of example.
With some CSS you can make the frame look like part of the text, just set fixed width and height and remove the borders.
setInterval(function(elem){ // here elem is the element node where you want to display the message
var status=checkStatus(); // supposing that the function which returns status is called checkStatus
if(status == 0){
window.location = '/another/page'
}
else {
elem.innerHTML="Number of remaining tasks:"+status;
}
},10000)
Using the javascript library jquery, you can set a repeating infinite loop.
That gets the data from a page and then sets the inner html of an element.
http://jsfiddle.net/cY6wX/14/
This code is untested
edit: demonstration updated
Also I did not use the jquery selector for setting the value in case you do not want to use jquery.

Javascript jquery - How do I build a delay into the search entry

I have an ajax search box that goes to the server on every key stroke and returns the result of the search.
When the user types quickly, I want to search only on the last entry and not on every key stroke. Otherwise the individual results flash annoyingly and the whole process is slowed.
For example: if the user types "statue of liberty" quickly, I don't want to search on "sta", "stat", "statu" etc.
the basics of my jQuery code is:
$('#searchbox').keyup(function(){
if (this.value.length > 2) {
$.post("remote.php",{'partial':this.value},function(data){
$("#gen_results").html(data);
});
}
});
<input id="searchbox" />
<div id="gen_results"></div>
use setTimeout or jQuery's autocomplete plugin
var timer;
$('#searchbox').keyup(function(){
if (this.value.length > 2) {
if (timer){
clearTimeout(timer);
}
timer = setTimeout(function(){
$.post("remote.php",{'partial':this.value},function(data){
$("#gen_results").html(data);
});
}, 1000);
}
});
You need to use a timeout, this one is set to 500ms, but you might want to go quicker.
$('#searchbox').keyup(function(){
window.clearTimeout(window.timeOutId);
window.timeOutId = window.setTimeout(function() {
if (this.value.length > 2) {
$.post("remote.php",{'partial':this.value},function(data){
$("#gen_results").html(data);
});
}
},500);
});
Hope that works for you!
Try this
var inProgress = false;
$('#searchbox').keyup(function(){
if (this.value.length > 2 && !inProgress) {
inProgress = true;
$.post("remote.php",{'partial':this.value},function(data){
$("#gen_results").html(data);
inProgress = false;
});
}
});
This way you dont have to maintain a timer, just another call if the previous call is complete and by that time user has typed something more.
function getResults(value) {
return function() {
$.post("remote.php",{'partial':value},function(data){
$("#gen_results").html(data);
});
};
}
var timerId;
$('#searchbox').keyup(function(){
if (this.value.length > 2) {
clearTimeout(timerId);
timerId = setTimout(getResults(this.value), 1000);
}
});
I did something similar once. What I did was set a timer each 500ms, and when the timer is called it does the AJAX request. The trick is that whenever the user typed something, I would reset the timer.
You could have a global variable holding the timestamp of the last keystroke. When the keyup method is called, take a timestamp reading and compare it to the previous value. If it is over a certain time frame, make your call, otherwise, reset the global value and exit.
Instead of building this yourself have a look at the jQuery Autocomplete plugin.
Using this you can set a delay option so that requests wait for a given period after a keystroke.
The delay in milliseconds the Autocomplete waits after a keystroke to
activate itself. A zero-delay makes sense for local data (more
responsive), but can produce a lot of load for remote data, while
being less responsive.

Categories

Resources