Danke, ich wünsche ebenfalls einen schönen Feiertagsabend!
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.
ZitatJedenfalls 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:
Code
Alles anzeigen// !!! Eventlisteners für Klick auf die Antworten registrieren. function addListeners(countofquestions) { // !!! im weiteren Verlauf steht jetzt countofquestions zur Verfügung for (let j = 0; j < answerBtns.length; j++) { document.getElementById(j + 1).addEventListener('click', () => { pointerEventsOff() const answerNumber = document.getElementById(j + 1).getAttribute('id'); // !!! An dieser Stelle steht uns die Antwort vom Server nicht mehr direkt zu Verfügung. // !!! Wir müssen sie daher aus dem HTML des Buttons holen: const answerTxt = answerBtns[j].innerHTML; answerReplay.innerHTML = answerTxt; answerReplayRight.innerHTML = answerTxt; // !!! usw. wie bisherJetzt 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:
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:
Die Nodelist mit den Buttons wird ja mit diesem Selektor ermittelt:
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:
Ich hatte vor, es zu testen, habe dann aber bemerkt, dass mir dafür die Datenbank und das PHP fehlt. Daher ungetestet.
ZitatUnd 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.
-
Zitat
Muss der Code Eventlistener an eine andere Stelle?
Ja genau, im Moment steht der Code mit dem addEventListener ja innerhalb des then-Zweiges beim fetch für das Holen einer neuen Frage und wird dort immer wieder ausgeführt. Du musst ihn dort heraus nehmen und z. B. am Ende des Skriptes platzieren wo Du die anderen Eventlistener registrierst.
-
Das ginge zwar, wäre aber unnötig kompliziert. Statisch im HTML ist völlig in Ordnung, Du brauchst es nur dahin gehend zu ändern, dass Du die Eventlistener nur einmal beim Start registrierst.
-
Danke, ich wünsche ebenfalls angenehme Weihnachtsfeiertage!
ZitatIch 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?
ZitatDeshalb 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:
Code
Alles anzeigenconst intv = 1000; // Open slave: let win = window.open('thread802-heartbeat-slave-2.html'); let timer; // This function is called from the slave periodically: function supervise() { console.log('lifesign received'); // restart timer: if (timer) clearTimeout(timer); timer = setTimeout(() => { // When timer has runout we consider the slave to be dead: console.log('slave is dead'); // win.close(); win = window.open('thread802-heartbeat-slave-2.html'); }, 2 * intv); } // Add event listener for messages being received from the slave: window.addEventListener("message", (event) => { // if (event.origin !== "http://example.org:8080") // return; supervise(); }, false);Slave-Skript:
Codeconst 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.
-
... gefunden, dieses soll Cross-Domain funktionieren:
https://developer.mozilla.org/en-US/docs/Web…dow/postMessage
ZitatThe
window.postMessage()method safely enables cross-origin communication betweenWindowobjects; e.g., between a page and a pop-up that it spawnedIch versuche, die Demo darauf umzustellen ...
-
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 ...
-
Um da schnell weiter zu kommen, schlage ich vor, dass Du beide Dateien auf deinen Webspace hoch lädst. Es gibt natürlich auch lokale Webserver wie XAMPP, die das Testen sehr erleichtern.
-
Dann werden wir jetzt offenbar mit den Problemen der SOP konfrontiert: Beide Seiten müssen auf der selben Domain liegen und über einen Webserver ausgeliefert werden. Ich vermute, Du rufst die Masterseite bei deinem Test ohne Webserver z. B. durch Doppelklick auf?
-
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:
-
Das liegt daran, dass die mobilen Browser die Seite eigenmächtig in der Größe ändern. Verhindern kannst Du das durch diese meta-Angabe:
-
Ich habe da mal eine Demo gemacht.
Du brauchst eine Masterseite und dort dieses Javascript:
Code
Alles anzeigenconst intv = 1000; let win; // Open slave when button is clicked: document.querySelector('button').addEventListener('click', event => { win = window.open('slave.html'); }); let timer; // This function is called from the slave periodically: function supervise() { console.log('lifesign received'); // restart timer: if (timer) clearTimeout(timer); timer = setTimeout(() => { // When timer has runout we consider the slave to be dead: console.log('slave is dead'); // win.close(); // Open slave window again: win = window.open('slave.html'); }, 2 * intv); }Dieses öffnet die Slaveseite. Dort laufen dann all deine Javascripts und zusätzlich dieses:
Codeconst 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.
-
Warum ist dir das unangenehm, Paint ist kein Powerprogramm aber naheliegend und wird häufig verwendet. Aber jetzt haben wir die Erklärung: Ich habe es schnell ausprobiert und dies bekommen beim Speichern:
html-seminar.de/woltlab/attachment/3253/
Versuche es mit Irfanview, das arbeitet zwar nicht interaktiv, indem man einen Rahmen aufzieht. aber vielleicht kannst Du damit erst Mal leben.
-
Ich schrieb "vielleicht". Erst Mal sollten wir klären, ob das zutrifft. Welches Programm hast Du denn nun benutzt?