2

How do I write a click event that acts on an element not yet loaded into the DOM?

Scenario:

  • native-btn is a div loaded at document ready.
  • ajax-loaded-element is a div that appears after an ajax form executes a series of client-side events

My event is as follows:

$(".native-btn").click(function() {
    $(".ajax-loaded-element").fadeOut();        
});

I can't seem to get the .ajax-loaded element to respond. I know that .live() is deprecated, and the .on() event only applies to interacting directly with a newly inserted element, not acting on it by means of a secondary action. Is there another usage of .on() that I'm missing?

Thanks!

UPDATE

I am now using the .on() event to access the . ajax-loaded-element div. However, while it responds to basic events like .hide() and .css(), it doesn't respond to .trigger(), which is what I ultimately need it to do.

$(document).on("click", ".native-btn", function() { 
    $('.ajax-loaded-element').trigger('click'); 
    $('.ajax-loaded-element').css("background-color","red"); 
});

Background changes to red, but trigger doesn't fire. I should add that the default functionality of the .ajax-loaded-element that is being loaded by the CMS advances a page on an ajax form. I am trying to trigger it remotely because I want to add custom animations before and after the default functionality.

THE WHOLE SCOOP

I am using a multipage webform in Drupal, which shows up as a block on a page. Because I've assigned ajax client-side functionality to it, it dynamically inserts "PREV" and "NEXT" divs to advance the form as needed.

From a UX perspective, I want to fade the whole form out, let the form advance to the next page, then fade the form in, instead of a blink-of-an-eye change wherein the user may not perceive that the form has advanced. I don't have access to the webform functionality, so I'm trying to do it with jQuery and trigger. The basic markup is:

<div id='webform'>
    ...form code...
    <div class='ajax-loaded-next'>Next</div>
    <div class='ajax-loaded-prev'>Prev</div>
</div>

<div class='native-btn-next'>NEXT</div>
<div class='native-btn-prev'>PREV</div>

$(document).on("click", ".native-btn-next", function() { 
    $('#webform').fadeOut(); 
    $('#webform .ajax-loaded-next').trigger('click'); 
    $('#webform').fadeIn(); 
});

$(document).on("click", ".native-btn-prev", function() { 
    $('#webform').fadeOut(); 
    $('#webform .ajax-loaded-prev').trigger('click'); 
    $('#webform').fadeIn(); 
});

Looks like this: (ajax NEXT/PREV are white, native NEXT/PREV are black)

screenshot

As you can see, it starts with only the Next button, which works like a charm. Webform fades out, the ajax-loaded-next trigger clicks, the page advances, webform fades in.

But on page 02, the ajax-loaded-prev button shows up:

screenshot

This was obviously not in the DOM when the form loaded. My native-btn-prev fades the webform in and out, but doesn't trigger click.

Hope that makes sense...

sakeferret
  • 305
  • 1
  • 6
  • 15
  • If `.native-btn` is loaded witht the document, did you forget the `$(document).ready()` wrapper around the event handler installation? The `.ajax-loaded-element` only needs to exist when the button is clicked, so that should not be a problem. – Bergi Apr 27 '13 at 18:46
  • thanks for the reminder. i do have a document ready, and now that i've updated to jquery 1.7, i can use the .on() event to access the div. However, while it responds to basic events like .hide() and .css(), it doesn't respond to .trigger(), which is what I ultimately need it to do. – sakeferret Apr 28 '13 at 02:52
  • `.hide` and `.css` are no *events*? Please show us how exactly you're trying to use `.trigger`. – Bergi Apr 28 '13 at 07:21
  • please see UPDATE comment above – sakeferret Apr 29 '13 at 14:02
  • Of course it correctly triggers the `click` event, but you have no event listeners attached for it? Show us those actions which you want to trigger on the `.ajax-loaded-element`, *they* need to be attached via event delegation - not those for the `.native-btn` which does exist on domready. – Bergi Apr 30 '13 at 13:39
  • Please see THE WHOLE SCOOP in the edit above. Thanks again for any suggestions. – sakeferret Apr 30 '13 at 15:32
  • So the `next` button on page 2 works, but not the `prev` button? Btw, you've got a little mismatching-quotes syntax error in the posted code. – Bergi Apr 30 '13 at 21:56
  • Sorry, i've sanitized the examples because the Drupal classes are way to illegible... yes, the next works and the prev does not. – sakeferret May 01 '13 at 01:16

4 Answers4

3
$(document).on('click', '.native-btn', function() {
    $(".ajax-loaded-element").fadeOut();        
});

This is an event handler for dynamically inserted elements, and you should replace document with the closest non-dynamic parent.

Note that you can't fade something out that is'nt really there.

adeneo
  • 312,895
  • 29
  • 395
  • 388
  • +1. Just worth to mention jQuery v1.7+ is required to use `.on()` – JFK Apr 27 '13 at 18:48
  • Thanks. The jQuery version was throwing me off. I got the `code`.on()`code` to work. However, now that I can access the newly created div, the `code`.trigger()`code event won't work on it: – sakeferret Apr 28 '13 at 02:35
  • `$(document).on("click", ".native-btn", function() { $('.ajax-loaded-element').trigger('click'); $('.ajax-loaded-element').css("background-color","red"); });` – sakeferret Apr 28 '13 at 02:36
  • sorry, getting used to the comment markup. In the following snippet: `$(document).on("click", ".native-btn", function() {` ` $('.ajax-loaded-element').trigger('click');` ` $('.ajax-loaded-element').css("background-color","red");` `});` the css background change works but the trigger click does not. any ideas? – sakeferret Apr 28 '13 at 02:37
  • wow, sorry, i can't figure out how to markup that function properly! see code in previous comment, sorry it's mashed up – sakeferret Apr 28 '13 at 02:39
  • i should add that if i manually click the newly added '.ajax-loaded-element' , the desired event takes place. I would like to fire it remotely with a trigger click because I need some other jquery animations to happen before and after the '.ajax-loaded-element' does it's thing. – sakeferret Apr 28 '13 at 02:43
0
$(document).on('click', '.native-btn', function() {
  $('.ajax-loaded-element').fadeOut();      
});
Danil Speransky
  • 29,891
  • 5
  • 68
  • 79
  • Thanks, this works. i can now use the .on() event to access the div. However, while it responds to basic events like .hide() and .css(), it doesn't respond to .trigger(), which is what I ultimately need it to do. – sakeferret Apr 28 '13 at 02:53
0

You could include an empty dom element with class ajax-loaded-element in the markup, so it exists when the page loads. When your ajax request succeeds, it will populate that div. The click event is already bound, so clicking on it will make the fadeOut() happen as expected.

vishakvkt
  • 864
  • 6
  • 7
0

Yes, use on method http://api.jquery.com/on/

$("body").on( "click", ".native-btn", function() {
    $(".ajax-loaded-element").fadeOut();        
});

or

$(".native-btn").on( "click", function() {
        $(".ajax-loaded-element").fadeOut();        
});
ripu1581
  • 300
  • 1
  • 9