Tach!
Wie geht es besser? Kann man "einfach" ein solches Dialogfenster nachbilden und fertig? Nein! Denn wenn man das Dialogfeld mit JavaScript "gebastelt" hat (z.B. mit dem
dialog
-Element), dann braucht es irgendeinen Trick, wie man die Wiederaufnahme der Weiterverarbeitung durch JavaScript anwirft.[... confirm()-Variante ...]
Wenn wir aber auf diese blockierenden Methoden verzichten wollen, wird der Programm-Ablauf ein wesentlich komplexerer, weil nicht mehr linear. Wir brauchen im Grunde drei Programme:
- Vorbereitung: Dialog bauen
- Eingabe: Dialog auswerten
- Verarbeitung: "OK" oder "Nicht OK" ausgeben
Wie man sehen kann, ist plötzlich sehr viel Aufwand notwendig geworden, da das Anbieten des Dialogs nicht in demselben Programm-Abschnitt geschieht, wie die Auswertung der Nutzeraktion mit demselben.
Das ist auch nicht weiter tragisch, denn das Dialog-Handling an sich kann man besser so allgemein halten, dass es wiederverwendbar ist. Damit befindet sich dessen Code sowieso an anderer Stelle als die Verwendung.
Daher ist die Antwort auf die ursprüngliche Frage "kann ich mit diesem [Tutorial für zugängliche Dialog-Box] dieses [window.confirm-Funktionalität] nachbauen?" ein klares "Nein, nicht ohne weitere Anstrengungen!".
Zumindest kann man mit modernem Javascript und der Verwendung eines Promise die Verwendung wieder so einfach gestalten, wie es bei confirm() der Fall war. (Statt eines Promise könnte man auch einen herkömmlichen Callback nehmen.) Damit (auch mit der Callback-Variante) wird der Dialog universeller verwendbar, weil die feste Koppung zu okOrNot
aufgehoben ist.
Meine Version sähe so aus:
function myConfirm(question) {
return new Promise((resolve, reject) => {
const diag = {
formElement: document.createElement("form"),
stopEvent: (event) => {
event.preventDefault();
event.stopPropagation();
},
hide: () => {
diag.formElement.parentNode.removeChild(diag.formElement);
}
};
// the question
diag.formElement.appendChild(
// <p>
document.createElement("p").appendChild(
document.createTextNode(question)
)
);
// add OK button <button name="ok">
//...
// add cancel button <button name="cancel">
//...
// capture form submission event
diag.formElement.addEventListener("submit", function (event) {
// no more standard form action
diag.stopEvent(event);
diag.hide();
// which button did the user press?
resolve(event.target == diag.formElement.querySelector('button[name="ok"]'));
});
// add escape button functionality
diag.formElement.addEventListener("keyDown", function (event) {
// escape key has keyCode 27
if (event.keyCode == 27) {
diag.stopEvent(event);
diag.hide();
resolve(false);
}
});
});
}
// ==========
// Verwendung
// ==========
myConfirm("Wollen Sie wirklich ...?")
.then(result => {
const el = result ? 'p' : '<p class="warning">';
const text = result ? 'OK' : 'Nicht OK';
document.body.appendChild(
// <p>
document.createElement(el).appendChild(
document.createTextNode(text)
)
);
});
Ich habe auch einige Stellen gekürzt, damit man sich nicht so sehr wiederholt. Vor allem im Teil 3. Auch im hide()
kann man sich das Stylen sparen, wenn das Element sowieso aus dem DOM entfernt wird.
Da ist auch noch mehr Optimierungspotential drin. Zum Beispiel hab ich nicht weiter geschaut, inwieweit man statt diag
this
nehmen kann. stopEvent()
kann auch eine Standalone-Funktion sein, weil sie nicht auf das Dinge des diag-Objekts zugreift. Jedenfalls konnte da das return false
raus, das ist bereits durch preventDefault()
abgedeckt. Dann muss das auch nicht mehr an letzter Stelle im Eventhandler stehen, was durch das Promise(oder Callback)-Handling sowieso ungünstig wäre.
Was übrigens noch fehlt ist das Einbetten des diag.formElement ins DOM. Aber das sollte ja nur das Prinzip zeigen und nicht als fertige Copy&Paste-Vorlage dienen.
dedlfix.