views:

693

answers:

1

Hi everyone! I'm very new to JQuery, and I'm having some trouble understanding how to do this:

I have an image of class "imgexpander" with the src attribute set to "img1.png". When the image is clicked on, it should look to see whether a div with class "expand" is currently hidden or visible.

  • If it's hidden (which is the default), it shows it (I know how to use show()) and changes the src attribute of the image to "img2.png".

OR:

  • If the div is visible, it hides it and changes the src attribute of the image to "img1.png".

I'm not familiar with the available functions in JQuery yet. How could this be accomplished? Can you give me some sample code that I can work with?

Thanks in advance!

UPDATE: I forgot to add a detail: is it possible to somehow make the onclick of an image of class "imgexpander" only influence divs that are all included together in one big div? So, the hierarchy would be something like:

  • big div
    • image with onclick
    • div that needs to be influenced
  • another big div
    • image with onclick
    • div that needs to be influenced

The desired result would be to have each "image with onclick" only influence "divs that need to be influenced" inside its respective "big div". Is this possible? I'm not sure the current answer would fit, but thanks!

+4  A: 

How about:

$("img.imgexpander").click
(
  function()
  {        
    var expandableDIVs = $(this)
                           .parents("div.bigdiv:first")
                           .find("div.expand");    
    expandableDIVs.toggle();
    this.src = expandableDIVs.is(":visible") ? "img2.png" : "img1.png";
  }
);

This code sets up a click event handler for all IMG elements of class imgexpander. The handler toggles the visibility of all DIV elements of class expand. The src attribute of the image is updated by testing if any of the DIV elements matched by "div.expand" are visible.

Notice that I can assign the jQuery wrapped set of DIVs matching the "div.expand" selector to a JavaScript variable for later use.

The this keyword in the event handler refers to the current DOM element matched by the "img.imgexpander" selector. Remember, there can be several elements matched by this expression.

EDIT: The method of acquiring the div.expand elements has been updated to reflect the changes to the OP. Only DIV elements that are children of the parent bigdiv classed DIV will be toggled when an img is clicked.

Note that care has been taken to ignore the way that elements are marked up. It is important to us that the IMG element has a parent DIV somewhere in its parent chain of class bigdiv, but this element does not have to be an immediate parent. This is the reason for my use of the :first pseudo-selector.

David Andres
I've had some trouble with toggling before. But I could have been messing up. Does the browser cache the src set by the function, potentially making a situation where the click/toggle gets reversed because it loads with img2.png but with the div hidden? I'd personally go with making the image a background image of a block link and simply have the `this.src` become `this.toggleClass("blah")`. Mind if I post that as a slight alternative?
Anthony
Please see my update, but thanks for the answer.
Maxim Zaslavsky
Different solutions are always welcome. I don't believe there is an element of caching on the browser side here because the browser will cache the page as received from the server and not in response to purely client-side code. It is a separate issue if the server has provided markup in which the IMG and DIV elements are not synchronized with each other. One could add behavior to the page that would initialize these elements to reasonable defaults after the page has been loaded to enforce the relationship between these elements.
David Andres
@Maximz2005: Does this code work for you?
David Andres
@David Andres: I'm about to try it, but please see my update, because I'm actually looking for a way to only influence divs that are enclosed in the img's own div, so to say. I've explained this better in the original question with an update. Thanks!
Maxim Zaslavsky
@Maximz2005: I've updated my post. Take a look and let me know.
David Andres
With your use of *this*, it will work for all cases, without any dynamic changing required on my part, yes? I'm about to leave, but when I get back in a few hours, I'll try this code out and update here. It looks to me as if it is the solution, because of its logic. Thanks so much!
Maxim Zaslavsky
The this keyword in jQuery event handlers will ALWAYS refer to the element that fired the event, which in this case is the IMG element. This makes it easy to share behavior between different elements on the page.
David Andres
I just tried it, and it works great! Thank you so much! I'm accepting the answer, but I have one more small question: is it possible to animate the toggle of the visibility (i.e. similar to show('fast'))?
Maxim Zaslavsky
@Maximz2005: Like slow and hide, toggle also supports parameters like "slow" and "fast."
David Andres