So habe ich noch ein weiteres kleines JavaScript-Problem mit meinem aktuellen Projekt: JS-Ereignisse werden nicht in der Reihenfolge, die ich erwarte sie zu feuern.Javascript-Ereignisse, die nicht in der erwarteten Reihenfolge ausgelöst werden
Angenommen, ich habe ein Textfeld mit einem onBlur-Ereignis, das einen AJAX-Aufruf auslöst, der einige Berechnungen auf dem Server durchführt (ich verwende .NET 3.5's WebServices mit JSON). Die Callback-Methode füllt eine Seite mit Textfeldern mit Ergebnissen aus der Berechnung.
Ich habe auch eine Schaltfläche mit einem onClick-Ereignis, die eine andere Berechnung initiiert, aber es hängt davon ab, die onBlur -Ereignis (s) des Textfelds abgeschlossen, bevor die Ergebnisse seiner onClick-Ereignis gültig sein werden.
Ich habe einen einfachen Mutex an Ort und Stelle, der ziemlich gut funktioniert, bis die folgende Situation: Der Benutzer ändert einen Wert in einem der Textfelder, hat es aber noch nicht verlassen, so dass der Fokus immer noch auf dem Textfeld ist. Während das Textfeld den Fokus hat, klicken sie auf eine Schaltfläche mit einem onClick-Ereignis.
In den meisten Fällen löst der Browser (in diesem Fall IE7) das onClick-Ereignis der Schaltfläche VOR dem onBlur-Ereignis des Textfelds aus!
Das verursacht einige Verwüstung, und ich habe keine Ahnung, wie die Reihenfolge der Ereignisse, die abgefeuert werden, erzwingen. Mein kleiner Mutex funktioniert wie folgt: Wenn eines der Ereignisse ausgelöst wird, setze ich ein Flag, das bedeutet "Warte auf den Rückruf". Alle nachfolgenden Ereignisse, die ausgelöst werden, überprüfen die Flagge, bevor sie etwas tun. Setzen Sie das Flag im Callback auf false zurück.
Also, irgendwelche Ideen? Ich denke, ich möchte fast alle Web-Service-Aufrufe synchron machen, aber ich weiß nicht, ob es einen einfachen Weg gibt, das zu tun.
Andere Dinge, die ich habe versucht, oder Dinge sollten Sie wissen: - Deaktivieren der Schaltflächen in der onBlur der Textfelder - ihre onClicks noch Feuer, bevor sie Behinderte bekommen - Denken Sie daran, dies geschieht nur, wenn eine Bearbeitung Textfeld und sofort auf eine Schaltfläche klicken. Wenn der Benutzer auf einen leeren Platz klickt, um die onBlur des Textfelds auszulösen, bevor er auf die Schaltfläche klickt, funktioniert alles perfekt.
EDIT:
Nach einigen Kommentaren und mehr Tests ist hier, was ich möchte in der Lage sein zu tun:
Im onBlur des Textfeldes, möchte ich auf die Schaltfläche deaktivieren, so dass Das Ereignis onClick wird nicht ausgelöst. Wenn ich das jedoch code, wird das onBlur-Ereignis ausgelöst, ich kann sehen, dass die Schaltfläche deaktiviert wird, aber ihr onClick-Ereignis wird weiterhin ausgelöst.
Hier ist ein Beispielcode. Manchmal tritt das Ereignis onClick auf und manchmal nicht. Wenn Sie das setTimeout auf 500 ms aufstocken, scheint es immer zu verhindern. Vielleicht ist dies eine Option ...
<html>
<head>
<script type="text/javascript">
var onClickFlag = false;
function whatHappensOnFocus(el) {
log('whatHappensOnFocus(): TextField focused.');
onClickFlag = false;
log('whatHappensOnFocus(): Set onClickFlag = false');
}
function whatHappensOnBlur(el) {
log('whatHappensOnBlur(): TextField blurred.');
document.getElementById('theButton').disabled = true;
log('whatHappensOnBlur(): Disabled the Button');
setTimeout(function() { someTestFieldFunction(); log('whatHappensOnBlur(): OnBlur callback called: someTestFieldFunction()'); }, 50);
log ('whatHappensOnBlur(): setTimeout for someTestFieldFunction() for 50ms');
}
function log(msg) {
document.getElementById('log').value += ('[' + (new Date().getTime()).toString() + '] ' + msg + '\n');
}
function someTestFieldFunction() {
log('someTestFieldFunction(): Inside someTestFieldFunction()');
log('someTestFieldFunction(): Test: onClickFlag = ' + onClickFlag);
//alert('you blurred the text field.');
//alert('onClickFlag = ' + onClickFlag);
setTimeout(enableButton, 50);
log('someTestFieldFunction(): setTimeout for enableButton()');
}
function enableButton() {
document.getElementById('theButton').disabled = false;
log('enableButton(): Button re-enabled');
//onClickFlag = false;
}
function whatHappensOnClick(el) {
log('whatHappensOnClick(): the Button onClick fired');
someFunction();
log('whatHappensOnClick(): someFunction() called');
}
function whatHappensOnMouseDown(el) {
log('whatHappensOnMouseDown(): inside whatHappensOnMouseDown()');
onClickFlag = true;
log("whatHappensOnMouseDown(): set onClickFlag = true");
}
function someFunction() {
log('someFunction(): inside someFunction()');
log('someFunction(): You have successfully clicked the button');
//alert("you clicked me! this shouldn't happen!")
}
</script>
</head>
<body>
<form id="testform">
<input type="text" size="10" onfocus="whatHappensOnFocus(this);" onblur="whatHappensOnBlur(this);" />
<br />
<br />
<input id="theButton" type="button" onmousedown="whatHappensOnMouseDown(this);" onmouseout="onClickFlag = false;" value="calculate" onclick="whatHappensOnClick(this);" />
<br />
<br />
<textarea rows="15" cols="100" id="log" style="overflow: scroll"></textarea>
<input type="reset" value="clear" />
</form>
</body>
</html>
UPDATE:
ich den Code aktualisiert ich gepostet einen Teil der Ausgabe zu reflektieren, so können Sie sehen, wie ich das getestet. Wenn Sie sich auf ein Textfeld konzentrieren und dann auf eine Schaltfläche klicken, wird das Ereignis onMouseDown der Schaltfläche vor dem Ereignis onBlur des Textfelds ausgelöst. Aus diesem Grund kann ich eine Flagge setzen, sodass ich weiß, dass sie versucht hat, auf die Schaltfläche zu klicken. Dann kann ich im onSuccess-Callback-Ereignis des AJAX-Aufrufs, der durch das onBlur-Ereignis des Textfelds ausgelöst wird, sehen, ob das Button-Flag gesetzt ist (also weiß ich, dass sie versucht hat, darauf zu klicken) und dieses Ereignis abbricht (alles andere deaktiviert) Komplett).Es gibt nur ein paar Schaltflächen auf dem Formular, die dieses Verhalten benötigen, also denke ich, dass diese Lösung für jetzt ausreichend sein wird.
Ich habe gerade einen schnellen Test gemacht, und das Blur-Ereignis * immer * feuert zuerst für mich in IE7. –
Wirklich? Ich glaube dir ... lass mich auch einen Schnelltest machen ... –
Ok, du hast Recht. Ich habe die Frage bearbeitet, weil ich immer noch verrücktes Verhalten habe. –