venty: jquery ajax wird 2 mal ausgeführt (?)

Hallo!

Ich habe wieder mal eine Nuss zu knacken, aber ohne Hilfe wird das nichts. Vor ein paar Tagen, habe ich mir einen Layer mit jQuery zusammengebastelt. Er funktioniert auch, aber wenn man Ihn abschickt, wird er gleich zwei mal abgeschickt und ich weiß nicht warum :S

Hier der Code, der dateien ...

... die datei in der ich den Layer eingebunden habe, vermutlich nicht wichtig ...

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">  
<html>  
    <head>  
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">  
        <script src="jsLayer/jquery.js" type="text/javascript"></script>  
        <script type="text/javascript">  
            var nl = true;  
            var fadeoutdirect = false;  
        </script>  
        <script src="jsLayer/jsLayer.js" type="text/javascript"></script>  
        <style type="text/css">  
            .jsLayer {  
                border:1px solid black;  
                -moz-border-radius:10px;  
                background-color:silver;  
            }  
        </style>  
        <title>jsLayer</title>  
    </head>  
    <body>  
        <h1>Fülltext h1</h1>  
  
        <!-- hier ist nurr fülltext -->  
  
    </body>  
</html>  

... der JS/jQuery Code ...

$('document').ready(function() {  
    $('body').append('<div class="jsLayer"><div class="jsLayerTasks"><img class="jsLayer-close" align="right" src="jsLayer/images/close.gif" /></div><div class="jsLayer-text"></div><div class="jsLayer-form"></div><div class="jsLayer-WaitImg"><img src="jsLayer/images/wait.gif" alt="please wait.." /></div></div>');  
    $('.jsLayer').hide();  
    $('.jsLayer-WaitImg').hide();  
    if (nl) {  
        $('.jsLayer-text').load('jsLayer/html/text.php #jsLayer-nl');  
    } else {  
        $('.jsLayer-text').load('jsLayer/html/text.php #jsLayer-gs');  
    }  
  
    $('.jsLayer-form').load('jsLayer/html/form.php');  
    $('div.jsLayer').fadeIn('slow');  
  
    $('.jsLayer-close').click(function(){  
        $('.jsLayer').fadeOut('slow');  
    });  
  
    $('.jsLayer-Form').submit(function(){  
        $('.jsLayer-text').fadeOut('slow');  
        $('.jsLayer-form').fadeOut('slow',function(){  
            $('.jsLayer-WaitImg').fadeIn('slow',function(){  
                $.ajax({  
                    url: "jsLayer/ajax/save.php",  
                    type: "POST",  
                    data: {  
                        email: $('.jsLayer-EMail').val(),  
                        ip: $('.jsLayer-IP').val(),  
                        newC: $('.jsLayer-NewC:checked').val()  
                    },  
                    success: function(data) {  
                        $('.jsLayer-WaitImg').fadeOut('slow',function(){  
                            $('.jsLayer').append(data);  
                            $('.jsLayer-success').hide();  
                            $('.jsLayer-success').fadeIn('slow');  
                        });  
                    },  
                    error: function(XMLHttpRequest, textStatus, errorThrown) {  
                        alert('Es gab einen Fehler im jsLayer!\nBitte benachrichtigen Sie den Homepage Betreiber.');  
                    }  
                });  
            });  
        });  
        if (fadeoutdirect) {  
            $('.jsLayer').fadeOut('slow');  
        }  
        return false;  
    });  
});

... PHP  Datei die die Mail an mich verschicken soll ...

<?php  
// hier die Emailadresse angeben an die diese Mail verschickt werden soll  
$to = "venty@venty.at";  
// hier den gewünschten Betreff angeben  
$subject = "===Neuer Abonennt::jsLayer===";  
// Nachrichten text zusammensetzen  
$message = "Neue Informationen\n\n"  
    ."Email:\t\t".$_POST['email']."\n"  
    ."IP:\t\t".$_POST['ip']."\n"  
    ."TimeStamp:\t".time()."\n"  
    ."Neuer Kunde:\t";  
if ($_POST['newC']) {  
    $message .= "Ja";  
} else {  
    $message .= "Nein";  
}  
// welche Mailadresse soll als sender vermerkt werden  
$from = "noreply@jsLayer.com";  
// header informationen  
$header = "From: ".$from;  
if (!mail($to, $subject, $message, $header)) {  
    die('<span style="color:red">Ihre Emailadresse konnte nicht gespeichert werden!</span>');  
}  
?>  
<div class="jsLayer-success">  
    <span style="color:green;">Ihre Emailadresse wurde erfolgreich gespeichert!</span>  
</div>

... alle anderen dateien bestehen nur aus HTML Elementen für die Texte und das Formular, können also nichts.

Dank jedem der mir hilft :)

MfG Venty

  1. Hallo, Venty!

    Die Antwort auf Deine Frage liegt in den Events, die Du verwendest.

    Diese funktionieren folgendermaßen: ein Event tritt auf, bspw. das Absenden eines Formulars. In modernen Browsern beginnt nun die erste Phase des Events, das sogenannte "Capturing", bei dem vom document bis zum betroffenen Node alle eventfähigen Knoten durchlaufen werden. Darauf folgt die zweite Phase, das "Bubbling", bei der die gleiche Reihenfolge noch einmal rückwärts durchlaufen wird, bevor die normale Reaktion ausgeführt wird.

    Daraus folgt, dass das submit-Callback, in dem Dein AJAX-Request stattfindet, doppelt aufgerufen wird. Das ist leicht zu unterbinden, indem Du eine der beiden Phasen ausschließt:

    function(ev){  
      ev.stopPropagation(); // verhindert das Bubbling  
      ...  
    }
    

    Das sollte den 2. Request wirksam unterbinden.

    Gruß, LX

    --
    RFC 1925, Satz 3: Mit ausreichendem Schub fliegen Schweine ganz wunderbar. (...)
    1. function(ev){

      ev.stopPropagation(); // verhindert das Bubbling
        ...
      }

      
      >   
      > Das sollte den 2. Request wirksam unterbinden.  
        
      Hi, leider funktioniert das nicht ganz :S Hab ich das so richtig gemacht?:  
      ~~~javascript
      ...  
      $('.jsLayer-Form').submit(function(ev){  
              ev.stopPropagation();  
      ...
      

      in der Dokumentation finde ich keinen guten Hinweis.

      Danke für die Hilfe :)

      1. Ansonsten lasse Dir mal vor dem Ajax-Request das Event-Objekt in Firebug ausgeben:

        try { console.log(ev); } catch(e) {}

        Dann kannst Du leicht feststellen, was da jeweils ankommt - und vielleicht eine Möglichkeit, den doppelten Aufruf zu unterscheiden und abzustellen.

        Gruß, LX

        --
        RFC 1925, Satz 3: Mit ausreichendem Schub fliegen Schweine ganz wunderbar. (...)
        1. Ansonsten lasse Dir mal vor dem Ajax-Request das Event-Objekt in Firebug ausgeben:

          try { console.log(ev); } catch(e) {}

          Dann kannst Du leicht feststellen, was da jeweils ankommt - und vielleicht eine Möglichkeit, den doppelten Aufruf zu unterscheiden und abzustellen.

          Gruß, LX

          Servus, habe die Dateien jetzt auf dem Server. Da ich nicht weiß wie das in Firebug aussehen soll, würde ich gerne dich darum bitten da mal schnell drauf zu schauen. Ich hab echt keine Ahnung was das DOM zeug zu bedeuten hat :-S

          Danke jetzt schon :)

          LG Venty

          1. Habe den Fehler gerade gefunden. Es war Bubbling, aber das lag daran, dass das div oberhalb des forms die gleiche Klasse hat. Du musst also das Event binding entsprechend anpassen:

            $('form.jsLayer-Form').submit(...)

            Gruß, LX

            --
            RFC 1925, Satz 3: Mit ausreichendem Schub fliegen Schweine ganz wunderbar. (...)
            1. Habe den Fehler gerade gefunden. Es war Bubbling, aber das lag daran, dass das div oberhalb des forms die gleiche Klasse hat.

              Hi LX,

              der div darüber, hat nicht den gleichen Namen. jsLayer-form/jsLayer-Form ... leider, aber danke :)

              1. Hi,

                Habe den Fehler gerade gefunden. Es war Bubbling, aber das lag daran, dass das div oberhalb des forms die gleiche Klasse hat.

                der div darüber, hat nicht den gleichen Namen.

                Den gleichen Namen kann er auch gar nicht haben, denn DIV hat kein name-Attribut.

                jsLayer-form/jsLayer-Form ... leider, aber danke :)

                Doch, das ist die „gleiche“ Klasse - zumindest in der Praxis.

                Gebe
                javascript:alert(document.getElementsByClassName("jsLayer-Form").length)
                in der Adresszeile vom Firefox ein, und du wirst beide Male die Ausgabe "2" erhalten - egal, ob du das F groß oder klein schreibst.

                Und damit kommt in folgendem Code

                        $('.jsLayer-form').fadeOut('slow',function(){  
                            $('.jsLayer-WaitImg').fadeIn('slow',function(){  
                                $.ajax({ [...]
                

                die Callback-Funktion *zwei* mal zur Ausführung, und daraus resultieren auch *zwei* AJAX-POST-Requests ...

                MfG ChrisB

                --
                RGB is totally confusing - I mean, at least #C0FFEE should be brown, right?
                1. ok jetzt funktionierts :)

                  danke für eure hilfe (und gedult ;)