check123
check123

Reputation: 2009

jQuery variable always evaluates to 'undefined'

I am trying something like:

var usernameDone = false;
/*Some application logic*/
alert(usernameDone);

This is always evaluating to undefined. However, if I change the variable name from usernameDone to anything else, even usrnameDone, the script works fine. Does usernameDone conflict with jQuery? If not, then why does it happen?

(I am testing on Chrome with jQuery-1.6.1 currently and have not tried other browsers.)

[Update]
The variable evaluates to undefined even if the application logic is eliminated.

[Update-2 The full code]
I have marked the usage using // comments

 $('document').ready( function() {

/**
 * The following set manages the effects for the login menu. The effects including highlighting
 * the login box when focused, showing guidance through a pop-up menu and handling transformation
 * through fade effects.
 * 
 */
var usernameDone = false;      //Declared here
/**
 * @function login-box focus()
 * Handles the onFocus() effects of the login box and displays the initial guidance pop-up box.
 * 
 */

$('#login-box').focus( function() {

/**
 * Color change effect of the login box
 */

    $(this).css('background-color' , '#000');
    $(this).css('color' , '#FFF');
    $(this).css('border' , '2px solid #000');

/**
 * Fade in effect of the login guide
 */

    $('#login-guide').fadeIn(1200);
    $('#login-guide-triangle').fadeIn(1200);

});


/**
 * @function login-box focusout()
 * Handles the focusOut effects of the login box and hides the guidance pop-up box.
 * 
 */

$('#login-box').focusout( function() {

/**
 * Color change effects of the login box
 */

    $(this).css('background-color' , '#FFF');
    $(this).css('color' , '#000');
    $(this).css('border' , '3px solid #000');

/**
 * Fade out effect of the login guide
 */

    $('#login-guide').fadeOut(1200);
    $('#login-guide-triangle').fadeOut(1200);
});

/**
 * @function login-box bind(keypress)
 * Handles the progression of the login steps. Specifically, what state the login box is in 
 * (ie, username or password) and how to respond when the state change key ('return/enter key')
 * is pressed.
 * 
 */

$('#login-box').bind('keypress' , function(e) {
/**
 * Checks for the current state (using usernameDone) if not, then registers the current username
 * changes the state to username done and converts the login box into password. Also, changes the
 * guidance contents.
 */
    alert(usernameDone);    //Always undefined (no modification before this)
    if(e.keyCode == 13 && usernameDone == false) {    //Owing to undefined it never evaluates to true.
        var loginUsername = $(this).val();
        $(this).val('');
        var usernameDone = true;
        $(this).fadeOut(0);
        document.getElementById('login-box').setAttribute('type' , 'password');
        $('#login-guide-title').html('Password');
        $('#login-guide-info').html('Press enter to login');
        $(this).fadeIn(800);
    }
});

});

Upvotes: 0

Views: 3969

Answers (6)

brymck
brymck

Reputation: 7663

Two things:

  1. usernameDone will be defined when your <document> tags are fully loaded. On the off-chance those don't exist, you want $(document).ready().
  2. Where are you trying to access usernameDone? I don't see an alert function in your example, so I can only assume you're trying to access it outside of $(document).ready(). That won't work. If you want that functionality, declare var usernameDone outside of that function block.

The following examples work just fine:

$(document).ready(function() {
  var usernameDone = false;
  alert(usernameDone);
});

and

var usernameDone;

function testMe() {
  alert(usernameDone);
}

$(document).ready(function() {
  usernameDone = false;
  testMe();
});

Upvotes: 0

Mutation Person
Mutation Person

Reputation: 30498

Some explanation is required here:

Douglas Crockford recomends that you declare all your JavaScript variables at the top of your nearest scope, because that's what effect Javascript does when it interprets the code.

This is a term known as 'hoisting'.

This is a perfect example of the confusion that can be caused by not doing this and why his JSLint tool highlights this.

You nearest scope is the function immediately above. JavaScript does not have 'block' scope, the if block does not define any local scope.

So in you example, the declaration is effectively moved to the top of the function, and the assinment made later (where you do it). This means that the variable is, in fact, undefined at the point you check it, as it overloads the one declared in the scope above.

Upvotes: 1

Emil
Emil

Reputation: 8527

You are re-declaring the variable in the last if statement. Since the second declaration happens inside a child scope (function), but after the alert is called, the javascript parser is waiting for the new value to be assigned, and until then it is undefined.

If you remove the var, you will be fine.

Upvotes: 1

Gabriele Petrioli
Gabriele Petrioli

Reputation: 195992

The problem lies at

    var loginUsername = $(this).val(); 
    $(this).val('');
    var usernameDone = true;  // <-- PROBLEM HERE

You re-define the variable inside the keypress method.. so it is undefined..

remove the var part

usernameDone = true;

and you will be fine..

demo http://jsfiddle.net/gaby/3CrZG/1/

Upvotes: 1

Dr.Molle
Dr.Molle

Reputation: 117334

remove the var when assigning the value inside the function, the var makes the variable private.

Upvotes: 2

Shef
Shef

Reputation: 45589

Of course it is going to be undefined, because you listen for a ready event on the string 'document' not on the variable document. Do NOT enclose the variable document with single or double quotes, otherwise the ready event will never fire, hence why your variable is never defined. Also, do not re-declare the variable usernameDone with var usernameDone = true;, just assign a value to it like this usernameDone = true;, because it is already defined.

Upvotes: 7

Related Questions