I have come accros this problem before. This time it is an HTML5 color input giving the problem. Here's the issue. I want to use an onChange event to send the user selected value from a color input to the server via Ajax - for an almost real time update to a database. However, when the user drags his mouse over the color swatch, it will trigger loads of onChange events in rapid succession, for each value change, so the server will get inundated with hundreds of pointless requests until the user stops sliding their mouse!
I could use onMouseOut for this particular issue, but I have had this issue with other things like detecting browser window resizing when a user click/drags to resize and the event is triggered with every pixel change. So I'm looking for an answer that will trigger on the final value only, for all similar scenarios.
What is the best method for dealing with this and just triggering when the data has finished changing. I.e. ignore every change until user has settled on a final value. An onAfterChange method event would be nice, but I can't find one!
You can prevent this by debouncing your event handler function.
Every time a debounced function is called, it "pushes back" its execution by nms. This means that while triggered numerous times within t ms (eg: while the mouse is moving), it will only execute the handler after not being triggered for t ms (eg: when the mouse has stopped moving).
Edit:
Ok, the jquery link was a bit out-of-date.. a better example of how to debounce can be found in the Underscore.js source here.
How about this:
Set a timeout to send request to server, after the first onChange triggering, and change the first flag to false.
Every onChange is triggered, reset the timeout count.
After sending request, reset the first flag.
Edit:
This is the sample code:
$(document).ready(function(){
var myInterval = undefined;
var mytimeoutcount = NaN;
var i =0; // for debug
$("#myinput").keyup(function(){
console.log("event trigger"); // for debug
mytimeoutcount = 300;
if(myInterval == undefined){
myInterval = setInterval(function(){
mytimeoutcount -= 10;
if(mytimeoutcount <= 0){
// do request, for debug
i+=1;
console.log(i);
window.clearInterval(myInterval);
myInterval = undefined;
}
}, 10);
}
});
});
#myinput{
width:100px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<input id="myinput" type="text" value="test" />
Related
So i want to make an input field, which would refresh everytime the user type something, without having to press a button or enter.
I already know about the 'oninput' event like this :
<input type='text' oninput='refresh'>
And in my script.js :
function refresh()
{
console.log('refreshed!');
}
The problem is that this fire an event every time I just write or delete one letter. And as I will have to make SQL queries to refresh, I don't think it's very efficient to make queries for every change.
So my idea was:
to find a way to fire the oninput event every 1 second, but this would feel a bit laggy;
I don't know if this exists but to only fire an event when the user stop typing.
So, do you know any way I could improve my search bar?
I use debounce function from lodash for this purpose. It calls function when user'll stop typing.
using onFocus,Onblur,Onchange you can build it efficiently.
var myVar ;
In OnFocus - myVar = setInterval(MyFunction, 1000); // calls for every 1 sec.
function MyFunction()
{
if(dataChanged)
<> and make dataChanged =false
}
In Onblur - clearInterval(myVar);//To stop once user out of the textinput
To make it efficient in Onchange method set a flag(dataChanged) when ever user inputs and clear the flag in MyFunction in onFocus after the server call. to avoid unnecessary calls
I've got this code in which an event is first triggered by the user.
Then the event is triggered again within the event-handler.
inputs.forEach(function(item) {
item.addEventListener('focus', function() {
item.parentNode.focus();
setTimeout(function() {
item.parentNode.blur();
item.focus();
}, 1000);
});
});
Currently this leads to an infinity recursion.
When I could find a way to detect if the event was triggered by the user then I could check for that. And so avoid the recursion.
Older StackOverflow answers talk about an "originalEvent"-property of the event-object: Detect if a scroll event is triggered manually in jQuery
But this property has always been undefined in my trying.
Therefore:
Is there a way how I can check if the event was triggered by the user?
Remove
item.parentNode.focus();
You can simply set a flag on the first run.
Then in the beginning of your handler check the state of the flag. If the flag is set already just unset it and return (so the next run will trigger the event again), but not run the remaining part.
If the flag is not yet set, run the remaining part normally, set the flag at the and again.
I have the following jQuery code in my page onload function:
$("#vid-pages").find("video").on('canplay', function() {
$(this)[0].currentTime = $(this)[0].duration / 2;
console.log($(this)[0].currentTime);
});
There are only two videos in that container, and none anywhere else on the page. When I check the console, it's continuously flooded with the time returned in that code block. What is the solution to make this trigger only once, instead of constantly?
When the current time is changed the browser needs to load more data either from cache or the network. This can trigger the canplay event. And since a time is set in the event handler you will get a never-ending loop (you can see the effect of canplay being triggered here by choosing a video, hit play then skip to the middle right after). It may depend on the browser.
This page on MDN states the following to the related canplaythrough (though not entirely the same it is reasonable to believe this also applies to canplay as shown in the media event page using Firefox):
Note: Manually setting the currentTime will eventually fire a
canplaythrough event in firefox. Other browsers might not fire this
event.
To avoid either unsubscribe from the event, or use a flag which forces exit at the second time the event is triggered.
var initialPlay = false;
$("#vid-pages").find("video").on('canplay', function() {
if (initialPlay) return;
initialPlay = true;
$(this)[0].currentTime = $(this)[0].duration / 2;
console.log($(this)[0].currentTime);
});
For unsubscribing you would need to use a non-anonymous function.
I've got a table with dozens of rows (up to 100), and each row has 1 element with a mouseover event attached to it. On mouseover, I open a tooltip and need to make an AJAX request to fill it with some data.
My problem is fairly simple: if the user moves his mouse up and down over all the elements that have that event attached, I'm firing tons of requests at a time. I wanna throttle it one way or another, but I'm unsure how to.
I'm gonna have to check whether that same event has been executed in the last n seconds, but how do I keep a link between the firing of event 1 and firing of event 2?
You need a flag in the start of your AJAX call, if the flag is ZERO, return from the function. How you scope the varialbe is up to you.
if(AJAXOK==0) {
return;
}
AJAXOK = 1;
Set the variable in the AJAX call, so that is resets itself after a timeout:
window.setInterval(function() { AJAXOK = 1 },5000);
AJAXOK = 0;
If you're interested in trying a different approach, reactive extensions are designed for exactly this sort of thing:
http://reactive-extensions.github.com/RxJS
I develop an app using phonegap and jquerymobile/jquery.
During development I only had a virtual iOS device and now since I'm testing the app on a real device I see, that time between click on an element and handle this event is very long.
E.g if i Click on an icon a loader icon is shown but this icon first come in the moment the next page is final loaded (a very short time the loader is shown).
I develop with Javascript since a long time and always have focus on performant execution but this is very strange.
The App has got about 10 views in one HTML file. And on click on an element only show the next part of these file.
Does anyone know about solutions to solve "Bugs" like these?
Thanks in advance.
The click delay on iPhones is a feature used to distinguish between clicks and scrolls. When you bind to the click event iOS waits approximately 300ms to decide whether you were clicking an object or trying to scroll the page.
You can use jQuery Mobile's vclick event which fires much faster however you will probably run into situations where the vclick event is fired off twice in a row which can result in multiple elements being clicked. Here is some sample code of how to use vclick events and only capture the event triggered first:
$(function () {
//setup a function to check if a vclick event has fired within the last 500ms
function check_vclick () {
//if a vclick event has fired in the last 500ms then return false
if (do_vclick == false) return false;
//otherwise set a flag to disallow vclicks for 500ms
do_vclick = false;
//setup a timeout to allow vclicks in 500ms
setTimeout(function () {
do_vclick = true;
}, 500);
//return true so the event handler knows it's ok to run its code
return true;
}
//setup a flag to allow/disallow vclick events from firing
var do_vclick = true;
//bind an event handler to the vclick event for an element
$('#link_id').bind('vclick', function () {
if (check_vclick()) {
//run the code associated with the element, if it's a link referencing a pseudo-page on the same HTML document, you can do something like this
$.mobile.changePage($(this.href));
}
});
});
Here's a link to the documentation for $.mobile.changePage(): http://jquerymobile.com/demos/1.0rc2/docs/api/methods.html
Here's a link to the documentation for vclick (notice the notes under the virtual mouse event section): http://jquerymobile.com/demos/1.0rc2/docs/api/events.html