Sunday, May 1, 2011

I need help with the $(this) context in jQuery

I need some help in this code block:

options.imgs.click(function() {
      var allImgs = $("#big img");
      $("#big img").each(function(n) {
       this.index = n;
      })
      animateImage(allImgs);
     })

    };

    function animateImage(images) {
     for(var i = 0; i < images.length; i++) {
      if (images[i].index == 0) {
       alert($(this).index)
      }
     }
    }

My problem is:

$(this).effect('scale', { percent: 200 }, 1000)

Isn't working. I want that statement to refer to the image with the index of 0, and scale it 200%. But $(this) isn't referring to the first image at all.

From stackoverflow
  • As soon as you call your function your "this" variable is changed:

    function test() {
      alert(this); // this will be the window object
    }
    $('p b').click(function() {
       alert(this); // this will be the bold element object
       test();
    });
    

    For example, running this against this page (using firebug), I can click on the "asked" and "viewed" items on the right at the top (they are bolded)... And what you get back is an alert from the test function where this is the window object, not the bold element as it is in the event handler.

    To fix this, just pass the object you would like to work on through the function:

    options.imgs.click(function() {
                var allImgs = $("#big img");
                $("#big img").each(function(n) {
                        this.index = n;
                })
                animateImage(allImgs, this);
        })
    
    };
    
    function animateImage(images, img) {
        for(var i = 0; i < images.length; i++) {
                if (images[i].index == 0) {
                        alert($(img).index)
                }
        }
    }
    
    Keira Nighly : Thanks altCognito
  • See Call function with “this”.

    Basically what you want is to replace

    animateImage(allImgs);
    

    with

    animateImage.call(this, allImgs);
    


    You can refactor your code into this (or something similar):

    options.imgs.click(function() {
        var allImgs = $("#big img");
        allImgs.each(function(n) {
            this.index = n;
        });
    
        allImgs.get(0).effect('scale', { percent: 200 }, 1000);
    });
    

    You can also begin the effect inside the each argument where n == 0. (I didn't do this in my example because it's not exactly like the code you have (ignoring ugly concurrency issues)).

  • When you are inside the call to click, the first parameter ("this") is the DOM element you clicked. Does your DOM element have a "index" property?

    I also recommend you to use a "object dump" function (an example here: http://weblogs.asp.net/skillet/archive/2006/03/23/440940.aspx ). The usage is similar to this:

    $("a").click( function(){ 
       alert( object_dump( this ) ) 
    });
    

    (note that the object_dump() function returns a string, you need to "alert()" it or do something else with it).

0 comments:

Post a Comment