Die letzten Jahre habe ich ständig Seminare und Vorträgen zu HTML5, CSS3, JavaScript und verwandten Themen gegeben. Bei diesen Themen ist es natürlich naheliegend, HTML/JS-Demos und -Codeschnipsel direkt in die Präsentation einzubetten. Auf HTML fußende Präsentationstools, mit denen das theoretisch denkbar wäre, gibt es wie Sand am Meer. Allerdings haben all diese meine dringendsten Präsentationsprobleme nicht gelöst, weswegen ich (nach mehreren Anläufen) mein eigenes Tool geschrieben habe. Die Hörsuppe hat mich vor ein paar Tagen dazu veranlasst, dem Ganzen mal ein ordentliches Release zu gönnen: Pik7 v. 1.0.0 ist da!
Ich bin nicht restlos davon überzeugt, dass irgendwer außer mir Pik7 einsetzen sollte, weil ich doch sehr spezielle Primärziele damit hatte:
Performance. Dinge wie mein Canvas-Intensivkurs haben deutlich mehr als 100 Slides, auf denen zu allem Überfluss auch noch allerhand Animationen usw. ablaufen. Das brauche ich in flüssig.
Presenter View. Ein aus „richtigen“ Präsentationstools wie Power Point bekanntes Feature, das auf einem Zweitbildschirm nicht für das Publikum gedachte Infos anzeigt – so kann der Vortragende zum Beispiel sehen, welche Slide als nächste dran ist und wie viel Zeit er noch hat. Bei der Masse meiner ganzen Folien darf dieses Feature nicht fehlen.
Druckbarkeit. Ich brauche PDF-Fassungen all meiner Slides. Druckbare Präsentationen + Chromes „print to PDF“ = Problem erledigt. Mit ein bisschen JavaScript und CSS kann man außerdem mehrere verschiedene PDFs erzeugen, z.B. einen Cheat Sheet für den Workshop und eine Komplettfassung für das spätere Nacharbeiten.
Einfache Programmier- und Stylebarkeit. Versteht sich von selbst: simple Themes, JavaScript-Events beim Folienwechsel usw.
Nobrainer-Funktionen für Nerds. Eingebautes Syntax-Highlighting. Eingebautes prefix-free. Auto-Synchronisation von mehreren offenen Präsentationen und Presenter Views. Ich muss kompliziertes Zeugs erzählen, ich habe keine Zeit komplizierte Tools zu bedienen.
Kein Firlefanz. Ich brauche weder fancy 3D-Animationen noch verschachtelte Slides noch eine Funktion, die mich Bullet Points nach und nach einblenden lässt. Die könnte man sicher alles einbauen, aber ich habe daran erst mal keinen Bedarf.
Da es, zumindest als ich anfing meine eigenen Tools zu basteln, diese Features in dieser Kombination nirgendwo zu finden gab, musste ich eben selbst ran. Pik7 ist selbstverständlich Open Source (MIT), liegt auf Github rum oder kann von pik.peterkroener.de heruntergeladen werden. Eine Präsentation zu erstellen ist recht einfach …
… aber wie schon gesagt: ich bin nicht sicher, ob ich Pik7 wirklich empfehlen sollte. Zu den Nachteilen gehört unter anderem der etwas bei HTML-Slides übliche, mühsame Folienbau (Snippets für ST2 liegen aber bei) und dass zwingend ein Websever benötigt wird. Ein kleiner Node.js-Server wird zwar mitgeliefert, ist aber sehr spartanisch gehalten. Außerdem fehlen, wie erwähnt, Animationen und Co. Aber falls ihr euer Glück mit Pik7 versuchen wollt, werde ich euch nicht aufhalten.
Ich bin zwar kein Doktor und draußen ist auch gerade alles andere als Sommer, aber Fragen beantworte ich trotzdem gern. Bevorzugt solche zu HTML5, CSS3, JavaScript und anderen Themen rund um Webentwicklung. Die folgenden vier Fragen sind alle in den letzten Wochen via Twitter und E-Mail an mich herangetragen worden, was genau die beiden Kanäle sind, über die ich auch euch gerne die Fragen beantworte, die euch unter den Nägeln brennen. Einfach anschreiben!
Leerzeichen bei mobiler Datenverbindung verschwunden?
In mobilen Browsern (Verbindung über EDGE/3G/LTE) werden manchmal Leerzeichen aus meiner Webseite entfernt. Weißt du etwas darüber? Ist das vielleicht eine Art von Kompression?
Ohne es konkret testen zu können ist eine Antwort schwer, aber es kann durchaus sein, dass Mobilfunkanbieter das HTML einer Seite komprimieren, um hier und da ein paar Bytes zu sparen. Es ist jedenfalls nicht unüblich, dass die Provider in auszulieferndes Markup eingreifen. Besonders problematisch wird das Ganze, wenn, wie im verlinkten Artikel beschrieben, der Inhalt verändert wird, aber auch wenn „nur“ komprimiert (d.h. Whitespace zwischen Tags entfernt) wird, kann es durchaus zu sichtbaren Veränderungen in der Seite kommen, denn egal ist solcher Whitespace bei HTML nicht. Vergleichen wir doch mal:
Der Unterschied zwischen den beiden Absätzen ist an im gerenderten Endergebnis sichtbar und kommt daher, dass die Leerzeichen und Zeilenumbrüche zu zusätzlichen Textknoten zwischen den Elementen führen. Man beachte die childNodes-Eigenschaft im DOM:
Streicht ein übereifrig optimierender Mobildatendienstleister diese Leerzeichen weg, hat man natürlich plötzlich ein ganz anderes DOM und das kann ein handfestes Problem werden. Schnelle Abhilfe schafft möglicherweise die Codierung von Leerzeichen als Entity ( ) an kritischen Stellen.
Bilder und Videos per Canvas verkleinern
Vielen Dank für das Tutorial! Eine Frage hätte ich allerdings: was müsste ich machen, um das Video oder das Bild in eine kleine Canvas zu skalieren, also z.B. statt 400×300 in ein 40×30, wenn die Originaldatei aber 400×300 hat?
Das ist zum Glück ganz einfach. Die drawImage-Methode kann man nicht nur mit zwei Parametern (Bild, X-Koordinate, Y-Koordinate) aufrufen, sondern auch mit vier oder acht. Die beiden zusätzlichen Parametern bestimmen dann die Höhe und Breite des gemalten Bildes und wenn die Quelle andere Maße hat, wird sie automatisch gestreckt oder verkleinert. Außerdem kann man auch nur einen Ausschnitt aus der Quelle verwenden. Ein Bild sagt mehr als tausend Worte; der Aufruf context.drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh) bedeutet:
Leider wird diese Technik noch viel zu selten genutzt. Warum zum Beispiel sollte man bei Bilduploads eine viel zu große Datei hochladen, nur um sie dann auf dem Server von einem PHP-Script kleinrechnen zu lassen? Das kann man dank HTML5 viel besser auf dem Client erledigen.
End-Slashes für Leer-Elemente
Hallo, ich beobachte, dass häufig ein End-Slash im IMG-Tag gesetzt wird (<img />). Bisher funktionieren auch die alten Tags ohne „/“. Kann es sein, dass der End-Slash zukünftig zwingend geschrieben werden muss? Und wenn ja, ab wann?
Nein, dieser schließende Slash wird voraussichtlich nie auf breiter Front Pflicht werden. Der Slash rührt daher, dass das W3C zwischenzeitlich mal plante, HTML auf XML-Basis neu aufzustellen – XHTML sollte der neue Standard werden. Dort wäre dann schließende Slash für Elemente wie <img> Pflicht geworden. Diese XML-Umstellung hat aber aus einer ganzen Reihe von Gründen nicht so recht funktioniert und heute (d.h. in HTML5) ist der Slash damit wieder optional. Die HTML5-Parser in modernen Browsern werden durch ihn nicht gestört, benötigen ihn aber auch nicht. Es ist buchstäblich völlig egal ob man ihn verwendet oder nicht.
Es existiert zwar auch XHTML5, wo der Slash Pflicht wäre, aber wegen vieler vieler Problem damit (u.A. funktioniert es nicht im Internet Explorer 6, 7 und 8) ist die Verwendung von XHTML5 nicht zu empfehlen. Man nur Nachteile, keine Vorteile.
Inline-Video mit HTML5 auf dem iPhone
Gibt es irgendwie die Möglichkeit, mit HTML5 eingebundene Videos auf dem iPhone inline d.h. ohne automatischen Fullscreen darzustellen?
Zunächst sollten wir festhalten, dass sich das iPhone nicht direkt unkorrekt verhält, wenn es Videos ausschließlich im Vollbild abspielt. Die in den Spezifikationen festgeschriebenen Regeln lassen sich mit geringem Aufwand so weit dehnen, dass dieses Verhalten standardkonform erscheint. Zitat:
User agents may allow users to view the video content in manners more suitable to the user (e.g. full-screen or in an independent resizable window). As for the other user interface features, controls to enable this should not interfere with the page's normal rendering unless the user agent is exposing a user interface. In such an independent context, however, user agents may make full user interfaces visible, with, e.g., play, pause, seeking, and volume controls, even if the controls attribute is absent.
Wenn der Browser ein Interface mit Steuerungselementen für das Video anzeigt, darf er das im Fullscreen-Modus machen. Und wenn der Browser im Fullscreen-Modus ein Video anzeigt, soll er dort auch ein Interface mit Steuerungselemente anzeigen, selbst wenn das dafür normalerweise nötige controls-Attribut auf dem Video-Element gar nicht gesetzt ist. Und so startet iOS auf iPhone und iPod Touch jedes Video im Vollbild, da es schließlich ein Steuerungsinterface zeigt, das es auch in Abwesenheit des controls-Attributs anzeigen darf, da das im Vollbild passiert. Richtig falsch ist das also nicht.
Kann man denn etwas dagegen tun? Leider nicht. Es gibt zwar das proprietäre HTML-Attribut webkit-playsinline, aber das scheint nur für native Apps mit UIWebViews gedacht zu sein und funktioniert nicht auf iPhones und dem iPod Touch.
Wie den wenigsten Webdesignern und -entwicklern entgangen sein dürfte, hat Opera angekündigt, in all ihren Produkten die hauseigene Presto-Engine gegen Webkit auszutauschen. So richtig habe ich die Gründe aus den entsprechendenBlogposts nicht herauslesen können, aber die wohl (für Nicht-Opera-Mitarbeiter) auch nicht so wichtig ist, wie die web-weiten Folgen dieses Schritts. An Prognosen hierüber herrscht kein Mangel – von goldener Zukunft bis hin zum Untergang der Webstandards lässt sich so ziemlich jede Aussage im Web finden. Eine besonders schöne Fundgrube stellt Hacker News dar. Ich habe zur Zeit noch keine fertige Meinung zu dieser Angelegenheit und möchte mich an dieser Stelle darauf beschränken, ein paar meiner Meinung nach leicht abenteuerliche Vorstellungen über die Folgen der Webkit-Entscheidung zu besprechen.
Alles wird besser! Auf dem Holzweg sind meines Erachtens vor allem jene, die glauben, dass es Entwicklern mit einer Engine weniger einfacher fallen wird, Web-Frontends zu bauen. Zum einen haben viele nicht ganz so professionelle Entwickler Opera ob seines eher geringen Marktanteils ohnehin völlig ignoriert. Alle, die ihre Werke auch in Opera getestet haben, werden gemerkt haben, dass dieser Browser sich seit jeher sehr standardkonform verhielt und selten die ganz großen Probleme machte (und wenn, dann hat selbst ein mittelschwerer Darstellungsfehler aufgrund des geringen Marktanteils wohl kaum fatale Auswirkungen auf das Gesamtprojekt gehabt). Und vor allem: um zu behaupten, dass es zwischen Browsern, die eine gemeinsame Engine haben, keine großen Unterschiede gibt, muss man die diversen Mobile-Browser ignorieren. Die verwenden zwar fast alle Webkit als Engine, aber in so unterschiedlichen Versionen und Zusammensetzungen mit anderen Komponenten, dass man davon als Webentwickler nicht wirklich viel merkt.
Das Ende ist nah! Die Apokalyptiker-Fraktion sieht hingegen eine neue Browsermonokultur unmittelbar vor der Tür stehen. Das ist, Stand heute (mit neben Webkit noch Gecko und Trident als relevanten Browserengines), natürlich noch längst nicht der Fall. Allerdings kann man das Ende von Presto schon als Wegfall eines Glieds aus der Monokultur-Abwehrkette interpretieren. Immerhin reicht es jetzt, wenn entweder Mozilla oder Microsoft aus dem Browsermarkt ausscheiden oder selbst zu Webkit wechselt, denn das dann bestehende Engine-Duopol könnte sich aufgrund des Übergewichts der Webkit-Browser als instabil erweisen. Aber selbst dann ist nicht gesagt, dass das Web im Innovationsstillstand versackt – die Konkurrenz durch die nativen Plattformen könnte das verhindern. Die Frage ist natürlich, wie der weitere Fortschritt dann aussehen könnte, was uns direkt zu Prognose Nummer drei bringt …
Gut für Webstandards! Manche sagen auch, weniger Engines seien besser für die Entwicklung und Durchsetzung von Standards. Ich weiß nicht so recht. Wenn man der Presto-Engine etwas nicht vorwerfen kann, dann sind das gewohnheitsmäßige Standards-Abweichungen. An dieser Front war Opera sicher nie das größte Problem. Andersherum könnte durchaus ein Schuh draus werden, denn Webstandards richten sich oft nach den Implementierungen – was in allen Browsern vorhanden ist, und sei es noch so größer Käse, wird früher oder später Standard. So war es zum Beispiel mit <center> oder der grausligen Drag & Drop-API. Mit nun einer Engine weniger fällt es vielleicht etwas leichter, Fakten zu schaffen, die dann in einem Standard münden. Das kann man durchaus gut finden weil es schneller gemeinsame APIs produziert, andererseits ist ein hohes Tempo ein Risiko für die Qualität dieser gemeinsamen Features. Allerdings hat Opera nun auch nicht all seine Entwickler entlassen, sondern lässt diese jetzt an Webkit mitbasteln, d.h. die Stimmen der Vernünftigen, die einst für Presto sprachen und programmierten, sind weiterhin zu hören. Ob das reicht wird man sehen.
Ich selbst habe, wie eingangs erwähnt, noch keine fertige Meinung zu diesem Schritt von Opera. Zu bejubeln finde ich nichts, aber die auch den unmittelbaren Weltuntergang vermag ich nicht festzustellen. Klar, im Prinzip sind das WWW der Webkit-Hegemonie einen Schritt näher gekommen, aber dass demnächst wirklich Mozilla und/oder Microsoft zumachen, fällt mir schwer zu glauben. Und beide haben einen ganz gesunden Marktanteil und können mit jeder Version steten Fortschritt vermelden. Selbst was die Entwicklung von Standards angeht, muss sich erst mal zeigen ob sich überhaupt etwas ändert. Das halte ich zwar noch am wahrscheinlichsten (jedenfalls wahrscheinlicher als eine Browser-Einheitsfront) aber wie genau sich das auswirkt, ist reine Spekulation.
Mein Fazit: Interessante Entwicklung, aber (noch) kein Grund die Gelassenheit zu verlieren.
Nachdem wir in Teil 1 dieses Artikels die wichtigsten Parts der Indexed Database API kennen gelernt haben und auch erfahren haben, dass dieses Feature bisher nur in Chrome, Firefox und IE 10 zu finden ist, stellt sich die übliche HTML5-Fragen: kann man das Ganze überhaupt benutzen? Ja, man kann. Für die Browser ohne Unterstützung für Indexed DB gibt es gute Polyfills und die wenigen Macken, die die vorhandenen Implementierungen haben, lassen sich recht einfach ausmerzen. Ein wenig problematischer ist der noch herrschende Mangel an Tools und Libraries. Aber alles der Reihe nach …
Polyfill(s) für Safari, Opera und andere
Opera und Safari inklusive Mobile-Varianten unterstützen die Indexed Database API nicht. Was sie allerdings unterstützen, ist Web SQL, dieser aufgegebene Nun-doch-nicht-Standard für relationale Datenbanken im Browser. Es ist dann ziemlich naheliegend, einen Polyfill zu bauen, der die Funktionalität von Indexed DB mittels Web SQL herstellt, was IndexedDBShim.js in gewohnt unkomplizierter Manier macht:
<script src="IndexedDBShim.js"></script>
Mit dieser Zeile Code im HTML läuft die Datenspeicherung dann auch in Opera, Safari, iOS, alten Android-Versionen und auch sonst fast allen Browsern, die zwar Web SQL unterstützen, denen es aber an Indexed DB gebricht.
Es gibt neben IndexedDBShim.js noch einen alternativen Polyfill aus der Feder Facebooks, den ich allerdings nicht getestet habe.
Härtefall 1: Android-Browser
Im Standard-Android-Browser (nicht mobile Chrome) ab Version 4 ist Indexed DB implementiert. Dummerweise basiert diese Implementierung aber auf einer älteren, nicht mit anderen Browsern kompatiblen Version der Spezifikationen. Der bequemste Ausweg aus diesem Problemchen ist, den Polyfill statt der nativen, aber fossilen Implementierung zu verwenden, denn Web SQL macht Android sehr viel richtiger als Indexed DB.
Ob eine Implementierung von Indexed DB veraltet ist, lässt sich am Vorhandensein von window.IDBVersionChangeEvent ablesen. Diese Variable wird nur von der aktuellen Version der Spezifikation beschrieben; ein Browser, der sie nicht hat, hat entweder gar keine Indexed DB oder eine alte Version. Der Rest ist dann ganz einfach:
// Keine (aktuelle) Implementierung von Indexed DB vorhanden?
var requireShim = typeof window.IDBVersionChangeEvent == 'undefined';
// WebSQL vorhanden?
var supportsWebSql = typeof window.openDatabase != 'undefined';
if(requireShim && supportsWebSql){
window.shimIndexedDB.__useShim(); // Verwendung des Polyfills erwzingen
}
Damit sind Android-Browser und auch alle anderen Fossilien, die eine alte Variante von Indexed DB mit sich herumschleppen, bedient.
Härtefall 2: Tools
Chrome bietet ein komfortables, in den Web Inspector einbgebautes UI zur Betrachtung von Indexed DB-Datenbanken im Resouces-Tab:
Und das war es dann auch schon mit guten Nachrichten von der Tool-Front, denn weder Firefox noch Internet Explorer können mit nativen Tools aufwarten. Am nächsten kommt man dem im Firefox noch mit dem Addon SQLite Manager, denn unter der Haube speichert dieser Browser die Indexed Database in einer SQLite-Datenbank. Diese befindet sich in aller Regel im Profil-Verzeichnis der jeweiligen Firefox-Users im Unterverzeichnis indexedDB/<ORIGIN>/ und hat den Namen <KRYPTISCHE_ID>.sqlite. Da sich SQLite und Indexed DB in ihrem Wesen stark unterscheiden, ist der SQLite Manager nicht wirklich ein super-komfortables Tool, aber er ist besser als gar nichts.
Stichwort „gar nichts“: für den IE 10 scheint es gar kein browserbasiertes Tool zu geben. Das nächstbeste sind sind diverse Ansätze für in HTML eingebaute Scripts, die dann einen Inspector-UI in die Seite rendern. Zu nennen wäre da vor allem der IDBExplorer, den ich allerdings nicht gründlich genug gestestet habe, um eine Aussage über dessen Tauglichkeit zu machen.
Härtefall 3: Libraries
Dem Indexed DB-Universum fehlen noch vernünftige Libraries. Zwar ist die API nicht schlecht, aber mehr Komfort und Funktionalität darf man sich als Entwickler durchaus wünschen. Zum Beispiel wäre ein Möglichkeit zur Definition von Schemata (inklusive Validierung, Defaultwerten und Virtuals) ganz wünschenswert und auch eine etwas mehr an moderne Befindlichkeiten angepasste API (Stichwort Verkettung) würde sicher Abnehmer finden. Außer Ansätzen ist in dieser Richtung aber bisher noch nicht viel zu finden.
Am nächsten kommen dem gewünschten Featureset noch db.js und IDBWrapper, die beide verkettbare APIs herstellen. Statt sich mit Transaktion und onsuccess-Callbacks herumzuschlagen, schreibt man einfach herunter, was man mit der Datenbank anstellen möchte:
// Beispiel mit db.js
server.people.add({
firstName: 'Aaron',
lastName: 'Powell',
answer: 42
}).done(function(item){
// item stored
});
Und das wäre eigentlich schon alles, was ich in Sachen Libraries auftreiben konnte. Aus der Ecke der Microsoft-Fans kommt außerdem noch Linq2IndexedDB, das aber in einem Maße unterdokumentiert ist, dass wir am besten so tun, als hätte ich es gar nicht verlinkt.
Fazit
Unter zuhilfenahme aller Polyfills und Tricks sieht es mit der Browserunterstützung für Indexed DB eigentlich vergleichsweise gut aus:
Browser
Unterstützung ab Version
Firefox
4*† / 16+
Chrome
11*† / 23* / 24+
Safari
- (< 5.1+)
Opera
- (< 12.1+)
Internet Explorer
10+
Mobile Safari
- (< 5.1+)
Android Browser
4.?† (2.1+)
* Mit Vendor-Prefix
† Implementierung entspricht nicht aktuellen Specs
In Klammern: mit Polyfill
Klar: die üblichen schwarzen Schafe, die alten IE und das, was bei Android als Browser durchgeht, sind mal wieder die Fortschrittsverhinderer. Richtig ruhmvoll ist natürlich auch das Abschneiden von Opera und Safari nicht, aber der recht gute Polyfill (bzw. die verschiedenen Polyfills) lindert den Schmerz doch erheblich. Dramatischer erscheint mir das Fehlen an richtig guten Tools für Indexed DB – die Browser mit nativer Unterstützung sowie interessierte JavaScript-Nerds mit Datenbank-Wissen sollten an dieser Front dringend nachrüsten. Ich hätte gern sowas wie Mongoose für Indexed DB.
Alles in allem lässt sich sagen, dass Indexed Database nach HTML5-Maßstäben eine bereits relativ runde Sache ist. Die Spezifikationen sind recht stabil und die Funktionen in allen Browserfamilien zum funktionieren zu bekommen. Allein in Sachen Tools und Libraries fehlt es noch, aber das sollte ein im Laufe der Zeit lösbares Problem sein.
Ein und Link eine Warnung
Da diese beiden Artikel hier nur einen sehr sehr grober Überblick geben konnten, möchte ich gern noch auf die wie immer erstklassige MDN-Dokumentation zum Thema hinweisen, die aktuell und auch sehr vollständig ist. Und zum Abschluss noch eine Warnung: ähnlich wie die Implementierung im Android-Browser gibt es auch Artikel zu Indexed DB, die auf einer heute veralteten Fassung der Spezifikationen basieren. Diese Artikel kann man daran erkennen, dass in ihnen eine setVersion()-Funktion besprochen wird, die es in der aktuellen Fassung nicht mehr gibt. Wenn ihr also in einem Artikel zu Indexed DB über setVersion() stolpert, lest lieber anderswo weiter.