Andre
Andre

Reputation: 613

jquery not running from <body>

I'm calling a function that's loaded in custom js file in the header.

<head>

<script type="text/javascript" src="/js/jquery-1.5.min.js"></script> 
<script type="text/javascript" src="/js/my.js"></script>

my.js has

$(document).ready(function(){
    function testFunction(){ 
        alert("inside testfunction");
    }
});

after a few clicks, this is loaded in the <body>:

$("#someid").live($.myapp.event.play, function(event) {
    alert("this works");
    testFunction();
});

the alert "this works", fires, but then nothing happens, what am I doing wrong?

Upvotes: 1

Views: 1189

Answers (2)

chriscauley
chriscauley

Reputation: 20991

It's a scoping issue. When you define variables (or objects, such as a function) in the $(document).ready function they are temporary.

var x = 1;
var y;
$(document).ready(function() {
    var x= 'a billiondy'; //does not affect the global variable
    y=2;
    z=3;
    window.a = 4;
});

At this point window has 3 variables, x, y,and a which are equal to 1,2, and 4 respectively.

Because x is redeclared with var, it is not overwritten (it is a local variable only).

Because y was defined in window, the scope chain finds y and assumes you meant window.y.

Because z was null (never declared) the ready function now declares a local variable. When the ready function closes, z is not referred to in any active scope, so it is garbage collected.

The same thing happens to a, but it is not garbage collected because you explicitly said "this is a window variable". Thus a is defined in the global scope. Got it?

EDIT: That is more of an answer than you wanted, but understanding this is important. At some point you'll ask "why was such and such variable overwritten/undefined". The answer is in the scope chain.

Second edit:

To answer Andre's question (see comments), the following code is invalid:

function testFunction(){ mySecondFunction(); }  //ran first
$(document).ready(function(){ // ran third;
        window.mySecondFunction = function(){alert("this will work");}
    });
testFunction(); // ran second

The reason is that the code inside the ready function is run after everything else is loaded. So when testFunction is run (last line), mySecondFunction is not defined. It's basically the same mistake you'd make if you tried:

function test() { test2() };
function test2() {alert('wtf?')};

Any code not in the ready function gets executed before any code in the ready function. However, any code executed AFTER the the document has loaded (and the ready function has fired) has access to mySecondFunction because it is now defined in the window scope. Consider the following.

function testFunction(){ mySecondFunction(); }
$(document).ready(function(){
        window.mySecondFunction = function(){alert("this will work");}
    });
//testFunction(); erroneous do not uncomment!
$(document).click(function() {testFunction();}); //works fine
//$("body").click(function() {testFunction();}); //does nothing

If you click on the document, you're clicking after the ready function is executed, hence the uncommented line works fine. The line after it does nothing (if this is in the <head> tag) because at this point there is no body, so $("body") returns an empty jquery list. The chronology of javascript is almost as confusing as the scope.

Upvotes: 3

Erin
Erin

Reputation: 2427

Try this.

function testFunction(){ alert("inside testfunction"); }
$(document).ready(function(){

    testFunction();

});

Upvotes: 2

Related Questions