views:

1851

answers:

2

Heres my link:

http://tinyurl.com/6j727e

If you click on the link in test.php, it opens in a modal box which is using the jquery 'facebox' script.

I'm trying to act upon a click event in this box, and if you view source of test.php you'll see where I'm trying to loacte the link within the modal box.

 $('#facebox .hero-link').click(alert('click!'));

However, it doesn't detect a click and oddly enough the click event runs when the page loads.

The close button DOES however have a click event built in that closes the box, and I suspect my home-grown click event is being prevented somehow, but I can't figure it out.

Can anyone help? Typically its the very last part of a project and its holding me up, as is always the way ;)

+5  A: 

First, the reason you're getting the alert on document load is because the #click method takes a function as an argument. Instead, you passed it the return value of alert, which immediately shows the alert dialog and returns null.

The reason the event binding isn't working is because at the time of document load, #facebox .hero-link does not yet exist. I think you have two options that will help you fix this.

Option 1) Bind the click event only after the facebox is revealed. Something like:

$(document).bind('reveal.facebox', function() {
  $('#facebox .hero-link').click(function() { alert('click!'); });
});

Option 2) Look into using the jQuery Live Query Plugin

Live Query utilizes the power of jQuery selectors by binding events or firing callbacks for matched elements auto-magically, even after the page has been loaded and the DOM updated.

jQuery Live Query will automatically bind the click event when it recognizes that Facebox modified the DOM. You should then only need to write this:

$('#facebox .hero-link').click(function() { alert('click!'); });
Ryan McGeary
be careful with live query, can eat your web app if you have large-ish dom, event delegation is a better bet and no extra plugin overhead.
redsquare
Option 1 did the trick for me ;) Thanks very much indeed.
Pickledegg
+1  A: 

Alternatively use event delegation

This basically hooks events to containers rather than every element and queries the event.target in the container event.

It has multiple benefits in that you reduce the code noise (no need to rebind) it also is easier on browser memory (less events bound in the dom)

Quick example here

jQuery plugin for easy event delegation

P.S event delegation is pencilled to be in the next release (1.3) coming very soon.

redsquare
Good warning on live query. Event delegation isn't perfect either though. What happens when you to bind an event to a container element inside the outer container element? The 'target' element could then very well be nested inside the inner container leading to a more difficult event mapping.
Ryan McGeary
Ryan - not with you at all, could you explain again.....The container (any parent upto and including the document itself receives the event bubble, the event target will always be the same element that invoked the event)
redsquare
Redsquare. In event delegation, you have a "false" container that all the events bubble to. This is fine, but if your intention was to grab events on a separate container inside that container, you lose control. The target will not match against the inner container necessarily.
Ryan McGeary
It's difficult to describe, but imagine an outer div A that controls the delegation, an inner div B that you want to capture events on, and an inner anchor tag C that actually invokes the event. C is the target, but won't match the delegation rules if your intention was to capture events on B.
Ryan McGeary
Thanks, mindblowing stuff ;)
Pickledegg