DOM Funktionalitaet fehlerhaft?

  • Hallo,

    mein Problem scheint am ehesten in dieses Forum zu passen:

    Ich entwickle eine chrome Anwendung fuer XULRunner 1.8.0.1. In dieser Anwendung lade ich mittels XMLHttpRequest eine "entfernte" xul Datei von einem Webserver. Sodann versuche ich, die in einem iframe enthaltene aktuelle Seite durch die soeben geladene Seite mittels DOM Funktionen zu ersetzen. Dabei stosse ich auf gravierende Probleme. Die mittlerweise tagelange Recherche auf dem Internet hat kein Ergebnis gebracht. Daher hier mein Problem (in aller Ausfuehrlichkeit), denn ausser ueber ein Forum sehe ich kein Weiterkommen mehr. (Das Problem tritt in derselben Weise auf, wenn ich die Anwendung mit firefox 1.5.0.1 starte)

    Und noch eine Anmerkung vorneweg; Ich >muss< XMLHttpRequest zum Laden von Seiten verwenden. Die Gruende dafuer kann ich gerne nachliefern.

    Problem:

    Meine Applikation oeffnet das triviale Fenster

    Sodann lade ich die Seite

    Code
    http://localhost:8080/GASWEB/login.jsf

    via XMLHttpRequest. Diese Seite sieht folgendermassen aus (in jsp, wobei das jsp-Gedoehns natuerlich nicht so vom Webserver geliefert wird... Wichtig ist alles innerhalb von <page>):

    Die Anwort von XMLHttpRequest steckt in retParams.responseXML und retParams.responseText. response ist der Handler von XMLHttpRequest, welcher asynchron aufgerufen wird (onload event). Sodann ersetze ich die alte Seite im iframe auf folgende Weise durch die neue Seite:

    Soweit sollte alles schulbuchmaessig sein. Die geladene Seite wird auch korrekt, inklusive Style, angezeigt. Ich habe auch den DOM Baum ueberprueft, alles wie zu erwarten korrekt.

    Das Problem haengt am JavaScript des importierten Dokuments, vgl.

    Code
    oncommand

    in der geladenen Seite. Wenn ich die im folgenden beschriebenen Interaktionen mit dem GUI ausfuehre, werden in den Faellen A-C je >zwei< Alertfenster nacheinander angezeigt , im Fall D sogar >drei<. Erwartet wird jedoch nur je ein Alertfenster!!! Das zweite bzw. dritte Fenster wird dabei immer erst angezeigt, wenn ich im vorhergehenden den OK Button gedrueckt habe.

    Hier die Fenster mit Titel und Text:

    [A] Klicke den Button "XXConnect" mit dem Ergebnis:

    Title: "http://localhost:8080"
    Text: "button XXConnect b1"

    Title: "[JavaScript Application]"
    Text: "button XXEdit b2"

    [B] Klicke den Button "XXEdit" mit dem Ergebnis:

    Title: "http://localhost:8080"
    Text: "button XXEdit b2"

    Title: "[JavaScript Application]"
    Text: "button XXEdit b2"

    [C] Fuege 'a' im Textfeld ein und druecke <enter> mit dem Ergebnis:

    Title: "http://localhost:8080"
    Text: "textbox"

    Title: "[JavaScript Application]"
    Text: "textbox"

    [D] Druecke <tab> so dass der Button "XXConnect" den Fokus hat und druecke <enter> mit dem Ergebnis:

    Title: "[JavaScript Application]"
    Text: "textbox"

    Title: "http://localhost:8080"
    Text: "button XXConnect b1"

    Title: "[JavaScript Application]"
    Text: "button XXEdit b2"

    Seltsam, oder? Erwartet wird in jedem Fall immer nur das Alertfenster mit dem Titel "http://localhost:8080".

    Zum Beweis habe ich die entfernte Seite einmal anders geladen, also nicht mit XMLHttpRequest, sondern mit

    Code
    var iframe = window.document.getElementById('topFrame');
    iframe.webNavigation.loadURI("http://localhost:8080/GASWEB/login.jsf", iframe.webNavigation.LOAD_FLAGS_NONE, null, null, null);

    Das Ergebnis ist:

    [A] Klicke den Button "XXConnect" mit dem Ergebnis:

    Title: "http://localhost:8080"
    Text: "button XXConnect b1"

    [B] Klicke den Button "XXEdit" mit dem Ergebnis:

    Title: "http://localhost:8080"
    Text: "button XXEdit b2"

    [C] Fuege 'a' im Textfeld ein und druecke <enter> mit dem Ergebnis:

    Title: "http://localhost:8080"
    Text: "textbox"

    [D] Druecke <tab> so dass der Button "XXConnect" den Fokus hat und druecke <enter> mit dem Ergebnis:

    Title: "http://localhost:8080"
    Text: "button XXConnect b1"

    Wie schon gesagt, ich habe absolut keine Idee, was hier falsch lauft, insbesondere, ob es mein Fehler ist, oder ein Bug.

    Ich hoffe, ueber das Forum Hilfe zu erhalten und bedanke mich im voraus dafuer,

    viele Gruesse

    Andreas.

  • Nicht wirklich. Aber zunaechst einmal vielen Dank fuer den Tipp!

    Das Problem ist, dass die geplante Anwendung "AJAX Funktionalitaet" bekommen soll. Fuer den Fall, dass sie eine neue Seite bekommt, kann sie diese wie von Dir beschrieben darstellen. Wenn sie aber nur ein Delta bekommt, muss sie den DOM Baum manipulieren. Ich fuerchte, dass mich das Problem dabei wieder einholen wird. (Vielleicht aber auch nicht, so weit blicke ich im Moment noch nicht.)

    Dein Tipp ist aber noch aus einem ganz anderen Grund wertvoll, was wahrscheinlich schon bekannt ist (ich habe es jedenfalls gerade gemessen):

    Das unmittelbare Laden mit loadURI (also loadURI("http://...)) ist schneller, als die Seite mit XMLHttpRequest zu laden und mit importNode einzuhaengen. Letzteres dauert ca. 35% laenger. Dein Tipp (laden mit XMLHttpRequest und darstellen mit loadURI("data:...) benoetigt etwa soviel Zeit wie das unmittelbare laden mit loadURI, ist also in jedem Falle vorzuziehen. Man wuerde also definitiv nur bei Delta Antworten am DOM Baum herumschrauben.

  • Nun, mein Verstaendnis der Theorie reicht nicht aus, um das Problem zu verstehen und zu loesen. Aber ich glaube nicht, dass ich noch etwas serialisieren oder deserialisieren muss. XMLHttpRequest liefert mir das neue Dokument serialisiert in responseText und als Node von Type Document (DOM Baum) in responseXML. Beides sieht auch gut aus. Deshalb funktioniert auch die Anzeige.

    Das Problem muss in der Funktion importNode liegen -- oder allgemeiner beim Importieren. Es reicht nicht, das alte Dokument im iframe (iframe.contentDocument.documentElement) durch das neue DOM (responseXML.documentElement) zu ersetzen. Die neuen Elemente werden dann zwar korrekt angezeigt und die alten verschwinden. Es fehlen aber die Style Sheets und JavaScript.

    Damit die Style Sheets wirken, muss ich die Kindknoten von responseXML, welche von Typ proccessing instruction sind, mit importNode in iframe.contentDocument importieren und anschliessend mit appendChild hinzufuegen. Das gleiche muss fuer die Dokumentwurzel (responseXML.documentElement) gemacht werden. So verstehe ich jedenfalls die DOM level 2 core Spezifikation zur Methode Document.importNode. Ich stelle auch fest, dass das JavaScript der neu geladenen Seite nur wirkt, wenn ich importNode verwende.

    Soweit die Theorie. Die Praxis funktioniert aber offensichtlich bei mir nicht -- entgegen meinem Verstaendniss der Spezifikation und aller sonst bisher gelesenen Dokumentation. Also

    (1) Mache ich noch etwas fasch? Wenn ja, was? Oder:

    (2) Gibt es einen Fehler in der Implementierung von xulrunner/firefox? Es scheint so zu sein, dass das JavaScript der neuen Seite durch importNode korrekt in iframe.contentDocument importiert wird. Darueber hinaus scheint ein Teil des JavaScript in top.window.document eingefuegt zu werden (Dies erzeugt die "falschen" Alertfenster mit dem Titel [Application JavaScript]). Wenn nun ein "command" ausgefuehrt wird, so laeuft der event durch das ganze Gebilde, also durch top.window und durch iframe.contentWindow. Dann wird einmal das korrekte JavaScript im iframe ausgefuehrt, und dann das in top.window.document zu viel (und falsch) eingefuegte JavaScript.

    Was mir dabei aufgefallen ist: Ich kann eine beliebige Anzahl von buttons in der neuen Seite einfuegen, ich bekomme bei einem Klick auf einen Button immer genau zwei Alertfenster: das korrekte, zu dem Button gehoerende, und das falsche, immer zum letzten Button in der Seite gehoerende.

    Bei Textelementen scheint es aehnlich zu sein, ich bekomme nur fuer das zuletzt eingefuegte ein falsches Alertfenster. (Dies habe ich aber nicht durch Experiment verifiziert.)

    Ferner: Wenn ich importNode nicht verwende, bleiben die korrekten Alertfenster aus. Die falschen bekomme ich aber trotzdem. D.h. das JavaScript scheint -- wenn mein Verdacht korrekt ist -- auch ohne importNode in top.window.document eingefuegt zu werden.


    Viel Text, vielleicht kann jemand was aus diesen Beobachtungen machen...

    Andreas