0

everyone. I have the following code which intercepts forms submition and make a Ajax call:

$(function () {
    $('form').each(function (id, el) {
        $(el).submit(function (event) {
            event.preventDefault();
            var _data = $(this).serialize();
            alert(id);
            $.ajax({
                    type: 'POST',
                    url: $(this).attr('action'),
                    data: _data
            })
            .done(function (response) {
                if (response === '') {
                    notifySuccess("Já recebemos sua história! Obrigado por compartilhá-la conosco!");
                    $(el).find('textarea').val(' ');
                } else {
                    notifyAlert(response);
                }
            })
            .fail(function(data) {
                notifyAlert(data.responseText);
            });
            grecaptcha.reset($(this).find('button').attr('id'));
        });
    });
    $('textarea').click(function () {
        if($(this).val() === ' ')
            $(this).val('');
    });
});

The code seems to be ok. However, when I run the site in my browser and put a breakpoint at line $.ajax({, it shows to me that it's executed 4 times when I try to submit a form. For debug reasons, I put a alert(id) to see what form it was submitting. My surprise is that the alert executes with the correct form ID, and a single time. In other words, only the AJAX line gets executed 4 times. The code before it don't. It's worthy to note that the callbacks (.done and .fail) also execute only one time. What can be happening here?

Here is the entire code:

var onLoadRecaptcha = function () {
 $('form').each(function (id, el) {
  $(el).ready(function () {
   var submit = function () {
    $(el).submit();
   }
   var _id = grecaptcha.render(
    $(el).find('button').get(0),
    {
     'sitekey': '6LeDwBoUAAAAANMD7VBNK2F2agKXl6rduUlelf5U',
     'callback': submit
    }
   );
   $(el).find('button').attr('id', _id);
  });
 });
}

$(function () {
 $('form').each(function (id, el) {
  $(el).submit(function (event) {
   event.preventDefault();
   var _data = $(this).serialize();
   alert(id);
   $.ajax({
     type: 'POST',
     url: $(this).attr('action'),
     data: _data
   })
   .done(function (response) {
    if (response === '') {
     notifySuccess("Já recebemos sua história! Obrigado por compartilhá-la conosco!");
     $(el).find('textarea').val(' ');
    } else {
     notifyAlert(response);
    }
   })
   .fail(function(data) {
    notifyAlert(data.responseText);
   });
   grecaptcha.reset($(this).find('button').attr('id'));
  });
 });
 $('textarea').click(function () {
  if($(this).val() === ' ')
   $(this).val('');
 });
});

var notifyAlert = function (message) {
 $("#notify-modal").find('.modal-body').removeClass('alert-success');
 $("#notify-modal").find('.modal-body').addClass('alert-danger');
 $("#notify-modal").find('.modal-body').text(message);
 $("#notify-modal").modal('show');
}

var notifySuccess = function (message) {
 $("#notify-modal").find('.modal-body').removeClass('alert-danger');
 $("#notify-modal").find('.modal-body').addClass('alert-success');
 $("#notify-modal").find('.modal-body').text(message);
 $("#notify-modal").modal('show');
}
<!doctype html>

<?php
 // error_reporting(0);

 require_once('scripts/connect.php');
 //require_once('scripts/fb.php');

 $res = mysqli_query($mysqli, "SELECT * FROM `personas`");
?>

<html class="no-js" lang="pt-BR">
 <head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
  <title>Campanha Anti-bullying | UNASP-EC</title>
  <meta name="description" content="Uma campanha anti-bullying bem bacaninha">
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" integrity="sha384-rwoIResjU2yc3z8GV/NPeZWAv56rSmLldC3R/AZzGRnGxQQKnKkoFVhFQhNUwEyJ" crossorigin="anonymous">
  <link href="https://fonts.googleapis.com/css?family=Oswald:300,400" rel="stylesheet">
  <link href="style.css" rel="stylesheet">

  <!--[if lt IE 9]>
   <script src="https://cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv.min.js"></script>
   <script>window.html5 || document.write('<script src="js/vendor/html5shiv.js"><\/script>')</script>
  <![endif]-->
 </head>
 <body>
  <!--[if lt IE 8]>
   <p class="browserupgrade">You are using an <strong>outdated</strong> browser. Please <a href="http://browsehappy.com/">upgrade your browser</a> to improve your experience.</p>
  <![endif]-->

  <section>
   <div class="fill-viewport cover d-flex flex-column justify-content-center align-items-center text-uppercase container" style="background-color: #000; color: #FFF">
    <img class="img-fluid" src="images/cover_text.png" alt="Bullying, esta brincadeira não tem graça!" />
   </div>
  </section>

  <section> <!-- Apresentação -->
   <div class="container my-5 text-justify stylize-text">
    <p>O sol queimava, mas dentro da menina magra e de cabelos crespos existia uma tempestade provinda do Alasca. O céu se estendia num azul pintado de anil, porém, a menina tímida de pequeno porte, o enxergava cinza. Os pássaros cantavam, no entanto, a menina de óculos e pele negra ouvia apenas um tom dissonante. Talvez hoje o som seja algo semelhante ao da trilha de Bernard Herrmann no filme Psicose.</p>
    <p>— Mãe, me dá R$0,50? — perguntou a pequena de oito anos.</p>
    <p>— Por que você quer esse dinheiro? — retrucou a mãe desconfiada.</p>
    <p>— Por nada mãe, eu só quero — respondeu, agora com os olhos lacrimejados.</p>
    <p>A mãe não tinha ideia do que acontecia e atordoada com os fatos relatados pela filha, se viu sem forças para continuar o caminho tortuoso até a escola.</p>
    <p>— Mãe ela me bate quando não dou o dinheiro e todos os dias eles me xingam e me deixam sozinha no recreio.</p>
    <p>O trecho acima poderia ser facilmente confundido com aquelas histórias ficcional, não fosse um fato vivido por 46,6% dos alunos entrevistados pelo Instituto Brasileiro de Geografia e Estatística (IBGE). O último senso confirmou o crescimento significativo desde o último levantamento feito em 2012, onde apontou 35,3% o número de vítimas nas escolas. De acordo com a pesquisa, 7,4% dos entrevistados atribuíram a aparência como principal motivo para as agressões.</p>
    <p>De acordo com o Código Civil Brasileiro, o <i>bullying</i> é crime e resulta em pena ao agressor, podendo ser advertência ou até mesmo restrição de liberdade. Alessandra Borelli, advogada e coordenadora do <i>Manual de Boas Práticas para Uso Seguro das Redes Sociais</i> da Ordem dos Advogados do Brasil de São Paulo (OAB/SP) e coordenadora do guia <i>Conhecendo para Prevenir bullying< e Cyberbullying</i>, explica as consequências de causar dano moral ou físico ao outro e lembra ser obrigação do agressor, dos pais ou até mesmo da escola reparar a ofensa. “Logo, se um menor for responsável pela prática de <i>bullying</i>, muito embora a legislação privilegie a adoção de medidas voltadas à orientação e resgate da boa disciplina, nada impede que a vítima do <i>bullying</i> promova medidas legais buscando a reparação dos danos suportados”, destaca. Ainda de acordo com Alessandra é responsabilidade de todos, família e escola, prestar ajuda necessária a vítimas de <i>bullying</i>, com o intuito de aliviar as consequências da agressão. “Considerando os aspectos morais que alicerçam as relações entre pais e filhos, alunos, escola e sociedade em geral, todos somos responsáveis e se, ao notarmos sinais de vítimas ou agressores em nossos filhos e alunos, devemos agir tempestivamente. Famílias e escolas precisam caminhar juntas”, pontua.</p>
    <p>O Centro Universitário Adventista de São Paulo (Unasp), campus Engenheiro Coelho, entende o <i>bullying</i> como um problema real na vida de crianças e jovens e por esse motivo, aderiu à campanha “Essa brincadeira não tem graça”, com o objetivo de conscientizar vítimas e agressores, alunos de escolas e universidades públicas e privadas para a luta contra o <i>bullying</i>.</p>
   </div>
  </section>

  <section> <!-- Imprensa -->
   <div class="container py-5">
    <h1>Imprensa</h1>
   </div>
  </section>

  <section> <!-- Eu Cuido de Você -->
   <div class="container py-5">
    <h1>Eu Cuido de Você</h1>
    <p class="text-justify stylize-text">Você acompanhou histórias reais de brincadeiras sem graça, mas isso não precisa continuar. Nós entendemos o momento difícil e delicado que envolve uma agressão, mas você deve saber que não está sozinho. O Unasp preparou uma equipe de psicólogos para te ajudar. Tudo o que você precisa fazer é nos contar sua história. Fique a vontade e desabafe nos comentários abaixo sobre o que você enfrenta em seu dia-a-dia. Fique tranquilo, pois não vamos contar para ninguém. Queremos cuidar de você!</p>
    <ul class="list-unstyled form-list">
     <?php while ($persona = $res->fetch_array(MYSQLI_ASSOC)) { ?>

      <li class="card card-inverse rounded-0 mb-4" style="background-color: #333;">
       <div class="card-block">
        <form id="story-<?php echo $persona['id']; ?>" action="scripts/story_submit.php" method="post" class="h-100">
         <input name="id" type="hidden" value="<?php echo $persona['id']; ?>" />
         <div class="d-flex form-body">
          <div class="d-flex flex-column">
           <img src="./images/personas/<?php echo htmlspecialchars($persona['image']); ?>" alt="" />
           <span class="persona-caption"><?php echo htmlspecialchars($persona['name']); ?></span>
          </div>
          <div class="d-flex flex-column w-100">
           <textarea name="story" class="form-control" maxlength="500" required></textarea>
           <button class="btn btn-primary g-recaptcha">Enviar</button>
          </div>
          <div class="recaptcha"></div>
         </div>
        </form>
       </div>
      </li>
     <?php } ?>
    </ul>

   </div>
  </section>

  <!-- Notify Modal -->
  <div class="modal fade" id="notify-modal" tabindex="-1" role="dialog" aria-hidden="true">
   <div class="modal-dialog " role="document">
    <div class="modal-content">
     <div class="modal-body alert mb-0">
     </div>
    </div>
   </div>
  </div>

  <script src="https://code.jquery.com/jquery-3.2.1.min.js" integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4=" crossorigin="anonymous"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/tether/1.4.0/js/tether.min.js" integrity="sha384-DztdAPBWPRXSA/3eYEEUWrWCy7G5KFbe8fFjk5JAIxUYHKkDx6Qin1DkWx51bBrb" crossorigin="anonymous"></script>
  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/js/bootstrap.min.js" integrity="sha384-vBWWzlZJ8ea9aCX4pEW3rVHjgjt7zpkNpZk+02D9phzyeVkE+jo0ieGizqPLForn" crossorigin="anonymous"></script>
  <script src="script.js"></script>
  <script src="https://www.google.com/recaptcha/api.js?onload=onLoadRecaptcha&render=explicit" async defer></script>
 </body>
</html>

<?php
 $res->free();
 $mysqli->close();
?>
Mateus Felipe
  • 1,071
  • 2
  • 19
  • 43

1 Answers1

0

Your issue is

$('form').each(function (id, el) {
    $(el).submit(function (event) {

id is the index and el is the element (form). see here: https://api.jquery.com/each/

Just add the event handler

$('form').submit(function (event) {

That says "Find all the form elements present, add an event handler for submit."

Now inside that alert(id); change to alert($(this).index());

Thus your index (as shown) is the "id" of the element as you had it. return false from within a jQuery event handler is effectively the same as calling both e.preventDefault and e.stopPropagation on the passed jQuery.Event object.

This should address that.

$(function() {
 $('form').on('submit', function(event) {
    event.preventDefault();
    event.stopPropagation();// could have "return false;" at the end
    var me = $(this);
    var myid = $(this).index();
    alert(myid); // not that this IS needed...
    var _data = me.serialize();
    $.ajax({
        type: 'POST',
        url: me.attr('action'),
        data: _data
      })
      .done(function(response) {
        if (response === '') {
          notifySuccess("Já recebemos sua história! Obrigado por compartilhá-la conosco!");
          me.find('textarea').val(' ');
        } else {
          notifyAlert(response);
        }
      })
      .fail(function(data) {
        notifyAlert(data.responseText);
      });
    // just to be clear, this happens NOW, before the ajax completes
    // is that what is desired?
    grecaptcha.reset(me.find('button').attr('id'));
    // return false;  // instead of event.xx above
  });
  $('textarea').click(function() {
    if ($(this).val() === ' ')
      $(this).val('');
  });
});

Side note

$("#notify-modal").find('.modal-body').removeClass('alert-success');
$("#notify-modal").find('.modal-body').addClass('alert-danger');
$("#notify-modal").find('.modal-body').text(message);

can perhaps be (avoid multiple DOM traversals)

$("#notify-modal").find('.modal-body')
  .removeClass('alert-success')
  .addClass('alert-danger')
  .text(message);
Mark Schultheiss
  • 32,614
  • 12
  • 69
  • 100
  • Hello, friend. I used your code, and it works exactly as mine. I'm going to use it, as it seems to be clearer. But unfortunately it doesn't solve my problem. – Mateus Felipe Apr 03 '17 at 19:11
  • See here for long explanation http://stackoverflow.com/questions/1357118/event-preventdefault-vs-return-false – Mark Schultheiss Apr 03 '17 at 19:19
  • Only a second, going to try your new answer. Edit: I tried your new answer with both ways (`event.stopPropagation()` and `return false`) but it didn't solve. Did you do the reproduction steps I said above? So you can see better what's happening. Thanks. – Mateus Felipe Apr 03 '17 at 19:21
  • `var onLoadRecaptcha = function () { $('form').each(function (id, el) { $(el).ready(function () { var submit = function () { $(el).submit(); } var _id = grecaptcha.render( $(el).find('button').get(0), { 'sitekey': '6LeDwBoUAAAAANMD7VBNK2F2agKXl6rduUlelf5U', 'callback': submit } ); $(el).find('button').attr('id', _id); }); }); } ` - same issue? submit for all forms? – Mark Schultheiss Apr 03 '17 at 19:42
  • On the live site,l I only see one request for each click on a capcha button - story_submit.php 200 xhr jquery-3.2.1.min.js:4 214 B 731 ms reload?k=6LeDwBoUAAAAANMD7VBNK2F2agKXl6rduUlelf5U 200 xhr recaptcha__en.js:163 6.6 KB 99 ms – Mark Schultheiss Apr 03 '17 at 19:53