Klick-Event mehrmals ausgeführt

  • Hallo,


    ich habe ein div "eingabe_container" und ein div "ausgabe_container":



    Im ersten div wird eaneingabe.php geladen. Es enthält ein Texteingabefeld und einen Button "Los":


    Code
        <div id="eingabe">
            <input type="text" id="textfeld" class="eaneingabeelement" value="" placeholder="EAN eingeben..." size="60">
            <button id="losbutton" class="eaneingabeelement"" value="Los">Los</button>
            <button id="loeschenbutton" class="eaneingabeelement" value="L&ouml;schen">Löschen</button>
        </div>


    Bei Klick auf den Button "Los" wird in das erste div film.php und in das zweite div liste.php geladen:


    Code
    $(document).ready(function() { 
            $('#losbutton').click(function() { 
                $('#eingabe_container').load('film.php', {
                    buttonGedrueckt: true,
                    textfeldwert: $('#textfeld').val()
                }); 
                $('#ausgabe_container').load('liste.php', {}); 
            }); 
        });


    film.php enthält ein div "film" und einen Button "Hinzufügen":


    PHP
                <div id="film">
                    <?php
                        include 'filmerstellen.php'
                    ?>
                </div>
                <div id="filmbuttons">
                    <p class="textfilmelement"><button id="hinzufuegenbutton" class="button" value="Hinzuf&uuml;gen">Zur Liste hinzufügen</button></p>
                    <p class="textfilmelement"><button id="zurueckzureaneingabebutton" class="button" value="Zur&uuml;ck">Zurück</button>&nbsp; &nbsp; &nbsp;</p>
                </div>


    Im div "film" wird filmerstellen.php geladen. Diese verarbeitet die in das Textfeld von eaneingabe.php eingegebenen Informationen, speichert Informationen in Session Variablen


    Code
          $_SESSION['ean'] = $row['ean'];
          $_SESSION['titel'] = $row['titel'];
          $_SESSION['disctyp'] = $row['disctyp'];
          $_SESSION['besonderheit'] = $row['besonderheit'];


    und gibt diese Informationen dann aus (die Ausgabe geschieht in filmaktualisieren.php):


    Code
    include 'filmaktualisieren.php';


    liste.php enthält ein div "liste" und einen Button "Löschen":


    PHP
    <div id="liste">
        <?php
            include 'listeaktualisieren.php';
        ?>
    </div>
    <button id="listeloeschenbutton" class="button" value="Liste l&ouml;schen">Liste löschen</button>


    Im div "liste" wird listeaktualisieren.php geladen. Diese listet die Einträge der Session Variable "filme" auf und gibt zu jedem Eintrag einen Button "Entfernen" aus:



    Durch den Button "Hinzufügen" in film.php kann ein neuer Eintrag der Liste hinzugefügt werden:


    Klick-Event, das durch den Button ausgelöst wird:


    Code
    $(document).ready(function() { 
        $('#hinzufuegenbutton').click(function() { 
            $('#liste').load('listeneueneintraghinzufuegen.php', {
                buttonGedrueckt: true
            });
        }); 
    });


    listeneueneintraghinzufuegen.php:


    PHP
    <?php
        session_start();
        if (isset($_POST['buttonGedrueckt'])) {
            if (isset($_SESSION['ean'])) {
                    $_SESSION['filme'][] = array($_SESSION['ean'], $_SESSION['titel'], $_SESSION['disctyp'], $_SESSION['besonderheit']);
            }
            include 'listeaktualisieren.php';  
        }
    ?>


    Durch den Button "Löschen" in liste.php können alle Einträge der Liste gelöscht werden:


    Klick-Event, das durch den Button ausgelöst wird:


    Code
    $(document).ready(function() { 
        $('#listeloeschenbutton').click(function() { 
            var loeschenBestaetigt = window.confirm('Möchten Sie die komplette Liste wirklich löschen?');
            if (loeschenBestaetigt == true) {
                $('#liste').load('listeloeschen.php', {
                    buttonGedrueckt: true
                }); 
            }
        }); 
    });


    listeloeschen.php:


    PHP
    <?php
        session_start();
        if (isset($_POST['buttonGedrueckt'])) {
            $_SESSION['filme'] = array();
            include 'listeaktualisieren.php'; 
        }
    ?>


    Durch den Button "Entfernen" in listeaktualisieren.php können Listeneinträge einzeln gelöscht werden:


    Klick-Event, das durch den Button ausgelöst wird:


    Code
    $(document).ready(function() { 
        $('#liste').on('click', '.entfernenbutton', function() { 
            $('#liste').load('elementauslisteentfernen.php', {
                nummerElement: $(this).val()
            }); 
        });
    });


    elementauslisteentfernen.php:


    PHP
    <?php
        session_start();
        if (isset($_POST['nummerElement'])) {
            array_splice($_SESSION['filme'], $_POST['nummerElement'], 1);
            include 'listeaktualisieren.php';
        }
    ?>


    Soweit zum Aufbau und dazu, was die Buttons tun sollten.


    Tatsächlich passiert Folgendes bei Klick auf die Buttons:


    - Bei Klick auf den Button zum Hinzufügen eines Eintrags werden mehrere gleiche Einträge hinzugefügt. Zusätzlich wächst die Anzahl der bei jedem Klick hinzugefügten Einträge mit der Anzahl der Klicks auf den Button.


    - Bei Klick auf den Button zum Löschen aller Einträge wird das Bestätigungsfenster (das vor dem Löschen aufgerufen wird) mehrmals aufgerufen, bevor die Einträge gelöscht werden. Auch hier wächst die Anzahl (hier: Aufrufe des Bestätigungsfensters) bei jedem Klick mit der Anzahl der Klicks auf den Button.


    - Bei Klick auf einen der Buttons zum Entfernen des einzelnen Listeneintrags werden der Listeneintrag und alle auf diesen folgenden Listeneinträge gelöscht.


    Wie erreiche ich das gewollte Verhalten?

  • Zitat

    - Bei Klick auf den Button zum Hinzufügen eines Eintrags werden mehrere gleiche Einträge hinzugefügt. Zusätzlich wächst die Anzahl der bei jedem Klick hinzugefügten Einträge mit der Anzahl der Klicks auf den Button.

    Das ist ein typisches Verhalten, wenn man einen Eventlistener in einem anderen Eventhandler hinzu fügt. Dann werden mit jedem Klick immer mehr Listener hinzu gefügt. Allerdings kann ich etwas derartiges in dem Code, den Du gepostet hast, nicht erkennen. Wäre gut, wenn man das im Zusammenhang sehen könnte: Wenn Du es online hast, dann poste die URL.

  • Hallo,


    danke für deine Antwort.


    Die Seite online zu stellen wäre im Moment ein enormer Aufwand, deshalb habe ich nochmal etwas Code (zu #1) hinzugefügt. Vielleicht erkennt man daran was?

  • Ich denke, es würde das Verständnis erleichtern, wenn Du erklären würdest, was es damit im realen Leben auf sich hat, d. h. was die Einträge in diesen beiden Divs zu bedeuten haben. Es hat ja irgend etwas mit Filmen zu tun.

  • Bei den durcheinander kann man nicht mal ein Test erstellen, da blickt man kaum durch, wann wo was geladen wird usw...

    Da du das ja noch nicht Online hast, wäre eine Erklärung, oder Beispiel Seite von wem anders ganz gut.


    Bist du sicher, dass du so viele Dateien brauchst?

    Könnte mir vorstellen, dass es auch einfacher geht und dadurch auch schon einige Probleme von alleine verduften.

  • Zitat

    Ich denke, es würde das Verständnis erleichtern, wenn Du erklären würdest, was es damit im realen Leben auf sich hat, d. h. was die Einträge in diesen beiden Divs zu bedeuten haben. Es hat ja irgend etwas mit Filmen zu tun.

    Zitat

    Da du das ja noch nicht Online hast, wäre eine Erklärung, oder Beispiel Seite von wem anders ganz gut.


    Im ersten div ist ein Eingabefeld, in das man die EAN eines Films eintragen kann. Bei Klick auf Los werden bestimmte Informationen zu dem Film (Titel, Medium, Besonderheiten) aus der Datenbank abgerufen und (anstelle des Eingabefelds) in das div geladen (durch einen Zurück Button kommt man wieder zurück zum EAN-Eingabefeld und kann so weitere Filme und Informationen abrufen).


    Im zweiten div ist zunächst (beim ersten Laden der Seite) eine Begrüßung. Klickt man auf den Los Button aus dem ersten div wird in dem div eine (wenn man nicht eingeloggt ist und bereits zuvor eine Liste erstellt hat, zunächst leere) Liste geladen.


    Durch einen Button im ersten div kann man den Film und die Informationen in die Liste seiner Filme laden.


    Die Seite dient dazu, eine Liste seiner Filme mit den dazugehörigen Filminformationen zu erstellen.


    Zitat

    Könnte mir vorstellen, dass es auch einfacher geht und dadurch auch schon einige Probleme von alleine verduften.


    Ihr seht, es ist schon ein bisschen kompliziert und man benötigt einige Seiten.


    Der jQuery Code ist komplett in einer Datei.


    Hier noch Bilder, die das Ganze vielleicht noch veranschaulichen können (Seite hat erst grundlegende Funktionen und ist nur grundlegend gestyled. Der "Löschen" Button am unteren Rand der Bilder verschwindet auf den Bildern etwas hinter der "Bild-Navigation". Am Besten "Originalversion aufrufen"):


    EAN-Eingabe und leere Liste:


    html-seminar.de/woltlab/attachment/3159/


    Filminformationen, die nach der Eingabe der EAN und Klick auf Los angezeigt werden und Liste, der bereits Filme hinzugefügt wurden:


    html-seminar.de/woltlab/attachment/3160/

  • Frage, Du schreibst:

    Zitat

    Durch den Button "Hinzufügen" in film.php kann ein neuer Eintrag der Liste hinzugefügt werden:


    Klick-Event, das durch den Button ausgelöst wird:


    Code

    1. $(document).ready(function() {
    2. $('#hinzufuegenbutton').click(function() {
    3. $('#liste').load('listeneueneintraghinzufuegen.php', {
    4. buttonGedrueckt: true
    5. });
    6. });
    7. });

    und:

    Zitat


    Der jQuery Code ist komplett in einer Datei.

    Wie kann das funktionieren? Wenn das Javascript im document-ready ausgeführt wird, existiert der Button doch noch gar nicht, weil das HTML erst später geladen wird?

  • Zitat

    Wie kann das funktionieren? Wenn das Javascript im document-ready ausgeführt wird, existiert der Button doch noch gar nicht, weil das HTML erst später geladen wird?

    Ich weiß nicht genau, was du meinst.


    Ich integriere in jede PHP-Datei, in der Elemente wie Buttons sind, die "von jQuery überwacht" werden, an den Anfang


    Code
    <!-- ---jQuery Import--- -->
    <script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
    
    <!-- ---Javascript / jQuery--- -->
    <script src="main.js"></script>


    Den jQuery-Code für alle Elemente habe ich komplett in der Datei main.js.


    Ich bin Anfänger, es kann also sein, dass ich einen einfachen Fehler gemacht habe.

  • Bingo, dann ist mir alles klar. Anfangs schrieb ich:

    Zitat

    Das ist ein typisches Verhalten, wenn man einen Eventlistener in einem anderen Eventhandler hinzu fügt.

    Das trifft hier nicht ganz zu, aber jedes Mal, wenn Du irgend etwas mit $('selector').load() lädst, wird das komplette Javascript wieder ausgeführt und für alle Buttons, die in dem Moment vorhanden sind, erneut jeweils ein Eventlistener neu hinzu gefügt. Das erklärt genau das Problem, das Du beschreibst.


    Das Nachladen von HTML mit eingebettetem Javascript ist immer fehleranfällig und meine Empfehlung lautet: Tu's nicht.


    Lösung indem Du das Javascript nur ein Mal in der Kopfseite einbindest. Für Elemente, die zu dem Zeitpunkt noch nicht vorhanden sind, kannst Du das Eventbubbling nutzen:

    https://learn.jquery.com/events/event-delegation/

    Du hast das schon getan bei den Entfernen-Buttons in der Filmliste:

    $('#liste').on('click', '.entfernenbutton', function() {

    Genau so funktioniert es mit den anderen Buttons auch.

  • Verstehe. Ich habe jetzt das Javascript nur in den Header eingebunden. Beim Eventbubbling könnte ich noch Hilfe gebrauchen:


    Am Beispiel vom Hinzufügen Button:


    Das nächste "Elternelement" ist das div filmbuttons und der Button soll listeneueneintraghinzufuegen.php in das div liste laden. Also müsste der jQuery-Code lauten:


    Code
    $(document).ready(function() { 
        $('#filmbuttons').on('click', '#hinzufuegenbutton', function() { 
            $('#liste').load('listeneueneintraghinzufuegen.php', {
                buttonGedrueckt: true
            }); 
        });
    });


    Leider funktioniert der Button so nicht.

  • BTW: Nachdem ich mich damit jetzt ein wenig beschäftigt habe, stimme ich Basti zu: Man kann das wahrscheinlich einfacher machen. Zunächst mal nur für den Eingabecontainer: Das HTML statisch für beide Varianten anlegen und mit einer Klasse "hidden" das andere jeweils verbergen. Dann braucht es nur das Laden mit Ajax für die Filmdaten und auch kein Eventdelegation. Könnte dann so aussehen:

  • Funktioniert alles! Vielen Dank!


    Zitat


    Das HTML statisch für beide Varianten anlegen und mit einer Klasse "hidden" das andere jeweils verbergen.


    Das ist eine gute Idee! Ich überlege es mir, das so anzupassen!

Jetzt mitmachen!

Sie haben noch kein Benutzerkonto auf unserer Seite? Registrieren Sie sich kostenlos und nehmen Sie an unserer Community teil!