views:

75

answers:

3

i'm trying to get my script to wait for user input (click of a button) before continuing, this is v feasible in other languages, but seems impossible in js. basically, i want the user to select an option within a given time frame, if the user selects the wrong option, they're told..script then conts...otherwise, if after a certain amount of time theres no response...script just continues again sowing them the correct ans, but there seems to be nothing in js to make the script wait for that user input! ive tried a while loop, but that is just a big no no in js, ive used settimeout but has no real effect because the script just continues like normal then performs an action after x amount of time, ive tried setting variables and letting the script cont only if it is of a particular value, which is set only if the user clicks...eg var proceed=false, this is only set to true if the user clicks a button, but it still doesn't work... ive tried sooo many other solutions but nothing actually seems to be working. i like the idea of a while loop, because it doeas exactly what i want it to so, but if completly freezes my browser, is there a more effecient type of loop that will will peroform in the same manner with crashing my browser?

heres my code below that compltely freezes my computer. this method is called within a for loop which calls another method after it.

function getUserResp(){
    $("#countdown").countdown({seconds: 15});
    setTimeout("proceed=true", 16000);

    $("#ans1").click(function(){
        ansStr=$(this).text();
        checkAns(ansStr);
     });    
    $("#ans2").click(function(){
        ansStr=$(this).text();
        checkAns(ansStr);
    });    
    $("#ans3").click(function(){
        ansStr=$(this).text();
        checkAns(ansStr);
        });

would like something like this.....or just some sort of loop to make the script wait before going ahead so at least it gives the user some time to respond rather than running straight though!

    do{
    $(".ans").mouseover(function(){
        $(this).addClass("hilite").fadeIn(800);
        });  

    $(".ans").mouseout(function(){
        $(this).removeClass("hilite");
        });

    }while(proceed==false);

}
+3  A: 

You're doing it wrong.

JavaScript in the browser uses an event-driven model. There's no main function, just callbacks that are called when an event happens (such as document ready or anchor clicked). If you want something to happen after a user clicks something, then put a listener on that thing.

What you've done just keeps adding an event listener every time round the loop.

If you want to wait for user input then just don't do anything - the browser waits for user input (it's got an internal event loop). The worst thing you can do is try to reimplement your own event loop on top of the browser's.

You need to learn JavaScript. Trying to write JavaScript like you would another language only leads to pain and suffering. Seriously.

Douglas Crockford said it best:

JavaScript is a language that most people don’t bother to learn before they use. You can’t do that with any other language, and you shouldn’t want to, and you shouldn’t do that with this language either. Programming is a serious business, and you should have good knowledge about what you’re doing, but most people feel that they ought to be able to program in this language without any knowledge at all, and it still works. It’s because the language has enormous expressive power, and that’s not by accident.

Skilldrick
could you elaborate? sorry, am new to javascript
michelle
i tried the do while loop thing only once, just as an alternative, but what i really want the program to do is wait 16 seconds to at least give the user a chance to respond. there are other methods called after this one, so even using setTimeout, doesnt make a difference becure it still runs straight through, and then settimeout performs what it was supposed to after x amount of time. ie setTimeout didnt work. i did do nothing with the script as suggested which is how i first wrote it, but there was nothing to make the program ask has the user clciked or has the time run out? ....
michelle
...which is when i thought maybe implmenting the while loop to check for that may be a good idea, so to do that i introduced the variable proceed=false, which is only set true by clicking on one of the ans. the while loop would heck to see if it is true or false and if true the next method could be called appriately, but the while loop crashes my browser
michelle
I **REALLY** think you should spend some time learning JavaScript before you try to do anything like this. It'll pay off, I promise.
Skilldrick
guys i really appreciate your advice, i just want a short example of what you are talking about, because like you said i should learn the language (although ive spent a fair amount of time and money reading up) but cant know what to do if i dont know where to start. a short example would be most appreciated. thank you.
michelle
+1  A: 

You can't block the Javascript from running in the same way that you can in some other imperative languages. There's only one thread for Javascript in the browser, so if you hang it in a loop, nothing else can happen.

You must use asynchronous, event-driven programming. Setting a click handler (or whatever) combined with a timeout is the right way to start. Start a 15 second setTimeout. Inside the click handler for the answers, cancel the timeout. This way the timeout's handler only happens if the user doesn't click an answer.

For example:

var mytimeout = setTimeout(15000, function() {
    // This is an anonymous function that will be called when the timer goes off.
    alert("You didn't answer in time.");
    // Remove the answer so the user can't click it anymore, etc...
    $('#ans').hide();
});

$('#ans').click(function() {
    // Clear the timeout, so it will never fire the function above.
    clearTimeout(mytimeout);
    alert("You picked an answer!");
});

See how the code must be structured such that it's event-driven. There's no way to structure it to say "do this thing, and wait here for an answer."

quixoto
thank you for your answer, am new to javascript, do you think you could give a quick example, just so i have an idea. thank you so much for the message posted already
michelle
hi quixoto...didnt understand what your were saying at first..but i had already implemented that in my code as below:function checkAns(check){ clearTimeout(); if(check==cAns){ checkAns=true;} else{ checkAns=false;}}is that what you meant?the only problem is js will set the time out but will still follow through with the rest of the code, because i dont have anything that for the response it runs straight through regardless of whether a button has been clicked. i guess this what am asking, how do i make the code wait for 15s or so before continuing?
michelle
@michelle: I added some example code that I hope makes this clearer.
quixoto
thanks for the response although set timeout will be set the function will only be called when the timer goes off, but there nothing it seems in js that says lets wait/sleep for 15s before we continue with the rest of the sript unless a user clciks ie 'lets give the user 15seconds to respond' if a button is clciked , we'll check that ans. settimeout only calls a function after a certain amount of time, but i does not mean to say the script wont still cont to run. in effect im looking for something that will do nothing more or less for 15s.....
michelle
....(in effect a pause which doesnt freeze the screen) all settimeout will do is call a function after 15s but the scrit will still continue to run and other functions will be performed before those 15s are over
michelle
@michelle: If you want to sleep for 15s, then do a setTimeout for 15 seconds, and for its handler, put the *rest of the code* that should continue operating. Don't have anything else in "the rest of the script", and that way nothing will "continue to run" until the 15s timer fires. (Frankly, if this doesn't make sense to you, you need to spend more time with tutorials or in-person courses. We're reaching the pedagogical limits of Stack Overflow here.)
quixoto
am not stupid, just new to js, you've helped and given examples, most appreciated but no need to be rude!
michelle
@michelle: Sorry, i wasn't intending to be rude. It was starting to seem as though you might have been tackling a problem without having the foundation for it. Apologies if I misread that.
quixoto
A: 

You're looking at client-side javascript as if it wasn't already in an event-driven loop. All you need to do is wait for the appropriate event to happen, and if it hasn't happened yet, continue to wait, or else perform some default action.

You don't need to:

create main loop: // All
    wait for user input // Of
        timer = start_timer() // This
        // Is done for you
        if [user has input data]: 
            process_data()
        else if [timer > allowed_time]:
            process_no_data()
        else:
            wait() // By the Browser

You only need the middle part. All you need to do is (Actual javascript follows, not pseudo-code):

// First, store all of the answer sections, 
// so you're not grabbing them every time 
// you need to check them.
var answers = {};
answers.ans1 = $("#ans1");
answers.ans2 = $("#ans2");
answers.ans3 = $("#ans3");

// This is a flag.  We'll use it to check whether we:
//    A. Have waited for 16 seconds
//    B. Have correct user input
var clear_to_proceed = false;
var timer_id;

// Now we need to set up a function to check the answers.    
function check_answers() {
    if ( ! clear_to_proceed ) {
        clear_to_proceed = checkAns(answers.ans1.text());
        clear_to_proceed = checkAns(answers.ans2.text());
        clear_to_proceed = checkAns(answers.ans3.text());
        // I assume checkAns returns
        // true if the answer is correct
        // and false if it is wrong
    } 
    if ( clear_to_proceed ) {
        clearTimeout(timer_id);
        return true; // Or do whatever needs be done, 
                     // as the client has answered correctly
    } else {
        // If we haven't set a timer yet, set one
        if ( typeof timer_id === 'undefined' ) {
            timer_id = setTimeout(function(){
                        // After 16 seconds have passed we'll check their
                        // answers one more time and then force the default.
                        check_answers();
                        clear_to_proceed = true;
                        check_answers(); 
                    }, 16000);
        }
        return false; // We're just waiting for now.
    }
}
// Finally, we check the answers any time the user interact
// with the answer elements.
$("#ans1,#ans2,#ans3").bind("focus blur", function() {
    check_answers();
});
Sean Vieira