Wait for keypress with timeout - javascript

In an experiment I'm coding, on every trial, I need to display a stimulus (search array) and then wait for a maximum of 5 seconds for the subject to respond with a keypress. If a key is pressed, the next trial begins immediately or else after 5 seconds.
I just want to know if I can code up something like this in JavaScript, and if so, how should I code up the experiment? Also, I should be able to store the identity and timestamp of the key pressed.

The flow of your experiment, as I understood them, are this:
Show Stimulus
Check for keypresses repeatedly
If 5 seconds have passed, show next stimulus
If key was pressed, store keypress in array, then show next stimulus.
To do this, I would use Keypress, a JS library for catching input.
You would first want to define your stimuli
E.g.:
var stimuli = ["Apple","Orange","Keira Knightley","Banana"];
You would then want to set up your event listeners. These will log your keypresses for you.
var listener = new window.keypress.Listener();
var results = [];
listener.simple_combo("shift s", function() {
results.push("You pressed shift and s");
});
Then you want to set up the timing system. I would use a setInterval() function to increment the position in the array that the subject is in.
var pos = -1; //Arrays start at 0, and you want to run this function to start.
function nextStim() {
pos = pos + 1;
myDiv.innerHTML = stimuli[pos]
}
var results = [];
listener.simple_combo("shift s", function() {
results.push("The stimulus was: " + stimuli[pos] + "And you pressed Shift + S" );
});
setInterval(nextStim,5000);

<script>
var timeout;
timeout = setTimeout(next, 5000); //execute function "next" after 5000 miliseconds
//With jQuery
//$("#element").on("keypress", function(){ clearTimeout(timeout); next();} );
//Without jQuery
function elementOnKeypress()
{
clearTimeout(timeout); //don't execute "next" after 5000 (or less) ms
next(); //run "next"
}
function next()
{
//your code ..
}
</script>
<element onkeypress="elementOnKeypress();"></element><!-- element is your html-element to be keypressed -->

Related

setTimeout function if user not active

I can do something such as the following every 30 seconds to reload the page, and the backend logic will determine which session have been invalidated:
setInterval(function () {
location.reload()
}, 30000);
However, how would I only run this 30s location.reload() if the user is not active? For example, how banks will have a user-timeout if the user has not been active on the page (which only starts counting after the user is 'inactive'). How would this be done?
One way is to track mousemoves. If the user has taken focus away from the page, or lost interest, there will usually be no mouse activity:
(function() {
var lastMove = Date.now();
document.onmousemove = function() {
lastMove = Date.now();
}
setInterval(function() {
var diff = Date.now() - lastMove;
if (diff > 1000) {
console.log('Inactive for ' + diff + ' ms');
}
}, 1000);
}());
First define what "active" means. "Active" means probably, sending a mouse click and a keystroke.
Then, design your own handler for these situations, something like this:
// Reseting the reload timer
MyActivityWatchdog.prototype.resetReloadTimer = function(event) {
var reloadTimeInterval = 30000;
var timerId = null;
...
if (timerId) {
window.clearInterval(timerId);
}
timerId = window.setInterval( reload... , reloadTimeInterval);
...
};
Then, make sure the necessary event handler will call resetReloadTimer(). For that, you have to look what your software already does. Are there key press handlers? Are there mouse movement handlers? Without knowing your code, registering keypress or mousemove on document or window and could be a good start:
window.onmousemove = function() {
...
activityWatchdog.resetReloadTimer();
...
};
But like this, be prepared that child elements like buttons etc. won't fire the event, and that there are already different event handlers. The compromise will be finding a good set of elements with registered handlers that makes sure "active" will be recognized. E.g. if you have a big rich text editor in your application, it may be enough to register only there. So maybe you can just add the call to resetReloadTimer() to the code there.
To solve the problem, use window blur and focus, if the person is not there for 30 seconds ,it will go in the else condition otherwise it will reload the page .
setTimeout(function(){
$(window).on("blur focus", function(e) {
var prevType = $(this).data("prevType");
if (prevType != e.type) { // reduce double fire issues
switch (e.type) {
case "blur":
$('div').text("user is not active on page ");
break;
case "focus":
location.reload()
break;
}
}
$(this).data("prevType", e.type);
})},30000);
DEMO : http://jsfiddle.net/rpawdg6w/2/
You can check user Session in a background , for example send AJAX call every 30 - 60 seconds. And if AJAX's response will be insufficient (e.g. Session expired) then you can reload the page.
var timer;
function checkSession() {
$.ajax({
url : 'checksession.php',
success: function(response) {
if (response == false) {
location.reload();
}
}
});
clearTimeout(timer);
timer = setTimeout(checkSession,30 * 1000);
}
checkSession();

how can I rearrange this code so my setInterval stops looping infinitely?

I'm trying to make a simple flip-card/memory match (like from super mario brothers 3) game in HTML/Javascript and am having a slight issue with the setInterval command.
Here is a link to the full code: http://jsfiddle.net/msfZj/
Here is the main issue/main logic of it:
if(click == 2) //denotes two cards being clicked
{
if(flippedArray[1].src === flippedArray[0].src) // if click 1 == click 2 then refer to function 'delayMatch' which sets click 1 and 2 cards to not be displayed
{
window.setInterval(function() { delayMatch() }, 500);
console.log("EQUAL");
}
else
{
window.setInterval(function() { delayNoMatch() }, 500); // if click 1 != click 2 then display card.png
console.log("NOT EQUAL");
}
function delayMatch() //function for matching pairs
{
flippedArray[0].style = "display:none;";
flippedArray[1].style = "display:none;";
}
function delayNoMatch() //function for non-matching pairs
{
flippedArray[0].src = "card.png";
flippedArray[1].src = "card.png";
}
click = 0; // when clicked two cards set click back to zero
}
The first two cards I click on always work: but from that point onward the setInterval keeps running the function over and over again in an endless loop every 500ms.
I'd be extremely appreciative if anybody can point my in the right direction on how I can do this properly.
Thank you very much for your time.
It looks like you need setTimeout, which only runs once?
window.setTimeout(function() { delayMatch() }, 500);
Otherwise, you need to clear the interval with clearInterval(i), but first set "i" using the return value of setInterval:
var i = window.setInterval(function() { delayMatch() }, 500);
Here's a demo (I JQuerified it a bit for JSFiddle).
You're going to want to go with setTimeout() instead of setInterval()
A handy function when you use setTimeout is clearTimeout. Say you want to set a timer, but maybe want a button to cancel
var timer = setTimeout(fn,1000);
//later maybe
clearTimeout(timer);

function is looped according to setinterval but with different parameters

i have a simple question, there is a function with parameter emp_id that opens up a form for a chat with different attributes, i want it to be refreshed automatically each 10 sec, now it works a bit wrongly, since there is a parameter emp_id that is can be changed, and once i change it, the chat with messages and form are refreshed double time or triple times :) depend on how many times u change the emp_id, i hope i was clear )) anyway here is the javascript function:
function load_chat(emp_id) {
var url = "#request.self#?fuseaction=objects2.popup_list_chatform"
url = url + "&employee_id=" + emp_id;
document.getElementById('form_div').style.display = 'block'; AjaxPageLoad(url,'form_div',1,'Yükleniyor');
setInterval( function() {
load_chat(emp_id);
},10000);
}
there a list of names, once i click on one of them, this form is opened by this function, but if i click another user, i mean if i change the emp_id, it refreshes, the previous and present form. how do i change it so that it will refresh only the last emp_id, but not all of id's which i've changed
thank you all for the help, i really appreciate it!
This would nicely encapsulate what you're doing. The timer id (tid) is kept inside the closure, so when you call load_chat it will stop the interval if there was one running.
Once the new url is set up, it will start the interval timer again.
var ChatModule = (function() {
var tid,
url;
function refresh()
{
AjaxPageLoad(url, 'form_div', 1, 'Yükleniyor');
}
return {
load_chat: function(emp_id) {
if (tid) {
clearInterval(tid);
}
// setup url
url = "#request.self#?fuseaction=objects2.popup_list_chatform"
url = url + "&employee_id=" + emp_id;
document.getElementById('form_div').style.display = 'block';
// load ajax
refresh();
// set timer
tid = setInterval(refresh, 10000);
}
}
}());
ChatModule.load_chat(123);
Use setTimeout instead. Each time your function is executed, it will set up the next execution (you could also make it conditional):
function load_chat(emp_id) {
... // do something
if (condition_still_met)
setTimeout(function() {
load_chat(emp_id); // with same id
}, 10000);
}
load_chat("x"); // to start
Or you will have to use setInterval outside the load_chat function. You can clear the interval when necessary.
function get_chat_loader(emp_id) {
return function() {
... // do something
};
}
var id = setInterval(get_chat_loader("x"), 10000); // start
// then, somewhen later:
clearInterval(id);

calling a function in javascript after a period of time has passed

I'm trying to write a function that will auto suggest what the user means when they type into an input field. Right now I have all of the auto suggest code complete but in my javascript I can't get to the first if in toggleGenusInput no matter what I do (this first if queries the database through php and gets the suggestions).
Does anyone know how I could modify my code so that if something is typed in the input field and is not changed after 2 seconds it will enter that first if? Thanks.
Here are my script globals:
var time = new Date();
var timeout = 2000; //query db every 2 seconds of not typing anything
var autoSuggest = true;
var lastQueryTyped = "";
var queryTypedAt = time.getTime(); //what time the last new text was entered
Here's the function that's connected to an input node's onfocus method:
function toggleGenusInput(inputNode) {
if(autoSuggest) {
if((time.getTime() - queryTypedAt) >= timeout && inputNode.value == lastQueryTyped) {
//the input has not changed and it's reached the timeout time, requery the db
responseDoc = getXMLFrom("getsimilaritems.php?query=" + inputNode.value);
if(queryFindsSuggestions(responseDoc)) {
cleanUpSuggestions();
appendSuggestions(inputNode, responseDoc);
}
}
else if(inputNode.value != lastQueryTyped) {
//something new was entered so update the time and what was put in
lastQueryTyped = inputNode.value;
queryTypedAt = time.getTime();
}
}
}
And here's the html object that function is attached to:
<input type="text" name="autoSuggestInput" onfocus="toggleGenusInput(document.myForm.autoSuggestInput)" />
You could use setTimeout and bind the handler to the keyup event instead:
function toggleGenusInput(inputNode) {
if(autoSuggest) {
if(_timeout) {
clearTimeout(_timeout);
}
_timeout = setTimeout(function() {
//the input has not changed and it's reached the timeout time, requery the db
responseDoc = getXMLFrom("getsimilaritems.php?query=" + inputNode.value);
if(queryFindsSuggestions(responseDoc)) {
cleanUpSuggestions();
appendSuggestions(inputNode, responseDoc);
}
}, 2000);
}
}
and
<input type="text" name="autoSuggestInput" onkeyup="toggleGenusInput(document.myForm.autoSuggestInput)" />
Now whenever a key is pressed (not on focus), your function will be called and wait a certain time to execute the functionality. If another timeout is running, it will be canceled first (otherwise you would keep creating timeouts over and over again while the user inserts text which would lead to strange results).

Jquery ajax live validation / timeout question

I'm still kindof new to jQuery, so there probably is an easy solution, but I can't find anything.
I've made this registration form, that checks if the username or email is taken as the user is typing in the username. Basically it just makes a json request that returns true or false depending on if the username / email is already taken.
The problem is, that now it makes a request on basically every keypress that the user makes while focused on the field if the input text is more than 3 characters long. For now, that works, but that's a lot of server requests. I'd like it to make a request only when the user has not typed for, say, a half second.
Any ideas on how I might be able to do that ?
$(document).ready(function() {
$("#user_username").keyup(function () {
var ln = $(this).val().length;
if (ln > 3) {
$.getJSON("/validate/username/",
{value:$(this).val()},
function(data){
if (data.reg == true) {
$("#status-for-username").html("Username already in use");
} else {
$("#status-for-username").html("Username available");
}
});
}
});
$("#user_email").keyup(function () {
var ln = $(this).val().length;
if (ln > 3) {
$.getJSON("/validate/email/",
{value:$(this).val()},
function(data){
if (data.reg == true) {
$("#status-for-email").html("E-mail already in use");
} else {
$("#status-for-email").html("");
}
});
}
});
});
For waiting an amount of time since the last keystroke, you could do something like the jQuery.typeWatch plugin does.
Here I post you a light implementation of the concept:
Usage:
$("#user_username").keyup(function () {
typewatch(function () {
// executed only 500 ms after the last keyup event.
}, 500);
Implementation:
var typewatch = function(){
var timer = 0; // store the timer id
return function(callback, ms){
clearTimeout (timer); // if the function is called before the timeout
timer = setTimeout(callback, ms); // clear the timer and start it over
}
}();
StackOverflow uses the plugin I mention, for syntax coloring the code on edition.
You can use window.setTimeout and window.clearTimeout. Basically trigger a function to invoke in x milliseconds and if another keypress event is fired beforehand then you clear that handler and start a new one.
//timeout var
var timer;
$('#username').keyUp( function(){
//clear any existing timer
window.clearTimeout( timer );
//invoke check password function in 0.5 seconds
timer = window.setTimeout( checkPasswordFunc, 500 );
});
function checkPasswordFunc(){
//ajax call goes here
}

Categories