Beiträge von Sempervivum

    Zitat

    Mir ist völlig unklar, welche beiden Werte ich nun miteinander vergleichen müsste.

    $choosen ist ja offenbar die Antwort, für die sich der Benutzer entschieden hat. Und $row['trueanswer'] die richtige Antwort, die in der Datenbank hinterlegt ist. D. h. Du müsstest testen, ob sie gleich sind:

    $choosen == $row['trueanswer']

    liefert true, wenn sie übereinstimmen und false, wenn nicht.

    Und das dann in die Antwort eintragen:

    Code
        $statement = $pdo->prepare("SELECT * FROM animals WHERE id = ?");
        $statement->execute(array($id));
        $statement->execute(array($choosen));
        $row = $statement->fetch();
        $trueanswer = [
          'id' => $id,
          'trueanswer' => ($choosen == $row['trueanswer']),
        ];
        echo json_encode($trueanswer);
    Zitat

    Geht das auch für wirklich jede Aktivität? Also z.b irgendwo hinklicken?

    Natürlich, Du kannst für das ganze Dokument einen Eventlistener registrieren und ebenfalls eine Nachricht an den Server schicken. Wahrscheinlich nur, wenn nach dem letzten Klick oder Keypress eine gewisse Zeit verstrichen ist, sonst kann es bei wildem Klicken zu einer Flut von Nachrichten kommen.

    Zunächst mal muss man festlegen, wann ein Benutzer als "noch aktiv" gelten soll:

    a) Er hat eine Seite geöffnet, unabhängig davon ob er Aktivitäten ausführt. Dann kannst Du mit einem Heartbeat arbeiten, d. h. der Browser sendet zyklisch ein Lebenszeichen und beim Empfang wird das "last_seen" aktualisiert. Problem: Die Seite kann in einem nicht aktiven Tab noch offen sein und der Benutzer hat sie vergessen:

    b) Der Benutzer führt irgend welche Aktivitäten aus. Dann kannst Du bei jeder Aktivität das "last_seen" aktualisieren. Kommt eine Aktivität nach Ablauf der Zeit, gilt er als ausgeloggt. Man kennt das ja, dass man eine Meldung bekommt der Form "Sie wurden aus Sicherheitsgründen ausgeloggt weil Sie mehr als xxx Minuten nicht aktiv waren."

    Zitat

    1. Wie müsste die Datenbank strukturiert sein, wie wird der richtige Eintrag gekennzeichnet?

    Wenn es nur eine Spalte "trueanswer" gibt, ist es einfach: Du brauchst nur die ausgewählte Antwort mit der zu vergleichen, die vom Client bzw. Browser kommt, sind sie gleich, lieferst Du true zurück, wenn nicht false.

    Zitat

    2. Wie schicke ich etwas zum Server? Bisher habe ich ja immer nur etwas geholt, habe also per JavaScript PHP-Dateien angesprochen, die Daten geholt haben.

    Doch, auch bisher schon schickst Du etwas an der Server, und zwar als POST-Parameter z. B. hier, indem Du dem Objekt oneQuestion die ID mit append hinzu fügst und es im Body der Anfrage einträgt:

    Code
      const oneQuestion = new FormData();
      oneQuestion.append('id', i);
      fetch('animalgame2.php', {
        method: 'post',
        body: oneQuestion
      }).then // usw.

    Beim Holen der Info "Antwort ist richtig" brauchst Du jetzt nur noch die gewählte Antwort ebenfalls hinzu zu fügen:

    Code
           // 3. Abfrage
    
            const trueAnswer = new FormData();
            trueAnswer.append('id', i);
            trueAnswer.append('choosen', questions.answers[j]);
            fetch('animalgame3.php', {
              method: 'post',
              body: trueAnswer
            }).then

    Statt der gewählten Antwort im Volltext könntest Du auch einfach nur den Index in der Datenbank eintragen und an den Server übertragen, das würde das Ganze etwas kompakter machen.

    Das sieht doch schon mal gut aus, kein Grund, dir Sorgen zu machen, dass es nicht korrekt ist.

    Am besten das ganze, ohne das i = 1; in eine Funktion packen. Dann im HTML ein Button-Element einfügen und einen Eventlistener für "click" darauf registrieren. Darin kannst Du dann die Variable i erhöhen und durch Aufruf der Funktion die Frage und die Antworten holen und anzeigen.

    Und bei der Definition von i besser ein let davor setzen: let i = 1:

    Der Fehler, den ich jetzt gemacht habe, besteht darin, dass ich das click() vor dem Registrieren der Eventlistener gemacht habe, dann läuft es natürlich ins Leere. Und bei diesem Ansatz musst Du die Klasse "active" beim ersten Button wieder löschen.

    BTW, ich vergaß: Willkommen im Forum :)

    OK, da lag ich offenbar daneben, weil die Elemente nicht über CSS sichtbar gemacht werden sondern über Javascript. Also neuer Versuch: Einfach einen Klick auf den ersten Button simulieren:

    (ebenfalls ungetestet)

    Ohne das groß getestet zu haben, scheint mir, dass das alles über die Klasse "active" bei den Buttons gesteuert wird. In dem Fall dürfte es ausreichend sein, bei dem betr. Button diese Klasse hinzu zu fügen:

    Code
    <button class="collapsible active"><span style='font-weight: 700; font-family: "Source Sans Pro"; font-size: 20px; color: rgb(000, 000, 000); padding-left: 47px;'>Marketing</button>

    Javascript beachtet Groß- und Kleinschreibung. getElementsByID musst Du so schreiben: getElementById.

    Wenn der erste Text gleich offen sein soll, brauchst Du dem betr. Element nur die Klasse "active" zu geben.

    Oder möchtest Du, dass er immer offen bleibt?

    Wenn man das vorige Element schließen will, wird es leider ein wenig komplizierter. Ich habe das folgende Javascript kommentiert, damit Du verstehst, was sich abspielt:

    Zitat

    Wie genau kann ich denn den vorherig angeklickten Button mit diesem Code ansprechen?

    Das kannst Du, indem Du querySelector verwendest und die Klasse "active" angibst:

    const contentActive = document.querySelector('.flexbox-content.active');

    Da gibt es jetzt zwei Probleme:

    1. Im HTML und CSS verwendest Du für die Buttons die Klasse "flexbox-button2", im Javascript jedoch "flexbox-button", d. h. Du musst das Javascript so ändern:

    Code
            <script>
                const buttons = document.getElementsByClassName('flexbox-button2'),
                    contents = document.getElementsByClassName('flexbox-content');
                for (let i = 0; i < buttons.length; i++) {
                    buttons[i].addEventListener('click', function () {
                        contents[i].classList.toggle('active')
                    });
                }
            </script>

    Und im CSS musst Du die den Content zunächst unsichtbar machen, indem Du die Höhe auf 0 setzt:

    Code
            /* Content zunächst unsichtbar machen: */
            .flexbox-content .flexbox-text {
                height: 0;
                overflow: hidden;
            }
    
            /* Ist die Klasse "active" gesetzt, den Content sichtbar machen: */
            .flexbox-content.active .flexbox-text {
                height: 100%;
            }

    Danke, so wird das Ganze klar. Ohne es ein wenig umzuorganisieren, wird sich dein gewünschtes Layout wohl nicht realisieren lassen. Also links ein Container mit den Buttons und rechts einer mit den Inhalten. Und dann muss man eine Beziehung zwischen den Buttons links und den Inhalten rechts herstellen. Ich dachte zunächst daran, das mit einem data-Attribut bei den Buttons zu machen, aber mit diesem HTML und Javascript dürfte das gar nicht notwendig sein:

    (ungetestet)

    Das HTML musst Du selber noch vervollständigen.

    Leider kann ich aus dem HTML und CSS nicht erkennen, wie dieses Accordion funktioniert. Weder finde ich Check- oder Radiobuttons noch ein Javascript, das es macht. Irgend wie mit diesem kit.fontawesome? Oder der CSS-Datei, die Du einbindest? Kannst Du das erklären?