onkeyup activates many ajax requests - javascript

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);
}

Related

with or without a save button for saving textarea content

I have a lot of textareas on a page and want to save the contents automatically by typing inside
$('textarea').on('input', function(){
let id = $(this).attr('data-id');
let story = $(this).val();
$.post('a_pro.php', {fn: 'tx_change', args: [id, story]}, function(data){
console.log('saved');
});
});
On server side I have a php function tx_change to store data in a mysql table.
Everything works fine, regardless what is the speed of typing, regardles I'm on a wire on wireless connection...
I even tried typing inside one textarea and at the same time pasting a content inside another one - it works - everything is saved.
Question is - why people use a SAVE button at all?
I suppose there is a hidden risk of using this?
In a second I type 4-5 characters, so each second the javascript, php and sql code is executed five times, and plus time for establishing connection and plus time for callback function (write console)...
I simply cannot believe that there is no any problem with this.
Any advice?
Yes that true you will increase overhead on server using auto save method.
if you still want auto save, you should decrease number of request and you can do it by using debounce function.
const debounce = (func, delay) => {
let debounceTimer
return function() {
const context = this
const args = arguments
clearTimeout(debounceTimer)
debounceTimer
= setTimeout(() => func.apply(context, args), delay)
}
}
var textareaElem = document.getElementById("textarea");
textareaElem.addEventListener('keyup', debounce(function() {
alert("Hello\nNo matter how many times you" +
"click the debounce button, I get " +
"executed once every 300 ms!!")
}, 300)); // <-- you can change debounce time
<textarea id="textarea"></textarea>

How to prevent users from affecting number of button clicked times

I have a game written in JavaScript and what it basically does is start a ten seconds timer and register the number of times the user is able to click on a certain button, before the timer elapses.
How the code works:
When a user clicks on the button, an element gets added to an array, using push function, then a different function returns the length of the array as the number of times clicked.
The problem with this:
If a user opens up the dev tools and alters the number of times an element is added to the array per click, this will change the outcome of the result.
My Approach:
What I decided to do is to store the length before I ran the push function and also after I ran the push function, then compare their differences and if it's greater than 1, it means something is not right. This seemed to work in my head until I wrote it down in code and discovered that if the user pushed multiple times before I checked the differences then it would go unnoticed. Please big brained guys, help me.
My code:
$('body').on('click', '.btn.z', function () {
// start listening
startCountingClicks()
})
var timerStarted = false;
var tc = [];
function startCountingClicks () {
$('.btn.z').html('ClickZed');
$('.Score').html('Your Score: '+gettc()+" clicks");
if (timerStarted == false) {
startTimer(10, $('#time'));
}
// user does multiple push before this function: startCountingClicks is called
var previous_length = tc.length; // get length before push
tc.push(1);
var new_length = tc.length; // get length after push
if (new_length - previous_length !== 1) {
console.log("fraud"); // this is supposed to catch a thief!!!
}
console.log(new_length+" "+previous_length);
timerStarted = true;
}
function gettc (){
// get number of clicks
return tc.length ;
}
A code that totally breaks this:
$('button').click(function(){tc.push(1); tc.push(1)})
EDIT:
I do not wish to protect against dev tools, though I am not against that method if it works. I just wish to get a better way of counting my clicks, a way that can't be affected by writing code on the dev tools.
You can't really stop people from doing stuff on the client side. It is pointless trying to prevent that. The best thing you can do is make sure whatever is sent matches what you expect on the server side.

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

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.

jQuery event only every time interval

$(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

Categories

Resources