Hello and welcome to our community! Is this your first visit?
Register
Enjoy an ad free experience by logging in. Not a member yet? Register.
Results 1 to 13 of 13
  1. #1
    Regular Coder Apothem's Avatar
    Join Date
    Mar 2008
    Posts
    380
    Thanks
    36
    Thanked 25 Times in 25 Posts

    "this" confusion

    I'm confused on how "this" works visavi jQuery bindings.

    function Foo()
    {
    this.stuff = 0;
    this.callback = function()
    {
    $(this).attr('src', '...'+this.stuff);
    };
    $('#image_id').load( this.callback );
    }

    For $("#image_id")... will the callback method be called?
    For the callback method, will using "$(this)" act as if it was "$("#image_id")"? If so, how does the method know the difference between the image's "this" and the object's "this"? (to be exact, will it be able to access "this.stuff")

  • #2
    Senior Coder
    Join Date
    Jul 2005
    Location
    New York, NY
    Posts
    1,084
    Thanks
    4
    Thanked 19 Times in 19 Posts
    This is resolved at runtime. It refers to the running context. If you attach your callback function to 25 objects and then call each of them from those objects, this will resolve 25 times to 25 difference referents.

  • #3
    Regular Coder Apothem's Avatar
    Join Date
    Mar 2008
    Posts
    380
    Thanks
    36
    Thanked 25 Times in 25 Posts
    So basically, this.stuff would in fact output its setted value (0) and $(this) would also work? What if I called another method within the callback method? Could I still use $(this) to refer back to the $("#image_id")?

  • #4
    Senior Coder
    Join Date
    Jul 2005
    Location
    New York, NY
    Posts
    1,084
    Thanks
    4
    Thanked 19 Times in 19 Posts
    You'll have to do some basic experimentation. I'm not going to be able to answer that confidently without writing some test code first. Make a hypothesis, code an experiment, check the results. If you can't figure out why something works or doesn't work, post the code and ask your questions then.

    But try it first.

  • #5
    Regular Coder Apothem's Avatar
    Join Date
    Mar 2008
    Posts
    380
    Thanks
    36
    Thanked 25 Times in 25 Posts
    First:
    Code:
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    	"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 
    	<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> 
    	<head> 
    		<meta http-equiv="content-type" content="text/html; charset=utf-8" /> 
    		<title>TEst</title> 
    		<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"></script> 
    		<script>
    (function ($) {
    
    $.event.special.load = {
    	setup: function(data, namespaces, hollaback) {
    		var retVal = false;
    		
    		if (this.tagName.toLowerCase() === 'img' && this.src !== "") {
    			// Image is already complete, fire the hollaback (fixes browser issues were cached
    			// images isn't triggering the load event)
    			if (this.complete || this.readyState === 4) {
    				$(this).bind('load', data || {}, hollaback).trigger('load');
    				retVal = true;
    			}
    			
    			// Check if data URI images is supported, fire 'error' event if not
    			else if (this.readyState === 'uninitialized' && this.src.indexOf('data:') >= 0) {
    				$(this).trigger('error');
    				retVal = true;
    			}
    		}
    		
    		return retVal;
    	}
    }
    
    }(jQuery));
    
    		$(document).ready(function()
    		{
    			function Foo()
    			{
    				this.stuff = 0;
    				this.callback = function()
    				{
    					//$(this).attr('title', '...'+this.stuff);
    				};
    				alert('foo');
    				$('#image_id').bind( 'load', function(){alert('bar');} );
    			}
    			
    			var f = new Foo();
    		});
    		</script>
    	</head> 
    	<body> 
    		<img src="http://codingforums.com/image.php?u=60583&dateline=1260771715" id="image_id" />
    	</body> 
    </html>
    For some reason in FF 3.6.x, only the first alert pops up and nothing else.
    Last edited by Apothem; 07-06-2010 at 10:17 PM.

  • #6
    Senior Coder
    Join Date
    Jul 2005
    Location
    New York, NY
    Posts
    1,084
    Thanks
    4
    Thanked 19 Times in 19 Posts
    FF is throwing a "too much recursion" error inside the jQuery library. I'm reviewing the code locally now.

  • #7
    Senior Coder
    Join Date
    Jul 2005
    Location
    New York, NY
    Posts
    1,084
    Thanks
    4
    Thanked 19 Times in 19 Posts
    change the alert('bar') event from 'load' to 'click' to get this working for testing purposes. I'm not interested in figuring out why the 'load' event is causing problems.

  • #8
    Regular Coder Apothem's Avatar
    Join Date
    Mar 2008
    Posts
    380
    Thanks
    36
    Thanked 25 Times in 25 Posts
    Well, for my personal project I actually do need an image to complete loading to activate a function. But I will do it for testing purposes.

    Regardless, I still need to know what is wrong.

    Edit: So I tested it, and this.stuff doesn't work. How can I make it work?
    Last edited by Apothem; 07-06-2010 at 11:52 PM.

  • #9
    Senior Coder
    Join Date
    Jul 2005
    Location
    New York, NY
    Posts
    1,084
    Thanks
    4
    Thanked 19 Times in 19 Posts
    Paste the code that doesn't work please.

  • #10
    Regular Coder Apothem's Avatar
    Join Date
    Mar 2008
    Posts
    380
    Thanks
    36
    Thanked 25 Times in 25 Posts
    Code:
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    	"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 
    	<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> 
    	<head> 
    		<meta http-equiv="content-type" content="text/html; charset=utf-8" /> 
    		<title>TEst</title> 
    		<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"></script> 
    		<script>
    (function ($) {
    
    $.event.special.load = {
    	setup: function(data, namespaces, hollaback) {
    		var retVal = false;
    		
    		if (this.tagName.toLowerCase() === 'img' && this.src !== "") {
    			// Image is already complete, fire the hollaback (fixes browser issues were cached
    			// images isn't triggering the load event)
    			if (this.complete || this.readyState === 4) {
    				$(this).bind('load', data || {}, hollaback).trigger('load');
    				retVal = true;
    			}
    			
    			// Check if data URI images is supported, fire 'error' event if not
    			else if (this.readyState === 'uninitialized' && this.src.indexOf('data:') >= 0) {
    				$(this).trigger('error');
    				retVal = true;
    			}
    		}
    		
    		return retVal;
    	}
    }
    
    }(jQuery));
    
    		$(document).ready(function()
    		{
    			function Foo()
    			{
    				this.stuff = 0;
    				this.callback = function()
    				{
    					$(this).attr('title', '...'+this.stuff);
    				};
    				//alert('foo');
    				$('#image_id').click( this.callback );
    			}
    			
    			var f = new Foo();
    		});
    		</script>
    	</head> 
    	<body> 
    		<img src="http://codingforums.com/image.php?u=60583&dateline=1260771715" id="image_id" />
    	</body> 
    </html>
    $(this).attr('title', '...'+this.stuff); results in the title "...undefined". I expected it to become "...0"

  • #11
    Senior Coder
    Join Date
    Jul 2005
    Location
    New York, NY
    Posts
    1,084
    Thanks
    4
    Thanked 19 Times in 19 Posts
    Right. So, as I said, this is resolved at runtime, let's try to figure out what the means.
    Code:
    function Foo() {
        this.stuff = 0;
        this.callback = function() {
            $(this).attr('title', '...'+this.stuff);
        };
        $('#image_id').click( this.callback );
    }
    			
    var f = new Foo();
    So, Foo() is executing. It defines stuff and callback in the current scope. Then it assigns callback to the click handler.

    Now, you have an issue. When callback is called, the running scope is different, so this is not the same as the defining context, hence stuff does not exist in it. How do we fix that? Well, one way is to make sure we always have a reference to the defining scope:
    Code:
    function Foo() {
        this.stuff = 0;
        var parent = this;
        this.callback = function() {
            $(this).attr('title', '...'+parent.stuff);
        };
        $('#image_id').click( this.callback );
    }
    			
    var f = new Foo();
    or, by not using the this keyword when defining the variables:
    Code:
    function Foo() {
        stuff = 0;
        this.callback = function() {
            $(this).attr('title', '...'+stuff);
        };
        $('#image_id').click( this.callback );
    }
    			
    var f = new Foo();
    Both of these techniques work. You can even drop the this regarding callback since callback isn't directly referred to by name outside of it's defining scope.

    Hope that helps!

  • #12
    Regular Coder Apothem's Avatar
    Join Date
    Mar 2008
    Posts
    380
    Thanks
    36
    Thanked 25 Times in 25 Posts
    Wait I thought that if you don't do this.var that means it is a global variable. I don't want a global variable; I want an object element so that multiple constructions can be made.

  • #13
    Senior Coder
    Join Date
    Jul 2005
    Location
    New York, NY
    Posts
    1,084
    Thanks
    4
    Thanked 19 Times in 19 Posts
    Quote Originally Posted by Apothem View Post
    Wait I thought that if you don't do this.var that means it is a global variable. I don't want a global variable; I want an object element so that multiple constructions can be made.
    No. If you define a var inside a function, it's local.
    Code:
    function a_x() {
      var x = 'x';
      alert(x);
    }
    
    a_x(); // 'x'
    
    alert(x); // undef


  •  

    Posting Permissions

    • You may not post new threads
    • You may not post replies
    • You may not post attachments
    • You may not edit your posts
    •