Erhellende Horrorstories aus dem Browser-API-Gruselkabinett

Peter Kröner, peter@peterkroener.de

Euer meistgelesenes Schriftstück?

Agenda: Gruselige oder seltsame APIs und Features der Webplattform und was wir von ihnen lernen können!

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title></title>
</head>
<body>
  <button>Click me!<button>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title></title>
  <script src="a.js"></script>
  <script src="b.js"></script>
  <script src="c.js"></script>
</head>
<body>
  <button>Click me!<button>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title></title>
  <script src="a.js"></script>
  <script src="b.js"></script>
  <script src="c.js"></script>
</head>
<body>
  <button>Click me!<button>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title></title>
  <script src="a.js"></script>
  <script src="b.js"></script>
  <script src="c.js"></script>
</head>
<body>
  <button>Click me!<button>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title></title>
  <script src="a.js"></script>
  <script src="b.js"></script>
  <script src="c.js"></script>
</head>
<body>
  <button>Click me!<button>
</body>
</html>
  1. Warum ist das so? Das war schon immer so!
  2. Und warum war das schon immer so? document.write()
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title></title>
</head>
<body>
  <p>
    Hello!
  </p>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title></title>
</head>
<body>
  <script>
    // Modifiziert den HTML-Output-Stream!
document.write("<p>Hello!</p>");
  </script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title></title>
</head>
<body>
  <script>
    // Modifiziert den HTML-Output-Stream!
document.write("<p>Hello!</p>");
  </script>
  <script>
    window.alert(42);
  </script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title></title>
</head>
<body>
  <script>
    // Modifiziert den HTML-Output-Stream!
document.write("<!--");
  </script>
  <script>
    window.alert(42);
  </script>
</body>
</html>

Webentwicklung in 1995 …

Frame
Frame
Frame
Frameset

Frameset (Parent)

var state = new Object();
state.value = 42;

function update (newValue) {
  state.value = newValue;
  document.frames[1].history.go(0); // Frame-Reload
}

Frame

<H1>Content Frame</H1>
<SCRIPT>
document.write("<P>Current value: " + parent.state.value + "</P>");
document.write("<INPUT TYPE=BUTTON");
document.write("ONCLICK='parent.update(" parent.state.value + 1 ")'>");
document.write(">");
</SCRIPT>

Deep dive: What's new in Netscape Navigator 2.0 (Marcin Szczepanski @ JSConf EU 2017)

document.write("<p>42<p>");

<?php echo "<p>42<p>"; ?>
  1. Warum ist das so? Das war schon immer so!
  2. Und warum war das schon immer so? document.write()

Warum ist das immer noch so?

Folge: Webstandards sind append-only!

Besseres Script-Verhalten ist immer Opt-In:

html.spec.whatwg.org/#the-script-element

Egal wie abseitig, alte APIs müssen unterstützt werden:

$ node
Welcome to Node.js v12.14.1.
Type ".help" for more information.
>"Hello".bold()
'<b>Hello</b>'

Fossilien sind Teil der Webstandards

Implementierung ist verpflichtend!

Was lernen wir aus blockierenden Scripts?

Nächstes Thema: Neptun!

Neptun

Urbain LeVerrier

John Couch Adams

Johann-Gottfried-Galle

Solar system orrery outer planets by Datumizer, CC BY-SA

Drag & Drop

Use Cases:

HTML5-DnD hat seine Kritiker …

“… a steaming pile of bovine manure.”

- Peter-Paul Koch, Webstandards-Experte

“The drag-and-drop API is horrible.”

- Ian Hixon, Autor des HTML5-Standards

Die drei wichtigsten Fakten

  1. Events feuern auf entweder dem gezogenen Element oder dem Drop-Ziel
  2. Es gibt in Event-Objekten Data-Store, der zu Beginn schreibbar und am Ende lesbar ist
  3. Es gibt in Event-Objekten den dropEffect, der die Auswirkungen eines erfolgten Drops kommuniziert

Die komplette API ist etwas komplexer …

html.spec.whatwg.org/#dndevents

Drag-Element

  1. dragenter
  2. dragover
  3. dragexit
  4. dragleave
  5. drop

Drop-Ziel

  1. dragstart
  2. drag
  3. dragend

dragstart: Operation beginnt, Daten schreiben, mögliche dropEffect definieren

drag: feuert alle paar Millisekunden

dragenter: Drop-Handbremse (lösen via preventDefault(), dropEffect lesbar)

dragover: feuert alle paar Millisekunden (wenn Handbremse gelöst)

dragexit/dragleave: Drop-Ziel verlassen (wenn Handbremse gelöst)

drop: Drop-Ereignis (wenn Handbremse gelöst, Daten und dropEffect lesbar)

dragend: Operation beendet. Wenn drop passiert ist, ist der dropEffect lesbar

Markup
Styling
HTML 4.01
XHTML 1.0
CSS Level 2
CSS Animations

Der dropEffect erlaubt in Fenster 1 den indirekten Nachweis eines drop-Events in Fenster 2!

  1. Was macht das in meinem Browser? Das Jahr 2004 hat angerufen!
  2. Und warum ist das so abstrus? Danke IE5!

2004

Fazit: 2004 konnten API im Standard landen, die heute keiner mehr braucht!

  1. Was macht das in meinem Browser? Das Jahr 2004 hat angerufen!
  2. Und warum ist das so abstrus? Danke IE5!
Support Existing Content. Do not Reinvent the Wheel. Pave the Cowpaths. Evolution Not Revolution. [...] In case of conflict, consider users over authors over implementors over specifiers over theoretical purity.

- HTML Design Principles (W3C, November 2007)

Die in HTML5 spezifizierte API für Drag & Drop stammt fast 1:1 aus dem Internet Explorer 5!

“The drag-and-drop API is horrible, but it has one thing going for it: IE6 implements it, as do Safari and Firefox.

- Ian Hixon, Autor des HTML5-Standards (2009)

Was lernen wir aus Drag & Drop?

Nächstes Thema: die Zukunft!

Zwei Bestandteile der gleichen Plattform:

<!-- Vollständiger Video-Player -->
<video controls src="movie.mp4"></video>
// Ultra-Low-Level-Datencontainer
new ArrayBuffer()

passt nicht ganz ins Bild

Nachträglich eingebaute Low-Level-APIs erklären die vorhandenen (und kommenden) High-Level-Layer!

<!-- Unbekanntes Element -->
<MyFoo></MyFoo>
<!-- Unbekanntes Element -->
<MyFoo></MyFoo>

<script src="webcomponent-foo.js"></script>
<!-- spätes Upgrade zur Web Component -->
<!-- Scipt für Web Component lädt zuerst -->
<script src="webcomponent-foo.js"></script>

<!-- Web Component von Anfang an -->
<MyFoo></MyFoo>
<!-- Scipt für Web Component lädt zuerst -->
<script src="webcomponent-foo.js"></script>

<!-- Web Component von Anfang an -->
<MyFoo></MyFoo>

<!-- Frühes und spätes Upgrade sind an ihren
     Nebenwirkungen unterscheidbar! -->
Nativ JS
Komponenten
Browserbugs
Viele Features
Iteration Lahm Schnell
Vorhalten Inkonsistent Konsistent
Legacy ~30 Jahre Viel weniger
Halbwertzeit Sehr lang Eher kurz
Cross-Framework

Web Components lösen nur sehr bestimmte ungelöste Probleme!

Aktueller Status

Preisfrage: werden hier irgendjemandes Probleme gelöst?

Was lernen wir aus dem Status Quo?

Andere Meinung? Reden wir drüber!