source4u: Übergeordnete DIV-Id aus Inline-Frame

Ich habe das gleiche Problem, wie es schonmal jemand in diesem Forum hatte, leider bekam der keine Antwort mit der ich etwas anfangen hätte können.
(siehe http://forum.de.selfhtml.org/archiv/2001/5/t24133/ )

Es handelt sich um folgenden Fall:

<div id="content5" ...>
  <iframe id="iexplorer6" src="...>

in "src-Seite"
    >>on click: " Spucke id des übergeordneten divs aus!"<<

</iframe>
</div>

Klar ist, dass das mit dem DOM lösbar ist, ich komme da jedoch nicht weiter: alert(this.parentNode.tagName) beispielsweise bleibt im Inline-Frame (also man kommt nicht heraus).
Wenn ich parent. ... verwende, weiß er ja nicht mehr welches Inline-Frame gemeint war und welche DIV-ID er zurückgeben soll.

Kann mir da jemand bitte weiterhelfen?

Viele Grüße

  1. Moin!

    Klar ist, dass das mit dem DOM lösbar ist, ich komme da jedoch nicht weiter

    Nein, mit dem DOM ist das eben NICHT lösbar. DOM steht ja für "DOCUMENT Object Model", du hast hier aber nicht ein DOCUMENT, sondern ZWEI. In zwei Window-Objekten.

    Es ist daher höchstwahrscheinlich eine extrem schlaue, weil problemabschaffende Idee, auf das IFrame zu verzichten und dessen Inhalt serverseitig in das äußere Dokument zu integrieren.

    Zumal du sowieso nur was reißen _könntest_, wenn beide Dokumente von der gleichen Domain kommen - ansonsten verhindert es die Same-Origin-Policy von Javascript.

    - Sven Rautenberg

    --
    "Love your nation - respect the others."
    1. Moin!

      Klar ist, dass das mit dem DOM lösbar ist, ich komme da jedoch nicht weiter

      Nein, mit dem DOM ist das eben NICHT lösbar. DOM steht ja für "DOCUMENT Object Model", du hast hier aber nicht ein DOCUMENT, sondern ZWEI. In zwei Window-Objekten.

      Es ist daher höchstwahrscheinlich eine extrem schlaue, weil problemabschaffende Idee, auf das IFrame zu verzichten und dessen Inhalt serverseitig in das äußere Dokument zu integrieren.

      Zumal du sowieso nur was reißen _könntest_, wenn beide Dokumente von der gleichen Domain kommen - ansonsten verhindert es die Same-Origin-Policy von Javascript.

      • Sven Rautenberg

      Hallo,

      das ganze auf "richtiges" Ajax umzustellen (um auf die Iframe-Lösung zu verzichten) wäre sowas von kompliziert, dass quasi jede Javascript-Lösung wohl einfacher wäre (solange Arbeitsaufwand unter 100 Stunden).
      Das Problem ist, dass das ganze lediglich nachgerüstet werden soll.

      Die Dokumente würden übrigens auf jeden Fall von der gleichen Domain kommen - also wie _könnte_ ich etwas reißen? ;-)

      Vielen Dank für die rasche Antwort!

      1. Hallo,

        • Sven Rautenberg

        Hallo,

        bitte zitiere sinnvoll. http://de.wikipedia.org/wiki/TOFU@link=TOFU ist hier unerwünscht, weil es das Lesen und Nachvollziehen des Dialogs erschwert, und außerdem das Archiv unnötig aufbläht.

        das ganze auf "richtiges" Ajax umzustellen (um auf die Iframe-Lösung zu verzichten) wäre sowas von kompliziert, ...

        Nur dass wir uns richtig verstehen: AJAX *ist* in erster Linie eine Javascript-Lösung. Und sie ist definitiv nicht das, was Sven dir empfehlen wollte, sondern:

        auf das IFrame zu verzichten und dessen Inhalt serverseitig in das äußere Dokument zu integrieren.

        Also wäre SSI hier eine vielversprechende Technik; eventuell auch PHP und readfile(), wenn dir PHP zur Verfügung steht.

        So long,
         Martin

        --
        Man sollte immer wissen was man sagt
         - aber auf keinen Fall alles sagen, was man weiß.
        1. Ich kenne mich mit dem Zitieren leider nicht so aus, sollte ich mal einen freien Abend habe, werde ich mich da fortbilden, bis dahin halte ich mich zurück, sorry.

          Wenn ich auf das IFrame und auf Ajax verzichte und das ganze serverseitig mache, wird jedesmal das ganze Dokument neu geladen und das würde bei hunderten Bildern (es handelt sich um ein 3D-Spiel) ewig dauern.

          Mir würde auch eine einfache Antwort genügen: Es geht nicht!
          Ich frage mich halt echt, ob es möglich ist, oder ob es schlichtweg nicht geht.

          [Ich bin gerne immer für Alternativen bereit, jedoch gibt es hier keine, das IFrame wird einfach benötigt.]

          1. Hallo,

            Wenn ich auf das IFrame und auf Ajax verzichte und das ganze serverseitig mache, wird jedesmal das ganze Dokument neu geladen ...

            richtig, und das ist gut so. Denn dann kann man auch jede Seite einzeln anhand ihrer eindeutigen URL aufrufen, was man bei (i)frame-Lösungen meistens nicht kann.

            und das würde bei hunderten Bildern (es handelt sich um ein 3D-Spiel) ewig dauern.

            nein, denn diese Bilder (Stylesheets, Javascripts etc.) befinden sich beim wiederholten Aufruf ja schon im Browser-Cache und müssen deshalb nicht neu geladen werden. Es fällt tatsächlich nur der Zeitbedarf für die Übertragung der neuen HTML-Ressource an, und der dürfte gering sein. Ähnlich gering wie das Neuladen einer HTML-Ressource in einem iframe.
            Es ist gängige Praxis, die Seiten *komplett* neu zu laden.

            [Ich bin gerne immer für Alternativen bereit, jedoch gibt es hier keine, das IFrame wird einfach benötigt.]

            Nein. Wenn du es benutzen möchtest, tu das - auch wenn die Lösung dadurch vielleicht etwas komplizierter wird. Aber sei bitte auch offen für andere Lösungsansätze, wenn du das schon behauptest.

            Ciao,
             Martin

            --
            Alleine sind wir stark...
            gemeinsam sind wir unausstehlich!
        2. Hallo nochmal,

          da überspringt man einmal die Vorschau, und schon geht's daneben.
          So war's gedacht:

          bitte zitiere sinnvoll. TOFU ist hier unerwünscht, ...

          Ciao,
           Martin

          --
          Moskito, ergo summ.
    2. Hallo Sven,

      Klar ist, dass das mit dem DOM lösbar ist, ich komme da jedoch nicht weiter

      Nein, mit dem DOM ist das eben NICHT lösbar. DOM steht ja für "DOCUMENT Object Model", du hast hier aber nicht ein DOCUMENT, sondern ZWEI. In zwei Window-Objekten.

      Naja, es ist nicht mit DOM _alleine_ Lösbar, aber das DOM-Konzept sieht explizit multiple Dokumentobjekte, die gleichzeitig vorgehalten werden, vor - warum gäbe es denn sonst importNode, ownerDocument & co?

      Es ist daher höchstwahrscheinlich eine extrem schlaue, weil problemabschaffende Idee, auf das IFrame zu verzichten und dessen Inhalt serverseitig in das äußere Dokument zu integrieren.

      Wie Du auf die Aussage kommst, ist mir irgendwie schleierhaft, denn meine Lösung ist zwar nicht trivial, aber doch ziemlich "straight-forward"... Und sie dürfte einfacher (und damit zeitsparender) sein, als das gesamte Konzept umzustellen.

      Viele Grüße,
      Christian

  2. Hallo source4u,

    Klar ist, dass das mit dem DOM lösbar ist, ich komme da jedoch nicht weiter: alert(this.parentNode.tagName) beispielsweise bleibt im Inline-Frame (also man kommt nicht heraus).

    Wenn ich parent. ... verwende, weiß er ja nicht mehr welches Inline-Frame gemeint war und welche DIV-ID er zurückgeben soll.

    Wie wäre es denn dann stattdessen, wenn du erst einmal mit "parent" auf das Elternfenster zugreifst, dort dann die FRAMES-Collection in einer For-Schleife durchläufst und schaust, ob self.location.href dem im jeweiligen IFRAME-Element referenzierten SRC-Attribut entspricht. Hast du es gefunden, kannst du mit parentNode weiterarbeiten.

    Gruß Gernot

    1. Hallo source4u,

      Klar ist, dass das mit dem DOM lösbar ist, ich komme da jedoch nicht weiter: alert(this.parentNode.tagName) beispielsweise bleibt im Inline-Frame (also man kommt nicht heraus).

      Wenn ich parent. ... verwende, weiß er ja nicht mehr welches Inline-Frame gemeint war und welche DIV-ID er zurückgeben soll.

      Wie wäre es denn dann stattdessen, wenn du erst einmal mit "parent" auf das Elternfenster zugreifst, dort dann die FRAMES-Collection in einer For-Schleife durchläufst und schaust, ob self.location.href dem im jeweiligen IFRAME-Element referenzierten SRC-Attribut entspricht. Hast du es gefunden, kannst du mit parentNode weiterarbeiten.

      Gruß Gernot

      Das Problem ist, dass es sein kann, dass mehrere Fenster die gleiche URL offen haben... Somit kann es sein, dass die ID von einem anderen Div zurückgegeben werden kann..

      Danke für's Bemühen :-)

      1. Hallo source4u,

        Danke für's Bemühen :-)

        Es war wahrscheinlich auch keine so gute Idee, denn du könntest ja durch einen Klick auf einen Link im Iframe dessen location mittlerweile abweichend von dessen ursprünglicher Source geändert haben.

        Aber über das eindeutige Name-Attribut des Iframe-Fensters müsste sich der Frame ja ansprechen lassen.

        Gruß Gernot

  3. Hallo,

    <div id="content5" ...>
      <iframe id="iexplorer6" src="...>

    in "src-Seite"
        >>on click: " Spucke id des übergeordneten divs aus!"<<

    </iframe>
    </div>

    Die Lösung ist etwas komplizierter, ich habe hier mal ein Beispiel geschrieben, das sowohl im Firefox, Opera und Konqueror funktioniert (IE habe ich gerade keinen da, müsste dort aber auch funktionieren).

    Äußere Seite:

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">  
    <html>  
    <head>  
    <meta http-equiv="Content-Type" content="text/html; charset="ISO-8859-1">  
    <title>Äußere Seite</title>  
    </head>  
    <body>  
    <div id="content5">  
      <iframe id="iexplorer6" src="beispiel-innen-1.html" width="500" height="500">  
      </iframe>  
    </div>  
    </body>  
    </html>
    

    Innere Seite:

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">  
    <html>  
    <head>  
    <meta http-equiv="Content-Type" content="text/html; charset="ISO-8859-1">  
    <title>Äußere Seite</title>  
    <script type="text/javascript">  
    [code lang=javascript]function zeigeIdAn (object) {  
     // ok, das ist doof, wir sind gar nicht in einem frame geladne  
     if (parent == self) {  
      object.innerHTML = "Nicht in einem Frame geladen.";  
     }  
     var iframes = parent.document.getElementsByTagName ("iframe");  
     for (var i = 0; i < iframes.length; i++) {  
      if (iframes[i].contentDocument == document) {  
       object.innerHTML = "ID des divs: " + iframes[i].parentNode.id;  
       return;  
      }  
     }  
     object.innerHTML = "ID konnte nicht ermittelt werden!";  
    }
    

    </script>
    </head>
    <body>
    <p onclick="zeigeIdAn (this);">Hier wird die ID angezeigt - bitte clicken.</p>
    </body>
    </html>[/code]

    Der Trick ist folgender: Ich kann (wenn die Same Origin Policy mir das nicht verbietet) auf das Elternfenster zugreifen. Dann weiß ich aber nicht, welches DOM-Element das zugehörige IFrame ist. Also gehe ich alle IFrames auf der Seite durch und suche das IFrame, dessen contentDocument (damit könnte ich vom Elternframe auf das Kindframe zugreifen) gleich meinem eigenen document ist - und dann habe ich das entsprechende IFrame gefunden und kann mich dann von dort mittels parentNode & Co im DOM-Baum der Elternseite hochhangeln.

    Ist jetzt nur ein Schnellschuss - Browserkompatibilität muss natürlich noch überprüft werden, aber an sich müsstest Du mit diesem Ansatz zum Ziel kommen.

    Viele Grüße,
    Christian

    1. Hallo nochmal,

      Achja, kleiner Nachtrag: das geht durchaus auch, wenn das gleiche (!) Dokument in unterschiedlichen IFrames geladen ist, zumindest in den von mir getesteten Browsern:

      http://www.christian-seiler.de/temp/selfforum/t151745/beispiel-aussen-2.html

      Viele Grüße,
      Christian

    2. Hallo,

      vielen Dank! Habe deine Lösung sofort eingebaut und sie funktioniert einwandfrei in Firefox und Co - aber nicht im Internet Explorer (weder 7 noch 6)..

      Dieser Teil trifft einfach nie zu:
      if (iframes[i].contentDocument == document) {

      Eine Idee, wie das lösbar ist?

      Viele Grüße und nochmals vielen Dank - find ich toll, wenn sich jemand die Arbeit macht!

      1. Hallo,

        nicht im Internet Explorer (weder 7 noch 6)..

        if (iframes[i].contentDocument == document) {

        IE kann kein .contentDocument, dafür kennt er .document und .contentWindow.document. Mit letzterem sollte man alle Browser erreichen:

        http://forum.de.selfhtml.org/archiv/2006/8/t134560/#m873073

        Mathias

      2. Hallo,

        Dieser Teil trifft einfach nie zu:
        if (iframes[i].contentDocument == document) {

        Eine Idee, wie das lösbar ist?

        Ok, ich hab etwas recherchiert und bin auf http://forum.de.selfhtml.org/archiv/2006/8/t134560/#m873073 gestoßen.

        Ich habe das ganze dann jetzt mal in eine praktische Funktion gepackt, die einem das DOM-Element oder null zurückgibt, falls das DOM-Element nicht ermittelbar ist. Zudem funktioniert die Funktion jetzt sowohl mit <iframe>, <object> und <frame> (in Framesets). Die sieht jetzt so aus:

        function parentFrameElement () {  
         function matches (iframe) {  
          return (iframe.contentWindow == self)  
           || (iframe.contentDocument == document)  
           || (iframe.document == document);  
         }  
          
         if (parent == self) {  
          return null;  
         }  
         var iframes = parent.document.getElementsByTagName ("iframe");  
         for (var i = 0; i < iframes.length; i++) {  
          if (matches (iframes[i])) {  
           return iframes[i];  
          }  
         }  
         var objects = parent.document.getElementsByTagName ("object");  
         for (var i = 0; i < objects.length; i++) {  
          if (matches (objects[i])) {  
           return objects[i];  
          }  
         }  
         var frames = parent.document.getElementsByTagName ("frame");  
         for (var i = 0; i < frames.length; i++) {  
          if (matches (frames[i])) {  
           return frames[i];  
          }  
         }  
         return null;  
        }
        

        Das *sollte* jetzt auch im Internet Explorer klappen. Wer das ganze mal ausprobieren will:

        2 <iframe>s und 1 <object>
        <frameset> mit <frame>s

        (Beim Frameset ist das Frameset allerdings beide Male das Elternelement von <frame>, deswegen zeigt mein Beispiel immer top-frameset an. Ich könnte es jetzt natürlich noch komplizierter machen, aber darauf habe ich keine Lust.)

        Viele Grüße,
        Christian

  4. Vielen vielen Dank!

    Das Problem wurde von Christian Seiler und molily letztendlich gelöst, deren Lösung einwandfrei in allen Browsern funktioniert.

    Die Lösung speziell für meine Frage ist:

      
    function getframeid () {  
     function matches (iframe) {  
      return (iframe.contentWindow == self)  
       || (iframe.contentDocument == document)  
       || (iframe.document == document);  
     }  
      
     if (parent == self) {  
      return null;  
     }  
     var iframes = parent.document.getElementsByTagName ("iframe");  
     for (var i = 0; i < iframes.length; i++) {  
      if (matches (iframes[i])) {  
       return iframes[i].parentNode.id;  
      }  
     }  
     return null;  
    }  
    
    

    Viele Grüße und einen schönen Samstag

    1. Hallo source4u,

      Ein einfaches:

        
        
      function getThisIframesParentElement () {  
         if(self != parent) {  
            var parentFrames = parent.document.getElementsByTagName('IFRAME');  
            for (i=0; i<parentFrames.length; i++) {  
               if(parentFrames[i].name == self.name)  
                  return parentFrames[i].parentNode.id;  
            }  
         }  
      }  
      
      

      ... sollte doch im Normalfall auch funktionieren, vorausgesetzt, man hat nicht vergessen, dem Parent-Element des Iframes eine ID und dem Iframe selbst einen einmaligen Fensternamen zu vergeben und dass dieser nicht "unterwegs" geändert wurde.

      Vielleicht sind das der Selbstverständlichkeiten doch zu viele, als dass man sie einfach voraussetzen könnte...

      ... man hat ja auch schon Pferde vor der Apotheke kotzen sehen.

      Gruß Gernot

      1. Hallo Gernot,

        Ein einfaches: [...] sollte doch im Normalfall auch funktionieren, vorausgesetzt, [...]

        Du schreibst ja selbst, dass die name-Lösung bestimmte Voraussetzungen braucht. Die andere Lösung funktioniert dagegen ohne eine derartige Einschränkung - und der einzige wirkliche Unterschied ist:

        name-Lösung:
        if (bla.name == self.name)

        Andere Lösung:
        if ((bla.contentWindow == self) || (bla.contentDocument == document) || (bla.document == document))

        Insofern kann ich nicht ganz nachvollziehen, warum Du die name-Lösung vorziehen willst - die andere Lösung funktioniert immer (außer wenn JS aus ist oder so), standardkompatibel (sprich: zukunftssicher) und sie hat im Endeffekt nur eine *leicht* kompliziertere if-Abfrage, ansonsten sind beide Ansätze identisch.

        Viele Grüße,
        Christian

        1. Hallo Christian,

          um der Pferde vor der Apotheke willen gebe ich dir Recht. Also geben wir ihnen ein "contentDocument". Man will die ja nicht wiklich kotzen sehen.

          ;-)

          Gruß Gernot