views:

150

answers:

2

I'm building a Q&A site where one can comment on questions and their answers.Its a threaded commenting system with ajax.

this is the javascript part:

function bindPostCommentHandler()
{
    $('.commentFormWrapper form').submit(function() {
    var current = $(this); 
        $.ajax({
            type: "POST",
            data: current.serialize(),
            url: "{% comment_form_target %}",
            cache: false,
            dataType: "html",
            beforeSend:function(xhr){
                $('.submit', current).html('<img id="preloader" class="va-mid" src="{{MEDIA_URL}}img/indicator.gif" title="processing.." />');
                $('#commentError').remove();
            },
            success: function(html, textStatus) {   
                current.parent().replaceWith(html);
                bindPostCommentHandler();                
            },
            error: function(xhr, textStatus, errorThrown) {
               $('#commentError').remove();
                $('.submit', current).html('<input type="submit" name="submit" class="submit-post small-button" value="Submit" />');
                if(xhr.status == 400){
                    current.before('<li id="commentError" class="no-bullet errornote margin10">OOPS ! your comment looked liked a spam. Try again with some modifications.</li>');
                }else {
                    current.before('<li id="commentError" class="no-bullet errornote margin10">Your comment was unable to be posted at this time. You may try after sometime.</li>');
                }   

            //bindPostCommentHandler();             

            }
        });
        return false;
    });        
}
$(document).ready(function() {
 bindPostCommentHandler();
});

the html part:

<!-- comment form for question -->
<div class="commentFormWrapper">                
     {% render_comment_form for question %}
</div>

<!-- comment form for answers -->
{% for answer in question.answers.all %}
<div class="commentFormWrapper">                
     {% render_comment_form for answer %}
</div>

The problem is, when there is only a single form in a page it works smoothly. With multiple forms its working but sending the request to the server muliple times(grows in multiples).

Also, it would be better to dynamically insert/remove forms. But if I add the html for forms manually, I'll miss out csrf tokens and timestamp fields in the comment form. Anybody has solutions to these ?

+1  A: 

assign an #id to every form, and use this id instead of 'this'

var current_id = $(this).attr("id");
zalew
then I need to add an argument to bindPostCommentHandler. Have u implemented something like this?
anand
A: 

The problem is, when the success function is called, then you call bindPostCommentHandler (again), which binds the anonymous function again to all form objects. I.e. after one submission, every form has two functions bound to the submit event, after two submission, three and so on.

So you have to change the success part of the Ajax function to only add the handler to the form contained in the response.

Maybe like this (I don't know if this works, I am not that good in Javascript/jQuery):

Edit:

You mentioned the first one is working. Then the code is probably not working because, the DOM gets replaced. See my updated code (use htmlinstead of replace).

Edit 2:

What about changing your HTML structure. Just wrap another div around the comments and the form and replace the contents of this. This should definitely work. Something like

<div class="new_around_comments">
   <div class="comments"></div>
   <div class="commentFormWrapper">
       <!-- Form -->
   </div>
</div>

Then you have to call two times parent():

function bindPostCommentHandler(parent)
{
    parent.find('form').submit(function() {
    var current = $(this); 
        $.ajax({
            //...
            success: function(html, textStatus) {
                // Edit 2
                parent = current.parent().parent()
                parent.html(html);
                bindPostCommentHandler(parent);         
            },
            //...
        });
        return false;
    });        
}
$(document).ready(function() {
 var parent = $('.commentFormWrapper')
 bindPostCommentHandler(parent);
});
Felix Kling
the error u mentioned is the one I'm facing. But your solution does not work
anand
Is there any error or is it the same problem?
Felix Kling
No error, but the browser redirects to the form preview page instead of retrieving it through ajax. It could be the case if it is not being binded but your solution seems to bind it!!!
anand
Ah I think I got it. `children` only looks for child elements not for descendant elements (I always forget this). Change `children` to `find` if the `form` tag is not a direct child of `.commentFormWrapper`.
Felix Kling
What exactly is not working, the first submit or submits after the first submit (i.e. after the success function is executed once?)
Felix Kling
there is only one child of .commentFormWrapper and it is <form></form>. So using children should work.Anyway using find also does not help.If I see what's in current.parent() using alert(current.parent.html()); It shows the form, but cannot bind. What's wrong?
anand
The first submit is only working.
anand
using html on parent will create nested .commentFormWrapper.Also, I think the dom is replaced with a new one with current.parent().replaceWith(html); , so why this is not binded.<strong>Ho do u highlight text in comments</strong>
anand
The same way as in **questions** (`**questions**`). Why not just return the response without a `.commentFormWrapper`?
Felix Kling
because the response may not always return a **.commentFormWrapper**.When the comment is posted successfully first the **posted comment** and then **.commentFormWrapper** is *displayed*
anand
Do you have to return a new form in the response? Or would it be sufficient just to return the comment(s) ?
Felix Kling
yes! a new form needs to be returned along with comments
anand
ok! I'll try that.
anand
I changed my code for this suggestion...
Felix Kling
thanx for u'r help! You solved my problem.And **u r good** at jquery.
anand