Beiträge von Sempervivum

    Ja, Du kannst den Code auch komplett auslagern aber dann muss Du die script-Tags und die Zeilen mit den Kommentarzeichen <!-- //-->

    weg lassen. Ich hoffe, Du hast sie bisher nicht drin. Nur das was ich in Posting #3 gepostet habe, in die js-Datei. Der Browser weiß schon durch das Einbinden mit dem Script-Tag, dass es sich um Javascript handelt.

    Du hast jetzt die Skript-Tags verschachtelt. Erst die Daten einbinden und dann den Rest:

    Code
    1. <script src="data.js" ></script>
    2. <script>
    3. /** Ab hier nichts mehr ändern! **/
    4. var num = Math.random();
    5. var ran = Math.floor((image.length - 1) * num) + 1;
    6. document.write('<div id="zahl1">' + link[ran] + '</div><div id="nichtmarkieren"><img src="' + image[ran] + '" border="0" /></div></a>');
    7. </script>

    (type, language und die Kommentarzeichen braucht man heute nicht mehr.)

    Da sehe ich zwei Hauptprobleme:

    1. Ein überflüssiges span-Tag innerhalb des Label. Dadurch überlappen sich die Labels.

    2. Eine ID muss auf der Seite eindeutig sein. Daher wirkt ein Klick auf das zweite Label auf den ersten Inhalt. Du musst für jedes Label-Input-Paar eine eigene ID verwenden.

    Davon abgesehen ist nav und ul für den Inhalt, der aufgeklappt wird, wenig angebracht. Besser z. B. ein section-Tag und den Inhalt darin mit Überschrift und Abschnitten strukturieren.

    Da das Javascript-Syntax ist, kannst Du diesen Code auch in eine js-Datei auslagern und mit dem script-Tag einbinden. D. h. die komplette Definition der beiden Arrays:

    in eine Datei, z. B. data.js schreiben, ohne script-Tags, und mit diesem Code einbinden:

    Code
    1. <script src="data.js"></script>

    Was Du da beschreibst stimmt genau mit dem überein was ich im Javascript sehe:

    (Kommentare habe ich hinzu gefügt)

    Es sollte machbar sein, das Hintergrundbild aus dem data-Attribut mit CSS so einzurichten, wie Du es brauchst.

    "Trying to access array offset on value of type bool in /users/music-quiz/www/animalgame3.php on line 21"

    liegt i. allg. daran, dass eine Funktion false statt eines Arrays liefert, weil bei der Ausführung ein Fehler aufgetreten ist. Siehe z. B. die Doku von fetch:

    https://www.php.net/manual/de/pdostatement.fetch.php


    Um heraus zu finden, was für ein Fehler kannst Du auch die SQL-Fehler anzeigen lassen, siehe hier:

    https://www.php.net/manual/de/pdostatement.errorinfo.php


    Ohne dies zu sehen, scheint mir aber, dass diese Zeile überflüssig ist:

    $statement->execute(array($choosen));

    Du willst ja den Datensatz auslesen, wo die ID passt und dieses $choosen ist etwas anderes als die ID.

    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
    1. $statement = $pdo->prepare("SELECT * FROM animals WHERE id = ?");
    2. $statement->execute(array($id));
    3. $statement->execute(array($choosen));
    4. $row = $statement->fetch();
    5. $trueanswer = [
    6. 'id' => $id,
    7. 'trueanswer' => ($choosen == $row['trueanswer']),
    8. ];
    9. 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
    1. const oneQuestion = new FormData();
    2. oneQuestion.append('id', i);
    3. fetch('animalgame2.php', {
    4. method: 'post',
    5. body: oneQuestion
    6. }).then // usw.

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

    Code
    1. // 3. Abfrage
    2. const trueAnswer = new FormData();
    3. trueAnswer.append('id', i);
    4. trueAnswer.append('choosen', questions.answers[j]);
    5. fetch('animalgame3.php', {
    6. method: 'post',
    7. body: trueAnswer
    8. }).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
    1. <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>