Clear Form Fields on Inactivity - javascript

I'm currently working on a simple form that stores users inputted information to a database.
The form will be displayed on iPads at a Kiosk.
If a user walks up to the form and starts to fill in the fields, but doesn't finish and walks away, I want the form fields to clear for the next person.
This is being done to prevent someone from walking up to an iPad with half of the previous users information that was never submitted.
I know I'll have to use Javascript, but I have no clue where to start.

I would say handle the keydown event of the window object and save the current time. Something like this:
var timerID = null;
var timeoutDuration = 60000; // Put the timeout duration here
window.addEventListener('keydown', function(e) {
if(timerID !== null) {
clearTimeout(timerID);
timerID = null;
}
timerID = setTimeout(function() {
// Clear all the fields here
}, timeoutDuration);
}, false);
Here's a demo.

Why not just reload the page after a period of inactivity? Safer bet. Just use setTimeout and clearTimeout JavaScript functions to achieve this when the fields get updated to reset the timers. Use setTimeout to reload the page. This will ensure that the page is reset.
See Reload and JavaScript timing.

In my opinion, the best thing to use it the javaScript timing event.
This can be done by setTimeout() and clearTimeout() functions. Then in those functions you can address the input boxes document.getElementById("nameofElement") and then clear them.
Good example that is easy to follow see :
JavaScript Timing Events
Hope this helps.

Related

How to delay event propagation using jQuery

I want to display a note after the user submits a form but before he leaves the page.
Currently I'm using this (reduced example code):
$('form').submit(function(event) {
$('.note').show();
setTimeout(function() {
$('form').unbind().submit();
}, 2000);
return false;
});
This works but doesn't seem to be nice. Is there any other way, like a function $.delayPropagation(2000);?
PS: The note covers the whole screen, so the user won't be able to submit again during this time.
That is an appropriate way to delay the operation.
You may actually want to unbind the event first to stop multiple calls (you currently have a 2 second window in which they could submit again).
As a standard practice, you should only run your jQuery selectors once (use a temp var to hold the result). $ prefixes are also another standard for naming jQuery variables. This now means the code below would support multiple forms on a page separately.
$('form').submit(function(event) {
var $form = $(this);
$('.note').show();
$form.unbind()
setTimeout(function() {
$form.submit();
}, 2000);
return false;
});
You must return false immediately to avoid blocking the browser.
Notes:
An alternative would be to use Ajax for the form post, then have the delay, then goto a new page
setTimeout is the most ubiquitous way to delay code from executing.
Note: I just wanted to use the term ubiquitous in a post :)

On event start calling function periodically

I have this problem:
I have real time form validation, but the inputs have autocomplete on, so when you choose a value from it, it wont trigger eny event and I cant start validating the new value.
Here is some solution which I have figured
I was thinking when input triggers onfocus event, i can start periodically (for example every one second) calling some validating functions on input, whether the value changes or not.
And on blur event I want to stop calling the function.
But I cant figure it out how to start call the function periodically...
What I have so far:
$('input[name="'+input_name+'"]').focus(function(){
checkInput(input_name);
});
function checkInput(input_name){
setInterval(doneTyping(input_name),700);
console.log(1);
}
But this only happens once, how could I do it?
Thanks.
setInterval needs an anonymous function
myInterval = setInterval(function(){doneTyping(input_name);},700);
//To clear
clearTimeout(myInterval);
do it like
var intervalID = window.setInterval(function(){ doneTyping(input_name); }, 700);
see this fiddle.

Jquery/js, taking a value from textfield and using ajax to send it to the server

I need to use this plugin: http://jstepper.emkay.dk/Default.aspx to be able to use "mousewheel" value incrementation.
This plugin offers a function onStep, which will run a my own function each time a value is incremented. Now it would be real simple to just send new value to the ajax function, but that would mean hundreds, if not thousands of POST requests, lots of mysql inserts/updates, it would be very messy...
I am trying to implement somekind of a timer that would take the value from the textfield, wait 1000milliseconds and then post it to the server, whenever a user should scroll for more values, it would cancel the previous timeout and start counting again.
This introduced two problems, first - if a user scrolls one textfield and then immediately starts scrolling the next textfield the previous textfield data wouldn't be sent, because the new field would take the control of the timer.
And secondly, I couldn't get the values anyway I tried, this is probably easy to fix, I just have to figure out how to...
So I'm hoping that someone might help me in this, because I am stomped.
$(".basket_input").jStepper({onStep:function(){ajaxSleeper(this.value, this.id)}});
var timer = 0;
function ajaxSleeper(val1,val2){
clearTimeout(timer);
timer = setTimeout(function(){
ajaxUpdate(val1,val2);
//alert('updated!');
}, 3000);
}
HTML
<td><input class="basket_input" size="5" maxlength="6" type="text" value="" name="1939" id="1939" /></td>
The easiest thing to do would be to use $.data to set the timer and keep using the context of the actual object.
jQuery
var $basket_input = $(".basket_input");
$basket_input.jStepper({
onStep: function() {
ajaxSleeper.call($basket_input.get(0)); // Call the function using the
// element as the context
}
});
function ajaxSleeper() {
// Get any timer that could be set for this element
var thisTimer = $(this).data('timer');
// Clear it if there is one
if (thisTimer) clearTimeout(thisTimer);
// We need this as the context in setTimeout will change to "window" object
// Yet we want to reference this object in the setTimeout
var $that = $(this);
$(this).data('timer', setTimeout(function() {
ajaxUpdate($that.val(), $that.attr('id'));
//alert('updated!');
}, 3000);
);
}
Two possible solutions.
If you haven't seen Underscore.js, you should. They have a _.throttle() that will do exactly what you want, along with a million other useful things.
If you don't want to use another library, you're close.
var timer;
var fireOffMyRequest = function()
{
// ... FIRE EVERYTHING! ...
};
var somethingThatGetsFiredOften = function()
{
clearTimeout(timer);
timer = setTimeout(fireOffMyRequest, 4000);
};
That limits to 4 seconds; you could change the 4000 to reflect whatever you want the throttle limit to be.
edit: I forgot to address your timer issue. Store off the timer onto the HTML element:
$(this).data('timer', timer);

Javascript: Do processing when user has stopped typing

I have a text box on a web page, whose value I want to send to a XMLHttpRequest. Now I want the user to just type the value, without pressing a button. But If i just send the request int he keyboard events, it will fire every time a key is pressed.
So basically I want something liek this
function KeyUpEvent()
{
if (user is still typing)
return;
else
//do processing
}
It would be great if the solution could come from plain javascript or mootools. I dont want to use any other library.
The way this is usually done is by restarting a timer on the keyup event. Something like this:
var keyupTimer;
function keyUpEvent(){
clearTimeout(keyupTimer);
keyupTimer = setTimeout(sendInput,1000); // will activate when the user has stopped typing for 1 second
}
function sendInput(){
alert("Do AJAX request");
}
Basically, you want to start a timer on KeyUp, and when KeyUp starts again, reset the timer. When the user stops typing, the timer runs out, and your request can go at that point.
Example:
var timout_id;
function keyup_handler(event) {
if (timout_id) {
clearTimeout(timout_id);
}
timout_id = setTimeout(function(){
alert('sending data: \n' + event.target.value)
}, 800);
}
Just attach the function to the input using your preferred method, and replace the alert with your preferred action.
Of course there are many ways you could generalize this approach and make it more reusable, etc, but I think this illustrates the basic idea.
I always use this simple function to handle a timer, that will fire a callback function, after the user has stopped typing for a specified amount of time:
var typewatch = (function(){
var timer = 0;
return function(callback, ms){
clearTimeout (timer);
timer = setTimeout(callback, ms);
}
})();
Usage (example with MooTools):
$('textInput').addEvent('keyup', function(e){
typewatch(function () {
// executed only 500 ms after the last keyup event
// make Ajax request
}, 500);
});
The main difference between this solution and solutions from other answers is that all the timer logic is handled by the typewatch function itself, the event handler doesn't need to know anything about the timer, it just invokes the function. Also, there are no global variables to take care (the timer id is not stored on a global variable).
You never know when a user is really "finished" typing. The user might take a sneeze break, or a stretch break, or a coffee break, and then continue typing.
However, if you're implementing something like an autocomplete mechanism, you can set a timer (cf. window.setTimeout(...)) to see if the user hasn't typed anything in a certain amount of time. If you get another key-up event while the timer is running, you can start the timer over.
var keyTimer;
function onKeyUp(){
clearTimeout(keyTimer);
setTimeout(stoppedTyping,1500);
}
function stoppedTyping(){
// Profit! $$$
}
EDIT: Damn ninjas
I wrote a custom jQuery event because I use this logic a lot:
jQuery.event.special.stoppedtyping = {
setup: function(data, namespaces) {
jQuery(this).bind('keyup', jQuery.event.special.stoppedtyping.keyuphandler);
},
teardown: function(namespaces) {
jQuery(this).bind('keyup', jQuery.event.special.stoppedtyping.keyuphandler);
},
keyuphandler: function(e) {
var interval = 1000;
var el = this;
if (jQuery.data(this, 'checklastkeypress') != null) {
clearTimeout(jQuery.data(this, 'checklastkeypress'));
}
var id = setTimeout(function() {
jQuery(el).trigger('stoppedtyping');
}, interval);
jQuery.data(this, 'checklastkeypress', id);
}
};
You can use it like this:
$('input.title').bind('stoppedtyping', function() {
// run some ajax save operation
});
For some reason I could never get it to work with .live( ... ). I'm not sure why...
Use onBlur and maybe an onKeyDown to check for the user pressing the return/enter key.

Avoiding a Javascript race condition

My users are presented a basically a stripped down version of a spreadsheet. There are textboxes in each row in the grid. When they change a value in a textbox, I'm performing validation on their input, updating the collection that's driving the grid, and redrawing the subtotals on the page. This is all handled by the OnChange event of each textbox.
When they click the Save button, I'm using the button's OnClick event to perform some final validation on the amounts, and then send their entire input to a web service, saving it.
At least, that's what happens if they tab through the form to the Submit button.
The problem is, if they enter a value, then immediately click the save button, SaveForm() starts executing before UserInputChanged() completes -- a race condition. My code does not use setTimeout, but I'm using it to simulate the sluggish UserInputChanged validation code:
<script>
var amount = null;
var currentControl = null;
function UserInputChanged(control) {
currentControl = control;
// use setTimeout to simulate slow validation code
setTimeout(ValidateAmount, 100);
}
function SaveForm() {
// call web service to save value
document.getElementById("SavedAmount").innerHTML = amount;
}
function ValidateAmount() {
// various validationey functions here
amount = currentControl.value; // save value to collection
document.getElementById("Subtotal").innerHTML = amount;
}
</script>
Amount: <input type="text" onchange="UserInputChanged(this)">
Subtotal: <span id="Subtotal"></span>
<button onclick="SaveForm()">Save</button>
Saved amount: <span id="SavedAmount"></span>
I don't think I can speed up the validation code -- it's pretty lightweight, but apparently, slow enough that code tries to call the web service before the validation is complete.
On my machine, ~95ms is the magic number between whether the validation code executes before the save code begins. This may be higher or lower depending on the users' computer speed.
Does anyone have any ideas how to handle this condition? A coworker suggested using a semaphore while the validation code is running and a busy loop in the save code to wait until the semaphore unlocks - but I'd like to avoid using any sort of busy loop in my code.
Use the semaphore (let's call it StillNeedsValidating). if the SaveForm function sees the StillNeedsValidating semaphore is up, have it activate a second semaphore of its own (which I'll call FormNeedsSaving here) and return. When the validation function finishes, if the FormNeedsSaving semaphore is up, it calls the SaveForm function on its own.
In jankcode;
function UserInputChanged(control) {
StillNeedsValidating = true;
// do validation
StillNeedsValidating = false;
if (FormNeedsSaving) saveForm();
}
function SaveForm() {
if (StillNeedsValidating) { FormNeedsSaving=true; return; }
// call web service to save value
FormNeedsSaving = false;
}
Disable the save button during validation.
Set it to disabled as the first thing validation does, and re-enable it as it finishes.
e.g.
function UserInputChanged(control) {
// --> disable button here --<
currentControl = control;
// use setTimeout to simulate slow validation code (production code does not use setTimeout)
setTimeout("ValidateAmount()", 100);
}
and
function ValidateAmount() {
// various validationey functions here
amount = currentControl.value; // save value to collection
document.getElementById("Subtotal").innerHTML = amount; // update subtotals
// --> enable button here if validation passes --<
}
You'll have to adjust when you remove the setTimeout and make the validation one function, but unless your users have superhuman reflexes, you should be good to go.
I think the timeout is causing your problem... if that's going to be plain code (no asynchronous AJAX calls, timeouts etc) then I don't think that SaveForm will be executed before UserInputChanged completes.
A semaphore or mutex is probably the best way to go, but instead of a busy loop, just use a setTimeout() to simulate a thread sleep. Like this:
busy = false;
function UserInputChanged(control) {
busy = true;
currentControl = control;
// use setTimeout to simulate slow validation code (production code does not use setTimeout)
setTimeout("ValidateAmount()", 100);
}
function SaveForm() {
if(busy)
{
setTimeout("SaveForm()", 10);
return;
}
// call web service to save value
document.getElementById("SavedAmount").innerHTML = amount;
}
function ValidateAmount() {
// various validationey functions here
amount = currentControl.value; // save value to collection
document.getElementById("Subtotal").innerHTML = amount; // update subtotals
busy = false;
}
You could set up a recurring function that monitors the state of the entire grid and raises an event that indicates whether the entire grid is valid or not.
Your 'submit form' button would then enable or disable itself based on that status.
Oh I see a similar response now - that works too, of course.
When working with async data sources you can certainly have race conditions because the JavaScript process thread continues to execute directives that may depend on the data which has not yet returned from the remote data source. That's why we have callback functions.
In your example, the call to the validation code needs to have a callback function that can do something when validation returns.
However, when making something with complicated logic or trying to troubleshoot or enhance an existing series of callbacks, you can go nuts.
That's the reason I created the proto-q library: http://code.google.com/p/proto-q/
Check it out if you do a lot of this type of work.
You don't have a race condition, race conditions can not happen in javascript since javascript is single threaded, so 2 threads can not be interfering with each other.
The example that you give is not a very good example. The setTimeout call will put the called function in a queue in the javascript engine, and run it later. If at that point you click the save button, the setTimeout function will not be called until AFTER the save is completely finished.
What is probably happening in your javascript is that the onClick event is called by the javascript engine before the onChange event is called.
As a hint, keep in mind that javascript is single threaded, unless you use a javascript debugger (firebug, microsoft screipt debugger). Those programs intercept the thread and pause it. From that point on other threads (either via events, setTimeout calls or XMLHttp handlers) can then run, making it seem that javascript can run multiple threads at the same time.

Categories