modale Fenster – SELFHTML-Forum Forum als Ergänzung zum SELFHTML-Wiki und zur Dokumentation SELFHTML https://forum.selfhtml.org/self modale Fenster Fri, 03 May 19 09:53:26 Z https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1747955#m1747955 https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1747955#m1747955 <p>Hallo zusammen</p> <p>Modale Fenster mit JS: dazu gibt es zuhauf Einträge im Netz. Ich habe früher Visual Basic 6 programmiert und auch dort gibt es modale Fenster und zwar in dem Sinne</p> <p><strong>Die Form, die den modalen Dialog aufruft, übernimmt nach dem Klicken die Eintragungen des Benutzers im Dialog, wenn der Benutzer OK geklickt hat, oder verwirft sie beim Klicken auf die Abbrechen-Schaltfläche</strong></p> <p>Bei allem was ich im Internet gefunden habe, ist mir nicht klar geworden, ob Javascript den Programmfluss anhalten kann, wenn ein modales Fenster aufgerufen wurde und die dort gemachten Eintragungen dann später im Hauptfenster verarbeiten kann.</p> <p>Also wenn mir jemand das einfach beantworten kann und am besten noch mit einem Beispiel verdeutlichen, dann wäre ich sehr dankbar dafür.</p> <p>Viele Grüße</p> modale Fenster Fri, 03 May 19 10:01:58 Z https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1747958#m1747958 https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1747958#m1747958 <p>Hallo JSKid,</p> <blockquote> <p>Bei allem was ich im Internet gefunden habe, ist mir nicht klar geworden, ob Javascript den Programmfluss anhalten kann, wenn ein modales Fenster aufgerufen wurde und die dort gemachten Eintragungen dann später im Hauptfenster verarbeiten kann.</p> </blockquote> <p>Es gibt <code>window.confirm</code>, <code>window.alert</code> und <code>window.prompt</code>, die genau das tun: den Programmfluss anhalten, bis der User seine Eingabe getätigt hat.</p> <p>Das vorausgesagt wirst du auf Probleme stoßen, wenn du das benutzt. Z.B. werden diese Dialogfenster im Chrome automatisch geschlossen (<em>dismissed</em>), wenn der Tab gewechselt wird. Wenn der Tab nicht aktiv ist, werden sie gar nicht erst angezeigt. Google und Mozilla raten explizit von der Verwendung ab.</p> <p>LG,<br> CK</p> <div class="signature">-- <br> <a href="https://wwwtech.de/about" rel="noopener noreferrer">https://wwwtech.de/about</a> </div> modale Fenster Fri, 03 May 19 10:08:58 Z https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1747961#m1747961 https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1747961#m1747961 <p>Tach!</p> <blockquote> <p>Bei allem was ich im Internet gefunden habe, ist mir nicht klar geworden, ob Javascript den Programmfluss anhalten kann, wenn ein modales Fenster aufgerufen wurde und die dort gemachten Eintragungen dann später im Hauptfenster verarbeiten kann.</p> </blockquote> <p>Nein, kann es nicht. Javascript ist single-threaded und du musst den Thread wieder freigeben, damit der Nutzer den Dialog selbst bedienen kann. Es gibt dann irgendwann ein Event, wenn das Formular abgesendet wurde oder der OK/Cancel-Button aktiviert wurde oder Backdrop geklickt oder Esc gedrückt oder was auch immer. In diesem Event kann man das Ergebnis des Dialogs aufbereiten und ruft dann eine Aktion auf, die damit was tun soll. Somit ist aber das Aufrufen des Dialogs und das Abarbeiten des Ergebnisses an getrennten Stellen im Code. Besser ist, wenn der Dialog-Aufruf ein Callback übergibt (oder zwei: eins für OK, eins für Cancel) und oben genanntes Event dieses Callback aufruft. Und dann kommt man an die Stelle, an der der Einsatz eines Promise sinnvoll ist. Die sind für asynchrones Arbeiten geschaffen, und so ein Dialog arbeitet ja auch nach diesem Prinzip. Der OK-Button (und verwandte Bedienhandlungen) löst das Promise (resolve), Cancel und Co. weisen es zurück (reject).</p> <p>dedlfix.</p> modale Fenster Sun, 12 May 19 09:33:10 Z https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1748529#m1748529 https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1748529#m1748529 <p>Liebe(r) JSKid,</p> <p>ich habe zum Thema modale Fenster und JavaScript einen Artikel erstellt: <a href="https://wiki.selfhtml.org/wiki/JavaScript/Tutorials/Eigene_modale_Dialogfenster" rel="nofollow noopener noreferrer">Eigene modale Dialogfenster</a>. Dieser Artikel bietet zunächst einen Ersatz für <code>alert</code>, <code>confirm</code> und <code>prompt</code> an, wird aber in einer späteren Erweiterung komplexere eigene Dialoge präsentieren. Die dazu notwendigen Grundlagen und Voraussetzungen werden aber schon in der jetzigen Fassung erklärt und dargestellt.</p> <p>Liebe Grüße,</p> <p>Felix Riesterer.</p> modale Fenster Mon, 06 May 19 06:44:59 Z https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1748103#m1748103 https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1748103#m1748103 <p>Ok, Vielen Dank für die Erlärung. Wie gesagt im Netz gibt es etliche Erklärungen und Beschreibungen wie modale Fenster erzeugt und benutzt werden. Das würde doch bedeuten, dass ein modales Fenster dann erst am Ende des Programm-Flußes angezeigt wird und lediglich eine Info beinhaltet.</p> modale Fenster Mon, 06 May 19 07:00:47 Z https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1748107#m1748107 https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1748107#m1748107 <p>Hallo</p> <blockquote> <p>Ok, Vielen Dank für die Erlärung. Wie gesagt im Netz gibt es etliche Erklärungen und Beschreibungen wie modale Fenster erzeugt und benutzt werden.</p> </blockquote> <p>Könntest du bitte einmal erklären, was du unter einem „modalen Fenster“ verstehst‽</p> <p>In den Antworten ist nämlich von zwei verschiedenen Techniken die Rede.</p> <ol> <li>Die modalen Fenster, die JavaScript selbst bereitstellt. Das wäre <code>window.confirm</code>, <code>window.alert</code> und <code>window.prompt</code>. Die warten, wie <a href="https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1747958#m1747958" rel="noopener noreferrer">Christian bereits beschrieb</a>, aber ihre ebenfalls beschriebenen Tücken haben.</li> <li>Modale Dialoge, die mit HTML-Elementen in einem vorhandenen HTML-Dokument erzeugt werden, wie sie in diesem Forum zum Beispiel für das erzeugen eines Links in einem Posting benutzt werden. In diesem Fall trifft <a href="https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1747961#m1747961" rel="noopener noreferrer">dedlfix' Beschreibung</a> zu, die da sagt, bei einem Event diese Elemente zu erzeugen und einzublenden sowie zum Ende der Programmausführung auch neue Events festzulegen, die bei Aktionen innerhalb des modalen Dialogs ausgelöst werden. Wenn eines dieser neuen Events anschlägt, wird ein neues Programm/eine neue Funktion ausgeführt, um beispielsweise eine Formulareingabe zu prüfen, an den Server zu senden und den Dialog zu schließen.</li> </ol> <blockquote> <p>Das würde doch bedeuten, dass ein modales Fenster dann erst am Ende des Programm-Flußes angezeigt wird und lediglich eine Info beinhaltet.</p> </blockquote> <p>Oder eben interaktive Elemente, mit denen später etwas geschehen soll/kann.</p> <p>Tschö, Auge</p> <div class="signature">-- <br> Ein echtes Alchimistenlabor musste voll mit Glasgefäßen sein, die so aussahen, als wären sie beim öffentlichen Schluckaufwettbewerb der Glasbläsergilde entstanden.<br> <em>Hohle Köpfe</em> von Terry Pratchett </div> modale Fenster Mon, 06 May 19 07:12:04 Z https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1748110#m1748110 https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1748110#m1748110 <p>Tach!</p> <blockquote> <p>Ok, Vielen Dank für die Erlärung. Wie gesagt im Netz gibt es etliche Erklärungen und Beschreibungen wie modale Fenster erzeugt und benutzt werden. Das würde doch bedeuten, dass ein modales Fenster dann erst am Ende des Programm-Flußes angezeigt wird und lediglich eine Info beinhaltet.</p> </blockquote> <p>Nein. Das modale Fenster ist erstmal nur eine Änderung des DOM, dergestalt dass die bisherigen Elemente der Seite überlagert und oft auch unbedienbar gemacht werden. Ansonsten verhalten sich die Dialog-Elemente nicht anders als andere HTML-Elemente, was die Bedienbarkeit und Interaktivität angeht. Nachdem diese Dialog-Elemente ins DOM eingebracht wurden, beendet man zunächst seine Arbeit (sprich: den Eventhandler, der zur Erstellung der Dialog-Elemente geführt hat) und der Programmfluss geht wieder an den Browser zurück, der sich wieder der Abarbeitung der Event Loop widmet oder idlet, wenn darin nichts zu finden ist. Es ist nun möglich, dass der Anwender Bedienhandlungen vornehmen kann, die der Browser wie üblich behandelt. Wenn es beispielsweise ein Klick auf den OK-Button ist, dann löst er dafür ein Event aus. Du kannst einen entsprechenden Eventhandler schreiben, der daraufhin die Elemente des Dialogs aus dem DOM entfernt, so dass die ursprünglichen Elemente wieder sichtbar und bedienbar werden. Der Eventhandler kann hier nun einfach enden, wenn nichts weiter zu tun ist. Oder aber, er ruft eine vorher definierte Funktion auf, die irgendwas macht, was auch immer getan werden soll. Das Aufrufen einer vordefinierten Funktion ist aber recht unflexibel, weswegen man generell lieber einen beim Erstellen übergebenen Callback aufruft, oder zu Mechanismen wie dem Promise greift.</p> <p>dedlfix.</p> modale Fenster Mon, 06 May 19 08:18:43 Z https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1748123#m1748123 https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1748123#m1748123 <p>Ich denke ich spreche von der Technik unter 1.) Nur sind die drei genannten "Fenster" nicht sehr schön und ich hätte sie gerne mit einem eigenen Stil versehen und halt den Progamm-Fluß genauso unterbrechen, bis der User etwas eingibt.</p> <p>Aber so wie ich dedlfix verstanden habe ist das nicht möglich.</p> modale Fenster Mon, 06 May 19 08:23:29 Z https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1748124#m1748124 https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1748124#m1748124 <p>Tach!</p> <blockquote> <p>Ich denke ich spreche von der Technik unter 1.) Nur sind die drei genannten "Fenster" nicht sehr schön und ich hätte sie gerne mit einem eigenen Stil versehen und halt den Progamm-Fluß genauso unterbrechen, bis der User etwas eingibt.</p> <p>Aber so wie ich dedlfix verstanden habe ist das nicht möglich.</p> </blockquote> <p>Richtig. confirm() und alert() halten das was im DOM passiert an. Der angezeigte Dialog findet unabhängig davon statt. Erst nach Bestätigung wird die DOM-Arbeit fortgesetzt.</p> <p>Ein selbst ersteller Dialog mit DOM-Elementen hingegen ist auf ein funktionierendes DOM angewiesen und kann dessen Tätigkeiten nicht anhalten, ohne selbst betroffen zu sein. Deswegen können Dialoge abseits von confirm() und alert() nicht synchron gestaltet werden.</p> <p>dedlfix.</p> modale Fenster Mon, 06 May 19 09:28:17 Z https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1748127#m1748127 https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1748127#m1748127 <p>Hallo</p> <blockquote> <p>Ich denke ich spreche von der Technik unter 1.)</p> </blockquote> <p>Gut, also die JS-eigenen Dialoge mit der Gefahr, dass ihre Anzeige von den Browsern von vornherein unterdrückt wird.</p> <blockquote> <p>Nur sind die drei genannten "Fenster" nicht sehr schön und ich hätte sie gerne mit einem eigenen Stil versehen …</p> </blockquote> <p>Womit wir bei Technik Nr. 2, HTML-Elemente als Dialog zu erzeugen, wären.</p> <blockquote> <p>… und halt den Progamm-Fluß genauso unterbrechen, bis der User etwas eingibt.</p> </blockquote> <p>Ich weiß nicht, warum du dich so sehr auf die Unterbrechung des Programmflusses kaprizierst. Dass das bei Technik Nr. 2 nicht geht, ist klar. Dass diese Unterbrechnung unnötig ist und durch einen geteilten Programmablauf ersetzt wird, hat dedlfix lang und breit erklärt.</p> <p>Beispiel:</p> <pre><code class="block language-html"><span class="token doctype"><span class="token punctuation"><!</span><span class="token doctype-tag">DOCTYPE</span> <span class="token name">html</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>html</span> <span class="token attr-name">lang</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>de<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>head</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>meta</span> <span class="token attr-name">charset</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>utf-8<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>meta</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>viewport<span class="token punctuation">"</span></span> <span class="token attr-name">content</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>width=device-width, initial-scale=1.0<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token comment"><!-- mehr Elemente --></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>title</span><span class="token punctuation">></span></span>Dialogtest<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>title</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>head</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>body</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>header</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>h1</span><span class="token punctuation">></span></span>Dialogtest<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>h1</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>nav</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>mainmenu<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>ul</span><span class="token punctuation">></span></span> <span class="token comment"><!-- diverse Listenelemente --></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>li</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>?dataset=search<span class="token punctuation">"</span></span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>indoc<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Adressen suchen<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>a</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>li</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>ul</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>nav</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>header</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>main</span><span class="token punctuation">></span></span> <span class="token comment"><!-- diverse Elemente --></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>main</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>template</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>template-search<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>dialog</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>popupform<span class="token punctuation">"</span></span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>entryform simple<span class="token punctuation">"</span></span> <span class="token attr-name">open</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>header</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>titlebar<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>h2</span><span class="token punctuation">></span></span>Suche von Adressen<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>h2</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>header</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>p</span><span class="token punctuation">></span></span>Teileingaben sind mit angehängtem Sternchen (*) möglich. Ohne Stern wird <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>em</span><span class="token punctuation">></span></span>exakt<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>em</span><span class="token punctuation">></span></span> nach dem eingegebenen Wert gesucht.<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>p</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>form</span> <span class="token attr-name">method</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>post<span class="token punctuation">"</span></span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>entryform<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>fieldset</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>legend</span><span class="token punctuation">></span></span>Suchparameter<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>legend</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>label</span> <span class="token attr-name">for</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>id-strasse<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Straße, Hausnummer<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>label</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>input</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>text<span class="token punctuation">"</span></span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>id-strasse<span class="token punctuation">"</span></span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>fld-strasse<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>label</span> <span class="token attr-name">for</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>id-plz<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>PLZ<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>label</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>input</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>text<span class="token punctuation">"</span></span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>id-plz<span class="token punctuation">"</span></span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>fld-plz<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>label</span> <span class="token attr-name">for</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>id-ort<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Ort<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>label</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>input</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>text<span class="token punctuation">"</span></span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>id-ort<span class="token punctuation">"</span></span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>fld-ort<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>fieldset</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>p</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>button</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>btn-search<span class="token punctuation">"</span></span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>id-btn-search<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Suche ausführen<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>button</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>button</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>reset<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Eingaben zurücksetzen<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>button</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>button</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>button<span class="token punctuation">"</span></span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>close-popupform<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Formular schließen<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>button</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>p</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>form</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>dialog</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>backdrop<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>template</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>body</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>html</span><span class="token punctuation">></span></span> </code></pre> <p>In einem HTML-Dokument wird per Template ein Suchformular bereitgehalten. Per JS wird ein Eventhandler für den Link im Hauptmenü der Seite registriert …</p> <pre><code class="block language-javascript">document<span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token string">'DOMContentLoaded'</span><span class="token punctuation">,</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">'mainmenu'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token string">'click'</span><span class="token punctuation">,</span> runActionMainMenu<span class="token punctuation">,</span> <span class="token boolean">true</span><span class="token punctuation">)</span><span class="token punctuation">;</span> document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">'mainmenu'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token string">'touchstart'</span><span class="token punctuation">,</span> runActionMainMenu<span class="token punctuation">,</span> <span class="token boolean">true</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> </code></pre> <p>… damit auf den Klick des Links reagiert werden kann, um den Dialog einzublenden.</p> <pre><code class="block language-javascript"><span class="token keyword">function</span> <span class="token function">runActionMainMenu</span><span class="token punctuation">(</span><span class="token parameter">event</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">var</span> c<span class="token punctuation">,</span> i<span class="token punctuation">,</span> em <span class="token operator">=</span> <span class="token keyword">null</span><span class="token punctuation">;</span> <span class="token keyword">var</span> elem <span class="token operator">=</span> event<span class="token punctuation">.</span>target<span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>elem<span class="token punctuation">.</span>classList<span class="token punctuation">.</span><span class="token function">contains</span><span class="token punctuation">(</span><span class="token string">'indoc'</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">var</span> url <span class="token operator">=</span> elem<span class="token punctuation">.</span><span class="token function">getAttribute</span><span class="token punctuation">(</span><span class="token string">'href'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>url <span class="token operator">==</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token keyword">null</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">var</span> urlTarget <span class="token operator">=</span> <span class="token function">gup</span><span class="token punctuation">(</span><span class="token string">'dataset'</span><span class="token punctuation">,</span> url<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// gup: Hilfsfunktion, um an den Wert des URL-Parameters zu kommen</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>urlTarget <span class="token operator">==</span> <span class="token string">'search'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">var</span> em <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">querySelector</span><span class="token punctuation">(</span><span class="token string">'#template-search'</span><span class="token punctuation">)</span><span class="token punctuation">.</span>content<span class="token punctuation">;</span> <span class="token comment">// finde das richtige Template</span> <span class="token punctuation">}</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>em <span class="token operator">!==</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">var</span> clone <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">importNode</span><span class="token punctuation">(</span>em<span class="token punctuation">,</span> <span class="token boolean">true</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// importiere den Inhalt des Templates in die Variable clone</span> document<span class="token punctuation">.</span><span class="token function">querySelector</span><span class="token punctuation">(</span><span class="token string">'main'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">appendChild</span><span class="token punctuation">(</span>clone<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// hänge den Inhalt des Templates ins DOM ein</span> <span class="token comment">/** * Der Dialog wurde bereitgestellt, das Programm kann beendet werden, wenn … * … die Events zum absenden und schließen des Dialogs registriert wurden */</span> document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">'entryform'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token string">'submit'</span><span class="token punctuation">,</span> searchDatasets<span class="token punctuation">,</span> <span class="token boolean">true</span><span class="token punctuation">)</span><span class="token punctuation">;</span> document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">'close-popupform'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token string">'click'</span><span class="token punctuation">,</span> closePopupForm<span class="token punctuation">,</span> <span class="token boolean">true</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"kein zur Aktion ("</span> <span class="token operator">+</span> urlTarget <span class="token operator">+</span> <span class="token string">") passendes Template gefunden."</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> event<span class="token punctuation">.</span><span class="token function">preventDefault</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// verhindere, dass dem angegebenen Linkziel gefolgt wird</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> </code></pre> <p>In closePopupForm werden die Events zum schließen des Dialogs deregistriert und der Dialog aus dem DOM entfernt und in <code>searchDatasets</code> wird zudem zuvor per Ajax/Fetch die Suchanfrage an den Server gestellt. Und auch dort geht man nach dem selben Prinzip vor, eine Aufgabe zu erledigen, und zu definieren, was bei der irgendwannn auftretenden reaktion zu erfolgen hat (asynchrone Abarbeitung).</p> <pre><code class="block language-javascript"><span class="token keyword">function</span> <span class="token function">closePopupForm</span><span class="token punctuation">(</span><span class="token parameter">event</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">var</span> elem <span class="token operator">=</span> event<span class="token punctuation">.</span>target<span class="token punctuation">;</span> <span class="token keyword">var</span> dialog <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">'popupform'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">var</span> backdrop <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">getElementsByClassName</span><span class="token punctuation">(</span><span class="token string">'backdrop'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>elem<span class="token punctuation">.</span>id <span class="token operator">==</span> <span class="token string">'close-popupform'</span> <span class="token operator">||</span> elem<span class="token punctuation">.</span>id <span class="token operator">==</span> <span class="token string">'close-popupform-icon'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">'close-popupform'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">removeEventListener</span><span class="token punctuation">(</span><span class="token string">'click'</span><span class="token punctuation">,</span> closePopupForm<span class="token punctuation">,</span> <span class="token boolean">true</span><span class="token punctuation">)</span><span class="token punctuation">;</span> dialog<span class="token punctuation">.</span><span class="token function">remove</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">var</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator"><</span> backdrop<span class="token punctuation">.</span>length<span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> backdrop<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">.</span><span class="token function">remove</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> </code></pre> <p>Zu guter Letzt gehört der Dialog zum Rest der Seite passend per CSS formatiert.</p> <pre><code class="block language-css"><span class="token selector">dialog</span> <span class="token punctuation">{</span> <span class="token property">position</span><span class="token punctuation">:</span> fixed<span class="token punctuation">;</span> <span class="token property">left</span><span class="token punctuation">:</span> 0<span class="token punctuation">;</span> <span class="token property">right</span><span class="token punctuation">:</span> 0<span class="token punctuation">;</span> <span class="token property">top</span><span class="token punctuation">:</span> 2em<span class="token punctuation">;</span> <span class="token property">margin</span><span class="token punctuation">:</span> auto<span class="token punctuation">;</span> <span class="token property">padding</span><span class="token punctuation">:</span> 1rem<span class="token punctuation">;</span> <span class="token property">border</span><span class="token punctuation">:</span> 1px solid #cbd4d8<span class="token punctuation">;</span> <span class="token property">border-radius</span><span class="token punctuation">:</span> 0.25rem<span class="token punctuation">;</span> <span class="token property">background-color</span><span class="token punctuation">:</span> #fff<span class="token punctuation">;</span> <span class="token property">display</span><span class="token punctuation">:</span> block<span class="token punctuation">;</span> <span class="token property">z-index</span><span class="token punctuation">:</span> 3<span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token selector">dialog + .backdrop</span> <span class="token punctuation">{</span> <span class="token property">position</span><span class="token punctuation">:</span> fixed<span class="token punctuation">;</span> <span class="token property">top</span><span class="token punctuation">:</span> 0<span class="token punctuation">;</span> <span class="token property">right</span><span class="token punctuation">:</span> 0<span class="token punctuation">;</span> <span class="token property">bottom</span><span class="token punctuation">:</span> 0<span class="token punctuation">;</span> <span class="token property">left</span><span class="token punctuation">:</span> 0<span class="token punctuation">;</span> <span class="token property">background</span><span class="token punctuation">:</span> <span class="token function">rgba</span><span class="token punctuation">(</span>0<span class="token punctuation">,</span> 0<span class="token punctuation">,</span> 0<span class="token punctuation">,</span> 0.375<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token property">z-index</span><span class="token punctuation">:</span> 2<span class="token punctuation">;</span> <span class="token punctuation">}</span> </code></pre> <p>Du brauchst also keine Möglichkeit, dass das Programm auf etwas wartet und bis dahin keine anderen Aufgaben erfüllt, sondern nur eine Trennung der Aufgaben in Erzeugung des Dialogs und die Reaktionen auf die möglichen Eingaben.</p> <p>Das Ganze geht bestimmt auch eleganter und eine Bedienung des Formulars per Touch habe ich im Codebeispiel nicht berücksichtigt, aber zur Verdeutlichung des Prinzips sollte es, so hoffe ich, reichen.</p> <p>Tschö, Auge</p> <div class="signature">-- <br> Ein echtes Alchimistenlabor musste voll mit Glasgefäßen sein, die so aussahen, als wären sie beim öffentlichen Schluckaufwettbewerb der Glasbläsergilde entstanden.<br> <em>Hohle Köpfe</em> von Terry Pratchett </div> modale Fenster Sat, 11 May 19 08:31:48 Z https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1748481#m1748481 https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1748481#m1748481 <p>Liebe(r) JSKid,</p> <blockquote> <p>Aber so wie ich dedlfix verstanden habe ist das nicht möglich.</p> </blockquote> <p>richtig, wenn Du die <code>window</code>-Methoden <code>alert</code>, <code>confirm</code> und <code>prompt</code> verschönern willst, musst Du sie komplett mit anderen Mitteln nachbauen und dabei eine asynchrone Vorgehensweise einsetzen.</p> <p>Liebe Grüße,</p> <p>Felix Riesterer.</p> modale Fenster Sun, 12 May 19 09:39:46 Z https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1748530#m1748530 https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1748530#m1748530 <p>Servus!</p> <blockquote> <p>ich habe zum Thema modale Fenster und JavaScript einen Artikel erstellt: <a href="https://wiki.selfhtml.org/wiki/JavaScript/Tutorials/Eigene_modale_Dialogfenster" rel="nofollow noopener noreferrer">Eigene modale Dialogfenster</a>.</p> </blockquote> <p>Den kannte ich noch gar nicht. Ach so: Niegel-nagelneu!</p> <p>Vielen Dank!</p> <p>Herzliche Grüße</p> <p>Matthias Scharwies</p> <div class="signature">-- <br> <em>"I don’t make typos. I make new words."</em> </div> modale Fenster Mon, 13 May 19 08:44:54 Z https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1748574#m1748574 https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1748574#m1748574 <p>Hallo Felix,</p> <p>ich finde es gut, das du dich den Thema gewidmet hast. Ich habe den Artikel jetzt nur überflogen, aber dabei sind mir zwei Dinge aufgefallen:</p> <ul> <li> <p>Du verwendest Einbuchstaben-Variablen, z.B. "s" für den Anzeigestring. Ich mache das auch gerne, aber in einem Tutorial sollten die Variablennamen sprechend sein.</p> </li> <li> <p>Du hast das Thema "Den Focus fangen" ausgeklammert. (Das habe ich bei meinen Warnfenstern auch gemacht.) Die Frage ist: sollten das in diesen Artikel mit rein, oder ist das so unwichtig, dass man da erst mal drauf verzichten kann?</p> </li> </ul> <p>Gruß<br> Jürgen</p> modale Fenster Mon, 13 May 19 12:09:54 Z https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1748595#m1748595 https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1748595#m1748595 <p>Tach!</p> <blockquote> <p>ich habe zum Thema modale Fenster und JavaScript einen Artikel erstellt: <a href="https://wiki.selfhtml.org/wiki/JavaScript/Tutorials/Eigene_modale_Dialogfenster" rel="nofollow noopener noreferrer">Eigene modale Dialogfenster</a>. Dieser Artikel bietet zunächst einen Ersatz für <code>alert</code>, <code>confirm</code> und <code>prompt</code> an, wird aber in einer späteren Erweiterung komplexere eigene Dialoge präsentieren. Die dazu notwendigen Grundlagen und Voraussetzungen werden aber schon in der jetzigen Fassung erklärt und dargestellt.</p> </blockquote> <p>Sehr schön bis hier her, und nun zur Kritik. Ein alert() hat keine Unterscheidung zwischen OK und Abbrechen, es gibt nur die Lesebestätigung. Man sollte da also nur einen Handler angeben müssen/können.</p> <p>Als Fortsetzung bietet sich an, über Promises nachzudenken.</p> <p>dedlfix.</p> modale Fenster Mon, 13 May 19 14:57:55 Z https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1748627#m1748627 https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1748627#m1748627 <p>Hallo Felix,</p> <blockquote> <p>ich habe zum Thema modale Fenster und JavaScript einen Artikel erstellt: <a href="https://wiki.selfhtml.org/wiki/JavaScript/Tutorials/Eigene_modale_Dialogfenster" rel="nofollow noopener noreferrer">Eigene modale Dialogfenster</a>.</p> </blockquote> <p>ich habe den Artikel nur überflogen, ich glaube man kann ihn etwas vereinfachen, indem man mit der Methode <a href="https://www.w3.org/TR/html52/interactive-elements.html#dom-htmldialogelement-showmodal" rel="nofollow noopener noreferrer">HtmlDialogElement.showModal()</a> arbeitet. Ich vermute, dass Browser dann auch das Fokus-Handling übernehmen, hab es aber nicht ausprobiert. Leider ist die Browser-Unterstützung noch unbefriedigend, aber ich glaube da wäre dem Artikel mit einem Hinweis auf einen Polyfill mehr gedient als mit einem handgestrickten Workaround.</p> <p>Viele Grüße</p> modale Fenster Fri, 17 May 19 17:08:50 Z https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1748885#m1748885 https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1748885#m1748885 <p>Hallo Ingrid,</p> <blockquote> <p>Dieser Artikel [...] wird aber in einer späteren Erweiterung komplexere eigene Dialoge präsentieren.</p> </blockquote> <p>[x] <a href="https://wiki.selfhtml.org/wiki/JavaScript/Tutorials/Eigene_modale_Dialogfenster#Individuelle_L.C3.B6sungen" rel="nofollow noopener noreferrer">done</a></p> <p>Liebe Grüße,</p> <p>Felix Riesterer.</p> modale Fenster Mon, 13 May 19 09:30:09 Z https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1748580#m1748580 https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1748580#m1748580 <p>Hallo JürgenB,</p> <blockquote> <ul> <li>Du hast das Thema "Den Focus fangen" ausgeklammert. (Das habe ich bei meinen Warnfenstern auch gemacht.) Die Frage ist: sollten das in diesen Artikel mit rein, oder ist das so unwichtig, dass man da erst mal drauf verzichten kann?</li> </ul> </blockquote> <p>Focus-Management für Modals ist ein essentielles A11y-Feature. Auf die Behandlung sollte man auf keinen Fall verzichten.</p> <p>LG,<br> CK</p> <div class="signature">-- <br> <a href="https://wwwtech.de/about" rel="noopener noreferrer">https://wwwtech.de/about</a> </div> modale Fenster Mon, 13 May 19 13:47:22 Z https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1748602#m1748602 https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1748602#m1748602 <p>Lieber JürgenB,</p> <blockquote> <ul> <li>Du verwendest Einbuchstaben-Variablen, z.B. "s" für den Anzeigestring. Ich mache das auch gerne, aber in einem Tutorial sollten die Variablennamen sprechend sein.</li> </ul> </blockquote> <p>wenn der Erklärtext direkt nach dem Code nicht genügt, werde ich <code>s</code> zu <code>str</code> erweitern.</p> <blockquote> <ul> <li>Du hast das Thema "Den Focus fangen" ausgeklammert. (Das habe ich bei meinen Warnfenstern auch gemacht.) Die Frage ist: sollten das in diesen Artikel mit rein, oder ist das so unwichtig, dass man da erst mal drauf verzichten kann?</li> </ul> </blockquote> <p>Ich habe keine Ahnung wohin ich den Fokus nach dem Schließen des Dialogs setzen soll. Woher soll ich denn wissen, wo er davor war?</p> <p>Etwas anderes ist es, den Fokusverlust bei einem offenen Dialogfenster zu unterbinden bzw. reparieren. Wohin soll er denn als Default zurück geführt werden? Auf den Schließen-Button wie schon zu Anfang beim Anzeigen des Dialogs?</p> <p>Liebe Grüße,</p> <p>Felix Riesterer.</p> modale Fenster Mon, 13 May 19 11:56:13 Z https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1748593#m1748593 https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1748593#m1748593 <p>Hallo Christian,</p> <p>dann sollte man Felix zumindestens mit Ideen versorgen.</p> <p>Meine spontane ungetestete Idee: auf das Blur-Event von der Modal-Box lauschen und dann den Focus zurückholen.</p> <p>Gruß<br> Jürgen</p> modale Fenster Mon, 13 May 19 12:05:51 Z https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1748594#m1748594 https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1748594#m1748594 <p>Hallo JürgenB,</p> <blockquote> <p>dann sollte man Felix zumindestens mit Ideen versorgen.</p> </blockquote> <p>Ja. Leider bin ich gerade mal wieder unterwegs, deshalb hatte/habe ich keine Zeit für eine ausführlichere Antwort… im Wesentlichen läuft es darauf hinaus, dass man bei aktivem Modal überwachen muss, dass der Fokus nicht auf ein Element ausserhalb des Modals fällt. Es gibt da ein paar Beispiel-Projekte, etwa das <a href="https://github.com/gdkraus/accessible-modal-dialog" rel="noopener noreferrer">accessible modal dialog</a> oder das <a href="https://github.com/edenspiekermann/a11y-dialog" rel="noopener noreferrer">a11y-dialog</a>, ein Fork und eine Weiterentwicklung von dem Accessible Modal Dialog.</p> <blockquote> <p>Meine spontane ungetestete Idee: auf das Blur-Event von der Modal-Box lauschen und dann den Focus zurückholen.</p> </blockquote> <p>Weiss nicht recht, ob das reicht. Die beiden verlinkten Projekte machen schon etwas mehr. Ein Blick in deren Code lohnt sich.</p> <p>LG,<br> CK</p> <div class="signature">-- <br> <a href="https://wwwtech.de/about" rel="noopener noreferrer">https://wwwtech.de/about</a> </div> modale Fenster Mon, 13 May 19 13:48:18 Z https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1748603#m1748603 https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1748603#m1748603 <p>Lieber JürgenB,</p> <blockquote> <p>dann sollte man Felix zumindestens mit Ideen versorgen.</p> </blockquote> <p>dieser Dein Satz wärmt mein Herz! Sagt er doch in etwa: Wenn ihr kritisiert, dann bitte konstruktiv!</p> <p>Liebe Grüße,</p> <p>Felix Riesterer.</p> modale Fenster Mon, 13 May 19 13:53:22 Z https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1748604#m1748604 https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1748604#m1748604 <p>Lieber Christian,</p> <blockquote> <p>im Wesentlichen läuft es darauf hinaus, dass man bei aktivem Modal überwachen muss, dass der Fokus nicht auf ein Element ausserhalb des Modals fällt. Es gibt da ein paar Beispiel-Projekte, etwa das <a href="https://github.com/gdkraus/accessible-modal-dialog" rel="noopener noreferrer">accessible modal dialog</a> oder das <a href="https://github.com/edenspiekermann/a11y-dialog" rel="noopener noreferrer">a11y-dialog</a>, ein Fork und eine Weiterentwicklung von dem Accessible Modal Dialog.</p> </blockquote> <p>das sind doch prima Links um unter "Weblinks" oder "Siehe auch" hinzugefügt zu werden! Im Rahmen des Tutorials kann ich die Problematik nur aufzeigen, keinesfalls aber zur Zufriedenheit aller möglicher Profis vollumfänglich lösen. Daher mein Dank für diese Anstöße, ich werde sehen, was ich damit tue.</p> <p>Liebe Grüße,</p> <p>Felix Riesterer.</p> modale Fenster Mon, 13 May 19 13:44:06 Z https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1748600#m1748600 https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1748600#m1748600 <p>Lieber dedlfix,</p> <blockquote> <p>Als Fortsetzung bietet sich an, über Promises nachzudenken.</p> </blockquote> <p>um das - für mich bisher nur dem Namen nach bekannte - Thema vorerst nicht anschneiden zu müssen, habe ich diesen ergänzenden Callback verwendet. Aber ja, das Thema liegt hier definitiv auf der Hand. Sobald ich mehr davon verstehe und wieder mehr Zeit habe, werde ich mir eine passende Ergänzung überlegen. Außerdem müsste man dann den Artikel auf mehrere Seiten auftrennen. Die Seite ist jetzt schon sehr lang...</p> <p>Liebe Grüße,</p> <p>Felix Riesterer.</p> modale Fenster Mon, 13 May 19 14:23:26 Z https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1748614#m1748614 https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1748614#m1748614 <p>Tach!</p> <blockquote> <blockquote> <p>Als Fortsetzung bietet sich an, über Promises nachzudenken.</p> </blockquote> <p>Aber ja, das Thema liegt hier definitiv auf der Hand. Sobald ich mehr davon verstehe und wieder mehr Zeit habe, werde ich mir eine passende Ergänzung überlegen.</p> </blockquote> <p>Als Tipp für den Einstieg: Meiner Erfahrung nach sollte man sich dem Thema Promises von zwei Seiten her nähern. Zum einen als Verwender und das ist der einfache Teil. Die meisten werden nur mit so etwas in Berührung kommen:</p> <pre><code class="block language-js">dialog<span class="token punctuation">.</span><span class="token function">open</span><span class="token punctuation">(</span>parameters<span class="token punctuation">)</span> <span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token parameter">result</span> <span class="token operator">=></span> <span class="token operator">...</span><span class="token punctuation">)</span> <span class="token punctuation">.</span><span class="token function">catch</span><span class="token punctuation">(</span><span class="token parameter">error</span> <span class="token operator">=></span> <span class="token operator">...</span><span class="token punctuation">)</span><span class="token punctuation">;</span> </code></pre> <p>Wenn man damit klarkommt (man kann das zum Beispiel mit der Fetch-API üben), kommt die andere Seite dran, ein Promise zu erstellen.</p> <pre><code class="block language-javascript"><span class="token keyword">function</span> <span class="token function">start</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">Promise</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">resolve<span class="token punctuation">,</span> reject</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>window<span class="token punctuation">.</span><span class="token function">confirm</span><span class="token punctuation">(</span><span class="token string">'Ja/Nein'</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token function">resolve</span><span class="token punctuation">(</span><span class="token number">42</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> <span class="token function">reject</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token function">start</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token parameter">result</span> <span class="token operator">=></span> <span class="token punctuation">{</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Die Antwort ist'</span><span class="token punctuation">,</span> result<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token punctuation">.</span><span class="token function">catch</span><span class="token punctuation">(</span><span class="token parameter">error</span> <span class="token operator">=></span> <span class="token punctuation">{</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Abgebrochen'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> </code></pre> <p>Sieht auch noch easy aus, aber wir müssen ja die Steuerung unverrichteter Dinge zurückgeben und bekommen das Zepter nur aufgrund von Events oder ähnlichem wieder, um das Promise erfüllen oder zurückweisen zu können. Das müssen wir dann etwas schachteln, damit wir eine Closure bekommen, die und das resolve und reject festhält. Das sieht dem Prinzip nach so aus:</p> <pre><code class="block language-javascript"><span class="token keyword">function</span> <span class="token function">start</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">Promise</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">resolve<span class="token punctuation">,</span> reject</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> ok_button<span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token string">'click'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token function">resolve</span><span class="token punctuation">(</span><span class="token number">42</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> cancel_button<span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token string">'click'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token function">reject</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> dialog<span class="token punctuation">.</span><span class="token function">open</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token function">start</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token parameter">result</span> <span class="token operator">=></span> <span class="token punctuation">{</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Die Antwort ist'</span><span class="token punctuation">,</span> result<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token punctuation">.</span><span class="token function">catch</span><span class="token punctuation">(</span><span class="token parameter">error</span> <span class="token operator">=></span> <span class="token punctuation">{</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Abgebrochen'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> </code></pre> <p>dedlfix.</p> modale Fenster Mon, 13 May 19 14:22:00 Z https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1748613#m1748613 https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1748613#m1748613 <p>Hallo Felix,</p> <blockquote> <p>... werde ich <code>s</code> zu <code>str</code> erweitern."</p> </blockquote> <p>ich dachte da eher an „Anzeigetext“, „Callback_bei_OK“, …</p> <blockquote> <p>Ich habe keine Ahnung wohin ich den Fokus nach dem Schließen des Dialogs setzen soll. Woher soll ich denn wissen, wo er davor war?</p> </blockquote> <p>Idee: über das Focus-Event merken, wer den Focus hatte, bis das modale Fenster geöffnet wurde.</p> <blockquote> <p>Etwas anderes ist es, den Fokusverlust bei einem offenen Dialogfenster zu unterbinden bzw. reparieren. Wohin soll er denn als Default zurück geführt werden? Auf den Schließen-Button wie schon zu Anfang beim Anzeigen des Dialogs?</p> </blockquote> <p>bei Shift-Tab zum letzten fokussierbaren Element springen, sonst zum ersten; oder auch immer zum beim Öffnen fokussierten.</p> <p>Gruß<br> Jürgen</p> modale Fenster Mon, 13 May 19 14:39:35 Z https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1748623#m1748623 https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1748623#m1748623 <p>Hallo Felix,</p> <blockquote> <blockquote> <p>dann sollte man Felix zumindestens mit Ideen versorgen.</p> </blockquote> <p>dieser Dein Satz wärmt mein Herz! Sagt er doch in etwa: Wenn ihr kritisiert, dann bitte konstruktiv!</p> </blockquote> <p>Du hast recht. Tut mir leid. Ich war, als ich das geschrieben habe, im Zug unterwegs und musste mein Zeug zusammenpacken, deshalb war das so kurz.</p> <p>LG,<br> CK</p> <div class="signature">-- <br> <a href="https://wwwtech.de/about" rel="noopener noreferrer">https://wwwtech.de/about</a> </div> modale Fenster Mon, 13 May 19 21:15:38 Z https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1748681#m1748681 https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1748681#m1748681 <p>Hallo Ingrid,</p> <blockquote> <p>das sind doch prima Links um unter "Weblinks" oder "Siehe auch" hinzugefügt zu werden!</p> </blockquote> <p>na wie gut, dass sie dort jetzt stehen.</p> <p>Liebe Grüße,</p> <p>Felix Riesterer.</p> modale Fenster Mon, 13 May 19 14:34:30 Z https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1748620#m1748620 https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1748620#m1748620 <p>Tach!</p> <blockquote> <blockquote> <p>Ich habe keine Ahnung wohin ich den Fokus nach dem Schließen des Dialogs setzen soll. Woher soll ich denn wissen, wo er davor war?</p> </blockquote> <p>Idee: über das Focus-Event merken, wer den Focus hatte, bis das modale Fenster geöffnet wurde.</p> </blockquote> <p>Im Zweifelsfall ist das der Button, dessen Betätigung zum Öffnen des Dialogs geführt hat. Ob es sinnvoll ist, den Focus wieder dorthin zu setzen, ist vielleicht auch eine Frage des Anwendungsfalles.</p> <p>dedlfix.</p> modale Fenster Mon, 13 May 19 16:11:07 Z https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1748652#m1748652 https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1748652#m1748652 <p>Lieber dedlfix,</p> <blockquote> <pre><code class="block language-javascript"><span class="token keyword">function</span> <span class="token function">start</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">Promise</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">resolve<span class="token punctuation">,</span> reject</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> ok_button<span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token string">'click'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token function">resolve</span><span class="token punctuation">(</span><span class="token number">42</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> cancel_button<span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token string">'click'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token function">reject</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> dialog<span class="token punctuation">.</span><span class="token function">open</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token function">start</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token parameter">result</span> <span class="token operator">=></span> <span class="token punctuation">{</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Die Antwort ist'</span><span class="token punctuation">,</span> result<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token punctuation">.</span><span class="token function">catch</span><span class="token punctuation">(</span><span class="token parameter">error</span> <span class="token operator">=></span> <span class="token punctuation">{</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Abgebrochen'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> </code></pre> </blockquote> <p>AHA! Also muss die aufgerufene Fuktion ein <code>Promise</code>-Objekt zurückliefern. Diesem <code>Promise</code>-Objekt kann man mit der <code>then</code>-Methode eine (Callback-)Funktion für den <em>resolve</em>-Fall geben, mit der <code>catch</code>-Methode eine für den <em>reject</em>-Fall.</p> <p>Ist das so richtig? Wenn ja, dann sieht das schon ziemlich aus wie meine <code>callBack</code>-Sammlung, nur dass diese im Zweifel noch zwischen "cancel" und "abort" unterscheiden kann, also neben <em>resolve</em> und <em>reject</em> noch <em>abort</em> liefert. Ein <code>Promise</code>-Objekt kann das also nicht? Das fände ich dann für mein Tutorial unzureichend!</p> <p>Ich <a href="https://wiki.selfhtml.org/wiki/JavaScript/Promise" rel="nofollow noopener noreferrer">lese gerade nach</a> und sehe, dass man mehrere <code>then</code>-Methodenaufrufe machen kann, und dass <code>Promise</code>-Objekte wesentlich komplexer sind (Status-Werte, innere und äußere Promises, Exceptions) als meine Callback-Lösung, die ich doch als recht elegant und für den vorliegenden Fall als bequem empfinde. Wenn man jetzt noch die Buttons frei benennen könnte, wäre sie sogar luxuriös, aber das will ich in diesem Tutorial nicht auch noch behandeln.</p> <p>Liebe Grüße,</p> <p>Felix Riesterer.</p> modale Fenster Mon, 13 May 19 15:06:59 Z https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1748632#m1748632 https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1748632#m1748632 <p>Hallo dedlfix,</p> <blockquote> <blockquote> <blockquote> <p>Ich habe keine Ahnung wohin ich den Fokus nach dem Schließen des Dialogs setzen soll. Woher soll ich denn wissen, wo er davor war?</p> </blockquote> <p>Idee: über das Focus-Event merken, wer den Focus hatte, bis das modale Fenster geöffnet wurde.</p> </blockquote> <p>Im Zweifelsfall ist das der Button, dessen Betätigung zum Öffnen des Dialogs geführt hat. Ob es sinnvoll ist, den Focus wieder dorthin zu setzen, ist vielleicht auch eine Frage des Anwendungsfalles.</p> </blockquote> <p>wenn das Öffnen auf eine Useraktion erfolgte, ja. Wenn das Fenster aber z.B. eine automatisch geöffnete Fehlermeldung ist, dann wird es schwieriger.</p> <p>Gruß<br> Jürgen</p> modale Fenster Mon, 13 May 19 15:31:34 Z https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1748639#m1748639 https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1748639#m1748639 <p>Hallo,</p> <p>ich habe gerade mal <a href="https://wiki.selfhtml.org/wiki/JavaScript/Tutorials/zug%C3%A4ngliche_Dialog-Box" rel="nofollow noopener noreferrer">dieses Beispiel</a> auch im Chrome ausprobiert, da wird der Fokus auch nicht gefangen.</p> <p>Gruß<br> Jürgen</p> modale Fenster Mon, 13 May 19 15:56:23 Z https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1748650#m1748650 https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1748650#m1748650 <p>Lieber 1unitedpower,</p> <blockquote> <p>ich glaube man kann ihn etwas vereinfachen,</p> </blockquote> <p>denke daran, dass die Zielgruppe für das Tutorial zunächst verinnerlichen muss, dass man hier nicht mehr linear programmiert. Das ist das eigentliche Kernthema. Die Sache mit den Dialog-Boxen ist in meinen Augen Semantik-Wichserei mit a11y-Religion. Hat sicherlich beste Gründe, warum man das so machen wollen können sollte, aber vor zehn Jahren hat man sich auch schon zu behelfen gewusst: Mit simplen <code><div></code>-Elementen und gleichermaßen passendem CSS - JavaScript natürlich inklusive. Insofern ist an diesem Artikel eigentlich nichts wirklich neues dabei, außer das Gehampel mit Polyfill für schönes <code><dialog></code>-Benutzen.</p> <blockquote> <p>indem man mit der Methode <a href="https://www.w3.org/TR/html52/interactive-elements.html#dom-htmldialogelement-showmodal" rel="nofollow noopener noreferrer">HtmlDialogElement.showModal()</a> arbeitet. Ich vermute, dass Browser dann auch das Fokus-Handling übernehmen, hab es aber nicht ausprobiert. Leider ist die Browser-Unterstützung noch unbefriedigend,</p> </blockquote> <p>Das nenne ich nicht "konstruktive Kritik"! Erst etwas bemängeln, dann zugeben, dass Du es nicht ausprobiert hast und dann noch obendrein zugeben, dass das aufgrund der aktuellen Unterstützung durch die Browser ohnehin noch Zukunftsmusik ist. Nee, konstruktiv geht definitiv anders!</p> <blockquote> <p>aber ich glaube da wäre dem Artikel mit einem Hinweis auf einen Polyfill mehr gedient als mit einem handgestrickten Workaround.</p> </blockquote> <p>Du darfst gerne den Artikel in Deinem Sinne verbessern. Nimm Dir einfach dazu die notwendige Zeit. Dann kannst Du vorführen, wie es besser geht.</p> <p>Auf der anderen Seite musst Du vielleicht überlesen haben, dass ich auf den Wiki-Artikel mit den zugänglichen Dialog-Boxen mehrfach hinweise, in dem die Sache mit der momentanen Notwendigkeit eines Polyfills ja hinlänglich besprochen wird. Dass ich einen "Workaround" gebastelt hätte, verbitte ich mir. Ich spreche konkret von einem <em>Polyfill</em>. Wenn der einmal nicht mehr notwendig sein sollte, kann man alles, was mit dem von mir zur Verfügung gestellten Polyfill nicht mehr gebraucht wird, wegkürzen, um nur noch das Handling mit den Callbacks übrig zu lassen. Darum kommt man so oder so nicht herum - naja, vielleicht doch mit den von <a href="/users/27" class="mention registered-user" rel="noopener noreferrer">@dedlfix</a> schon erwähnten Promises. Aber darauf bist Du hier ja nicht eingegangen.</p> <p>Ich erinnere Dich hiermit in aller Deutlichkeit an Deine Kritik an Jörgs Login-System-Tutorial, in der Du auch sehr vage und könnte/müsste/würde formuliert hast. Das macht Deine Kritik wertlos, da sie nicht konkret und damit nicht mehr konstruktiv ist. Auch wenn Du ein in der Sache begründetes Teilanliegen haben magst, entwertest Du durch solche Formulierungsweise in Deiner Kritik das Engagement anderer. Das hat kein Wiki-Autor verdient!</p> <p>Wenn Du Dir zur Zeit keine Freizeit abringen kannst, um Wiki-Artikel zu bearbeiten/verbessern oder sogar neue zu schreiben, dann überlege Dir, ob es einen Sinn hat, Deine Zeit in herabwürdigende Kritik zu investieren. Es mag vielleicht sein, dass Du auch hierfür möglicherweise doch keine Zeit hast...</p> <p>Liebe Grüße,</p> <p>Felix Riesterer.</p> modale Fenster Tue, 14 May 19 19:11:25 Z https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1748733#m1748733 https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1748733#m1748733 <blockquote> <p>Das nenne ich nicht "konstruktive Kritik"! Erst etwas bemängeln, dann zugeben, dass Du es nicht ausprobiert hast und dann noch obendrein zugeben, dass das aufgrund der aktuellen Unterstützung durch die Browser ohnehin noch Zukunftsmusik ist. Nee, konstruktiv geht definitiv anders!</p> </blockquote> <p>Du hast Recht, ich hätte mich intensiver mit deinem Aritkel beschäftigen müssen und bin dir eine ausführlichere Antwort schuldig. Dass man mit einer Kritik auch ihre Limitierungen benennt, halte ich grundsätzlich für guten Stil, aber nichtsdestotrotz ist meine Kritik zu kurz ausgefallen. Dafür möchte ich mich zunächst bei dir entschuldigen.</p> <p>Ich habe den Test von <code>showModal</code> nachgeholt und bei mir wird der Fokus in dem Dialog gefangen. <a href="/users/68" class="mention registered-user" rel="noopener noreferrer">@JürgenB</a> hat bei seinem Test im Nachbar-Thread allerdings etwas anderes beobachtet, dafür habe ich zur Zeit keine Erklärung. Möglicherweise ist das ein Versionssunterschudied, ich habe mit Chrome 74 getestet.</p> <blockquote> <p>Auf der anderen Seite musst Du vielleicht überlesen haben, dass ich auf den Wiki-Artikel mit den zugänglichen Dialog-Boxen mehrfach hinweise, in dem die Sache mit der momentanen Notwendigkeit unserer Browser eines Polyfills ja hinlänglich besprochen wird.</p> </blockquote> <p>Auch damit bist du im Recht.</p> <blockquote> <p>Dass ich einen "Workaround" gebastelt hätte, verbitte ich mir. Ich spreche konkret von einem <em>Polyfill</em>.</p> </blockquote> <p>Das war von mir nicht abschätzig gemeint. Workarounds sind ein notwendiges Übel, in deren Entwicklung viel Know-How fließen muss. Polyfills sind auch Workarounds, die dazu dienen (noch) nicht nativ implementierte Features nachzurüsten. Ich hätte das Adjektiv "handgestrickt" aber besser mit einem wertschätzenderen Begriff ausgetauscht.</p> <blockquote> <p>Wenn der einmal nicht mehr notwendig sein sollte, kann man alles, was mit dem von mir zur Verfügung gestellten Polyfill nicht mehr gebraucht wird, wegkürzen, um nur noch das Handling mit den Callbacks übrig zu lassen.</p> </blockquote> <p>Vorschlag zur Güte: Du hast ja selber vorgeschlagen den Artikel aufzuteilen, ich glaube das Polyfill wäre eine sinnvolle Schnittmarke und könnte in einem eigenen Artikel untergebracht werden.</p> <p>Außerdem möchte ich vorschlagen, statt <code>setCallback</code> das native Event-System mit <code>addEventListener</code> zu benutzen. Die Spec definiert für das dialog-Element zwei mögliche Events: <code>close</code> und <code>cancel</code>.</p> <p>Dafür müssten im Code des Polyfills die folgenden Zeilen gestrichen werden.</p> <pre><code class="block language-js"> dialog<span class="token punctuation">.</span><span class="token function-variable function">setCallback</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">key<span class="token punctuation">,</span> f</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> callBacks<span class="token punctuation">[</span>key<span class="token punctuation">]</span> <span class="token operator">=</span> f<span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> dialog<span class="token punctuation">.</span><span class="token function-variable function">triggerCallback</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">key</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">typeof</span> callBacks<span class="token punctuation">[</span>key<span class="token punctuation">]</span> <span class="token operator">==</span> <span class="token string">"function"</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> callBacks<span class="token punctuation">[</span>key<span class="token punctuation">]</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> </code></pre> <p>Und anstelle von <code>dialog.triggerCallback("cancel")</code> müsste der Aufruf wie folgt lauten <code>dialog.dispatchEvent(new Event('cancel'))</code>. Ebenso für das <code>open</code>-Event.</p> <p>Auf der aufrufenden Seite, muss der Aufruf <code>dialog.setCallback('cancel', fn)</code> durch <code>dialog.addEventListener('cancel', fn)</code> getauscht werden.</p> <blockquote> <p>Ich erinnere Dich hiermit in aller Deutlichkeit an Deine Kritik an Jörgs Login-System-Tutorial, in der Du auch sehr vage und könnte/müsste/würde formuliert hast.</p> </blockquote> <p>Die Eskalation damals bedaure ich auch heute noch und habe, wie du ja auch weißt, Jörg dafür ebenfalls um Entschuldigung gebeten. Dass meine Kritik zu vage war, weise ich allerdings zurück. Ich habe mich regelmäßig an den Diskussionen um den Artikel beteiligt, dabei habe ich auf mehrere konkrete Sicherheitslücken hingewiesen. Zum Beispiel die Anfälligkeit für <a href="https://forum.selfhtml.org/meta/2015/feb/13/php-anwendung-und-praxis-loginsystem/1632288#m1632288" rel="noopener noreferrer">Session-Fixation-Angriffe</a>, <a href="https://forum.selfhtml.org/meta/2016/jun/30/artikel-loginsystem-geloescht/1670317#m1670317" rel="noopener noreferrer">der Konflikt</a> mit der Apache Implementierung von HTTP Basic Auth und die <a href="https://forum.selfhtml.org/self/2016/feb/29/ein-loginscript/1662245#m1662245" rel="noopener noreferrer">Verwendung eines Algorithmus</a> für Pseudozufälle anstelle von kryptografisch sicheren Zufallsgeneratoren. Darüber hinaus habe ich mehrfach und ausführlich die schlechte Lesbarkeit des Codes und die Abwesenheit von Qualitätssicherungs-Maßnahmen bemängelt.</p> modale Fenster Mon, 13 May 19 17:18:51 Z https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1748655#m1748655 https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1748655#m1748655 <p>Tach!</p> <blockquote> <p>AHA! Also muss die aufgerufene Fuktion ein <code>Promise</code>-Objekt zurückliefern. Diesem <code>Promise</code>-Objekt kann man mit der <code>then</code>-Methode eine (Callback-)Funktion für den <em>resolve</em>-Fall geben, mit der <code>catch</code>-Methode eine für den <em>reject</em>-Fall.</p> <p>Ist das so richtig?</p> </blockquote> <p>Ja.</p> <blockquote> <p>Wenn ja, dann sieht das schon ziemlich aus wie meine <code>callBack</code>-Sammlung, nur dass diese im Zweifel noch zwischen "cancel" und "abort" unterscheiden kann, also neben <em>resolve</em> und <em>reject</em> noch <em>abort</em> liefert. Ein <code>Promise</code>-Objekt kann das also nicht? Das fände ich dann für mein Tutorial unzureichend!</p> </blockquote> <p>Was ist der Unterschied zwischen Cancel und Abort? Für mich ist ein Dialog erfolgreich, wenn Daten zurückzugeben sind und abgewiesen (rejected), wenn der Nutzer ihn abgebrochen hat. Meist muss man auf das Abbrechen nicht reagieren, wenn doch, kann man den Fall catch()en. Wenn es wichtig ist, unterschiedliche Abbruch-Situationen unterscheiden zu können, kann man das zwar einerseits über den error-Wert tun. Aber sind das dann andererseits immer noch Abbrüche? Ich denke, dass das dann eher unterschiedliche Rückgabewerte für den Erfolgsfall sind (resolve). Der Rückgabewert kann durchaus komplexer natur sein, also zum Beispiel auch ein Objekt mit Status-Eigenschaft und Content-Eigenschaft. Also wenn der Dialog ein Eingabefeld hat und mehrere Buttons, dann käme die Information zum ausgelösten Button in die Status-Eigenschaft und der Eingabewert ist der Content.</p> <blockquote> <p>Ich <a href="https://wiki.selfhtml.org/wiki/JavaScript/Promise" rel="nofollow noopener noreferrer">lese gerade nach</a> und sehe, dass man mehrere <code>then</code>-Methodenaufrufe machen kann, und dass <code>Promise</code>-Objekte wesentlich komplexer sind (Status-Werte, innere und äußere Promises, Exceptions) als meine Callback-Lösung, die ich doch als recht elegant und für den vorliegenden Fall als bequem empfinde. Wenn man jetzt noch die Buttons frei benennen könnte, wäre sie sogar luxuriös, aber das will ich in diesem Tutorial nicht auch noch behandeln.</p> </blockquote> <p>Wir wollen das nicht zu einem Tutorial über Promises machen. Es soll lediglich gezeigt werden, wie durch die Verwendung von Promises der Verwender seinen Code besser strukturieren kann. Statt herumliegender Callback-Funktionen, die man ansonsten für nichts anderes braucht, hängen diese direkt über then/catch am Dialog-Öffner. Zugegeben, man könnte die Callbacks auch direkt als Funktion im Aufruf von myAlert() etc. notieren, aber sowas macht die Geschichte nicht lesbarer.</p> <p>Schau dir mal an, wie ein Ajax-Request herkömmlich verglichen mit fetch() aussieht.</p> <pre><code class="block language-js"><span class="token keyword">var</span> req <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">XMLHttpRequest</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> req<span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token string">"load"</span><span class="token punctuation">,</span> machwas_mit_daten<span class="token punctuation">)</span><span class="token punctuation">;</span> req<span class="token punctuation">.</span><span class="token function">open</span><span class="token punctuation">(</span>url<span class="token punctuation">)</span><span class="token punctuation">;</span> req<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//----</span> <span class="token function">fetch</span><span class="token punctuation">(</span>url<span class="token punctuation">)</span> <span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span>machwas_mit_daten<span class="token punctuation">)</span><span class="token punctuation">;</span> </code></pre> <p>Der (hier gekürzte) fetch()-Aufruf liest sich auch gleich flüssiger. Statt einzelner Anweisungen ist das schon fast ein Satz. Vor allem kommt die Reihenfolge besser zur Geltung: <em>erst</em> den Request abarbeiten, <em>dann</em> mit den Daten arbeiten.</p> <p>Mehrere then() brauchst du für den Dialog eher nicht. Das ist kein switch-Ersatz, sondern kann man für nacheinander abzuarbeitende Tätigkeiten nutzen. Das nächste then() bekommt das Ergebnis des vorhergehenden reingereicht und nicht das Ergebnis des Promises. Der Verwender kann das nutzen, wenn er meint, in seinem Fall etwas verketten zu müssen. Du brauchst das nicht weiter zu berücksichtigen, wenn du das Promise für den Dialog erstellst.</p> <p>Eine Verbesserung könnte sein: In deinem Code prüfst du, ob die Callbacks Funktionen sind, bevor du sie aufrufst. Das kann beim Promise wegfallen, weil der Callback im then() angegeben wird. Wenn der Verwender da was Komisches angibt, dann ignoriert das Promise das einfach, ohne einen Fehler zu werfen (ist so definiert). Es ist ja sowieso sein Problem, was der Verwender mit dem Ergebnis anstellt, und wenn er damit Mist macht, muss du das nicht weiter beachten noch dem vorbeugen.</p> <p>dedlfix.</p> modale Fenster Mon, 13 May 19 18:00:15 Z https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1748666#m1748666 https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1748666#m1748666 <p>Lieber dedlfix,</p> <blockquote> <blockquote> <p>Ist das so richtig?</p> </blockquote> <p>Ja.</p> </blockquote> <p>juhu! Etwas über <code>Promise</code> gelernt!</p> <blockquote> <p>Was ist der Unterschied zwischen Cancel und Abort?</p> </blockquote> <p>Frage: Sind Sie ein guter Mensch?</p> <pre><code class="block">| [X]| | [Ja] [Nein] | </code></pre> <p>Hier sehe ich drei Möglichkeiten. Das "Nein" entspricht dem "Abbrechen". Natürlich ist von der natürlich Sprache ein "Abbrechen" mit einem "Schließen" gleich zu setzen. Wenn nun aber die beiden Buttons als Ja/Nein-Frage benutzt werden, ist ein "nein" nicht automatisch auch ein "abgebrochen"...</p> <blockquote> <p>Wir wollen das nicht zu einem Tutorial über Promises machen.</p> </blockquote> <p>Einverstanden. Der Denkanstoß ist angekommen. Danke dafür.</p> <blockquote> <p>Es soll lediglich gezeigt werden, wie durch die Verwendung von Promises der Verwender seinen Code besser strukturieren kann.</p> </blockquote> <p>Es sei denn, er baut sich etwas ähnliches, das das auch leistet.</p> <blockquote> <p>Eine Verbesserung könnte sein: In deinem Code prüfst du, ob die Callbacks Funktionen sind, bevor du sie aufrufst.</p> </blockquote> <p>Du meinst also anstelle von</p> <pre><code class="block bad language-javascript">dialog<span class="token punctuation">.</span><span class="token function-variable function">setCallback</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">key<span class="token punctuation">,</span> f</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> callBacks<span class="token punctuation">[</span>key<span class="token punctuation">]</span> <span class="token operator">=</span> f<span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> </code></pre> <p>sollte da besser stehen:</p> <pre><code class="block good language-javascript">dialog<span class="token punctuation">.</span><span class="token function-variable function">setCallback</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">key<span class="token punctuation">,</span> f</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">typeof</span> f <span class="token operator">==</span> <span class="token string">"function"</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> callBacks<span class="token punctuation">[</span>key<span class="token punctuation">]</span> <span class="token operator">=</span> f<span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> </code></pre> <p>Ja, das könnte ich noch aufnehmen. Aber wer da absichtlich Müll hineinschreibt, dem ist ohnehin nicht zu helfen.</p> <p>Liebe Grüße,</p> <p>Felix Riesterer.</p> modale Fenster Mon, 13 May 19 18:20:18 Z https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1748669#m1748669 https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1748669#m1748669 <p>Tach!</p> <blockquote> <blockquote> <p>Was ist der Unterschied zwischen Cancel und Abort?</p> </blockquote> <p>Frage: Sind Sie ein guter Mensch?</p> <pre><code class="block">| [X]| | [Ja] [Nein] | </code></pre> <p>Hier sehe ich drei Möglichkeiten. Das "Nein" entspricht dem "Abbrechen". Natürlich ist von der natürlich Sprache ein "Abbrechen" mit einem "Schließen" gleich zu setzen. Wenn nun aber die beiden Buttons als Ja/Nein-Frage benutzt werden, ist ein "nein" nicht automatisch auch ein "abgebrochen"...</p> </blockquote> <p>Auch ein Ja schließt den Dialog. Somit kann er durch jede der drei Möglichkeiten geschlossen werden. Das ist also nicht das Kriterium, das zur Entscheidung zwischen resolve und reject führen kann. In dem Fall sehe ich Ja und Nein als gültige Antworten, die resolve() aufrufen sollten. Das Ja gibt in dem Fall dem resolve() dann ein true mit auf den Weg, das Nein ein false. Der X-Button oder Esc oder Klick auf den Backdrop sind keine gültigen Antworten und landen auf reject().</p> <blockquote> <blockquote> <p>Wir wollen das nicht zu einem Tutorial über Promises machen.</p> </blockquote> <p>Einverstanden. Der Denkanstoß ist angekommen. Danke dafür.</p> <blockquote> <p>Es soll lediglich gezeigt werden, wie durch die Verwendung von Promises der Verwender seinen Code besser strukturieren kann.</p> </blockquote> <p>Es sei denn, er baut sich etwas ähnliches, das das auch leistet.</p> <blockquote> <p>Eine Verbesserung könnte sein: In deinem Code prüfst du, ob die Callbacks Funktionen sind, bevor du sie aufrufst.</p> </blockquote> <p>Du meinst also anstelle von</p> <pre><code class="block bad language-javascript">dialog<span class="token punctuation">.</span><span class="token function-variable function">setCallback</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">key<span class="token punctuation">,</span> f</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> callBacks<span class="token punctuation">[</span>key<span class="token punctuation">]</span> <span class="token operator">=</span> f<span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> </code></pre> <p>sollte da besser stehen:</p> <pre><code class="block good language-javascript">dialog<span class="token punctuation">.</span><span class="token function-variable function">setCallback</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">key<span class="token punctuation">,</span> f</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">typeof</span> f <span class="token operator">==</span> <span class="token string">"function"</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> callBacks<span class="token punctuation">[</span>key<span class="token punctuation">]</span> <span class="token operator">=</span> f<span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> </code></pre> </blockquote> <p>Nein, ich meinte anstelle von</p> <pre><code class="block language-js"><span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">typeof</span> <span class="token constant">OK</span> <span class="token operator">==</span> <span class="token string">"function"</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> dialog<span class="token punctuation">.</span><span class="token function">setCallback</span><span class="token punctuation">(</span><span class="token string">"ok"</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token constant">OK</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> dialog<span class="token punctuation">.</span><span class="token function">setCallback</span><span class="token punctuation">(</span><span class="token string">"ok"</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> </code></pre> <p>braucht es nur</p> <pre><code class="block language-js">dialog<span class="token punctuation">.</span><span class="token function">setCallback</span><span class="token punctuation">(</span><span class="token string">"ok"</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token function">resolve</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// in dem Fall auch noch kürzer</span> <span class="token comment">// dialog.setCallback("ok", resolve);</span> </code></pre> <p>Abgesehen davon kann man sich wohl auch im obigen Code das Setzen des Callbacks auf eine Funktion sparen. Zum einen wäre <code>null</code> kürzer und du testest im Dialog-Polyfill sowieso dass der Callback eine Funktion ist. Zum anderen dürfte es auch egal sein, ob da nach dem OK noch irgendwas dem Callback zugewiesen wird, weil eh kein HTML-Element mehr da/sichtbar ist, dass zu einem Aufruf führen könnte.</p> <p>dedlfix.</p> modale Fenster Mon, 13 May 19 19:21:34 Z https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1748678#m1748678 https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1748678#m1748678 <p>Lieber dedlfix,</p> <blockquote> <p>In dem Fall sehe ich Ja und Nein als gültige Antworten, die resolve() aufrufen sollten. Das Ja gibt in dem Fall dem resolve() dann ein true mit auf den Weg, das Nein ein false. Der X-Button oder Esc oder Klick auf den Backdrop sind keine gültigen Antworten und landen auf reject().</p> </blockquote> <p>verstehe. Überzeugt mich. :-)</p> <blockquote> <p>Zum anderen dürfte es auch egal sein, ob da nach dem OK noch irgendwas dem Callback zugewiesen wird, weil eh kein HTML-Element mehr da/sichtbar ist, dass zu einem Aufruf führen könnte.</p> </blockquote> <p>Das habe ich mir auch schon gedacht. Naja, weg kann es immer noch.</p> <p>Liebe Grüße,</p> <p>Felix Riesterer.</p> modale Fenster Mon, 13 May 19 21:16:52 Z https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1748682#m1748682 https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1748682#m1748682 <p>Hallo Ingrid,</p> <p>ich habe die Vorschläge ins Tutorial und in die Live-Beispiele eingearbeitet.</p> <p>Liebe Grüße,</p> <p>Felix Riesterer.</p> modale Fenster Tue, 21 May 19 15:04:14 Z https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1749090#m1749090 https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1749090#m1749090 <p>Hallo,</p> <blockquote> <p>Ich habe den Test von <code>showModal</code> nachgeholt und bei mir wird der Fokus in dem Dialog gefangen. <a href="/users/68" class="mention registered-user" rel="noopener noreferrer">@JürgenB</a> hat bei seinem Test im Nachbar-Thread allerdings etwas anderes beobachtet, dafür habe ich zur Zeit keine Erklärung. Möglicherweise ist das ein Versionssunterschudied, ich habe mit Chrome 74 getestet.</p> </blockquote> <p>ich habe den Test wiederholt:</p> <p>Browser: Chrome Version 74.0.3729.157 (Offizieller Build) (64-Bit) (Windows 10) Seite: <a href="https://wiki.selfhtml.org/extensions/Selfhtml/example.php/Beispiel:JS-Anw-accessible-dialog.html" rel="nofollow noopener noreferrer">https://wiki.selfhtml.org/extensions/Selfhtml/example.php/Beispiel:JS-Anw-accessible-dialog.html</a></p> <p>Wenn ich die Seite öffne und dann den Tabulator drücke, verlässt der Focus den Dialog.</p> <p>Gruß<br> Jürgen</p> modale Fenster Wed, 22 May 19 05:45:48 Z https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1749117#m1749117 https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1749117#m1749117 <p>Lieber 1unitedpower,</p> <p>vielen Dank für die ausführliche Rückmeldung. Jetzt kann ich mit Deinen Kritikpunkten umgehen.</p> <blockquote> <p>Vorschlag zur Güte: Du hast ja selber vorgeschlagen den Artikel aufzuteilen, ich glaube das Polyfill wäre eine sinnvolle Schnittmarke und könnte in einem eigenen Artikel untergebracht werden.</p> </blockquote> <p><a href="/users/3833" class="mention registered-user" rel="noopener noreferrer">@Matthias Scharwies</a> und ich arbeiten an einer solchen Aufteilung. Und ja, die Sache mit dem Polyfill verdient dabei eine ganze eigene Sektion.</p> <blockquote> <p>Außerdem möchte ich vorschlagen, statt <code>setCallback</code> das native Event-System mit <code>addEventListener</code> zu benutzen. Die Spec definiert für das dialog-Element zwei mögliche Events: <code>close</code> und <code>cancel</code>.</p> </blockquote> <p>Auf den ersten Blick klingt das überzeugend. Aber wenn ich etwas mehr darüber nachdenke, dann habe ich folgenden Zweifel:</p> <p>EventListener kann man an Elemente binden und wieder lösen. Wenn ich nun eine Funktion für das <code>cancel</code>-Event anbinde, muss ich die später wieder lösen, sonst wird sie bei Wiederbenutzung der Dialog-Box erneut ausgeführt, was ich ja nicht will, wenn diese Funktionalität dynamisch übertragen werden soll.</p> <blockquote> <p>Auf der aufrufenden Seite, muss der Aufruf <code>dialog.setCallback('cancel', fn)</code> durch <code>dialog.addEventListener('cancel', fn)</code> getauscht werden.</p> </blockquote> <p>Dann verwaltet also nicht meine <code>setCallback</code>-Methode, welche Funktion gerade an das <code>cancel</code>-Event gebunden ist, sondern das DOM selbst. Das ist unhandlicher, denn ich müsste ja nach der Ausführung des Events den EventListener wieder entfernen. So habe ich diesen einmal eingerichtet, aber was er jeweils tut, regelt meine Komfort-Funktion, die das einfach in einer lokalen Variable (Closure) verwaltet.</p> <p>Ich könnte mir also vorstellen, für die beiden Events <code>close</code> und <code>cancel</code> jeweils einen EventListener anzubinden, der meine Komfort-Funktion bedient, damit auf der einen Seite weiterhin das Handling der Callback-Funktionen so einfach geregelt werden kann, aber auf der anderen Seite die (geplanten) nativen Merkmale im Sinne eines Polyfills unterstützt werden.</p> <blockquote> <p>Dass meine Kritik [am Login-System] zu vage war, weise ich allerdings zurück. Ich habe mich regelmäßig an den Diskussionen um den Artikel beteiligt, dabei habe ich auf mehrere konkrete Sicherheitslücken hingewiesen.</p> </blockquote> <p>Ich erinnere mich nur noch an eine Sache wirklich konkret, nämlich an einen Vorwurf, dass die ganze Sache für eine Veröffentlichung im Wiki deshalb zu unsicher und daher löschungswürdig sei, weil es keine automatisierten Tests gäbe. In dieser vagen und absoluten Form habe ich das in Erinnerung. Mag sein, dass die mittlerweile sehr gelitten hat und sich im Nachhinein manche Dinge in die eine oder andere Richtung verklärt haben, aber genau hierin hat mich Deine hiesige Kritik an den damaligen Vorgang erinnert.</p> <blockquote> <p>Darüber hinaus habe ich mehrfach und ausführlich die schlechte Lesbarkeit des Codes und die Abwesenheit von Qualitätssicherungs-Maßnahmen bemängelt.</p> </blockquote> <p>Richtig. Aber ein reines Bemängeln der Abwesenheit von QA-Maßnahmen ist das eine. Die Schlussfolgerung, dass daraus prinzipiell eine Unsicherheit des Systems abzuleiten sei, die eine Löschung aus dem Wiki nach sich zieht, ist eine ganz andere Form von Kritik. Mir ist nicht bekannt, dass Du eine konkrete Sicherheitslücke damals hättest benennen können, sondern nur allgemein auf eben diese Abwesenheit von automatisierten Tests als Begründung verwiesen hattest.</p> <p>Gerade bei solchen sicherheitsrelevanten Dingen können automatisierte Tests ja auch nur das testen, was der Testersteller im Sinn hat. Für den Login-System-Artikel hätte es einen regelrechten Fuzzer gebraucht, von dem ich nicht einmal im Ansatz wüsste, wie man so etwas erstellt. Aus meiner Sicht heute ging Dein Bemängeln damals also sogar nicht weit genug (Test vs. Fuzzer). Aber deshalb im Umkehrschluss zu behaupten, dass ein Login-Script deswegen unsicher sei, und vor allem, dass deshalb eine Veröffentlichung im Wiki insgesamt schadhaft wäre, wage ich bis heute nicht.</p> <p>Liebe Grüße</p> <p>Felix Riesterer</p> modale Fenster Mon, 20 May 19 13:11:49 Z https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1748971#m1748971 https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1748971#m1748971 <p>Tach!</p> <blockquote> <p>[x] <a href="https://wiki.selfhtml.org/wiki/JavaScript/Tutorials/Eigene_modale_Dialogfenster#Individuelle_L.C3.B6sungen" rel="nofollow noopener noreferrer">done</a></p> </blockquote> <p>Habs mir mal angeschaut. Dazu ein paar Anmerkungen.</p> <p>Die Variable p wird durch einen lokalen Scope überlagert.</p> <pre><code class="block language-js"> <span class="token comment">// jedes <ul> und <p> entfernen, außer <p class="button-row"></span> <span class="token class-name">Array</span><span class="token punctuation">.</span>prototype<span class="token punctuation">.</span><span class="token function">slice</span><span class="token punctuation">.</span><span class="token function">call</span><span class="token punctuation">(</span> dialog<span class="token punctuation">.</span><span class="token function">querySelectorAll</span><span class="token punctuation">(</span><span class="token string">"ul, p:not(.button-row)"</span><span class="token punctuation">)</span> <span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">p</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> p<span class="token punctuation">.</span>parentNode<span class="token punctuation">.</span><span class="token function">removeChild</span><span class="token punctuation">(</span>p<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> </code></pre> <p>Ich würde das lokale p etwas sprechender (um)benennen, zum Beispiel node, denn es sind ja nicht nur <code>p</code>s zu entfernen . Zudem muss <code>p</code> nicht "global" in myDialog rumliegen sondern kann als <code>const p = ...</code> innerhalb der For-Schleife im dortigen lokalen Scope existieren. Der Wert wird nie verändert, weswegen sie als const deklariert werden kann. Ebenso geht es der Variable <code>element</code> und <code>elements</code>, die jeweils nur innerhalb eines eines Blocks existiert. Alle anderen <code>var</code> können auch zu <code>const</code> umgeschrieben werden, weil sich ihr Inhalt nicht ändert.</p> <p>Außerdem lässt sich obiger Code problemlos kürzen zu:</p> <pre><code class="block language-js"> dialog<span class="token punctuation">.</span><span class="token function">querySelectorAll</span><span class="token punctuation">(</span><span class="token string">"ul, p:not(.button-row)"</span><span class="token punctuation">)</span> <span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">node</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> node<span class="token punctuation">.</span>parentNode<span class="token punctuation">.</span><span class="token function">removeChild</span><span class="token punctuation">(</span>node<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> </code></pre> <p>Die von querySelectorAll() zurückgegebenen NodeList ist non-live und braucht keine slice()-Kopie, um damit gefahrlos arbeiten zu können. Und obwohl sie kein Array ist, forEach() hat sie jedenfalls.</p> <p>Bei beiden <code>for (prop in data)</code> möchte das <code>in</code> lieber ein <code>of</code> sein, damit nur direkte Eigenschaften und keine eventuell aus dem Prototyp geerbten berücksichtigt werden. Das <code>prop</code> ist auch wieder nur lokal verwendet und kann als <code>for (let prop of data)</code> notiert werden, so dass man es ebenfalsl nicht "global" in myDialog braucht.</p> <p>Zudem meckert meine IDE an, man solle bei diesen Stellen den typsicheren Vergleich nehmen.</p> <pre><code class="block language-js"><span class="token keyword">if</span> <span class="token punctuation">(</span>data<span class="token punctuation">[</span>prop<span class="token punctuation">]</span><span class="token punctuation">.</span>type <span class="token operator">&&</span> data<span class="token punctuation">[</span>prop<span class="token punctuation">]</span><span class="token punctuation">.</span>type <span class="token operator">==</span> <span class="token string">"info"</span><span class="token punctuation">)</span> </code></pre> <p>Aber das ist ziemlich egal. Ob der nun Vergleich fehlschlägt, weil irgendein x-beliebiger Wert auch nach Typumwandlung nicht gleich dem gegebenen String ist oder die Typen der Werte nicht stimmen, kommt aufs gleiche raus.</p> <p>Für das nachfolgende Aufrufbeispiel gilt ebenfalls das oben gesagte sinngemäß.</p> <p>Generell wäre noch anzumerken, dass die Individualität sehr enge Grenzen hat. Mit einigermaßen Aufwand werden ein paar wenige Elemente unterstützt. Eine freie Gestaltung des HTML-Inhalts ist so nicht möglich. Hier wäre eine Lösung mit <code><template></code> sowohl einfacher als auch flexibler. Als Bonus kann man das HTML des Templates mit allen Finessen des HTML-Editors erstellen. Zu lösen wäre dabei die Frage, wie mit Formularelementen umgegangen werden soll. Ich würde da grundlegend nur anbieten, dass beim OK ein übergebener Callback aufgerufen werden kann, wo der Verwender das in seinem Fall benötigte Datenauslesen tun kann. Der Callback sollte ein Objekt zurückgeben, das dann vom üblichen Dialog-Handling an den Aufrufer übergeben wird. - Man kann ja immer noch für den Komfort eine vordefinierte Callback-Funktion anbieten, die ein generisches Formulardaten-Auslesen bietet. Andererseits könnte das auch gleich ein Beispiel sein, wie dieser Callback auszusehen hat.</p> <p>dedlfix.</p> modale Fenster Mon, 20 May 19 16:23:32 Z https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1749006#m1749006 https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1749006#m1749006 <p>Lieber dedlfix,</p> <blockquote> <p>Habs mir mal angeschaut. Dazu ein paar Anmerkungen.</p> </blockquote> <p>wunderbar! Vielen Dank!</p> <blockquote> <p>Die Variable p wird durch einen lokalen Scope überlagert. [...] Ich würde das lokale p etwas sprechender (um)benennen, zum Beispiel node, denn es sind ja nicht nur <code>p</code>s zu entfernen .</p> </blockquote> <p>Ja, das wäre sehr sinnvoll.</p> <blockquote> <p>Zudem muss <code>p</code> nicht "global" in myDialog rumliegen sondern kann als <code>const p = ...</code> innerhalb der For-Schleife im dortigen lokalen Scope existieren. Der Wert wird nie verändert, weswegen sie als const deklariert werden kann. Ebenso geht es der Variable <code>element</code> und <code>elements</code>, die jeweils nur innerhalb eines eines Blocks existiert. Alle anderen <code>var</code> können auch zu <code>const</code> umgeschrieben werden, weil sich ihr Inhalt nicht ändert.</p> </blockquote> <p>Dieses <code>const</code> kenne ich noch nicht so lange wie <code>var</code>. Beide sind für mich nur dazu da, eine Variable nicht als Eigenschaft von <code>window</code>, also als globale Variable zu definieren, sondern als lokale. Dabei ist mir das <code>var</code> ebenso lieb, wie das <code>const</code>, nur dass ich mich an letzteres noch nicht gewöhnt habe. Mir ist es völlig egal, ob man den Inhalt von <code>const</code> später mit einem anderen Datentyp befüllen kann, oder nicht - wegen mir bräuchte es das überhaupt nicht. Aber für ein Tutorial sollte man diese Unterscheidung durchaus nutzen.</p> <blockquote> <p>Die von querySelectorAll() zurückgegebenen NodeList ist non-live und braucht keine slice()-Kopie, um damit gefahrlos arbeiten zu können.</p> </blockquote> <p>Deswegen tue ich es auch nicht.</p> <blockquote> <p>Und obwohl sie kein Array ist, forEach() hat sie jedenfalls.</p> </blockquote> <p>In wirklich allen Browsern? Zuletzt meine ich mich zu erinnern, wollte es im IE nicht so recht. Ist das jetzt nicht mehr so?</p> <blockquote> <p>Bei beiden <code>for (prop in data)</code> möchte das <code>in</code> lieber ein <code>of</code> sein, damit nur direkte Eigenschaften und keine eventuell aus dem Prototyp geerbten berücksichtigt werden.</p> </blockquote> <p>Wieder so etwas neumodisches. <em>grins</em> Von mir aus darf es <code>for..in</code> oder auch <code>for..of</code> sein. Ich sehe jetzt nicht, wo prototypische Eigenschaften hoch kommen sollten. Aber man muss es ja nicht erst darauf anlegen.</p> <blockquote> <p>Das <code>prop</code> ist auch wieder nur lokal verwendet und kann als <code>for (let prop of data)</code> notiert werden, so dass man es ebenfalsl nicht "global" in myDialog braucht.</p> </blockquote> <p>Ich empfand das immer als "unsauber", weil eine so definierte Variable nicht am Anfang meines Programms steht. Aber der Scope innerhalb einer Schleife geht ja nicht nach außen, daher würde <code>prop</code> tatsächlich so nur innerhalb der Schleife existieren. Also besser.</p> <blockquote> <p>Zudem meckert meine IDE an, man solle bei diesen Stellen den typsicheren Vergleich nehmen.</p> </blockquote> <p>Du meinst ein Boolean <code>true</code> würde sonst auch akzeptiert? Kann das als Bezeichner einer Eigenschaft überhaupt sein?</p> <blockquote> <pre><code class="block language-js"><span class="token keyword">if</span> <span class="token punctuation">(</span>data<span class="token punctuation">[</span>prop<span class="token punctuation">]</span><span class="token punctuation">.</span>type <span class="token operator">&&</span> data<span class="token punctuation">[</span>prop<span class="token punctuation">]</span><span class="token punctuation">.</span>type <span class="token operator">==</span> <span class="token string">"info"</span><span class="token punctuation">)</span> </code></pre> <p>Aber das ist ziemlich egal. Ob der nun Vergleich fehlschlägt, weil irgendein x-beliebiger Wert auch nach Typumwandlung nicht gleich dem gegebenen String ist oder die Typen der Werte nicht stimmen, kommt aufs gleiche raus.</p> </blockquote> <p>So betrachtet schon. Ich habe mir immer angewöhnt, auf das prinzipielle Vorhandensein zu prüfen. Daher die erste Bedingung. Sollte also jemand vergessen haben, dass das Objekt noch eine <code>type</code>-Eigenschaft benötigt, und würde die erste Bedingung fehlen, dann würde der Code mit einer Fehlermeldung in der Konsole abgebrochen. So aber wird das Objekt schlicht nicht verarbeitet und die Ausführung nicht unterbrochen. Ist ein <em>silent fail</em> an dieser Stelle wirklich schlechter, als eine echte Fehlermeldung in der Konsole?</p> <p>Wenn man das Ganze noch ordentlich weitertreibt, dann würde man die Datenobjekte nicht von Hand als Literal notieren, sondern mittels einer Klasse bauen lassen, die dafür Sorge trägt, dass alle notwendigen Eigenschaften auch vorhanden sind - und als <em>default</em>-Typ eben <code>info</code> verwendet.</p> <blockquote> <p>Generell wäre noch anzumerken, dass die Individualität sehr enge Grenzen hat. Mit einigermaßen Aufwand werden ein paar wenige Elemente unterstützt. Eine freie Gestaltung des HTML-Inhalts ist so nicht möglich. Hier wäre eine Lösung mit <code><template></code> sowohl einfacher als auch flexibler.</p> </blockquote> <p>Ja, wenn jemand damit umgehen kann. So bietet das Tutorial eine von vielen möglichen Ideen, die hoffentlich zu weiteren neuen und vielleicht sogar besseren Ideen führt.</p> <blockquote> <p>Als Bonus kann man das HTML des Templates mit allen Finessen des HTML-Editors erstellen.</p> </blockquote> <p>Der Phantasie sind eben keine Grenzen gesetzt. Man kann mit seiner Programmlogik alles Denkbare umsetzen.</p> <blockquote> <p>Zu lösen wäre dabei die Frage, wie mit Formularelementen umgegangen werden soll.</p> </blockquote> <p>Das darf jeder Entwickler für sich selbst entscheiden. Das Tutorial bietet wie ausdrücklich angemerkt nur eine von unendlich vielen Möglichkeiten das zu tun.</p> <blockquote> <p>Ich würde da grundlegend nur anbieten, dass beim OK ein übergebener Callback aufgerufen werden kann, wo der Verwender das in seinem Fall benötigte Datenauslesen tun kann.</p> </blockquote> <p>OK. Ich zeige gleich ein Beispiel mit einer möglichen Vorgehensweise, um ein konkretes Ergebnis vorführen zu können.</p> <p>Mal sehen, wann ich Deine Anregungen umsetzen kann. Jedenfalls noch einmal ein herzliches Danke dafür!</p> <p>Liebe Grüße</p> <p>Felix Riesterer</p> modale Fenster Mon, 20 May 19 20:13:08 Z https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1749025#m1749025 https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1749025#m1749025 <p>Tach!</p> <blockquote> <blockquote> <p>Zudem muss <code>p</code> nicht "global" in myDialog rumliegen sondern kann als <code>const p = ...</code> innerhalb der For-Schleife im dortigen lokalen Scope existieren. Der Wert wird nie verändert, weswegen sie als const deklariert werden kann. Ebenso geht es der Variable <code>element</code> und <code>elements</code>, die jeweils nur innerhalb eines eines Blocks existiert. Alle anderen <code>var</code> können auch zu <code>const</code> umgeschrieben werden, weil sich ihr Inhalt nicht ändert.</p> </blockquote> <p>Dieses <code>const</code> kenne ich noch nicht so lange wie <code>var</code>.</p> </blockquote> <p>const/let gibt es ja auch noch nicht so lange. Aber laut CanIUse kann das sogar der IE11 in Grundzügen.</p> <blockquote> <p>Beide sind für mich nur dazu da, eine Variable nicht als Eigenschaft von <code>window</code>, also als globale Variable zu definieren, sondern als lokale.</p> </blockquote> <p>Es gibt noch den Unterschied im Scope-Verhalten, const/let gilt nur innerhalb der nächstgelegenen {}-Klammern, var innerhalb der gesamten Funktion.</p> <blockquote> <p>Mir ist es völlig egal, ob man den Inhalt von <code>const</code> später mit einem anderen Datentyp befüllen kann, oder nicht - wegen mir bräuchte es das überhaupt nicht.</p> </blockquote> <p>Vermutlich ist const für die Laufzeitumgebung interessant, dass es da besser optimieren kann als bei veränderbaren Variablen.</p> <blockquote> <blockquote> <p>Die von querySelectorAll() zurückgegebenen NodeList ist non-live und braucht keine slice()-Kopie, um damit gefahrlos arbeiten zu können.</p> </blockquote> <p>Deswegen tue ich es auch nicht.</p> <blockquote> <p>Und obwohl sie kein Array ist, forEach() hat sie jedenfalls.</p> </blockquote> <p>In wirklich allen Browsern? Zuletzt meine ich mich zu erinnern, wollte es im IE nicht so recht. Ist das jetzt nicht mehr so?</p> </blockquote> <p>Naja, keiner der IEs hat diese Methode an der NodeList.</p> <blockquote> <blockquote> <p>Das <code>prop</code> ist auch wieder nur lokal verwendet und kann als <code>for (let prop of data)</code> notiert werden, so dass man es ebenfalsl nicht "global" in myDialog braucht.</p> </blockquote> <p>Ich empfand das immer als "unsauber", weil eine so definierte Variable nicht am Anfang meines Programms steht. Aber der Scope innerhalb einer Schleife geht ja nicht nach außen, daher würde <code>prop</code> tatsächlich so nur innerhalb der Schleife existieren. Also besser.</p> </blockquote> <p>Ich empfinde es eher unübersichtlich, alles am Anfang aufzuführen, selbst wenn es nur lokal verwendet wird. Das ist ja seit let/const schon besser geworden.</p> <p>Um nicht nur beiden Vorlieben gerecht zu werden, sondern auch der Lesbarkeit zu dienen, könnte man den Code weiter in logische und kürzere Einheiten (lies Funktionen) aufbrechen. Damit werden die Teile einfacher zu verstehen, weil sie kürzere in sich abgeschlossene Einheiten bilden. Und auch der Hauptcode ist dann nicht mehr so lang.</p> <p>Wenn man es schafft, die Funktionen mit beschreibenden Namen zu versehen, hat man als Leser gleich noch einen Hinweis auf das, was die Funktion tun soll, ohne erst den Code verstehen zu müssen und auch ohne dass da ein Kommentar zur Erläuterung steht.</p> <blockquote> <blockquote> <p>Zudem meckert meine IDE an, man solle bei diesen Stellen den typsicheren Vergleich nehmen.</p> </blockquote> <p>Du meinst ein Boolean <code>true</code> würde sonst auch akzeptiert? Kann das als Bezeichner einer Eigenschaft überhaupt sein?</p> </blockquote> <p>Kann nicht, aber der <a href="https://de.wikipedia.org/wiki/Lint_(Programmierwerkzeug)" rel="nofollow noopener noreferrer">Linter</a> in meiner IDE ist nicht clever genug, um das zu erkennen. Der kennt nur die Crockford-Regel, alles was ein Vergleich sein soll, habe === zu nehmen, selbst wenn es überhaupt nicht nötig ist.</p> <p>Es gibt da eine <a href="https://dorey.github.io/JavaScript-Equality-Table/" rel="nofollow noopener noreferrer">Comparison Table für Javascript</a>. Alle Strings, die nicht mit Zahlen beginnen oder Leerstrings sind, sind nur zu Strings mit gleichem Inhalt gleich. In der Tabelle sind <code>"true"</code> und <code>"false"</code> (die mit den Anführungszeichen) Vertreter dieser Sorte. Es ist also komplett egal, was da an Wert reinkommt, denn nichts davon ergibt true außer dem Wert "info" in diesem Fall. Deswegen ist das Gemecker vom Linter hier sinnlos. Man kann aber trotzdem === statt == notieren, wenn man mag.</p> <blockquote> <blockquote> <pre><code class="block language-js"><span class="token keyword">if</span> <span class="token punctuation">(</span>data<span class="token punctuation">[</span>prop<span class="token punctuation">]</span><span class="token punctuation">.</span>type <span class="token operator">&&</span> data<span class="token punctuation">[</span>prop<span class="token punctuation">]</span><span class="token punctuation">.</span>type <span class="token operator">==</span> <span class="token string">"info"</span><span class="token punctuation">)</span> </code></pre> <p>Aber das ist ziemlich egal. Ob der nun Vergleich fehlschlägt, weil irgendein x-beliebiger Wert auch nach Typumwandlung nicht gleich dem gegebenen String ist oder die Typen der Werte nicht stimmen, kommt aufs gleiche raus.</p> </blockquote> <p>So betrachtet schon. Ich habe mir immer angewöhnt, auf das prinzipielle Vorhandensein zu prüfen. Daher die erste Bedingung.</p> </blockquote> <p>Diesen Teil hatte ich gar nicht beachtet, nur den Vergleich nach dem <code>&&</code>. Aber jetzt wo du es sagst, fällt mir auf, dass ich doch was daran auszusetzen habe. Prinzipiell ist so ein Testen auf Vorhandensein richtig und wichtig, aber man muss es richtig tun. Ein einfacher Zugriff auf eine nicht vorhandene Eigenschaft erzeugt noch keinen Fehler, sondern ergibt stillschweigend <code>undefined</code> zurück. Aber das Verketten und Durchgreifen misslingt mit Fehlermeldung, wenn zwischendrin eine Eigenschaft auf undefined läuft, weil undefined ein primitiver Wert ist, der keine Eigenschaften hat.</p> <pre><code class="block language-js"><span class="token keyword">let</span> obj <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token keyword">let</span> x <span class="token operator">=</span> obj<span class="token punctuation">.</span>nicht_da<span class="token punctuation">;</span> <span class="token comment">// problemlos, x enthält undefined</span> <span class="token keyword">let</span> x <span class="token operator">=</span> obj<span class="token punctuation">.</span>nicht_da<span class="token punctuation">.</span>irgendwas<span class="token punctuation">;</span> <span class="token comment">// Laufzeitfehler, undefined hat keine Eigenschaften</span> </code></pre> <p>Man muss also nur "vorn" alles testen, aber nicht die letzte Eigenschaft selbst.</p> <pre><code class="block good language-js"><span class="token keyword">if</span> <span class="token punctuation">(</span>obj <span class="token operator">&&</span> obj<span class="token punctuation">.</span>nicht_da <span class="token operator">&&</span> obj<span class="token punctuation">.</span>nicht_da<span class="token punctuation">.</span>irgendwas <span class="token operator">==</span> <span class="token number">0</span><span class="token punctuation">)</span> </code></pre> <pre><code class="block bad language-js"><span class="token keyword">if</span> <span class="token punctuation">(</span>obj <span class="token operator">&&</span> obj<span class="token punctuation">.</span>nicht_da <span class="token operator">&&</span> obj<span class="token punctuation">.</span>nicht_da<span class="token punctuation">.</span>irgendwas <span class="token operator">&&</span> obj<span class="token punctuation">.</span>nicht_da<span class="token punctuation">.</span>irgendwas <span class="token operator">==</span> <span class="token number">0</span><span class="token punctuation">)</span> </code></pre> <p>Letzteres würde auch bereits false liefern, wenn der Wert in irgendwas zu false kompatibel ist. Also wenn er in dem Beispiel 0 wäre, würde die erste Zeile true ergeben, die zweite nicht.</p> <p>Um zu deinem Code zurückzukommen</p> <blockquote> <pre><code class="block language-js"><span class="token keyword">if</span> <span class="token punctuation">(</span>data<span class="token punctuation">[</span>prop<span class="token punctuation">]</span><span class="token punctuation">.</span>type <span class="token operator">&&</span> data<span class="token punctuation">[</span>prop<span class="token punctuation">]</span><span class="token punctuation">.</span>type <span class="token operator">==</span> <span class="token string">"info"</span><span class="token punctuation">)</span> </code></pre> </blockquote> <p>Die erste Prüfung ist so nicht sinnvoll. Man müsste <code>data[prop]</code> prüfen. Wenn das auf undefined/null läuft, erzeugt der Zugriff auf <code>.type</code> eine Fehlermeldung und Script-Abbruch. Um undefined oder null zu ergeben, reicht es, wenn der Anwender die Eigenschaft mit dem Wert null oder undefined statt einem Objekt erstellt. Besser also wie folgt, aber es geht hier noch besser.</p> <pre><code class="block good language-js"><span class="token keyword">if</span> <span class="token punctuation">(</span>data<span class="token punctuation">[</span>prop<span class="token punctuation">]</span> <span class="token operator">&&</span> data<span class="token punctuation">[</span>prop<span class="token punctuation">]</span><span class="token punctuation">.</span>type <span class="token operator">==</span> <span class="token string">"info"</span><span class="token punctuation">)</span> </code></pre> <p>Man muss das nun nicht bei jeder Eigenschaft einzeln notieren, sondern kann diese Prüfung einmal am Schleifenanfang vornehmen.</p> <pre><code class="block language-js"><span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">const</span> prop <span class="token keyword">in</span> data<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>data<span class="token punctuation">[</span>prop<span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token keyword">continue</span><span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>data<span class="token punctuation">[</span>prop<span class="token punctuation">]</span><span class="token punctuation">.</span>type <span class="token operator">==</span> <span class="token string">"info"</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// ...</span> </code></pre> <p>Außerdem muss ich mich in einem Punkt revidieren. <code>for...of</code> geht nur mit iterierbaren Dingen wie Arrays. Objekte gehören ohne Spezialbehandlung nicht dazu. Das muss also weiterhin eine <code>for...in</code>-Schleife bleiben, damit das über die Objekteigenschaften laufen kann. Falls man die prototypische Vererbung verhindern möchte, muss man das über hasOwnProperty() prüfen und entsprechend verzweigen. Das kann man hier aber wohl weglassen.</p> <blockquote> <p>Wenn man das Ganze noch ordentlich weitertreibt, dann würde man die Datenobjekte nicht von Hand als Literal notieren, sondern mittels einer Klasse bauen lassen, die dafür Sorge trägt, dass alle notwendigen Eigenschaften auch vorhanden sind - und als <em>default</em>-Typ eben <code>info</code> verwendet.</p> </blockquote> <p>Jein, wenn es "ordentlich" sei sollte, müsste man dieses <a href="https://en.wikipedia.org/wiki/XY_problem" rel="nofollow noopener noreferrer">XY-Problem</a> durch Verwendung von <template> vermeiden.</p> <blockquote> <blockquote> <p>Als Bonus kann man das HTML des Templates mit allen Finessen des HTML-Editors erstellen.</p> </blockquote> <p>Der Phantasie sind eben keine Grenzen gesetzt. Man kann mit seiner Programmlogik alles Denkbare umsetzen.</p> </blockquote> <p>Da hast du mich wohl missverstanden. Ich meinte, dass dein Ansatz über das Konfigurationsobjekt nicht nur bei der Gestaltung des Dialoginhalts einschränkt auf das was der dieses Objekt auswertende Code bietet, auch im Editor beim Erstellen des Objekts hat man keinerlei Hilfe durch Autovervollständigung und ähnliche Hilfsmittel. Man erstellt ein Objekt mit für die IDE unbekannte Struktur. Wenn man die Eigenschaften nicht richtig tippt, gibt es zur Laufzeit kein Ergebnis. Wenn man stattdessen den Dialoginhalt direkt als HTML notieren könnte, wäre die IDE in der Lage, Syntaxprüfungen und Vervollständigung anzubieten.</p> <p>dedlfix.</p> modale Fenster Mon, 20 May 19 20:36:35 Z https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1749028#m1749028 https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1749028#m1749028 <p>Lieber dedlfix,</p> <blockquote> <p>const/let gibt es ja auch noch nicht so lange. Aber laut CanIUse kann das sogar der IE11 in Grundzügen.</p> </blockquote> <p>sind Grundzüge ausreichend, dass ein Tutorial-Leser, der das in seinem IE ausprobiert, damit auch nicht scheitert?</p> <blockquote> <p>Vermutlich ist const für die Laufzeitumgebung interessant, dass es da besser optimieren kann als bei veränderbaren Variablen.</p> </blockquote> <p>Wenn ein JS-Neuling den Code mit seinem IE ausprobiert und an <code>const</code>/<code>let</code> scheitert, wem ist denn dann damit geholfen, dass ich kein <code>var</code> benutzt habe?</p> <blockquote> <p>Naja, keiner der IEs hat diese Methode an der NodeList.</p> </blockquote> <p>Also bleibe ich besser noch bei meiner <code>Array.prototype.slice.call</code>-Weise, damit's auch beim <em>noob</em> im IE funzt.</p> <blockquote> <p>Wenn man es schafft, die Funktionen mit beschreibenden Namen zu versehen, hat man als Leser gleich noch einen Hinweis auf das, was die Funktion tun soll, ohne erst den Code verstehen zu müssen und auch ohne dass da ein Kommentar zur Erläuterung steht.</p> </blockquote> <p>Ist das in meinen Beispielen nicht gegeben?</p> <blockquote> <blockquote> <p>So betrachtet schon. Ich habe mir immer angewöhnt, auf das prinzipielle Vorhandensein zu prüfen. Daher die erste Bedingung.</p> </blockquote> <p>Diesen Teil hatte ich gar nicht beachtet, nur den Vergleich nach dem <code>&&</code>. Aber jetzt wo du es sagst, fällt mir auf, dass ich doch was daran auszusetzen habe.</p> </blockquote> <p>Also gut. Da <code>data[prop]</code> zwingend existiert (kann ein leerer Wert unter diesem Eigenschaftsnamen sein), kann ich gleich <code>data[prop].type</code> auf den Wert testen, den ich haben will (also <code>info</code>).</p> <blockquote> <p>Außerdem muss ich mich in einem Punkt revidieren. <code>for...of</code> geht nur mit iterierbaren Dingen wie Arrays. Objekte gehören ohne Spezialbehandlung nicht dazu. Das muss also weiterhin eine <code>for...in</code>-Schleife bleiben, damit das über die Objekteigenschaften laufen kann.</p> </blockquote> <p>Danke für diese erweiterte Klarstellung. Mich freut, dass ich meinen Code an dieser Stelle nun doch nicht anzupassen brauche.</p> <blockquote> <p>Falls man die prototypische Vererbung verhindern möchte, muss man das über hasOwnProperty() prüfen und entsprechend verzweigen. Das kann man hier aber wohl weglassen.</p> </blockquote> <p>Sehe ich auch so.</p> <blockquote> <p>Jein, wenn es "ordentlich" sei sollte, müsste man dieses <a href="https://en.wikipedia.org/wiki/XY_problem" rel="nofollow noopener noreferrer">XY-Problem</a> durch Verwendung von <template> vermeiden.</p> </blockquote> <p>Aha... OK. Das überblicke ich jetzt gerade nicht, da ich mich noch nicht mit Templates befasst habe.</p> <blockquote> <p>Da hast du mich wohl missverstanden. Ich meinte, dass dein Ansatz über das Konfigurationsobjekt nicht nur bei der Gestaltung des Dialoginhalts einschränkt auf das was der dieses Objekt auswertende Code bietet, auch im Editor beim Erstellen des Objekts hat man keinerlei Hilfe durch Autovervollständigung und ähnliche Hilfsmittel.</p> </blockquote> <p>Meine Zielgruppe erwartet wohl solche Features in diesem Zusammenhang nicht. Und wenn, dann braucht sie mein Tutorial wahrscheinlich nicht mehr. Mein Ansatz geht auch nicht in die Richtung, dass die Dialoge wirklich alle Möglichkeiten ausreizen, sondern dass sie programmatisch erstellt werden können, um übliche Formulardaten erfassen zu können und so über <code>confirm</code> und <code>prompt</code> weit hinaus gehen. Wer noch mehr will, geht freilich anders vor!</p> <blockquote> <p>Man erstellt ein Objekt mit für die IDE unbekannte Struktur. Wenn man die Eigenschaften nicht richtig tippt, gibt es zur Laufzeit kein Ergebnis. Wenn man stattdessen den Dialoginhalt direkt als HTML notieren könnte, wäre die IDE in der Lage, Syntaxprüfungen und Vervollständigung anzubieten.</p> </blockquote> <p>Das will der Profi. Der Profi sucht aber nicht mehr unser Tutorial hier zum Lernen auf. Oder doch?</p> <p>Liebe Grüße</p> <p>Felix Riesterer</p> modale Fenster Mon, 20 May 19 21:20:49 Z https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1749032#m1749032 https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1749032#m1749032 <p>Tach!</p> <blockquote> <blockquote> <p>const/let gibt es ja auch noch nicht so lange. Aber laut CanIUse kann das sogar der IE11 in Grundzügen.</p> </blockquote> <p>sind Grundzüge ausreichend, dass ein Tutorial-Leser, der das in seinem IE ausprobiert, damit auch nicht scheitert?</p> </blockquote> <p>Ist es wirklich so, das man davon ausgehen muss, dass nur der IE zur Verfügung steht und kein anderer Browser?</p> <blockquote> <blockquote> <p>Wenn man es schafft, die Funktionen mit beschreibenden Namen zu versehen, hat man als Leser gleich noch einen Hinweis auf das, was die Funktion tun soll, ohne erst den Code verstehen zu müssen und auch ohne dass da ein Kommentar zur Erläuterung steht.</p> </blockquote> <p>Ist das in meinen Beispielen nicht gegeben?</p> </blockquote> <p>Kommentare sind vorhanden. Aber das lindert nur zum Teil, dass die Funktion sehr lang ist. Man muss immer noch verstehen, was da wie zusammenspielt. Bei kleineren Funktionen, die über ihre Parameter und den Rückgabewert eine definierte Schnittstelle zur Außenwelt haben, ansonsten aber eigenständig arbeiten, kann man besser deren Details ausblenden, wenn diese für das Verstehen des großen Ganzen nicht weiter benötigt werden. Das ist quasi wie mit Fachbegriffen. Man lernt diese und was dahintersteht, und kann dann effizient zum eigentlichen Thema kommunizieren.</p> <blockquote> <blockquote> <p>Jein, wenn es "ordentlich" sei sollte, müsste man dieses <a href="https://en.wikipedia.org/wiki/XY_problem" rel="nofollow noopener noreferrer">XY-Problem</a> durch Verwendung von <template> vermeiden.</p> </blockquote> <p>Aha... OK. Das überblicke ich jetzt gerade nicht, da ich mich noch nicht mit Templates befasst habe.</p> </blockquote> <p>Die Template-Variante würde die Codemenge sehr reduzieren und gleichzeitig mehr Freiheiten geben. Der Dialog definiert nur das Grundgerüst und die grundlegenden Funktionen die zum allgemeinen Handling (Öffnen und Schließen) notwendig sind. Dazu gehört auch, den Inhalt des angegebenen Templates in den Body des Dialogs zu kopieren. Das Template muss nicht einmal in einem <template> sitzen, auch ein verstecktes Div oder ähnlich für ältere Browser geht. Wobei für die ebenfalls das ihnen unbekannte <template> verwendet werden könnte, nur muss das ausgeblendet werden.</p> <p>Wegfallen kann bei diesem Ansatz, ein Konfigurationsobjekt zu erstellen, dessen Syntax man erst noch lernen muss, und selbiges parsen und zu DOM-Elementen umarbeiten zu müssen. Stattdessen erstellt man HTML und es kommt nur ein wenig Code zum Einsatz, der dieses lediglich in den Dialog kopiert.</p> <blockquote> <blockquote> <p>Da hast du mich wohl missverstanden. Ich meinte, dass dein Ansatz über das Konfigurationsobjekt nicht nur bei der Gestaltung des Dialoginhalts einschränkt auf das was der dieses Objekt auswertende Code bietet, auch im Editor beim Erstellen des Objekts hat man keinerlei Hilfe durch Autovervollständigung und ähnliche Hilfsmittel.</p> </blockquote> <p>Meine Zielgruppe erwartet wohl solche Features in diesem Zusammenhang nicht.</p> </blockquote> <p>Nun, selbst wenn sie keine ausgefeilte IDE zur Verfügung haben, so werden viele von ihnen zumindest einen Editor haben, der grundlegende Syntaxhervorhebung kann. Auch da hilft es, bekanntes HTML erstellen zu können statt ein unbekanntes Objekt.</p> <p>Aber was erwartet die Zielgruppe wirklich?</p> <blockquote> <p>Und wenn, dann braucht sie mein Tutorial wahrscheinlich nicht mehr.</p> </blockquote> <p>Nun ja, möchtest du zeigen, wie man ein Konfigurationsobjekt liest und wie man DOM-Elemente erstellt? Oder wie man die eingebauten vorgefertigten Dialoge durch eine eigene Variante mit ein paar mehr, jedoch relativ fest vorgegebenen Gestaltungselementen ersetzt? Oder möchtest du zeigen, wie man nicht nur die eingebauten vorgefertigten Dialoge wegbekommt, sondern gleich noch mit recht wenig Code-Aufwand Dialoge mit vollständig individuellen Inhalt bekommen kann?</p> <blockquote> <p>Mein Ansatz geht auch nicht in die Richtung, dass die Dialoge wirklich alle Möglichkeiten ausreizen, sondern dass sie programmatisch erstellt werden können, um übliche Formulardaten erfassen zu können und so über <code>confirm</code> und <code>prompt</code> weit hinaus gehen. Wer noch mehr will, geht freilich anders vor!</p> </blockquote> <p>Aber du treibst einen unnötig hohen Aufwand, den man bei gleichzeitig mehr Freiheit deutlich reduzieren kann.</p> <blockquote> <blockquote> <p>Man erstellt ein Objekt mit für die IDE unbekannte Struktur. Wenn man die Eigenschaften nicht richtig tippt, gibt es zur Laufzeit kein Ergebnis. Wenn man stattdessen den Dialoginhalt direkt als HTML notieren könnte, wäre die IDE in der Lage, Syntaxprüfungen und Vervollständigung anzubieten.</p> </blockquote> <p>Das will der Profi. Der Profi sucht aber nicht mehr unser Tutorial hier zum Lernen auf. Oder doch?</p> </blockquote> <p>Auch der Anfänger mag es einfach.</p> <p>dedlfix.</p> modale Fenster Thu, 23 May 19 09:22:13 Z https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1749211#m1749211 https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1749211#m1749211 <p>Tach!</p> <p>Ich hab mich mal rangesetzt, und <a href="https://plnkr.co/edit/BS2yiWz8KenIcqLceHi7" rel="nofollow noopener noreferrer">eine eigene Version</a> entworfen. (Beim Testen Browser-Konsole öffnen nicht vergessen!) Damit verbinde ich keinerlei Ansprüche. Wenn du das oder Ideen daraus übernehmen möchtest, finde ich das gut, wenn nicht, ist das auch in Ordnung.</p> <p>Vorab, ich hab deine Version als Vorlage genommen abzüglich dem Formular-Handling. Dabei ist mir aufgefallen, dass sie nicht läuft, so wie sie derzeit im Wiki steht. In den Javascript-Verwendungen wird ein textElement selektiert, das nicht unter diesem Selektor im HTML-Teil steht. Sicher nur ein Aufmerksamkeitstest </p> <p>Anmerkungen zu meiner Version:</p> <p>Es gibt ja bereits Polyfills für Dialoge, beispielsweise <a href="https://github.com/GoogleChrome/dialog-polyfill" rel="noopener noreferrer">jenen</a>. Trotzdem hab ich eine eigene Variante erstellt, die aber unvollständig ist. Mein Anliegen war, dass das Polyfill nur die standardisierten Teile abdeckt und keine eigene Funktionalität hinzufügt. Somit ist das Polyfill auch gegen jenes austauschbar oder kann im Falle von Chrome ganz weggelassen werden.</p> <p>Im Beispiel-Code gibt es dialog.html für meine Variante und dialog-polyfill.html für das GoogleChrome-Polyfill. Der Unterschied ist eine Script-Einbindung im Head, die Funktion registerDialog und unter window.myDialog die Zeile</p> <pre><code class="block language-js">dialogPolyfill<span class="token punctuation">.</span><span class="token function">registerDialog</span><span class="token punctuation">(</span>dialog<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//vs. registerDialog(dialog);</span> </code></pre> <p>Mein Polyfill ist unvollständig, weil showModal nicht implementiert ist sowie das Backdrop-Handling. Auch die ganzen Feinheiten für veraltete Browser sind nicht enthalten.</p> <p>Wie kann man nun mit dem Polyfill bezüglich Wiki umgehen? Im Prinzip könnte man es weglassen und lediglich auf die vollständige Variante verweisen. So umfangreich, wie das dort ist, könnten wir das nicht nachbauen, ohne den Artikel zu sprengen. Als Kompromiss könnte man für Schulungszwecke das eigene Polyfill zeigen, für den Produktivbetrieb aber zu einem vollständigen raten.</p> <p>In meinem Code wird das Polyfill durch die Funktion <code>registerDialog</code> implementiert. Zusätzlich braucht es noch das globale Escape-Handling für das Schließen des Dialogs mit Esc-Taste. Im oben verlinkten Plunkr ist das unter "Individuelle Funktionalität" angesiedelt, müsste aber zum Polyfill gerechnet werden. Andererseits reagiert zwar das <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dialog" rel="nofollow noopener noreferrer">Beispiel in der MDN</a> im Chrome auf Escape (wenn der Focus im Beispielkasten ist), das GoogleChrome-Polyfill ignoriert es jedoch. Meine Ergänzung spielt jedoch problemlos mit dem GoogleChrome-Polyfill zusammen. Außerdem wäre vielleicht noch erwähnenswert, dass mein Polyfill auch <code><form method="dialog"></code> berücksichtigt.</p> <p>Soweit zum Polyfill. Für unsere Belange brauchen wir jedoch noch weitergehende Funktionalität. Die wird bei mir durch <code>window.myDialog</code> hinzugefügt. Generell habe ich auf die bereits vorgeschlagenen Features gesetzt: Promises und Templates. (Vielleicht wird damit jetzt auch klarer, wie ich einige meiner Vorschläge gemeint hatte.)</p> <p>Es gibt bei mir keine drei Dialoge, sondern nur einen, in den durch ein beliebiges Template beliebiger Inhalt eingefügt werden kann. Die drei Varianten alert, prompt und confirm sind nur Anwendungsbeispiele dieses Prinzips.</p> <p>Nicht umsetzen konnte ich, dass das Escape-Schließen und das Klicken auf den Schließen-Button (d.h. alles mit close als Klasse) ins Reject läuft. Bei ordentlichem Schließen wird das Promise generell resolved. Man muss dann anhand des Rückgabewertes entscheiden, wie der Anwender den Dialog beendet hat. Das ist das value vom geklickten Button, inklusive dass der Browser selbständig bei Enter den ersten Button als geklickt simuliert.</p> <p>Auch kam ich nicht völlig ohne herkömmliche Callbacks aus. Mit Promises kann man dem Verwender nur anbieten, individuell handzuhaben, was "danach" passiert. Ich brauchte jedoch auch eine Möglichkeit der individuellen Initialisierung sowie zum Bereitstellen des Ergebnisses, dazu gleich mehr. Durch Promises fällt auch weg, mit den Handler für "nach dem Schließen" irgendwas anzustellen, beispielsweise sich ihn merken zu müssen. Allerdings habe auch ich an anderer Stelle das Problem zu lösen gehabt, Eventhandler zu registrieren und das nicht mehrfach bei mehrfacher Verwendung von Dialogen. (Die entsprechende Stelle in window.myDialog ist kommentiert.)</p> <p>Für das Individualisieren brauchte ich die Möglichkeit, Werte übergeben zu können. Dazu gibt es den options-Parameter. Dessen Eigenschaften sind</p> <ul> <li>dialogSelector, der auf den Dialog verweist mit Default-Wert #mydialog</li> <li>contentSelector, der auf das zu verwendende Template verweist</li> <li>returnValue, als optionale Vorbelegung</li> <li>initialize, als optionales Callback für die Initialisierung des Template-Inhalts</li> <li>resultHandler, als optionales Callback für die Ermittlung des Ergebnisses. Ansonsten wird ein FormData-Objekt erzeugt.</li> </ul> <p>Die Möglichkeit, einen Result-Handler anzugeben, brauchte ich, weil das Promise erst nach meinen Aufräumarbeiten (dialog.removeChild …) zum then() übergeht. Ein konkretes Beispiel für den Result-Handler habe ich nicht beigefügt, FormData sollte für die meisten Fälle reichen.</p> <p>Durch Templates ist man zwar frei, was die Gestaltung des Dialog-Inhalts angeht. Aber manchmal möchte man auch zum Beispiel lediglich einen anderen Text anzeigen. Wie das gehen kann, habe ich im Beispiel zum Alert-Dialog eingebaut. Das Alert-Beispiel hat übrigens keinen then()-Handler, weil mein angedachter Anwendungsfall hier vom Typ "Fire and Forget" ist, ohne dass man danach noch etwas tun möchte.</p> <p>Zu beachten ist generell auch, dass alles was "nach dem Schließen des Dialog" stattfinden soll, im then()-Handler stattfinden oder von diesem aufgerufen werden muss. Das ist jedoch das übliche Wesen von asynchron ablaufenden Prozessen. Der Profi jongliert dann mit den Möglichkeiten von Promises, um hier noch mehr für seinen konkreten Bedarf herauszuholen.</p> <p>Ich hatte ja auch erwähnt, dass es besser ist, kleinteilige Funktionseinheiten zu bilden, statt Monsterfunktionen. Das habe ich im Polyfill meines Erachtens recht gut umgesetzt, so dass der Teil auch ohne Kommentare selbsterklärend sein sollte - bilde ich mir zumindest ein. (Siehe show - recht übersichtlich, obwohl da einiges zu tun ist.) Bei window.myDialog habe ich das nicht so umgesetzt und musste Kommentare setzen, für die bessere Nachvollziehbarkeit der Einzelteile. Das könnte man noch refaktorisieren.</p> <p>Was man auch noch verbessern könnte, mehr Objektorientiertheit reinbringen, so dass im Polyfill nicht immer der Dialog an die dortigen Funktionen übergeben werden muss. Hmm, eigentlich könnte man die Übergabe auch weglassen, weil dialog ja sowieso im Closure zur Verfügung steht.</p> <p>Die Internet Explorers habe ich nicht weiter beachtet. Der kann eh keine Promises, jedenfalls nicht ohne Polyfill. Ich bin der Meinung, wenn jemand unsere Dialog-Versionen im produktiven Umfeld verwenden möchte, kann er sich auch die Mühe machen, das für seinen konkreten Bedarf anzupassen. Wir wollen ja erklären und nicht einfach nur kopierfertigen Code anbieten.</p> <p>dedlfix.</p> modale Fenster Tue, 21 May 19 15:35:24 Z https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1749094#m1749094 https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1749094#m1749094 <blockquote> <p>ich habe den Test wiederholt:</p> <p>Browser: Chrome Version 74.0.3729.157 (Offizieller Build) (64-Bit) (Windows 10) Seite: <a href="https://wiki.selfhtml.org/extensions/Selfhtml/example.php/Beispiel:JS-Anw-accessible-dialog.html" rel="nofollow noopener noreferrer">https://wiki.selfhtml.org/extensions/Selfhtml/example.php/Beispiel:JS-Anw-accessible-dialog.html</a></p> <p>Wenn ich die Seite öffne und dann den Tabulator drücke, verlässt der Focus den Dialog.</p> </blockquote> <p>Aah, dann haben vermutlich aneinander vorbei geredet. Ich meinte, dass der Fokus gefangen wird, wenn der Dialog mit der Methode <code>showModal</code> geöffnet wird. In dem verlinkten Beispiel wird der Dialog manuell mit <code>setAttribute('open','open')</code> geöffnet, da wird der Fokus dann nicht gefangen.</p> modale Fenster Wed, 22 May 19 11:37:40 Z https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1749130#m1749130 https://forum.selfhtml.org/self/2019/may/3/modale-fenster/1749130#m1749130 <blockquote> <p>EventListener kann man an Elemente binden und wieder lösen. Wenn ich nun eine Funktion für das <code>cancel</code>-Event anbinde, muss ich die später wieder lösen, sonst wird sie bei Wiederbenutzung der Dialog-Box erneut ausgeführt, was ich ja nicht will, wenn diese Funktionalität dynamisch übertragen werden soll.</p> </blockquote> <p>Ich glaube, ich verstehe worauf du hinaus möchtest. Der Event-Handling-Mechanismus mit <code>addEventListener</code> macht den Fall aufwendiger einen Event-Handler auszutauschen, er macht es aber auch einfacherer einen Event-Handler hinzuzufügen. Traditionell unterstüzt das DOM daher auch zwei verschiedene Event-Handling-Mechanismen: Den klassischen mit <code>oncancel</code> und den modernen mit <code>addEventListener</code> (<a href="https://jsfiddle.net/15otLguw/" rel="noopener noreferrer">Beispiel</a>). Deine Variante mit <code>setCallback</code> entspricht in etwa dem klassischen System.</p> <blockquote> <p>Ich könnte mir also vorstellen, für die beiden Events <code>close</code> und <code>cancel</code> jeweils einen EventListener anzubinden, der meine Komfort-Funktion bedient, damit auf der einen Seite weiterhin das Handling der Callback-Funktionen so einfach geregelt werden kann, aber auf der anderen Seite die (geplanten) nativen Merkmale im Sinne eines Polyfills unterstützt werden.</p> </blockquote> <p>Ja, das halte ich ebefalls für gut.</p> <blockquote> <blockquote> <p>Darüber hinaus habe ich mehrfach und ausführlich die schlechte Lesbarkeit des Codes und die Abwesenheit von Qualitätssicherungs-Maßnahmen bemängelt.</p> </blockquote> <p>Richtig. Aber ein reines Bemängeln der Abwesenheit von QA-Maßnahmen ist das eine. Die Schlussfolgerung, dass daraus prinzipiell eine Unsicherheit des Systems abzuleiten sei, die eine Löschung aus dem Wiki nach sich zieht, ist eine ganz andere Form von Kritik.</p> </blockquote> <p>Ich möchte mal versuchen von den absoluten Begrifflichkeiten "sicher" und "unsicher" wegzukommen. Grundsätzlich unterliegen Software-Lösungen Unsicherheiten (im Sinne des englischen Uncertainty, nicht im Sinne von Insecurity). Die Risiken, die mit solchen Ungewissheiten einhergehen, lassen sich durch vielfältige Maßnahmen minimieren. Je mehr und je sorgfältiger diese Risiko-Minimierung betrieben wird, desto höher ist der Konfidenz-Level, dass sich das System zuverlässig verhält. Im Umkehrschluss gilt, wenn man nur wenig Risiko-Minimierung betreibt, besteht eine hohe Ungewissheit bzgl. der Zuverlässigkeit des Systems.</p> <p>Jetzt gibt es mehrere Ebenen, auf denen man diese Risko-Mimimierung betreiben kann. Die erste Ebene betrifft den Entwickler persönlich, seine Qualifikation, seine Selbstreflexion, -kontrolle und Coding-Disziplin. Dieser Faktor ist von außen nur schwer mittelbar, es gibt aber Alarmsignale, z.B. wenn der Entwickler versucht sich durch überhöhte Statements, wie "mein Code ist noch nie gehackt worden" oder "mein System ist viel sicherer als Wordpress", Geltung zu verschaffen.</p> <p>Die zweite Ebene betrifft die Einbeziehung und die Kommunikation mit Dritten. Ein klassisches Medium für diese Kommunikation ist der Code-Review, davon habe ich ein paar zu dem genannten Artikel geschrieben. Die sind allerdings nicht gut aufgenommen worden, zum Teil habe ich das auch selbst zu zuverschulden, indem ich damals nicht die richtige Tonart gewählt habe. Das Gegenteil von gut ist "gut gemeint".</p> <p>Die dritte Ebene befasst sich mit technischen Maßnahmen zur Qualitätssicherung. Darunter fallen automatisierte Tests, statische Analyseverfahren und Programm-Verfikation. Um diese Verfahren zu ermöglichen, muss der Code aber bereits bestimmte Hygiene-Vorschriften erfüllen, die damals nicht gegeben waren. Ein Teil meiner Kritik damals bezog sich vor allem auch darauf, dass nicht einmal die Grundvoraussetzungen bestehen, um technsiche QS-Maßnahmen zu ergreifen unabhängig davon, ob sie denn nun wirklich ergriffen werden.</p> <p>Zusammenfassend, ist es uns also nicht gelungen den Konfidenz-Level in die Vertrauenswürdigkeit des Login-Systems zu erhöhen, und inhaltlich stelle ich mich deshalb auch heute wieder auf den Punkt, dass es eine Fahrlässigkeit gewesen wäre, den Artikel unserer Leserschaft weiter anzubieten.</p> <blockquote> <p>Mir ist nicht bekannt, dass Du eine konkrete Sicherheitslücke damals hättest benennen können, sondern nur allgemein auf eben diese Abwesenheit von automatisierten Tests als Begründung verwiesen hattest.</p> </blockquote> <p>Auf drei konkrete Sicherheitslücken haben ich ja in meinem vorherigen Posting verlinkt.</p> <blockquote> <p>Gerade bei solchen sicherheitsrelevanten Dingen können automatisierte Tests ja auch nur das testen, was der Testersteller im Sinn hat. Für den Login-System-Artikel hätte es einen regelrechten Fuzzer gebraucht, von dem ich nicht einmal im Ansatz wüsste, wie man so etwas erstellt. Aus meiner Sicht heute ging Dein Bemängeln damals also sogar nicht weit genug (Test vs. Fuzzer).</p> </blockquote> <p>Zum Beispiel mit <a href="https://github.com/giorgiosironi/eris" rel="noopener noreferrer">eris</a>, das ist eine Erweiterung für PHPUnit für generatives Testen.</p>