Feature Detection, my ass!

Ein Tag wie jeder andere „im IE funktioniert die Anwendung nicht mehr, nichts lädt mehr“. Man ist es ja eigentlich gewohnt, zumal es sich hierbei ja um eine umfangreiche RIA in Ext JS handelt. Trotz laufender JSLint-Überwachung für Fehler wie trailing comma mogelt sich immer mal wieder ein Problem herein. Ungewöhnlich war diesmal allerdings, dass bei der weiteren Untersuchung auffiel, dass das Problem auf einem IE9 auftrat (Hut ab vor Microsoft, IE9 ist eigentlich sehr gut). Ein Gegencheck in der VM mit IE6 und IE8 zeigte das Verhalten nicht. Auch die Prüfung auf einem realen Windows 7-System mit IE9 war problemlos.

Nun ja, genauer gesagt, das Problem trat auf einem (Test-) Windows Server 2008 mit IE9 auf. Aha..?

Nach einem schnellen Aufschalten auf den Testserver und dem Aufruf der Debugging-Tools offenbarte, dass der IE9 an genau einer Stelle auf Nase flog: aAudio=“Audio“in window?new Audio(„“):{} Im Prinzip ein ganz normale Art und Weise, eine Feature Detection durchzuführen. Für diejenigen, die nicht in JavaScript firm sind: Die Variable aAudio wird, falls im Objekt window eine Eigenschaft Audio vorhanden ist, mit einer neuen Instanz eben dieser Audio-Klasse belegt, andernfalls mit einem leeren Objekt (hilfreich ist hierbei zu wissen, dass window der Standardscope ist).

Das heißt also, nur wenn der Browser die HTML5-API „Audio“ kann, wird auch eine Instanz davon erstellt. Weiter später wird im Script auf eine spezielle Eigenschaft/Methode dieser Variable geprüft: Damit lässt sich dann feststellen, ob HTMl5-Audio implementiert wird (hier: canPlay). Das gesamte Problem gilt natürlich auch analog für die HTML5-API des Tags video.

Eine Exception „Not implemented“, die nicht aus der Anwendung kam, nicht aus dem Framework und auch nicht aus dem Plugin, welches im Endeffekt diese Zeile beinhaltet, wurde geschmissen und stoppte die gesamte Anwendung bzw. das verursachende Script. Und genau diese Zeile war die Feature Detection für HTML5-Audio in einer Sammlung von Flash/Video/Audio-Funktionalitäten.

Lange Rede, kurzer Sinn: Der Internet Explorer 9 hat u.a. die HTML5-APIs für Audio und Video implementiert — eigentlich. Nicht jedoch auf einem Windows Server 2008, denn dort wird dafür ein optional zu installierendes Feature — so called Desktop Experience Feature — des Betriebssystems benötigt. Und damit das ganze auch richtig gegen die Wand fahren kann und muss, tut man (der Browser) erstmal so, als würde er HTML5-Audio anbieten können (API window.Audio gibt es!), schmeißt dann aber eine Exception, wenn man das Objekt tatsächlich nutzt.

Tatsächlich ist die einzige Lösung, dies mit einem billigen try-catch zu lösen. Eine Post-Recherche ergab, die Macher von Feature-Detection-Framework Modernizr haben das genauso gemacht.

Es hat sich in den Jahren nicht viel geändert: Sonderwürste für den IE stehen weiterhin an.

Hintergrund – oder: Die Sache selbst

Eine granulare Feature Detection ist heutzutage bei modernen Webanwendungen oder besser -frameworks quasi Pflicht. Hat man früher noch eine grobe Browser Detection (Browserhersteller und -version) vorgenommen, um daraus herzuleiten, ob Feature X unterstützt wird, so prüft man heute besser auf dieses Feature direkt. Erstens sind die Features unzählig mehr geworden, zum anderen benötigt das das „Wissen“, welcher Browser welches Feature kann. Außerdem ist es mit den modernen Workingdraft/Livingstandard-Trends quasi unmöglich geworden, Features zu bestimmten Browsern zuzuordnen. Chrome und Firefox aktualisieren sich mittlerweile  mehr oder weniger selbstständig; und überhaupt ist die Geschwindigkeit der Browserentwicklungen so schnell geworden, dass eine Browser-basierte Herleitung von Feature-Verfügbarkeiten schwierig wird. Ein ganz gutes Beispiel ist HTML5 — denn HTML5 ist als Standard weder komplett fertig, noch in einem/jedem Browser gleichwertig implementiert.

In der Regel läuft eine Feature-Detection wie folgt ab: Man prüft, ob die Voraussetzungen bspw. für einen Tag oder eine DOM-API-Funktion vorhanden ist und ermittelt gegebenenfalls noch weitere Ausprägungen.

Beispiele

  • navigator.geolocation ist nicht undefined, wenn der Browser die Geolocation-API kann.
  • document.createElement(‚canvas‘).getContext ist nicht undefined, wenn der Browser Canvas-Tags unterstützt und damit Canvas zeichnen kann.
  • document.createElement(‚audio‘).canPlay ist nicht undefined, wenn der Browser HTML5-Audio-Tags unterstützt und demnach HTML5-Audio abspielen kann.

Weitere Links