IT-Academy Logo
Sign Up Login Help
Home - Programmieren - JavaScript - Javascript: Scriptausführung Browser-abhängig machen



Javascript: Scriptausführung Browser-abhängig machen

Javascript bietet zwar tolle Möglichkeiten, jedoch bleibt dabei die Kompatibilität zu verschiedenen Browsern dabei auf der Strecke. Die meisten Techniken um die Scripte Browser-abhängig zu machen sind lang, unübersichtlich und nur sehr mühsam zu erweitern. Dieser Artikel möchte eine Alternative zeigen.


Autor: Patrick Faes (dreamer)
Datum: 12-01-2005, 16:04:09
Referenzen: siehe Text
Schwierigkeit: Fortgeschrittene
Ansichten: 22086x
Rating: 8 (1x bewertet)

Hinweis:

Für den hier dargestellte Inhalt ist nicht der Betreiber der Plattform, sondern der jeweilige Autor verantwortlich.
Falls Sie Missbrauch vermuten, bitten wir Sie, uns unter missbrauch@it-academy.cc zu kontaktieren.

[Druckansicht] [Als E-Mail senden] [Kommentar verfassen]



Einführung

Es ist nicht leicht Javascripte zu erstellen die in alle gängigen Browsern funktionieren. Meistens erreicht man dies mit Abfragen wie "document.all?" Wenn der Browser true (wahr) meldet, geht es meistens um dem Internet Explorer von Microsoft. Wenn man jedoch für jede Funktion solch eine Abfrage für mehrere Browser machen muss, wird der Code schnell recht groß. Das hat zu folge dass der Code länger zum Downloaden braucht, unübersichtlich ist und wenn man es nachher ändern muss, braucht sehr viel Zeit.

Deshalb möchte ich hier eine Methode zeigen wo die Abfrage nur einmal gemacht wird und der Code danach automatisch ausgefüllt wird. Dazu brauchen wir folgende Techniken:
  • (assoziative) Arrays: Container die mehrere Variabele Werte speichern können (mehr dazu)
  • das navigator-Objekt: enthält Daten des Browsers (mehr dazu)
  • einige Methoden des string-Objektes (mehr dazu)
  • die Funktion eval(): die Funktion setzt Text um in ausführbarem Code (mehr dazu)
  • bedingte Anweisungen (mehr dazu)
In diesem Artikel werde ich das Script demonstrieren mit der Unterscheiden zwischen die verschienen DOM's, oder Dokument Objekt Modelle (mehr dazu). Die Modelle dienen dazu Elemente (oder Objekte) in einer Seite an zu sprechen. Der ältere Syntax von Microsoft Internet Explorer verwendet document.all(), während ältere Versionen von Mozilla/Netscape document.layers() verwenden. Der jetzige Standard ist document.getElementById().

Natürlich unterscheiden diese sich auch noch in andere Objekteigenschaften, wie z.B. das der Abstand zum oberen Fensterrand, wobei das scrollen beachtet wird (pageYOffset in Mozilla/Netscape, scrollTop in Internet Explorer). Eine Auflistung aller möglichen Eigenschaften würde aber zu lange sein. Als Nachschlagewerk empfehle ich de.SelfHTML.org.

Die Praxis

Anfangs müssen wir heraus finden welchen Browser der Besucher verwendet. In der Welt gibt es eine schier unendliche Zahl an Browsern, deshalb kann eine Liste nie volständig sein. In diesem Beispiel wird auf folgende Browser getestet:
  1. Microsoft Internet Explorer
  2. Mozilla Firefox
  3. Opera Browser
  4. Netscape Navigator
Lassen wir uns erst mal ansehen woran Browser erkennbar sind (und wir speichern den boolischen Wert gleich in eine Variable - Booleans ergeben wahr oder falsch):
var a = document.all;               //ältere Versionen von Internet Explorer
var b = document.layers;            //ältere Versionen von Netscape Navigator
var c = document.getElementById;    //jetziger Standard
Danach können wir in eine bedingte Anweisung das Script auswerten lassen um welchen Browser es sich (warscheinlich) handelt:
if ( (a) && !(c) ) {}     //Internet Explorer bis Version 4
else if ( (a) && (c) )    //Internet Explorer ab Version 6
else if ( (b) && !(c) )   //Netscape Navigator bis Version 4
else if ( !(b) && (c) )   //Netscape Navigator ab Version 6
Als kleine Erklärung:
  1. ältere Versionen von Internet Explorer verwenden nur das alte DOM
  2. neuere Versionen von Internet Explorer verwenden das alte als das neue DOM
  3. ältere Versionen von Netscape Navigator/Mozilla Firefox erkennen nur das alte DOM
  4. neuere Versionen von Netscape Navigator/Mozilla Firefox erkennen nur das neue DOM
Leider ist dies jedoch unzureichend um heraus zu finden um welchen Browser es sich genau handelt. So z.B. versteht Opera auch das ältere DOM vom Internet Explorer, jedoch kann ich nicht garantieren dass diese im Übrigen dieselbe Javascript-Fähigkeiten besitzen.

Etwas genauer können wir den Browser erkennen mit dem Objekt navigator. Ein Beispiel:
var d = navigator.appName == 'Microsoft Internet Explorer';
Hier wird getestet ob der Name der Anwendung (Ihren Browser) gleich Microsoft Internet Explorer ist und speichert dann einen boolischen Wert in die Variable d.

Aber leider ist auch dies unzureichend, da Mozilla Firefox sich anmeldet als Netscape, und auch Opera tendiert dazu sich an zu melden als Internet Explorer (unter Opera kann man sogar selbst wählen wie sich der Browser nennt).

Es gäbe da noch navigator.appCodeName, allerdings meldet sich Internet Explorer da an als Mozilla, und auch navigator.appVersion hilft uns nicht weiter.

Eine letzte Möglichkeit ist da navigator.userAgent. Dies speichert eine komplette Zeichenkette mit Daten. Darin stehen jetzt aber sehr viele Daten. Für die vier Browser die ich in diesem Test verwende, sehen die Resultate so aus:

Microsoft Internet Explorer: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)
Mozilla Firefox:Mozilla/5.0 (Windows; U; Windows NT 5.1; nl-NL; rv:1.7.5) Gecko/20041202 Firefox/1.0
Opera:Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) Opera 7.54 [de]
Netscape Navigator:Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.2) Gecko/20040804 Netscape/7.2 (ax)

Wie Sie sehen bekommen wir eine ganze Fülle an Daten. Jedoch brauchen wir nur ein ganz kleiner Teil davon. Wie Sie sehen nennen sich alle Browser hier Mozilla (warum das so ist, ist mir schleierhaft).
Jedoch steht am Ende jeweils der richtige Name, nämlich Opera, Firefox oder Netscape (Internet Explorer hat dies nicht). Dies können wir also auslesen mit der Funktion search(), welche mit einem regulärem Ausdruck suchen kann (reguläre Ausdrücke sind Muster die eine Suchabfrage beschreiben).

Der Code könnte dann so aussehen:
var d = navigator.userAgent.search(/Firefox/);
var e = navigator.userAgent.search(/Opera/);
var f = navigator.userAgent.search(/Netscape/);
Wir können das also testen, aber nicht in Internet Explorer. Dafür muss eine andere Lösung her, z.B. mit der Funktion exec(). Die könnte dann so aussehen:
var ff = /Firefox/;
var op = /Opera/;
var ns = /Netscape/;
if ( !(ff.exec(navigator.userAgent)) && !(op.exec(navigator.userAgent))
   && !(ns.exec(navigator.userAgent)) ) {var g = true;} else {var g = false;}
Jetzt stellt sich natürlich die Frage, wie wir das alles zusammen fügen. Da es etwas schwieriger ist die richtige Versionsnummer aus zu lesen, kombinieren wir die beiden Methoden die oben besprochen wurden und speichern dann ein Name in der Variable Browser (wie ich zu diese Namen kommen sehen wir weiter unten). Das sieht dann so aus:
Browser = '';
var a = document.all;
var b = document.layers;
var c = document.getElementById;
var d = navigator.userAgent.search(/Firefox/);
var e = navigator.userAgent.search(/Opera/);
var f = navigator.userAgent.search(/Netscape/);

if ( (a) && (c) && !(e) ) {Browser = 'IE_ab_5';}
else if ( (a) && !(c) && !(e) ) {Browser = 'IE_bis_4';}
else if (d) {Browser = 'FF';}
else if (b) {Browser = 'NS_bis_4';}
else if ( !(b) && (c) ) {Browser = 'NS_ab_6';}
else if (e) {Browser = 'OP';}
Hier geschieht eine Reihe an Abfragen. Wenn eine davon wahr ist, dann werden die folgenden nicht mal mehr getestet. Die Variable bekommt einen Wert, abhängig davon welchen Browser erkannt wird. Hier sind das (in dieser Reihenfolge):
  1. wenn document.all und document.getElementById erkannt werden, und der Name nicht Opera ist, ist es Internet Explorer ab der Version 5 (IE_ab_5)
  2. wenn document.all erkannt wird, document.getElementById aber nicht und der Name ist nicht Opera, ist es Internet Explorer bis der Version 4 (IE_bis_4)
  3. wenn der Name Firefox ist, ist es (das hätten Sie wohl nie geraten) Firefox (FF)
  4. wird document.layers erkannt, kann es nur um Netscape Navigator bis Version 4 sein (NS_bis_4)
  5. wenn document.layers erkannt wird und document.getElementById ebenso, handelt es sich um Netscape Navigator ab der Version 6 (NS_ab_6) - eine 5-er-Version gab es nie
  6. zum Schluss, wenn der Name Opera ist, handelt es sich natürlich um Opera (OP)
Hier stellt sich natürlich die Frage was man machen soll wenn der Browser mit keinen der aufgelisteten übereinstimmt. Es gibt da zwei Möglichkeiten: entweder man stellt eine Alternative auf die auf alle anderen Browsern zugreift (und riskiert dabei solche hässlichen Fehlermeldungen) oder man geht auf Nummer sicher und verhindert einfach die weitere Ausführung des Scriptes.

Wenn Sie sich für's erstere entscheiden, komplementieren Sie den Code wie folgt:
else {Browser = 'alternativ';}
ansonsten
else {Browser = false;}
Da wir jetzt (endlich) durch die Browsererkennung durch sind, müssen wir jetzt sehen wie das Script anhängig vom Browser weiter ausgeführt wird. Dabei können wir die altmodische Methode nehmen, dann währe die ganze Arbeit aber umsonst.
//altmodische Methode, sollte man nicht verwenden

if (FF) {}  //Firefox-spezifischer Code
Die neue Methode, wie ich sie hier zeigen möchte, ist weitaus flexibeler. Im obigen Code müsste man für jede einzelne Zeile der spezifische Code manuel einfügen. Für kleine Scripte haut das hin, bei Scripte die aber 50 oder mehr Zeilen lang würde das zu hirnrissige Probleme führen.

Die neue Methode besteht darin dass die verschiedene Codes in einem Array gespeichert werden und im Rest des Scriptes (an Hand des Browsers) automatisch ausgefüllt werden.

Dabei fangen (was hätten Sie wohl erwartet?) an mit die Arrays zu füllen (da es sehr viel ist, beschränke ich mich hier ein bisschen).
JS = new Array();

JS["IE_ab_5"] = new Array();
JS["IE_ab_5"]["modell"] = 'getElementById';
JS["IE_ab_5"]["abstand_oben_mit_scroll"] = 'scrollTop';

JS["NS_ab_6"] = new Array();
JS["NS_ab_6"]["modell"] = 'getElementById';
JS["NS_ab_6"]["abstand_oben_mit_scroll"] = 'pageYOffset';
Dann muss das alles nur noch in eine Funktion ausgeführt werden können. In der Funktion wird auch abgefragt ob die Variable Browser nicht einfach false ist, denn dann müsste der Code überhaupt nicht weiter ausgeführt werden und kann stattdessen eine Alternative ausgeführt werden. Wenn Sie sich dazu entscheiden dennoch einfach ein Standardcode als Alternative nehmen möchten, brauchen Sie dies nicht weiter.
function etwas()
  {
  if (Browser)
    {

    }
  else
    {

    }
  }
Aber sehen wie uns jetzt mal an wie der Code ausgeführt werden kann. Man kann die Eigenschaften die man verwenden möchten immer über den Array-Index ansprechen. Jedoch können Sie diesen nicht einfach so im Code einbauen. Ein schlechtes Beispiel:
document.JS["IE"]["Modell"]('Tabelle').style.height
Die Variable kann ich so einfach im Code 'hineingeklebt' werden. Was man schon tun kann, ist die Variable in eine andere Variable vom Typ String (Zeichenkette) einbauen und diese mit der Funktion eval() ausführen. eval() ist eine sehr mächtige Funktion. Sie wurde dazu konzipiert um Text in ausführbarem Code um zu setzen. Es kommt so z.B. sehr vor dass man als Webmaster noch nicht weiß was der Besucher machen wird. Dann kan man nachher, an Hand was der Besucher macht, den Code zusammen schneiden und ihn ausführen.

In diesem Fall würde dass so aussehen:
var text = 'document.' + JS["IE"]["Modell"] + '("Tabelle).style.height = 100';
eval(text);
zum Schluss

Jetzt haben wir das ganze abgearbeitet und ich hoffe es ist Ihnen jetzt klar wie in Javascript Script kompatibel zu verschiedenen Browsern gemacht werden können. Es ist ein sehr flexibeles Script, vor allem dann, wenn Sie ein neuer Browser hinzufügen möchten. Sie müssen dann nicht Ihre ganzen Scripte durchstöbern und alles ändern, nein Sie müssen dann nur noch eine einzige zentrale Datei erweitern.
Das Script wird hier unten nochmal ganz gezeigt, allerdings in zwei geteilt. Der obere Teil mit dem Deklarationen können Sie auslagern und dann von jeder Seite aus einzeln aufrufen (oder per PHP includieren). Dann untere Script ist ein Beispiel für eine einzelne Seite.
<script src="browser.js" type="text/javascript" language="javascript"></script>

Browser = '';
var a = document.all;
var b = document.layers;
var c = document.getElementById;
var d = navigator.userAgent.search(/Firefox/);
var e = navigator.userAgent.search(/Opera/);
var f = navigator.userAgent.search(/Netscape/);

if ( (a) && (c) && !(e) ) {Browser = 'IE_ab_5';}
else if ( (a) && !(c) && !(e) ) {Browser = 'IE_bis_4';}
else if (d) {Browser = 'FF';}
else if (b) {Browser = 'NS_bis_4';}
else if ( !(b) && (c) ) {Browser = 'NS_ab_6';}
else if (e) {Browser = 'OP';}
else {Browser = 'alternative';}   //nur wenn man eine Alternative anbieten möchte
else {Browser = false;}           //wenn man jeglich Fehlermeldung verhindern möchte
                                  //dabei ist dann aber auch das Javascript abgeschaltet

JS = new Array();

JS["IE_ab_5"] = new Array();
JS["IE_ab_5"]["modell"] = 'getElementById';
JS["IE_ab_5"]["abstand_oben_mit_scroll"] = 'scrollTop';

JS["IE_bis_4"] = new Array();
JS["IE_bis_4"]["modell"] = 'all';
JS["IE_bis_4"]["abstand_oben_mit_scroll"] = 'scrollTop';

JS["NS_ab_6"] = new Array();
JS["NS_ab_6"]["modell"] = 'getElementById';
JS["NS_ab_6"]["abstand_oben_mit_scroll"] = 'pageYOffset';

JS["NS_bis_4"] = new Array();
JS["NS_bis_4"]["modell"] = 'layers';
JS["NS_bis_4"]["abstand_oben_mit_scroll"] = 'pageYOffset';

JS["FF"] = new Array();
JS["FF"]["modell"] = 'getElementById';
JS["FF"]["abstand_oben_mit_scroll"] = 'pageYOffset';

JS["OP"] = new Array();
JS["OP"]["modell"] = 'getElementById';
JS["OP"]["abstand_oben_mit_scroll"] = 'scrollTop';

JS["alternativ"] = new Array(); //nur wenn man diese Alternative anbieten möchte
JS["alternativ"]["modell"] = 'getElementById';
JS["alternativ"]["abstand_oben_mit_scroll"] = 'pageYOffset';

function etwas()
  {
  if (Browser)  //Abfrage nur notwendig wenn man eine Alternative anbietet
    {

    }
  else         //nur wenn man die Methode von false verfolgt
    {

    }
  }
<script type="text/javascript" language="javascript">


[back to top]



Userdaten
User nicht eingeloggt

Gesamtranking
Werbung
Datenbankstand
Autoren:04508
Artikel:00815
Glossar:04116
News:13565
Userbeiträge:16552
Queueeinträge:06246
News Umfrage
Ihre Anforderungen an ein Online-Zeiterfassungs-Produkt?
Mobile Nutzung möglich (Ipone, Android)
Externe API Schnittstelle/Plugins dritter
Zeiterfassung meiner Mitarbeiter
Exportieren in CSV/XLS
Siehe Kommentar



[Results] | [Archiv] Votes: 1154
Comments: 0