Jquery event binding

I wrote some code to insert a form into the page, whenever a link with class .reply is clicked. However I can’t seem to bind the submit event. It actually works fine the first time the form is submitted, but it won’t work for any other submit attempts.


$(document).ready(function(){

//Inserts comment box when reply button is clicked
$('.reply').click(function(){
	var replybox = $('.replybox');
	var replyHtml = '<div class="replybox"><form action="sadf" method="post" id="commentform"><textarea rows="6" cols="10" name="comment" id="comment"></textarea><br class="br"/><input type="submit" value="" id="scomment" class=""/></form></div>';
	var clickedLink = $(this);
	
	if(replybox.length > 0){
		replybox.slideUp('slow', function(){
			replybox.remove();
			clickedLink.parents('.comment').append(replyHtml);
			$('.replybox').slideDown('fast');
		});
	}
	else{
		$(this).parents('.comment').append(replyHtml);
		$('.replybox').slideDown('fast');
	}
	
	$('#commentform').bind('submit', submitComment);
		
});

function submitComment(){
//do something
}



});

It works fine if I move the $(‘#commentform’).bind statement into each of the if/else branches, but I don’t understand why it doesn’t work the way I have it written above.

Any ideas?

Thanks.

Your problem stems not understanding how javascript timers works. setInterval() and setTimeout() are the underlying functions used to do animations in javascript(as well as other things).

Let me give an example


function sayHi() {
    alert("i'm the sayHi function");
}

javascript is executed line by line, in a top to bottom fashion. So, you would expect the correct order of messages from the following code.


sayhi();
alert("i'm the line after");

setTimeout() is used to tell the javascript engine to call a function after some time has elapsed.


setTimeout(sayHi, 1000);
alert("i'm the line after");

It doesn’t wait 1000 miliseconds before advancing to the next line. Script execution immediately advances to the next line. The javascript engine just knows that in about 1000 miliseconds, it needs to call the sayHi function, but in the meantime, it should continue processing other statements.

So, the order that the messages appear is not based on the order in the source code.

Again, jquery uses setTimeout() internally to acheive it’s animation effects. I won’t get into the why or how, but you should think of slideUp and other effects as being javascript timers.

Back to your code. You can’t bind an event handler to an element until that element actually exists. You’re element won’t exist until the slideUp animation completes. When the animation completes, jquery calls your function which removes the old html, and appends the new html(which destroys the existing div, and creates a new one). Once that the new element exists, you can bind an event handler to it. That’s why it worked when you did this


		replybox.slideUp('slow', function(){
			replybox.remove();
			clickedLink.parents('.comment').append(replyHtml);
                        $('#commentform').bind('submit', submitComment);
			$('.replybox').slideDown('fast');
		});

That makes perfect sense, and is one of the best explanations I’ve ever gotten. Thanks for taking the time to explain all that :slight_smile: