Felix Riesterer: Dialog-Box - Confirm

Beitrag lesen

Lieber Barksalot,

ergänzend noch dieser Gedanke:

// hier hält der Browser alles an, bis das Fenster wieder weg ist:
var a = window.confirm("Ist das so OK?");

// danach erst kann es hier weiter gehen (was wiederum den Browser anhält):
alert("Es ist also " + (a ? "" : "so nicht ") + "OK.");

Mittlerweile sollte sich herumgesprochen haben, dass sowohl confirm, als auch alert oder prompt aus heutiger Sicht sehr problematische Methoden sind, da sie jegliche Ausführung von JavaScript so lange blockieren, bis ihre modalen Dialoge vom User in irgendeiner Weise bestätigt wurden. Das ist vor allem für asynchrone Requests ein Problem, die dann im Hintergrund ebenfalls angehalten werden.

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.

Betrachten wir das (vereinfachte) obige Beispiel erneut:

var a = confirm("OK?");
alert(a ? "Ja." : "Nein!");

Wie wir sehen, ist der Programmfluss dieser:

  1. Eingabe: Variable a mit dem Rückgabewert von window.confirm befüllen
  2. Verarbeitung: Basierend auf a entweder ein "Ja." oder ein "Nein!" ausgeben

Das sieht sehr einleuchtend und bequem aus, da wir unser Programm genau so schreiben können, wie wir uns dessen Ablauf vorstellen.

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:

  1. Vorbereitung: Dialog bauen
  2. Eingabe: Dialog auswerten
  3. Verarbeitung: "OK" oder "Nicht OK" ausgeben

Das könnte (wiederum stark vereinfacht) so aussehen:

/**
 * process user input
 *
 * @param bool
 */
function okOrNot (userChoice) {
  if (userChoice) {
    // OK
    document.body.appendChild(
      // <p>
      document.createElement("p").appendChild(
        document.createTextNode("OK")
      )
    );
  } else {
    // NOT OK!
    document.body.appendChild(
      // <p>
      document.createElement("p").appendChild(
        document.createTextNode("Nicht OK")
      )
    // <p class="warning">
    ).setAttribute("class", "warning");
  }
}

/**
 * create GUI for user interaction
 *
 * @param string
 */
function myConfirm (question) {
  // build my dialog
  const diag = {};

  // prevent any further event action
  diag.stopEvent = function (event) {
    event.preventDefault();
    event.stopPropagation();
    return false;
  };

  // hide dialog
  diag.hide = function () {
    // 1. possibility: manipulate style object
    diag.formElement.style.display = "none";
    // 2. possibility: remove <form> element from document
    diag.formElement.parentNode.removeChild(diag.formElement);
    // 3. possibility with suitable CSS like form[data-disabled] {display:none;}
    diag.formElement.setAttribute("data-disabled", "disabled");
  };

  diag.formElement = document.createElement("form");

  // 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) {
    // which button did the user press?
    okOrNot(event.target == diag.form.querySelector('button[name="ok"]');

    // no more standard form action
    return diag.stopEvent(event);
  });

  // add escape button functionality
  diag.formElement.addEventListener("keyDown", function (event) {
    // escape key has keyCode 27
    if (event.keyCode == 27) {
      okOrNot(false);
      return diag.stopEvent(event);
    }
  });
}

Zum Verständnis: Das zweite Programm aus obiger Liste (Eingabe: Dialog auswerten) befindet sich im diag-Objekt eingebaut.

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. 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!". Und dabei habe ich die Aspekte der Zugänglichkeit, die im von Dir genannten Artikel aufgeführt wurden, noch nicht berücksichtigt!

Liebe Grüße,

Felix Riesterer.