-1

I have a page with two forms on the same page. The two forms is displayed based on viewport (responsive design/media queries css).

On the page I am using bootstrapvalidator in order to validate the fields, and Ajax in order to submit the forms without browser reload. Because of the bootstrapvalidator, the Ajax code looks like this - a code that targets ALL forms:

  $('form').on('success.form.bv', function(e) {
    var thisForm = $(this);

    //Prevent the default form action
    e.preventDefault();

    //Hide the form
    $(this).fadeOut(function() {
      //Display the "loading" message
      $(".loading").fadeIn(function() {
        //Post the form to the send script
        $.ajax({
          type: 'POST',
          url: thisForm.attr("action"),
          data: thisForm.serialize(),
          //Wait for a successful response
          success: function(data) {
            //Hide the "loading" message
            $(".loading").fadeOut(function() {
              //Display the "success" message
              $(".success").text(data).fadeIn();
            });
          }
        }); 
      });
    });

The problem with this code, as it seems, is the fact that the code will send two mails, one for the visible form, and one for the hidden mobile/tab form - the success msg will actually be displayed for both forms (when I resize the browser to target both desktop and mob/tablet, I can see the success msg for both forms). First I thought is was because of something wrong with the e.preventDefault(); and then I thought the problem was caused by name conflicts on the submit name/id of the submit button. But now I am pretty sure it has to do with the existence of the two forms on the same page - because the only way I manage to fix this whole problem right now is by completely remove one of the forms, and that's really not a solution!

My forms look like this with different form id (html5form/html5formmob) and input submit id (mob/desk):

    <form id="html5Form" method="post" action='mail/mail.php'
          class="form-horizontal"
          data-bv-message="This value is not valid"
          data-bv-feedbackicons-valid="glyphicon glyphicon-ok"
          data-bv-feedbackicons-invalid="glyphicon glyphicon-remove"
          data-bv-feedbackicons-validating="glyphicon glyphicon-refresh">    

              <div class="form-group">
                      <label>Name</label>
                      <input class="form-control" type="text" name="name" id="name"
                             data-bv-message="The username is not valid"
                             required data-bv-notempty-message="Please give a name"/>
              </div>

              <div class="form-group">
                  <label>Mail</label>
                      <input class="form-control" name="email" id="email" type="email" required data-bv-emailaddress-message="No valid email"  />
              </div>

              <div class="form-group">
                <label>Msg</label>
                <textarea class="form-control" name="message" id="message" rows="7" required 
                data-bv-notempty-message="No empty msg"></textarea>
              </div>  

                <input type="submit" id="mob" value="Send"/>
            </form>
<div class="loading">
        Sending msg...
  </div>
  <div class="success">
  </div>

So my question, is there a way to disable/enable the entire form using CSS or JS? ..and could this be a solution, or do you have other suggestions?

Sparky
  • 98,165
  • 25
  • 199
  • 285
Sepi
  • 75
  • 2
  • 13

2 Answers2

0

Try to change your JS part into this:

$('form').on('success.form.bv', function(e) {
    var thisForm = $(this), parent = thisForm.parent();

    //Prevent the default form action
    e.preventDefault();

    if (thisForm.is(':visible')) {
        //Hide the form
        thisForm.fadeOut(function() {
        //Display the "loading" message
        $(".loading", parent).fadeIn(function() {
            //Post the form to the send script
            $.ajax({
                type: 'POST',
                url: thisForm.attr("action"),
                data: thisForm.serialize(),
                //Wait for a successful response
                success: function(data) {
                    //Hide the "loading" message
                    $(".loading", parent).fadeOut(function() {
                        //Display the "success" message
                        $(".success", parent).text(data).fadeIn();
                    });
                }
            }); 
        });
    }
});

Will work dynamicly, so even when you switch forms by resizing your browser.

redelschaap
  • 2,774
  • 2
  • 19
  • 32
  • Thank you for answering! I tried your suggestion.. whats now happening is the same as if I was to remove the `e.preventDefault();` - the default form action is taking place and the browser reloads at submit. – Sepi Dec 08 '14 at 07:54
  • I tried this new code, but unfortunately - still the same result! – Sepi Dec 08 '14 at 08:35
  • Then your second form is not really hidden, or there is another visible form being posted. ':visible' evaluates to FALSE (which we want for the mobile form) when the whole form element's css is `display: none;` or `visibility: hidden;`. `display: none;` is prefered – redelschaap Dec 08 '14 at 09:18
  • Another suggestion, you may want to change the way things disappear. Now the form disappears immediately when the form is posted. But what if the request could not be completed or your server gives an error? I would suggest to fade out the form when the success event is triggered. – redelschaap Dec 08 '14 at 09:20
  • Thank you for not giving up on me ;) I am using `display: none`, and I have tried to change the order of the way things disappear, without getting the desired result. Just for the record I do have a server-side php validation in the `mail.php` file as well as the client-side bootstarpvalidator - an error in the php file will display an error in the success msg, and the email will not be submitted! Is there another way to target the `display: block` in the class before the form is submitted? – Sepi Dec 08 '14 at 16:05
  • Yes I get that, but if the user made a mistake in the form or the request to the server is stopped for some reason, the form is gone. That's not really friendly. On topic: are both of your forms being submitted? If not, try to place each form and the .loading and .success divs inside another div, and then try my updated JS code. – redelschaap Dec 08 '14 at 19:13
  • I'll certainly will consider to not fade away the form before success is triggered! Well, both forms + .loading and .success are already placed inside different div's, the same div's that will display or hide the forms based on viewport – Sepi Dec 09 '14 at 09:15
  • Is your website public? Can you give me the link so I can take a look myself? – redelschaap Dec 09 '14 at 09:29
  • http://tinyurl.com/owhtpw7 - as you can see in dev tools the mail.php is called twice at submit! – Sepi Dec 09 '14 at 22:04
0

Try the following approach:

$('form').on('success.form.bv', function(e) {
var thisForm = $(this);

//Prevent the default form action
e.preventDefault();

if (getComputedStyle(thisForm[0], null).display != "none" )
{
    //Hide the form
    $(this).fadeOut(function() {
      //Display the "loading" message
      $(".loading").fadeIn(function() {
        //Post the form to the send script
        $.ajax({
          type: 'POST',
          url: thisForm.attr("action"),
          data: thisForm.serialize(),
          //Wait for a successful response
          success: function(data) {
            //Hide the "loading" message
            $(".loading").fadeOut(function() {
              //Display the "success" message
              $(".success").text(data).fadeIn();
            });
          }
        }); 
      });
    });
}
});

But you can also validate each form by itself:

  $('#html5Form')
    .formValidation({
        ... options ...
    })
    .on('success.form.fv', function(e) { ... ajax call ...} );

Or even better. wrap the ajax call in a function

function callAjax(form)
{
      form.fadeOut(function() {
      //Display the "loading" message
      $(".loading").fadeIn(function() {
        //Post the form to the send script
        $.ajax({
          type: 'POST',
          url: form.attr("action"),
          data: form.serialize(),
          //Wait for a successful response
          success: function(data) {
            //Hide the "loading" message
            $(".loading").fadeOut(function() {
              //Display the "success" message
              $(".success").text(data).fadeIn();
            });
          }
        }); 
      });
    });
}


  $('#html5Form')
    .formValidation({
        ... options ...
    })
    .on('success.form.fv', callAjax.bind(null, $(this)) );

  $('#html5formmob')
    .formValidation({
        ... options ...
    })
    .on('success.form.fv', callAjax.bind(null, $(this)) );
Mouser
  • 13,132
  • 3
  • 28
  • 54
  • Thank you for answering! This does not work either... What about somehow remove/disable the form action based on screen size using JS? `if (screen.width > 801) { $("html5FormMob").removeAttr("action"); } else { $("html5Form").removeAttr("action"); } ` – Sepi Jan 09 '15 at 03:19
  • @Sepi Good thinking, but you don't want to do this. If somebody loaded your site into a small screen on a desktop it uses the wrong form. Which solution did you implement? – Mouser Jan 09 '15 at 10:25
  • This is the result of your suggestions: Solution 1) Ajax working - still two mails. Solution 2) Ajax not working - reload page to mail.php. Solution 3) Ajax not working - reload page to mail.php. What I realized checking the DOM after the desktop-form is submitted, is the fact that the mobile-form is also displaying the load and success msg - could this somehow trigger the mail.php to fire off twice? – Sepi Jan 09 '15 at 12:20