views:

76

answers:

3

I've built a working page with lots of javascript. The javascript is placed in between the <head></head> tags without a problem, but I really want to move it an external file.

I though I would be able to simply cut and paste all the code minus <script></script> tags but incuding $(document).ready(function() { }); it into a .js file and reference it in the usual way, but it's causing me big headaches. Can anyone suggest why I can't just do this?

As a compromise, I though I would detach at least some of my functions and put them in an external file but there are problems there too.

function look(){
  var word_id = $(this).attr("id");  
  //    Other stuff
  var   value = $(this).val(); 
  //    Other stuff
}

$("input").focus(function(){look();});

In the above function, this is not the this it used to be when the code looked like this:

$("input").focus(function(){
  var word_id = $(this).attr("id");  
  //    Other stuff
  var   value = $(this).val(); 
  //    Other stuff
});

I hope that a really clever person will spot my errors easily. Many thanks, Patrick.

+2  A: 

Try using this code:

$("input").focus(look);

The problem is that when the look function was wrapped with an anonymous function the this pointer inside look was clobbered. Here's a more explicit explanation:

$("input").focus(function() { 
    this; // Refers the DOM element jQuery is acting on
    // The _this_ pointer of the anonymous function is not passed to look.
    look(); // The _this_ pointer in look instead points to the window scope.
});

If for whatever reason you need to wrap a function call with anonymous function, you can use the apply or call to pass the this pointer of the outer scope to look. Here's a quick example:

$("input").focus(function() { 
    ...
    look.apply(this);
    // This works too:
    // look.call(this);
});

The call and apply method are nearly identical. They only difference in how they take parameters. Here's more info on call and apply

Xavi
You are both heros.
Patrick Beardmore
+2  A: 

When you call a function with no context specified, as you are calling look(), the this keyword inside that function will be the global object.

In your case you could only pass a reference to your function, and it will work properly:

$("input").focus(look);

Also, it might be helpful to know that the this keyword is not completely implicit, can be set explicitly by using the call and apply functions:

function test(arg1){
  alert(this + arg1);
}

test.call('hello ', 'world'); // will alert 'hello world'

And that the context (the this keyword) is set implicitly in the following cases:

1- When calling a function that is member of an object, eg.:

obj.myFunc(); // 'this' will refer to obj

2- When calling a function with the new operator:

var test = new Func(); // 'this' will refer to a new object

3- When calling a function not associated with any object:

foo();
// or
(function () {})(); // 'this' will be the global object
CMS
You are both heros.
Patrick Beardmore
A: 

I would advise putting your JS in the footer, so that you can ensure that will be only loaded after everything else on the page (DOM) is fully loaded.

jrutter