IE6: Vorgang abgebrochen
In den letzten Wochen ist uns immer wieder ein kniffeliges Problem mit dem InternetExplorer 6 begegnet. Scheinbar ohne dass etwas geändert wurde, sind einige Seiten im IE6 nicht mehr aufrufbar. Dieser bricht einfach mit der folgenden Meldung ab:
"Die Internetseite http... kann nicht geöffnet werden.
Vorgang abgebrochen"
Nach unserer Recherche war klar, dass das Problem immer auf Seiten mit GoogleMaps und/oder dem swfobject, also immer im Zusammenhang mit JavaScript, auftritt. Und offensichtlich hat Google an ihrer Maps-Version zwischendurch irgendwas geändert, so dass es gestern ging und heute nicht mehr. Weiter fällt auf, dass das Problem nicht auf allen Webseiten auftritt: Später stellt sich heraus, dass nur Seiten betroffen sind, die z.B. RealURL verwenden.
Die Lösungsvorschläge, die wir im Netz oder durch ausprobieren gefunden hatten, waren bspw. das Attrib defer="defer" in den script-Tags zu setzen oder das Maps-JavaScript als letzten Tag vor dem </body> zu setzen. Aber so richtig funktionieren bzw. nachvollziehen lies sich das Problem so nicht.
Der Blog-Beitrag von Ron Hall auf buzz.typo3.org gab mir heute Anlass mich der Thematik nochmal anzunehmen.
Letztlich hängt der Fehler mit folgenden zwei Problemen zusammen:
- der IE6 kann keine DOM-Manipulation per JavaScript ausführen, wenn das Script innerhalb eines Tags steht, dass noch nicht geschlossen wurde
- der IE6 versteht das /> im base-Tag nicht als schließendes Element
Gehen wir diesen beiden Punkten mal auf die Spur.
1. Der IE6 kann keine DOM-Manipulation per JavaScript ausführen
Folgender Code erzeugt ein DOM-Text-Node und fügt diesen dynamisch im body ein.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head><title></title></head>
<body>
<script>
var child = document.createTextNode("Ein neuer Text");
document.getElementsByTagName('body')[0].appendChild(child);
</script>
</body>
</html>
Steht das script nun aber nicht direkt im body, sondern innerhalb z.B. eines div funktioniert der Code nicht und die oben genannte Fehlermeldung wird angezeigt.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head><title></title></head>
<body>
<div>
<script>
var child = document.createTextNode("Ein neuer Text");
document.getElementsByTagName('body')[0].appendChild(child);
</script>
</div>
</body>
</html>
Damit haben wir also Problem 1 in einem Minimal-Beispiel nachgewiesen.
2. der IE6 versteht das /> im base-Tag nicht als schließendes Element
In XHTML ist es so, dass jedes Node geschlossen werden muss. Das kann man entweder durch ein explizites schließendes Tag machen, bspw.
<tag></tag>
oder bei "leeren" Elementen durch die Kurzform "/>", bspw.
<tag />
Das base-Tag, dass im head gesetzt wird um eine Adressbasis zu definieren (notwendig z.B. für RealURL!) wird aber augenscheinlich im IE6 falsch geparst. Denn benutzt man (wie z.B. SelfHTML es vorschlägt) die oben genannte Kurzform wird dieses Schließen vom IE6 einfach ignoriert. Das wiederum bedeutet, dass alle darauf folgenden Tags (z.B. script oder link) im DOM unterhalb des base angeordnet werden und nicht dahinter. Außerdem wird das base-Tag nie korrekt geschlossen.
Dazu wieder ein kleines Beispiel:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title></title>
<base href="http://foo.bar/" />
<link rel="stylesheet" type="text/css" href="style.css" />
</head>
<body>
<div>
<script>
var kind = document.getElementsByTagName('base')[0].firstChild;
if (kind) {
alert(kind.tagName);
} else {
alert('Kein Kind-Element');
}
</script>
</div>
</body>
</html>
Im Firefox gibt das alert() die Meldung 'Kein Kind-Element' aus, weil kind leer (also null) ist. Das ist auch korrekt, denn das base-Tag wird geschlossen, ist leer und hat somit keine Kind-Elemente.
Der IE6 findet aber als Kind des base-Tags ein Node mit dem tagName "LINK". Der IE6 hat das base also nicht korrekt geschlossen.
Schließen wir das base nun explizit:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title></title>
<base href="http://foo.bar/"></base>
<link rel="stylesheet" type="text/css" href="style.css" />
</head>
<body>
<div>
<script>
var kind = document.getElementsByTagName('base')[0].firstChild;
if (kind) {
alert(kind.tagName);
} else {
alert('Kein Kind-Element');
}
</script>
</div>
</body>
</html>
Jetzt verhält sich auch der IE6 richtig und das base-Tag hat keine Kind-Elemente mehr. Das Problem mit dem nicht schließenden body-tag wird auch hier bei mg.to nochmal näher erläutert.
Nach Lokalisieren dieser "Basis"-Probleme wird der Zusammenhang nun klar:
Der IE6 findet keinen Abschluss für das base, die nachfolgenden script-Tags werden zu Kind-Elementen des base und können so keine DOM-Manipulation durchführen.
Sowohl GoogleMaps also auch swfobject nutzen aber DOM-Manipulationen. Und da der GoogleMaps-Code direkt vom Google-Server eingebunden wird, kann sich dort ab und zu der Code bzw. die Version auch mal ändern. So tritt das Problem z.B. bei der GoogleMaps Version 2.118 nicht auf, wohl aber bei der 2.119. Eine Google-Mitarbeiterin empfiehlt entweder eine andere Maps-Version zu nutzen oder eben das base-Tag explizit zu schließen.
Wie löst man das ganze nun mit TYPO3
Wie Ron in seinem Beitrag schon schreibt, kann man das base-Tag in TYPO3 nicht direkt beeinflussen und so nicht explizit schließen. Ron schlägt daher vor, den base-tag selber an die möglichst oberste Position im head zu schreiben. Für unsere Kunden-Installation sieht das ganz im TypoScript dann in etwa so aus:
config {
baseURL = http ://foo.bar/
}
# Base-URL-Fix für IE6 Fehler "Vorgang abgebrochen"
[browser= msie6]
config.baseURL >
config.headerComment = --> <base href="http://foo.bar/"></base> <!--
config.xhtml_cleaning = 0
[GLOBAL]
Zunächst setzen wir die baseURL als Defaultwert. Handelt es sich aber um einen IE6, wird die config.baseURL geleert und das base-Tag selber in den head geschrieben. Das eventuell gesetzte xhtml_cleaning wird für den IE6 wieder deaktiviert, da dieses den Code invalide gemacht hätte.
Die Problematik mit der DOM-Manipulation und der Meldung "Vorgang abgebrochen" ist auch bei Microsoft dokumentiert.
Übrigens besteht das Problem tatsächlich nur im alten InternetExplorer 6. In der Version 7 und in allen anderen getesteten Browsern (Firefox2 und 3, Opera, Safari) trat das Problem nicht auf. Daher sei an dieser Stelle auf www.savethedevelopers.org hingewiesen.
Sie können eine Antwort hinterlassen oder einen trackback von Ihrer eigenen Seite setzen.


