2

I am attempting to create a "Leave Comment" form which is loaded by AJAX on demand and then shown using a jQuery popup. There are three motivations for this:

  • Less clutter on page.
  • Reduced automated spam.
  • Faster page load time (with caching enabled the page load time goes from 400ms to 120ms when the comment form is not included in the article template).

Here is what I have currently:

enter image description here

I have created the following template which is called ajax/blog-comment-form:

{exp:comment:form channel="blog" entry_id="{segment_3}"}
{if logged_out}
    <label for="name">Name:</label> <input type="text" name="name" value="{name}" size="70" /><br />
    <label for="email">Email:</label> <input type="text" name="email" value="{email}" size="70" /><br />
    <label for="url">URL:</label> <input type="text" name="url" value="{url}" size="70" /><br />
{/if}

    <label class="outline" for="comment">Comment:</label>
    <textarea name="comment" cols="70" rows="7">{comment}</textarea>
    <div class="comment-note">Note: HTML tags are not supported.</div>

{if captcha}
    <div class="captcha">
        <label for="captcha">Please enter the word you see in the image below:</label>
        {captcha} <input id="captcha" type="text" name="captcha" value="{captcha_word}" maxlength="20" />
    </div>
{/if}

    <div class="button-strip">
        <input class="ui-pink-button" type="submit" name="submit" value="Submit" />
    </div>
</div>
{/exp:comment:form}

I am currently using the following JavaScript to submit the form via AJAX. This is almost working except there is no way to display error messages when inputs are entered incorrectly.

form.find('input[name="submit"]').click(function() {
    $.ajax({
        type: 'POST',
        url: form.attr('action'),
        data: form.serialize(),
        success: function(data) {
            // ???
        },
        failed: function(data) {
            // ???
            // this never seems to actually occur
        }
    });
    return false;
});
3
  • 1
    I'm not following your question 100%. Can you add more detail/code so we can see the whole picture?
    – Anna_MediaGirl
    Dec 10 '12 at 7:16
  • Are you needing JS to handle your own custom error/success messages or are you needing a way to access EE's default error messaging for comments?
    – Anna_MediaGirl
    Dec 10 '12 at 7:56
  • @MediaGirl The former, a way to add custom error/success messages once the comment form has been posted.
    – Lea Hayes
    Dec 10 '12 at 16:56
3

TL;DR: You're binding a callback to the wrong $.ajax option, but that isn't enough to fix this: I would use the Ajax Babble addon and get on with your day, as this problem turns out to be more complex than it looks. While you could do client side validation as Anna suggests, there are all sorts of other error conditions not related to request content that you can't validate client side, such as requiring an IP, minimum time between comments etc.

Anyway if $35 is too much for your budget then by all means read on...

The long answer...

Sorry this is so long, but I had a little time on my hands...

The first reason that your failed callback is never called is failed is not the name of the $.ajax option that you want, you want fail (jQuery 1.8+) or error (pre jQ 1.8).

However, even if you change that, the callback still won't fire because of the fact that the ajax request is returning successfully (ie an HTML response with a 200 HTTP status code), it's just that the response is an EE error page, rather than an error code. jQuery doesn't understand the content of that page, so unless it returns HTTP error code such as a 403 or 500, which it doesn't that code will never run.

Before we get to the non-addon route to solving this, a few jQuery/JS notes:

You should bind to the forms submit event, rather than a click handler on the submit button, as forms can be submitted without clicking (keyUp/JS triggered submit etc).

Use event.preventDefault() instead of return false, as doing the latter from a jQuery event handler is the equivalent of calling both event.preventDefault() and event.stopPropagation(), the latter of which which stops the event from bubbling.

You may want to do this, but if so do it explicitly to avoid debugging headaches with delegated events:

$('form').on('submit', function(e){
  //the first argument passed to the event handler is the jQ wrapped event object
  e.preventDefault();
  //handle event here
}).addClss

Consider using jQuery deferreds instead of passing callbacks as options to $.ajax. It makes your code easier to read and you can register callbacks where it makes sense rather than where $.ajax wants you too. You can even register callbacks on requests that have already returned (in which case they execute immediately):

$('form').on('submit', function(e){
  var req = $.ajax({...}); //returns a jQ deferred object

  e.preventDefault();
  ...
  req.done(function(){
    //handle success
    alert('yay!');
  })
  .fail(function(){
    //handle error
    alert('boo!');
  })
  .always(function(){
    //fires when request done whether successful or not
    alert('finished!');
  });

});

Enough already, how do I roll my own Ajax comment submission?

Okay so, if you really want to go down the route of rolling your own for this one, you're going to need to parse the response in some way (such as by looking for an id on the body element of the message template) and then extract the message:

In your system message template:

<body class="system-msg">
  <div class="system-msg-content">
    {content}
  </div>
</body>

In your jQuery:

//not tested, may need tweaking
req.done(function(data, status){
  var $data = $(data),
      msg = $('<p class="msg"/>'),
      msgContent;
  if ($data.find('body').hasClass('system-message')){
    //handle error message
    msgContent = $data.find('.system-msg-content').html();
    $msg.html(msgContent);
    $form.prepend($msg);
  }
  else {
    //do normal success stuff here
  }
})

You could even use the Custom System Messages addon and Mo'Variables to use a regular template for your error and then detect an ajax request and return a differently formatted response (or even an error code, in which case you can use fail())for consumption by your jQuery.

But to be honest, I wouldn't do any of that unless you don't really value your time or you enjoy the challenge, instead I'd stump up $35 for Ajax Babble and go home early instead.

4
  • This answer is why Tom wins at Rep! Great answer Tom.
    – Anna_MediaGirl
    Dec 10 '12 at 22:17
  • I am loving the way that most answers to EE questions are "Buy plugins X, Y and Z" lol. In this case I decided to write the script and it works nicely: pastebin.com/nJNRLQ7N
    – Lea Hayes
    Dec 10 '12 at 22:37
  • Deferreds are new to me, so I will need to read up a little on those.
    – Lea Hayes
    Dec 10 '12 at 22:41
  • Really glad you got it working Lea. Be sure to test, test, test though :)
    – Tom Davies
    Dec 12 '12 at 16:39
1

Here's a simplified version of a contact form I coded last week which might work for you. Since my potential "errors" can be checked with validation I make sure everything is correct before submitting the form. Your validation can be much more complex if needed obviously.

$("#contact-form .submit").click(function(){
    var url = $("#contact-form").attr("action");
    var email = $("#contact-form #email").val();
    if (email == ""){
        $("#contact-form .error").show();
        return false;
    }
    $.ajax({
        type: "POST",
        url: url,
        data: $("#contact-form").serialize(),
        success: function(data){
            if (data.success == true){
                $("#contact-form .success").show();
            }
        }
    });
    return false;
});

Can I assume from your code example that you are want to trigger the error for incorrect captcha data? If yes, you may consider switching to Snaptcha for spam protection. It's invisible captcha and may work for what you are doing. One less thing the user needs to enter.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.