Beiträge von Sempervivum

    Zitat

    dass ich den Tooltip mit div.tooltip im CSS ansprechen kann, was nicht funktioniert. Wenn ich mich richtig erinnere bedeutet das ja auch, dass es die Unterklasse .div in .tooltip gibt.

    Das letztere trifft nicht ganz zu, div.tooltip spricht ein div an, das selber die Klasse "tooltip" hat.

    Zitat

    Jedenfalls mit .tooltip div hat es geklappt.

    Dieses spricht jetzt ein div-Element innerhalb eines Elementes mit der Klasse "tooltip" an.

    Ja, auch dies ist ein unerwünschtes Ergebnis davon, dass wir das Registrieren aus der Funktion heraus genommen haben. Ich dachte zunächst daran, diese Anzahl in einer globalen Variablen zu speichern, was unbefriedigend wäre, aber es gibt eine bessere Lösung:

    In der Funktion makeQuestion brauchen wir die Variable countofquestions jetzt nicht mehr, denn sie wird nur in den Eventlistenern für die Antwort-Buttons gebraucht. Also können wir diesen Parameter bei makeQuestion löschen. Statt dessen definieren wir eine Funktion z. B. addListeners, die die Eventlistener registriert und die Anzahl countofquestions als Parameter hat:

    Jetzt müssen wir nur noch dafür sorgen, dass die Funktion auch mit diesem Parameter aufgerufen wird. Das erreichen wir, indem wir die Funktion als Callback an getCountRows übergeben. Für makeQuestion ist dies jetzt nicht mehr nötig, diese Funktion können wir direkt aufrufen:

    Code
    getCountRows(addListeners);
    makeQuestion();

    Wieder ungetestet, wenn noch Fehler übrig sind, müssen wir weiter sehen.

    Verflixt, ich hatte vergessen, auf einen Punkt hinzuweisen: Damit man die Buttons leicht ermitteln kann, muss man dem Container die Klasse "answers" geben:

    Code
    <div class="backgroundLight answers">

    Die Nodelist mit den Buttons wird ja mit diesem Selektor ermittelt:

    Code
    const answerBtns = document.querySelectorAll('div.answers button');

    Fehlt die Klasse "answers" bleibt die Nodelist leer und nichts passiert wenn man versucht, die Eventlistener zu registrieren.

    Hast Du dich schon mit dem Debugger für Javascript vertraut gemacht? Dieser ist sehr hilfreich, wenn man solche Fehler finden will. Man muss nicht jedes Mal ein console.log einfügen, um eine Variable zu überprüfen etc.

    Danke für die guten Wünsche, ich wünsche ebenfalls einen angenehmen 2. Feiertag!

    Ich habe mir das jetzt etwas genauer angesehen und bemerkt, dass es mit einem trivialen Verschieben des Registrierens nicht getan ist, denn innerhalb der Listener wird auf die Antwort vom Server zugegriffen und die steht nach dem Verschieben nicht zu Verfügung. Man kann das jedoch relativ leicht lösen, indem man den Text der Antwort aus dem innerHTML des betr. Buttons liest. Hier das geänderte Javascript, ich habe die geänderten Stellen mit !!! markiert:

    https://pastebin.com/FXekS8LQ

    Ich hatte vor, es zu testen, habe dann aber bemerkt, dass mir dafür die Datenbank und das PHP fehlt. Daher ungetestet.

    Zitat

    Und zweitens: Wie kann ich meine Vorstellungskraft für die Abläufe trainieren? Immer, wenn es um Verschachtelungen geht, steigt mein Gehirn aus.

    Um einen Überblick über die Verschachtelungen im Code zu bekommen, sind das A und O die sinnvollen Einrückungen des Codes aber die hast Du ja schon, wie ich sehe.

    Etwas anderes sind die zeitlichen Abläufe. Man muss ein Gefühl dafür bekommen, wann ein Codeabschnitt ausgeführt wird und welche Variablen dabei zur Verfügung stehen. Die kritischen Dinge sind hier:

    • Das Holen von Daten vom Server mit fetch. Dabei muss man sich im klaren darüber sein, dass das asynchron abläuft und die Antwort nur im then-Zweig zur Verfügung steht.
    • Die Eventlistener. Hier muss man sich im klaren darüber sein, dass der Code darin erst ausgeführt wird, wenn, in unserem Fall, auf einen Button geklickt wird. Und ein Fallstrick in der Form, dass immer mehr und mehr Listener registriert werden.

    Hier braucht es u. U. Übung und Erfahrung um die Abläufe schneller zu verstehen.

    Danke, ich wünsche ebenfalls angenehme Weihnachtsfeiertage!

    Zitat

    Ich kann zwar den Elementstatus auf :hover stellen, aber der Tooltip verschwindet trotzdem.

    Zunächst mal bist Du damit schon auf dem richtigen Wege, es ist nur manchmal ein wenig schwierig, das richtige Element zu erwischen, für das das Hover zugeordnet wurde, denn häufig sind die fraglichen Elemente verschachtelt.

    Allerdings kann es auch sein, dass der Hover-Effekt mit Javascript realisiert wurde, dann hilft dir das :hover in den Entwicklerwerkzeugen nicht weiter. Wenn der Effekt jedoch mit einer Klasse realisiert wurde kannst Du diese Klasse setzen und das Element sichtbar zu machen.

    Danke, ich wünsche ebenfalls einen angenehmen Rest von den Weihnachstsfeiertagen!

    Das liegt daran, dass Du jedes Mal, wenn Du eine neue Frage holst, die Eventlistener für Klick auf den Button neu registrierst. Deshalb werden es mit jeder Frage mehr. Das HTML der Buttons bleibt ja unverändert und die alten Eventlistener bleiben bestehen.

    Etwas anderes wäre es, wenn Du das innerHTML des ganzen Containers div.question austauschen würdest. Dann würden die Buttons neu erzeugt und die alten Eventlistener gingen verloren und müssten neu registriert werden.

    Zitat

    Der Restart klappt, aber das Absturzproblem ist leider noch nicht aus der Welt.

    Wie ist das zu verstehen? Wird der Absturz vom Master nicht erkannt, weil der Slave trotzdem Lebenszeichen sendet?

    Zitat

    Deshalb müsste ich es jetzt hinkriegen, das Slave-Fenster nach der Fehlermeldung zu schließen, damit der Master es neu öffnet. Ein einfaches 'close;' hat nicht genügt. Wie macht man das?

    Wenn der Absturz direkt auf der Seite erkannt wird, könntest Du einfach einen Reload versuchen:

    https://developer.mozilla.org/en-US/docs/Web/API/Location/reload

    Wenn das funktioniert, brauchtest Du die Struktur mit Master und Slave nicht.

    Das Senden von Nachrichten vom Slave zum Master funktioniert mit postMessage auch mit dem file-Protokoll, d. h. wenn man die Seite mit Doppelklick aufruft.

    Master-Skript:

    Slave-Skript:

    Code
            const intv = 1000;
            setInterval(() => {
                // Send alive message to opener:
                opener.postMessage('alive', '*');
                console.log('livesign sent');
            }, intv);

    Die schlechte Nachricht: Es ist mir nicht gelungen, den Popup-Blocker nur für diese eine Seite auszuschalten sondern musste es global tun. Lag wohl am file-Protokoll.

    Hm, das wäre natürlich unangenehm, wenn Du nur wegen dieser Kleinigkeit XAMPP installieren müsstest. Man kann eine Seite auch für Cross-Domain-Access frei geben, aber das erfordert ebenfalls einen Webserver. Wenn wir die Slave-Seite in einem iFrame anzeigen bekommen wir die selben Probleme wenn Master und Slave kommunizieren sollen. Ich erinnere da noch eine andere Möglichkeit, muss nachsehen, ob ich es wiederfinde ...

    Tut mir Leid, das vergaß ich ganz: Weil das Popup durch meinen Browser blockiert wurde, hatte ich einen Button eingeführt, um den Slave zu öffnen. Das war auch zunächst erfolgreich aber nützte nichts, wenn ich später beim Ausfall des Slave das Fenster durch das Skript neu öffnen wollte. Das ging dann nur, wenn ich den Popup-Blocker ausschaltete. Damit war dann die Notwendigkeit für den Button entfallen.

    Reduziere das Skript auf dieses:

    Code
            const intv = 1000;
            let win;
            // Open slave when button is clicked:
            // document.querySelector('button').addEventListener('click', event => {
                win = window.open('slave.html');
            // });
            let timer;
            // usw. wie bisher

    Ich habe da mal eine Demo gemacht.

    Du brauchst eine Masterseite und dort dieses Javascript:

    Dieses öffnet die Slaveseite. Dort laufen dann all deine Javascripts und zusätzlich dieses:

    Code
            const intv = 1000;
            // Send lifesign to master periodically:
            setInterval(() => {
                // opener is the page that has opened this one,
                // i. e. the master page.
                // We call the function supervise over there:
                opener.supervise();
                console.log('livesign sent');
            }, intv);

    So weit getestet, man muss jedoch unbedingt für die Masterseite den Popupblocker ausschalten.

    Offene Frage: Du schriebst, dass die Seite nicht komplett abstürzt, sondern dass einige Funktionen (Uhrzeitanzeige) noch gehen. Wenn das auch für das JS für das Senden der Lebenszeichen zutrifft haben wir zunächst mal schlechte Karten.