Formular absenden nach Ablauf des Countdowns
fatal_error
- html
- javascript
0 Gunnar Bittersmann- javascript
-2 pl0 pl0 Gunnar Bittersmann0 pl
Hi, ich arbeite im Moment an einem Quiz. Um den Schwierigkeitsgrad zu erhöhen, soll man genau 60 Sekunden Zeit haben, um die Frage zu lösen (Dieser Countdown soll auch angezeigt werden.). Danach soll das Formular automatisch abgeschickt werden. Hier erstmal der HTML Code:
<p id='timer'></p>
<form action='auswertung.php' method='post'>
<input class='button' type='submit' id='submitb' value='weiter'>
</form>
Mein eigentliches Problem ist der Countdown. Ich habe hier versucht mit einer for-Schleife zu arbeiten, weiß aber nicht ob ich es überhaupt richtig gemacht hab. Bis jetzt bekomme ich immer die Fehlermeldung: TypeError: null is not an object (evaluating 'document.getElementById('submitb').click') und der Countdown wird nicht im <p> tag angezeigt.
for (var i = 60; i=0; i--) {
document.getElementById('timer').innerHTML = 'i';
setTimeout(1000);
}
document.getElementById('submitb').click();
Aber wenn ich die Schleife weglasse funktioniert das Senden mit onload oder onclick.
document.getElementById('submitb').click();
Ich würde mich freue wenn jemand mir folgende Fragen beantworten könnte: Ist die For-Schleife so überhaupt richtig? Wie kann ich den Countdown anzeigen lassen? Und Warum bekomme ich die oben genannte Fehlermeldung?
Im Voraus schonmal vielen Dank.
@@fatal_error
for (var i = 60; i=0; i--) { document.getElementById('timer').innerHTML = 'i'; setTimeout(1000); }
Pack da doch mal eine Kontrollausgabe wie console.log('loop')
rein um zu sehen, wie oft die Schleife denn durchlaufen wird.
Du könntest überrascht sein.
Der Abschnitt im Wiki-Artikel beginnt verwirrend: „Die Schleifenbedingung einer for
-Schleife sieht von vorne herein einen Zähler und eine Abbruchbedingung vor.“
Nein, keine Abbruchbedingung.
Weiter im Text steht’s dann richtig: „Die zweite Anweisung enthält die Bedingung für den Schleifenablauf; die Schleife wird ausgeführt, wenn und solange diese zutrifft.“ (Hervorhebung von mir.)
LLAP 🖖
Hallo Gunnar Bittersmann,
Der Abschnitt im Wiki-Artikel beginnt verwirrend:
begann.
Bis demnächst
Matthias
@@Gunnar Bittersmann
for (var i = 60; i=0; i--) { document.getElementById('timer').innerHTML = 'i'; setTimeout(1000); }
[…] wie oft die Schleife denn durchlaufen wird.
Wenn du das mit der Schleife hinbekommen hast, wirst du merken, dass das immer nocht nicht läuft. setTimeout()
geht anders: „Diese Funktion erwartet zwei oder mehr Parameter: …“
Statt setTimeout()
bietet sich hier aber auch an, setInterval()
und clearInterval
zu verwenden.
LLAP 🖖
Edit: Parallelpost zu Gunnar :)
Dein Code hat gleich mehrere Probleme. Nur den Type Error hat er eigentlich nicht, DEN kann ich nicht nachvollziehen. Das muss etwas sein, das im Kontext deiner Seite stattfindet aber hier nicht sichtbar ist.
Zum einen: manche Abfragen sind gleicher als andere. Ich will Dir Gunnars Quiz aber nicht verderben. Du kommst bestimmt selbst drauf. Generation von C Programmierern haben diesen Fehler schon vor Dir gemacht.
Zum zweiten: Zuweisen von 'i' an das Zeitanzeigefeld ergibt die Zeichenkette 'i' und nicht den Wert der Variablen i. Verwende i.toString(). Bzw. etwas anderes, siehe unten.
Zum dritten ist setTimeout keine Funktion zum Warten in einer Schleife. Diese Denke funktioniert in JavaScript nicht. JavaScript ist wie eine heiße Kartoffel: Anpacken, schnell damit hantieren und wieder weg damit. Denn solange ein Script läuft, blockiert der Browser.
Mit setTimeout registriert man eine Funktion, die nach Ablauf einer gewissen Zeit aufgerufen werden soll. Um einen kontinuierlichen Aufruf im Sekundentakt zu erreichen, kann diese Funktion sich zum Schluss selbst erneut mit setTimeout zum Aufruf registrieren.
Einfacher ist es aber, setInterval zu verwenden, damit registriert man eine Funktion zum ständigen Neuaufruf in einem bestimmten Zeitabstand. Normalerweise müsste man diese Funktion auch wieder deregistrieren, aber wenn Du dein Form submittest, wird die Seite neu geladen und damit werden registrierte Intervallfunktionen entfernt.
Deine Zeitanzeige wird nun aber unregelmäßig springen. Das liegt daran, dass ein Intervall von 1000 Millisekunden nie genau eingehalten wird. Du solltest 100ms als Intervallzeit setzen. Vorher speicherst Du Dir in einer Variablen startZeit = Date.now()
. In der Intervall-Funktion berechnest Du laufZeit = (Date.now()-startZeit)/1000
. Die kannst Du mit 60 vergleichen, und für die Anzeige der Restzeit gibst Du Math.floor(60-laufZeit)
aus.
So, ich hoffe, damit hast Du genug Ideen für eine erfolgreiche Umsetzung :)
Rolf
moin,
for (var i = 60; i=0; i--) { document.getElementById('timer').innerHTML = 'i'; setTimeout(1000); }
Ist die For-Schleife so überhaupt richtig?
So überhaupt nicht. Sie wird gar nicht erst anlaufen, weil mit i=0
die Abbruchbedingung bereits erfüllt ist (Zuweisung ist wahr). /pl
@@pl
So überhaupt nicht.
Oh ja. Zuweisungsoperator =
vs. Vergleichsoperator ==
oder ===
auch noch.
Sie wird gar nicht erst anlaufen, weil mit
i=0
die Abbruchbedingung bereits erfüllt ist (Zuweisung ist wahr).
Hier irrst du – doppelt.
Zum einen ist der Rückgabewert einer Zuweisung der Wert rechts vom Gleichheitszeichen, in dem Fall also 0, ein falsy value.
!!(i = 0); // false
Zum anderen ist – wie ich bereits zu verstehen gab – die Bedingung bei for
-Schleifen in JavaScript (und allen anderen an C angelehnten Sprachen) keine Abbruchbedingung.
Der doppelte Irrtum führt dazu, dass du darin recht hast, dass die Schleife gar nicht erst anlaufen wird.
LLAP 🖖
Ist die For-Schleife so überhaupt richtig?
So überhaupt nicht. Sie wird gar nicht erst anlaufen, weil mit
i=0
die Abbruchbedingung bereits erfüllt ist (Zuweisung ist wahr). /pl
Spielverderber ;-)
Hi,
So überhaupt nicht. Sie wird gar nicht erst anlaufen, weil mit
i=0
die Abbruchbedingung bereits erfüllt ist (Zuweisung ist wahr).
Nein. Der Wert einer Zuweisung ist in Javascript der zugewiesene Wert.
Schreib
javascript:alert(i=42)
in die Adreßzeile des Browsers und drück return.
Der Wert von i=0 ist also 0. Das wird als false interpretiert.
Außerdem gibt es bei einer for-Schleife keine Abbruch-Bedingung, wie hier im THread schon erwähnt wurde. Die Schleife wird so lange ausgeführt, wie die Bedingung wahr ist.
Deine beiden Irrtümer heben sich hier zufällig wieder auf, die Schleife wird tatsächlich nicht durchlaufen. Aber Deine Begründung hat nichts mit der Realität zu tun.
cu,
Andreas a/k/a MudGuard
@@MudGuard
Deine beiden Irrtümer heben sich hier zufällig wieder auf, die Schleife wird tatsächlich nicht durchlaufen. Aber Deine Begründung hat nichts mit der Realität zu tun.
Erster! 😜
LLAP 🖖
Hi,
Erster! 😜
Immerhin nicht Letzer! ;-) Da ist noch einer nochmal 2 Minuten später ...
cu,
Andreas a/k/a MudGuard
Außerdem gibt es bei einer for-Schleife keine Abbruch-Bedingung
Soweit mir bekannt, kann man eine Schleife mit break abbrechen.
@@Linuchs
Außerdem gibt es bei einer for-Schleife keine Abbruch-Bedingung
Soweit mir bekannt, kann man eine Schleife mit break abbrechen.
Oder (wenn man sich innerhalb einer Funktion befindet) auch mit return
.
Oder auch durch Verlassen der Seite location.href = '…';
LLAP 🖖
@@MudGuard
Deine beiden Irrtümer
Muss es im Plural nich „Irrten“ heißen?
LLAP 🖖
Nein. Das Wort endet auf -um. Der Plural demzufolge auf -a. Das Irrtum, die Irrta. Ganz einfach für den geübten Latainer.
@@Rolf b
Nein. Das Wort endet auf -um. Der Plural demzufolge auf -a. Das Irrtum, die Irrta. Ganz einfach für den geübten Latainer.
Jetzt kommt der mit seinem großen Latrinum!
LLAP 🖖
@@MudGuard
Deine beiden Irrtümer
Muss es im Plural nich „Irrten“ heißen?
Pluralierung ist ganz einfach: Hänge ein 's' an den Einzeiler! Beispiele:
MfGs
Tach!
Pluralierung ist ganz einfach: Hänge ein 's' an den Einzeiler!
Das richtige Wort wäre Einzahler gewesen.
dedlfix.
@@pl
Pluralierung ist ganz einfach: Hänge ein 's' an den Einzeiler! Beispiele:
- Kuh => Kuhs
Ausnahmsweise aber auch mal ein e:
„Eine Kuh macht muh, viele Kühe machen Mühe“ (Agnes Kraus als Tante Alma in „Viechereien“)
LLAP 🖖
@@
Pluralierung ist ganz einfach: Hänge ein 's' an den Einzeiler! Beispiele:
- Kuh => Kuhs
Ausnahmsweise aber auch mal ein e:
„Eine Kuh macht muh, viele Kühe machen Mühe“ (Agnes Kraus als Tante Alma in „Viechereien“)
Ja die Agnes, sie war ne liebe Frau. Hab se och mal jetroffen form Zoo -- 78 oder so.
MfGs
Hallo,
Ja die Agnes, sie war ne liebe Frau.
Eine? Da hängt doch ein 's' hinten dran; das müssen wohl mehrere Agne sein.
Gruß
Kalk
Hi,
Eine? Da hängt doch ein 's' hinten dran; das müssen wohl mehrere Agne sein.
Wieso hast Du mehrere 'da' nach dem Semikolon? ;-)
cu,
Andreas a/k/a MudGuards
Hallo,
Eine? Da hängt doch ein 's' hinten dran; das müssen wohl mehrere Agne sein.
Wieso hast Du mehrere 'da' nach dem Semikolon? ;-)
Na, für jede Agne ein!
Gruß
Kalk
Jetzt weiß ich endlich, warum es bei mir nie bei einem Glas bleibt, wenn ich Pils bestelle. Beim nächsten mal probiere ich es mit "ein Gla Pil", dann klappt das bestimmt besser mit dem Nachhauseweg.
Rolf 🍺
Tach!
So überhaupt nicht. Sie wird gar nicht erst anlaufen, weil mit
i=0
die Abbruchbedingung bereits erfüllt ist (Zuweisung ist wahr).
Falsch. In dem Fall. Das Ergebnis einer Zuweisung ist der Wert, der zugewiesen wird. Bei false oder einem falsy Wert, wie 0, ist es false, bei true oder einem truthy Wert (alles was nicht 0 ist und eine Zahl ist) ist es true.
Für den Probleminhaber: Eine Zuweisung =
ist kein Vergleich ==
.
dedlfix.
Hi, falls Du noch dran bist ?
ich arbeite im Moment an einem Quiz. Um den Schwierigkeitsgrad zu erhöhen, soll man genau 60 Sekunden Zeit haben, um die Frage zu lösen (Dieser Countdown soll auch angezeigt werden.).
Idee: Mach ein Feld und setze zum Zeitpunkt der Auslieferung der Seite eine 60 da ein. Evntl. lass den Besucher entscheiden wann er den Countdown startet.
Dann starte eine Funktion die jede Sekunde auf dieses Feld zugreift, die 60 (sichtbar) runterzählt und bei 0 das Quiz beendet.
Danach soll das Formular automatisch abgeschickt werden.
Die Alternative (nicht automatisch senden) wäre zu überlegen.
MfG, Code:
<input id="cdown" value="60">
<script>
function countdown(){
var cdown = document.getElementById('cdown');
cdown.value = --cdown.value;
if(cdown.value == 0){
alert("Baz!");
return;
}
window.setTimeout(countdown, 1000);
}
countdown();
</script>
@@pl
function countdown(){ var cdown = document.getElementById('cdown');
Nein. Du bist doch schon lange genug hier dabei, dass du wissen solltest, dass man sich ein Element nicht in jedem Funktionsaufruf/Schleifendurchlauf erneut aus dem DOM raussuchen sollte. Das macht mal einmal am Anfang – außerhalb des Funktionsaufrufs/Schleifendurchlaufs.
cdown.value = --cdown.value;
Hier hast du wohl pures Glück, dass der Typecast wie gewünscht funktioniert. cdown.value
ist vom Typ "string". Bei cdown.value = cdown.value + 1
erlebst du dein blaues Wunder.
if(cdown.value == 0){
Hier verlässt du dich darauf, dass der Typecast wie gewünscht funktioniert. Saubere Programmierung geht anders.
LLAP 🖖
@@
Nein. Du bist doch schon lange genug hier dabei, dass du wissen solltest, dass man sich ein Element nicht in jedem Funktionsaufruf/Schleifendurchlauf erneut aus dem DOM raussuchen sollte. Das macht mal einmal am Anfang – außerhalb des Funktionsaufrufs/Schleifendurchlaufs.
Nein: Weil ich das produktiv übern Template machen würde. D.h., Variablen gibt es nur noch im Scope der jeweiligen Funktion.
Hier hast du wohl pures Glück, dass der Typecast wie gewünscht funktioniert
Produktiv: Siehe oben. Eine Funktion, ein Scope. Die ganze Progammlogik wird nicht mehr übers DOM geschleift sondern über ein oder mehrere Templates komplett vom DOM getennt.
Guck mal im Beispiel wie einfach das dann wird. Skalierbar isses auch, ich kann das ohne Handstand nachrüsten auf eine bidirektionale Kommunikation mit dem Funksensor (falls der das unterstützt, wird die Rückmeldung einfach ins Template gerendert).
MfG