Internet Explorer reagiert nicht auf AJAX generierte Links
kawinga
- javascript
0 Robert Kabinger1 molily1 molily0 Frank Weber0 molily
Guten Tag!
Ich weiss nicht so recht in welches Unterforum das gehört, vl ja auch zu Barrierefreiheit.
Ich bin mit HTML, JavaScript, PHP und Ajax doch schon etwas vertraut, aber jetzt bin ich mit meinem Latein am Ende und deshalb macht mich dieses Problem leicht fertig.
Ich möchte (aus welchem Grund auch immer) eine XML-Datei einlesen und als HTML-Menü ausgeben
XML-Datei-Auszug:
<navi> <!-- WurzelElement -->
<link id="1" name="home" />
<box id="2" name="news">
<box id="2_1" name="2008">
<link id="2_1_1" name="fruehling" />
<link id="2_1_2" name="sommer" />
<link id="2_1_3" name="herbst" />
<link id="2_1_4" name="winter" />
</box>
<link id="2_2" name="2007" />
<link id="2_3" name="2006" />
</box>
...
Es gibt also <link> und <box>, in einem <box> können weitere <link>s und <box>s sein.
* id identifiziert das Element und ist gleichzeitig auch die URL.
* name ist einfach ein Bezeichner.
Beim body-onload wird folgende JavaScript-Funktion aufgerufen:
function navi_build(xmlDocument, target)
{
var nodeName = xmlDocument.nodeName;
if (nodeName == "navi")
{
for (var i = 0; i < xmlDocument.childNodes.length; i++)
{
if (xmlDocument.childNodes[i] != null)
navi_build(xmlDocument.childNodes[i], target);
}
}
else if (nodeName == "link" || nodeName == "box")
{
var id = xmlDocument.getAttribute("id");
var name = xmlDocument.getAttribute("name");
var link = document.createElement("div");
... es folgen diverse Deklarationen, Namen sind sprechend
var box = null;
var box_class = document.createAttribute("class");
var box_id = document.createAttribute("id");
if (nodeName == "box")
{
link_class.nodeValue = "switcher";
link_id.nodeValue = "switcher_" + id;
a_href.nodeValue = "#" + id;
a_onclick.nodeValue = "navi_click("" + id + "")";
img_src.nodeValue = "layout/switcher_0.gif";
img_alt.nodeValue = " + ";
img_id.nodeValue = "img_" + id;
box = document.createElement("div");
box_class.nodeValue = "box_invisible";
box_id.nodeValue = "box_" + id;
for (var i = 0; i < xmlDocument.childNodes.length; i++)
{
if (xmlDocument.childNodes[i] != null)
navi_build(xmlDocument.childNodes[i], box);
}
}
else if (nodeName == "link")
{
link_class.nodeValue = "link";
link_id.nodeValue = "link_" + id;
a_href.nodeValue = "#" + id;
a_onclick.nodeValue = "navi_click('" + id + "')";
img_src.nodeValue = "layout/link_0.gif";
img_alt.nodeValue = " o ";
img_id.nodeValue = "img_" + id;
}
link.setAttributeNode(link_class);
link.setAttributeNode(link_id);
a.setAttributeNode(a_href);
a.setAttributeNode(a_onclick);
img.setAttributeNode(img_src);
img.setAttributeNode(img_alt);
img.setAttributeNode(img_id);
a.appendChild(img);
a.appendChild(a_text);
link.appendChild(a);
target.appendChild(link);
if (box)
{
box.setAttributeNode(box_class);
box.setAttributeNode(box_id);
target.appendChild(box);
}
}
}
Beim Click auf einen Menü-Eintrag werden folgende Funktionen ausgeführt:
function navi_click(id)
{
navi_clear(navi);
navi_mark(id);
}
function navi_clear(node)
{
for (var i = 0; i < node.childNodes.length; i++)
{
var nodeType = node.childNodes[i].getAttribute("class");
var node_class = document.createAttribute("class");
if (nodeType == "box")
{
navi_clear(node.childNodes[i]);
node_class.nodeValue = "box_invisible";
node.childNodes[i].setAttributeNode(node_class);
}
else if (nodeType == "link_mark" || nodeType == "switcher_mark")
{
var src = document.createAttribute("src");
var alt = document.createAttribute("alt");
if (nodeType == "link_mark")
{
node_class.nodeValue = "link";
src.nodeValue = "layout/link_0.gif";
alt.nodeValue = " o ";
}
else if (nodeType == "switcher_mark")
{
node_class.nodeValue = "switcher";
src.nodeValue = "layout/switcher_0.gif";
alt.nodeValue = " + ";
}
node.childNodes[i].firstChild.firstChild.setAttributeNode(src);
node.childNodes[i].firstChild.firstChild.setAttributeNode(alt);
node.childNodes[i].setAttributeNode(node_class);
}
}
}
function navi_mark(id)
{
if ((document.getElementById("box_" + id) && document.getElementById("switcher_" + id)) || document.getElementById("link_" + id))
{
var path = id.split("_");
id = 0;
for (var i = 0; i < path.length; i++)
{
if (id)
id = id + "_" + path[i];
else
id = path[i];
if (document.getElementById("box_" + id))
{
var node = document.getElementById("box_" + id);
var node_class = document.createAttribute("class");
node_class.nodeValue = "box";
node.setAttributeNode(node_class);
}
var node;
var node_class = document.createAttribute("class");
var src = document.createAttribute("src");
var alt = document.createAttribute("alt");
if (document.getElementById("switcher_" + id))
{
node = document.getElementById("switcher_" + id);
node_class.nodeValue = "switcher_mark";
src.nodeValue = "layout/switcher_1.gif";
alt.nodeValue = " - ";
}
else if (document.getElementById("link_" + id))
{
node = document.getElementById("link_" + id);
node_class.nodeValue = "link_mark";
src.nodeValue = "layout/link_1.gif";
alt.nodeValue = " x ";
}
node.setAttributeNode(node_class);
node.firstChild.firstChild.setAttributeNode(src);
node.firstChild.firstChild.setAttributeNode(alt);
}
}
}
Das wurde alles erfolgreich bei FF (ab v2), Opera (ab v9), Safari (ab v3) getestet.
Nur beim Internet Explorer will es einfach nicht funktionieren.
Das seltsame daran ist, wenn man den mit JavaScript generierten Code (DOM) kopiert, und in eine statische Datei einfügt funktioniert es.
Dass heisst, der Internet Explorer reagiert einfach nicht auf die generierten Links.
Der gesamte Sourcecode lässt sich hier bewundern: http://rapidshare.com/files/132292487/sch_selfhtml.zip.html
Weiss irgendjemand was ich falsch mache oder wie ich das richtig mache?
Mfg kawinga
Eigentlich wenn ich mir das so anschaue müsste es eigentlich schon reichen wenn ich einfach nur das poste:
<a onclick="navi_click('1')" href="#1">
<img id="img_1" alt=" x " src="layout/link_1.gif" />
<span>home</span>
</a>
Weis irgendjemand wieso der Internet-Explorer auf so etwas nicht reagiert wenn der Code mit JavaScript erstellt wurde?
Hallo,
ich habe mir das nur oberflächlich angeschaut, aber sehe schon einige Faux-pas, die sich auf die Browserkompatibilität negativ auswirken könnten. createAttribute/setAttributeNode solltest du auf jeden Fall vermeiden. Das ist umständlich, langsam und erfreut sich insbesondere bei Attributen wie class udn style schlechter Unterstützung. Du kannst einfach elementknoten.attribut = "wert" schreiben. Dadurch wird dein Code auch viel, viel kürzer und übersichtlicher.
Allerdings kannst du einige Attribute nicht auf diese Weise setzen. Dazu gehören JavaScript-Event-Handler. Du kannst nicht element.onclick = "navi_click('1')"; schreiben (gilt genauso für createAttribute/setAttributeNode), sondern musst der onclick-Eigenschaft eine JavaScript-Funktionsreferenz zuweisen. Als z.B. element.onclick = function () { navi_click('1') };
Mathias
Du kannst einfach elementknoten.attribut = "wert" schreiben.
Das class-Attribut kannst du übrigens über http://de.selfhtml.org/javascript/objekte/htmlelemente.htm#universaleigenschaften@title=className setzen (weil class ein reserviertes Wort ist, wäre element.class = ... nicht möglich, daher className).
Hallo Mathias,
createAttribute/setAttributeNode solltest du auf jeden Fall vermeiden.
Zu setAttribute hatte ich das hier schon öfter gelesen und deshalb setAttributeNode genommen. Aber das ist dann wohl auch nicht besser.
Du kannst einfach elementknoten.attribut = "wert" schreiben.
Das hatte ich auch schon probiert, nur kam im IE das Gleiche wie bei setAttributeNode raus und in Firefox funktionierte es dann überhaupt nicht mehr.
Allerdings kannst du einige Attribute nicht auf diese Weise setzen. Dazu gehören JavaScript-Event-Handler. Du kannst nicht element.onclick = "navi_click('1')"; schreiben (gilt genauso für createAttribute/setAttributeNode), sondern musst der onclick-Eigenschaft eine JavaScript-Funktionsreferenz zuweisen. Als z.B. element.onclick = function () { navi_click('1') };
Das ist nun in der Tat interessant. Und funktioniert anscheinend auch in allen Browsern. Nur gefallen tut's mir nicht - aber das ist mein Bier.
Die Frage ist nun, wieso funktioniert es über setAttributeNode und ohne Funktionsreferenz in Firefox, Opera und Safari. Weil sie nett sein wollen obwohl es nicht gehen müsste?
Und schlußendlich ist at nach
element.onclick = function () { navi_click('1') }
at = element.getAttribute("onsubmit")
in Firefox null. Ist es also gar kein reguläres Attribut?
at = element.onsubmit
funktioniert allerdings.
Über das Thema würde ich gerne mehr nachlesen, hast Du da einen Tip?
Gruß,
Frank
Hallo,
Die Frage ist nun, wieso funktioniert es über setAttributeNode und ohne Funktionsreferenz in Firefox, Opera und Safari. Weil sie nett sein wollen obwohl es nicht gehen müsste?
Ja, das kann man so sagen.
Es ist nirgendwo geregelt, dass ein Browser element.onevent = "string" akzeptieren muss. Das traditionelle Event-Handling weist ausschließlich Funktionsobjekte zu. Allerdings sollte setAttribute("onevent", "javascript-code") funktioniert. Das tut es im IE nicht, das ist einfach ein Fehler des IEs.
Und schlußendlich ist at nach
element.onclick = function () { navi_click('1') }
at = element.getAttribute("onsubmit")in Firefox null. Ist es also gar kein reguläres Attribut?
Nein, es ist eine Objekteigenschaft, man speichert einfach ein Funktionsobjekt als Eigenschaft des Elementobjektes.
Wie sich das zu getAttribute verhält, ist wie gesagt nirgends definiert, daher hat Firefox wohl eigenmächtig entschieden, in dem Fall null zurückzugeben.
Über das Thema würde ich gerne mehr nachlesen, hast Du da einen Tip?
Weiß ich leider nicht - worauf du da gestoßen bist sind auch bloß Unterschiede aufgrund fehlender Standardisierung und aufgrund von bekannten Browserfehlern.
Faustregel ist, dass Event-Handler mit JavaScript immer nach dem Schema
element.onevent = funktionsreferenz;
gesetzt werden. Und dort kann man auch einen Funktionsausdruck definieren, also element.onevent = function (...) { ... };
(Es gibt natürlich noch fortgeschrittene Möglichkeit zum Registrieren von Event-Handlern.)
Mathias