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

Beitrag lesen

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