michelle
michelle

Reputation: 1

javascript, while loop

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

}

Upvotes: 0

Views: 2215

Answers (3)

Sean Vieira
Sean Vieira

Reputation: 159875

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

Upvotes: 0

Ben Zotto
Ben Zotto

Reputation: 71008

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."

Upvotes: 1

Skilldrick
Skilldrick

Reputation: 70819

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.

Upvotes: 3

Related Questions