7

Here's a condensed example.

Keep in mind that the .chat-reply class has a click event handler bound to it.

The HTML (Reply Button):

<div class="container">
    <a href="#" class="btn small chat-reply">Reply</a>
</div>

This jQuery function is called when someone clicks another button that sends a message to the server to be saved in the database. This is done via ajax and is done successfully. In the aforementioned .ajax() success() callback this function is called:

$.ajax({
      type      :  'GET',
      url       :  '/some_controller/some_method',
      success   :  function(data) {

      $('.container').replaceWith(data);
    }
});

The 'data' in the success callback above will replace the entire .container div including the child .chat-reply button. After this replaceWith(), the click event is no longer bound to the button.

Logically, I'm attempting to have the end user post a message to a timeline, then have that message display in the timeline without needing to refresh the screen.

generalopinion
  • 1,437
  • 2
  • 13
  • 21

4 Answers4

3

Grab jquery 1.7 that now uses 'on' to bind: http://blog.jquery.com/2011/09/28/jquery-1-7-beta-1-released/

Or if < 1.7 use 'live' instead of 'bind' as it will look for DOM changes and re-apply the events of changed content. If not you can reapply the event on your callback.

Old api to replacement to bind with live type event handlers after DOM changes.

this $(selector).live(events, fn)

becomes this $(document).on(events, selector, fn)

Or in code

This

$(".container a.chat-reply").live("click", function(){
 // do it live!
});

Becomes this in 1.7

$(".container").on("click", "a.chat-reply", function(event){
 // do it live!
});

With various options to selecting the object you want.

Ryan Christensen
  • 7,843
  • 1
  • 27
  • 25
  • Your code example is a little confusing to me. If you don't mind clarifying a little, that would be great. – generalopinion Feb 14 '12 at 03:37
  • Sry the block was just pointing from old 'live' to 'on' but Vigrond's example is how you do an 'on'. It would almost be better to attach the event after the html is received in your callback. – Ryan Christensen Feb 14 '12 at 05:17
2

In your click handler, use .on() as a delegate instead

$("div.container").on("click", "a.chat-reply", function(even){
  //click handler here
});

the event will 'bubble' up to container, and if it matches a.chat-replay it will trigger.

Vigrond
  • 8,148
  • 4
  • 28
  • 46
  • The "bubbling up" worked however once I do a replaceWith(), those event bindings are gone--still. – generalopinion Feb 14 '12 at 03:33
  • of course. my bad, replaceWith will replace the entire element. Is it possible for you to do .html(content) instead? That will replace its content, not the .container element. Otherwise you'll have to start looking at the ancestors of .container to attach the .on event handler to. – Vigrond Feb 14 '12 at 03:38
  • Ewww. That can get nasty. I found another post that suggested having a function that "wires-up" the event binding. Then calling it again AFTER the replaceWith(). It's not pretty but I might not have much of a choice. – generalopinion Feb 14 '12 at 03:42
  • Furthermore, I thought about the .html(content) approach but it's just too much other stuff going on, on the back end to make this approach efficient. – generalopinion Feb 14 '12 at 03:43
  • Here's a link to the similar question: http://stackoverflow.com/questions/770308/events-not-registering-after-replacewith – generalopinion Feb 14 '12 at 03:45
  • Ok, it's hard to give you an accurate answer if you don't details. – Vigrond Feb 14 '12 at 03:47
  • I understand. And I appreciate your help. I condensed the example down to focus more on the most important aspect. What's returned from the .ajax call (i.e. the data variable), I felt was irrelevant because I'm not at the point where I would consider changing the data returned from my controller. I hope that makes sense. – generalopinion Feb 14 '12 at 03:53
1

Decided on a rather not-so-elegant solution thanks in part to this post: Events not registering after replaceWith

I created a function called wireUpChatReply() that binds a click event to the .chat-reply button.

Then after the replaceWith(), I make a call to wireUpChatReply() to rebind the events. I make this same call to wireUpChatReply on document.ready.

It's not pretty but it works.

Community
  • 1
  • 1
generalopinion
  • 1,437
  • 2
  • 13
  • 21
0

The two answers regarding live events do not fix the problem, because the container itself is replaced and the event binding is gone.

Instead of rebinding the events, in which case you need to know the already bound events, you can do the following:

$(".container").parent().on("click", ".container a.chat-reply", function(){
  // do something
});

or, if there are several containers:

$(document.body).on("click", ".container a.chat-reply", function(){
  // do something
});
RiZKiT
  • 2,107
  • 28
  • 23