gschade: javascript, eigenes modales Fenster, Aufrufbutton in <form>

problematische Seite

Das wunderbare Bespiel unter selfhtml -> javascript -> tutoraials -> eigene modale Dialogfenster, dort unter "komplexere Dialogbox" wollte ich gern weiterverwenden. Mein Aufrufbutton soll aber zwischen <form> und </form> stehen. Dann blitzt die Dialogbox kurz auf und verschwindet wieder. Also, mit folgendem HTML-Code tritt diese Dysfunktionalität auf:

<main>
 <form>
	<p>Eine Dialog-Box mit mehreren Eingabefeldern als modales Fenster.  <button>anzeigen</button>.  </p> 
   <pre id="result"></pre>
   <dialog id="my-dialog" role="dialog" aria-labelledby="my-dialog-heading">
 	  <button class="close">Schließen</button>
	   <h2 id="my-dialog-heading">Eingabe</h2>
	    <p class="button-row">
		   <button name="ok">OK</button>
		   <button name="cancel">Abbrechen</button>
	    </p>
   </dialog>
  </form>
</main>

und wenn ich <form> und </form> lösche, dann wartet das modale Fenster wie gewünscht auf Eingaben. Kann mir jeman einen Tipp geben, wie es auch mit innerhalb von <form> gehen könnte?

Hier zur Vervollständigung der zugehörige Javascript-Code aus dem Tutorial:

'use strict';
document.addEventListener("DOMContentLoaded", function () {
	var button = document.querySelector("main button");
	// Polyfill für Browser, die das dialog-Element nicht komplett unterstützen
	(function () {
		var backdrop;
		Array.prototype.slice.call(document.querySelectorAll("dialog"))
			.forEach(function (dialog) {
				var callBacks = {
						cancel: function () {},
						ok: function () {}
					},
					close = dialog.querySelector(".close");
				if (!dialog.close) {
					dialog.close = function () {
						if (dialog.hasAttribute("open")) {
							dialog.removeAttribute("open");
						}
						if (backdrop && backdrop.parentNode) {
							backdrop.parentNode.removeChild(backdrop);
						}
					}
				}
				if (!dialog.show) {
					dialog.show = function () {
						var closeButton = dialog.querySelector(".close");
						dialog.setAttribute("open", "open");
						// after displaying the dialog, focus the closeButton inside it
						if (closeButton) {
							closeButton.focus();
						}
						if (!backdrop) {
							backdrop = document.createElement("div");
							backdrop.id = "backdrop";
						}
						document.body.appendChild(backdrop);
					}
				}
				dialog.setCallback = function (key, f) {
					callBacks[key] = f;
				};
				dialog.triggerCallback = function (key) {
					if (typeof callBacks[key] == "function") {
						callBacks[key]();
					}
				};
				if (close) {
					close.addEventListener("click", function () {
						dialog.close();
						dialog.triggerCallback("cancel");
					});
				}
				// handle buttons for user input
			["cancel", "ok"].forEach(function (n) {
					var button = dialog.querySelector('[name="' + n + '"]');
					if (button) {
						button.addEventListener("click", function () {
							dialog.close();
							dialog.triggerCallback(n);
						});
					}
				});
			});
		// ESC and ENTER closes open dialog and triggers corresponding callback
		document.addEventListener("keydown", function (event) {
			var currentElement = event.target || event.soureElement,
				prevent = (currentElement.tagName && currentElement.tagName.match(
					/^button|input|select|textarea$/i));
			Array.prototype.slice.call(document.querySelectorAll("dialog"))
				.forEach(function (dialog) {
					if (dialog.hasAttribute("open")) {
						// ENTER
						if (event.keyCode == 13 && !prevent) {
							dialog.close();
							setTimeout(function () {
								dialog.triggerCallback("ok");
							}, 50);
						}
						// ESC
						if (event.keyCode == 27) {
							dialog.close();
							setTimeout(function () {
								dialog.triggerCallback("cancel");
							}, 50);
						}
					}
				});
		}, true);
	}());
	// komplexere Dialog-Box anzeigen
	window.myDialog = function (data, OK, cancel) {
			var dialog = document.querySelector("#my-dialog"),
				buttonRow = document.querySelector("#my-dialog .button-row"),
				heading = document.querySelector("#my-dialog-heading"),
				element, p, prop;
			if (dialog && buttonRow) {
				// Standard-Titel
				if (heading) {
					heading.textContent = "Eingabe";
				}
				// jedes <ul> und <p> entfernen, außer <p class="button-row">
				Array.prototype.slice.call(dialog.querySelectorAll(
						"ul, p:not(.button-row)"))
					.forEach(function (p) {
						p.parentNode.removeChild(p);
					});
				// Elemente erstellen und gegebenenfalls mit Inhalten befüllen
				for (prop in data) {
					// alles bekommt ein <p> drumherum
					p = document.createElement("p");
					buttonRow.parentNode.insertBefore(p, buttonRow);
					// simple Textausgabe
					if (data[prop].type && data[prop].type == "info") {
						p.textContent = data[prop].text;
					}
					// anderer Titel
					if (data[prop].type && data[prop].type == "title" && heading) {
						heading.textContent = data[prop].text;
						// neues <p> wird hierfür nicht benötigt
						p.parentNode.removeChild(p);
					}
					// numerischer Wert
					if (data[prop].type && data[prop].type == "number") {
						// <label> als Kindelement für Beschriftung
						p.appendChild(document.createElement("label"));
						p.lastChild.appendChild(document.createTextNode(data[prop].text + " "));
						// <input type="number">
						element = p.appendChild(document.createElement("input"));
						if (data[prop].hasOwnProperty("max")) {
							element.max = data[prop]["max"];
						}
						if (data[prop].hasOwnProperty("min")) {
							element.min = data[prop]["min"];
						}
						if (data[prop].hasOwnProperty("step")) {
							element.step = data[prop]["step"];
						}
						element.name = prop;
						element.type = "number";
						element.value = element.min = data[prop]["min"] || 0;
						if (data[prop].default) {
							element.value = data[prop].default;
						}
					}
					// Mehrfachauswahl
					if (data[prop].type && data[prop].type == "multiple") {
						p.textContent = data[prop].text;
						// alle Optionen wandern in ein <ul>
						element = document.createElement("ul");
						buttonRow.parentNode.insertBefore(element, buttonRow);
						data[prop].options.forEach(function (d, index) {
							var input = document.createElement("input"),
								label = document.createElement("label"),
								li = document.createElement("li");
							// <li> in <ul> einhängen
							element.appendChild(li);
							input.id = prop + "-" + index;
							input.name = prop + "-" + index;
							input.type = "checkbox";
							input.value = d;
							li.appendChild(input);
							label.htmlFor = prop + "-" + index;
							label.textContent = " " + d
							li.appendChild(label);
							if (data[prop].default && data[prop].default == d) {
								input.setAttribute("checked", "checked");
							}
						});
					}
					// Einfachauswahl
					if (data[prop].type && data[prop].type == "select") {
						// <label> als Kindelement für Beschriftung
						p.appendChild(document.createElement("label"));
						p.lastChild.appendChild(document.createTextNode(data[prop].text + " "));
						// alle Optionen wandern in ein <ul>
						element = p.appendChild(document.createElement("select"));
						element.name = prop;
						data[prop].options.forEach(function (d) {
							var o = document.createElement("option");
							o.textContent = d;
							o.value = d;
							element.appendChild(o);
							if (data[prop].default && data[prop].default == d) {
								o.setAttribute("selected", "selected");
							}
						});
					}
					// Texteingabe
					if (data[prop].type && data[prop].type == "text") {
						// <label> als Kindelement für Beschriftung
						p.appendChild(document.createElement("label"));
						p.lastChild.appendChild(document.createTextNode(data[prop].text));
						// alle Optionen wandern in ein <ul>
						element = p.appendChild(document.createElement("textarea"));
						element.name = prop;
						if (data[prop].default) {
							element.textContent = data[prop].default;
						}
					}
				}
				dialog.setCallback("cancel", cancel);
				dialog.setCallback("ok", function () {
					var result = {},
						elements;
					// Ergebnisse ermitteln
					for (prop in data) {
						elements = Array.prototype.slice.call(dialog.querySelectorAll(
							'[name^="' + prop + '"]'));
						if (data[prop].type && data[prop].type == "multiple") {
							result[prop] = [];
							elements.forEach(function (element) {
								if (element.checked) {
									result[prop].push(element.value);
								}
							});
						} else {
							if (data[prop].type != "title" && data[prop].type != "info") {
								result[prop] = null;
								if (elements[0]) {
									result[prop] = elements[0].value;
								}
							}
						}
					}
					// Ergebnisse an die Callback-Funktion zurück geben
					OK(result);
				});
				dialog.show();
			}
		}
		// anzeigen-Button aktivieren
	if (button) {
		button.addEventListener("click", function () {
			myDialog(
				// data
				{
					instructions: {
						text: "Bitte seien Sie jetzt komplett ehrlich und füllen Sie wahrheitsgemäß alles aus!",
						type: "info"
					},
					title: {
						text: "Sonderabfrage",
						type: "title"
					},
					sex: {
						"default": "weiblich",
						options: ["männlich", "weiblich"],
						text: "Geschlecht",
						type: "select"
					},
					age: {
						"default": 18,
						"max": 150,
						"min": 0,
						step: 1,
						text: "Alter",
						type: "number"
					},
					preferences: {
						"default": "Pop",
						options: ["Jazz", "Swing", "Latin", "Klassik", "Hiphop", "Pop"],
						text: "Diese Musik mag ich gerne",
						type: "multiple"
					},
					message: {
						text: "Das will ich mitteilen",
						type: "text"
					}
				},
				// OK
				function (data) {
					var output = document.querySelector("main pre"),
						prop,
						result = "Ergebnis:\r\n=========\r\n\r\n";
					for (prop in data) {
						result += prop + ":";
						if (typeof data[prop] == "object") {
							data[prop].forEach(function (value, index) {
								result += (index ? "," : "") + "\r\n\t" + value;
							});
						} else {
							result += " " + data[prop];
						}
						result += "\r\n";
					}
					if (output) {
						output.textContent = result;
					}
				},
				// cancel
				function () {
					var output = document.querySelector("main pre");
					if (output) {
						output.textContent = "(kein Ergebnis)";
					}
				});
		});
	}
});

akzeptierte Antworten

  1. problematische Seite

    Liebe(r) gschade,

    Dein Button ist ein submit-Button (das ist der Default-Typ und bei Dir steht kein type-Attribut), der das Formular versendet:

    <p>Eine Dialog-Box mit mehreren Eingabefeldern als modales Fenster.  <button>anzeigen</button>.  </p> 
    

    Probiere doch einmal, ob ein type="button" das Problem bereits löst.

    Liebe Grüße

    Felix Riesterer

    1. problematische Seite

      Servus!

      Liebe(r) gschade,

      Dein Button ist ein submit-Button (das ist der Default-Typ und bei Dir steht kein type-Attribut), der das Formular versendet:

      <p>Eine Dialog-Box mit mehreren Eingabefeldern als modales Fenster.  <button>anzeigen</button>.  </p> 
      

      Probiere doch einmal, ob ein type="button" das Problem bereits löst.

      Das kommt so oft vor (und passiert selbst mir immer mal wieder), dass man's noch mal deutlich irgendwo hinschreiben müsste.

      Ich hab's jetzt im Artikel zum form-Element getan. Wo sollte es sonst noch hin?

      Herzliche Grüße

      Matthias Scharwies

      --
      Einfach mal was von der ToDo-Liste auf die Was-Solls-Liste setzen.“
      1. problematische Seite

        Hi there,

        vielleicht sollte man das ein bisschen besser kommunizieren, es kommt in der letzten Zeit immer öfter vor, daß jemand als "Problematische Seite" den Verweis auf jene Seite im selfhtml-Wiki einträgt, die er gerade nicht versteht...😉

        1. problematische Seite

          Servus!

          Hi there,

          vielleicht sollte man das ein bisschen besser kommunizieren, es kommt in der letzten Zeit immer öfter vor, daß jemand als "Problematische Seite" den Verweis auf jene Seite im selfhtml-Wiki einträgt, die er gerade nicht versteht...😉

          Na ja, teilweise ist dort ja der Fehler oder das Problem zu finden - duckundwech. 😀

          Es gab schon Diskussionen, diese Linkmöglichkeit umzubenennen, aber die perfekte Lösung wird's da nicht geben.

          Herzliche Grüße

          Matthias Scharwies

          --
          Einfach mal was von der ToDo-Liste auf die Was-Solls-Liste setzen.“
        2. problematische Seite

          Hallo klawischnigg,

          es kommt in der letzten Zeit immer öfter vor, daß jemand als "Problematische Seite" den Verweis auf jene Seite im selfhtml-Wiki einträgt, die er gerade nicht versteht...😉

          Ja, er hat also mit der Wiki-Seite ein Problem 😉

          vielleicht sollte man das ein bisschen besser kommunizieren,

          Wie lautet dein Vorschlag?

          Bis demnächst
          Matthias

          --
          Du kannst das Projekt SELFHTML unterstützen,
          indem du bei Amazon-Einkäufen Amazon smile (Was ist das?) nutzt.
          1. problematische Seite

            Hi there,

            es kommt in der letzten Zeit immer öfter vor, daß jemand als "Problematische Seite" den Verweis auf jene Seite im selfhtml-Wiki einträgt, die er gerade nicht versteht...😉

            Ja, er hat also mit der Wiki-Seite ein Problem 😉

            vielleicht sollte man das ein bisschen besser kommunizieren,

            Wie lautet dein Vorschlag?

            Gute Frage. Vielleicht irgendetwas mit "Meine problematische Seite" und "Seite im Wiki, die ich nicht versteh'"...😉

            1. problematische Seite

              Hallo,

              Ich finde es ok, die

              "Seite im Wiki, die ich nicht versteh'"

              als problematische Seite zu bezeichnen. Man kann das als Arbeitshypothese nehmen und in der folgenden Diskussion gradebiegen…

              Gruß
              Kalk

              1. problematische Seite

                Hi there,

                Ich finde es ok, die

                "Seite im Wiki, die ich nicht versteh'"

                als problematische Seite zu bezeichnen. Man kann das als Arbeitshypothese nehmen und in der folgenden Diskussion gradebiegen…

                Weiß nicht, ich klick' da immer drauf, in einer leicht masochistischen Erwartungshaltung auf absolut grottiges Webdesign und haarsträubend schlechtes Javascript - und wenn ich dann auf einer Seite des selfhtml-Wikis lande...ich muß es bekennen, ich bin dann echt ein bisschen entäuscht...😉

                1. problematische Seite

                  Lieber klawischnigg,

                  ich bin dann echt ein bisschen entäuscht...😉

                  davon, dass Du kein absolut grottiges Webdesign findest, oder vom Wiki? Oder empfindest Du das Wiki als absolut grottiges Webdesign und bist nur enttäuscht, dass es "schon wieder das Wiki" ist?

                  Disclaimer: Dieses Posting ist nicht ernst gemeint.

                  Liebe Grüße

                  Felix Riesterer

                  1. problematische Seite

                    Hi there,

                    ich bin dann echt ein bisschen entäuscht...😉

                    davon, dass Du kein absolut grottiges Webdesign findest, oder vom Wiki?

                    Das Wiki hat mich noch nie enttäuscht. Das selfhtml-Wiki ist für mich der Leuchtturm an den rauhen, gischtspritzenden und vor Untiefen nur so strotzenden Gewässern der Webgestaltung.

                    Oder empfindest Du das Wiki als absolut grottiges Webdesign und bist nur enttäuscht, dass es "schon wieder das Wiki" ist?

                    Ersteres nein, zweiteres ja...😉