Oliver Hunger: wiedermal: warten auf geladenen (php) iframe (mit gutem grund!)

schönen tag!

in den beiden variationen meines skripts wird zwar wohl die php routine loadmenu.php aufgerufen, aber nicht jedesmal. ich nehme an, weil javascript schneller läuft als php das skript ausgeführen kann.

deshalb der versuch, auf den fertig geladenen inhalt des iframes zu warten (onload="loaded=true"). das artet jedoch stets in einer endlosschleife aus, weil loaded nicht auf true gesetzt wird. auch der versuch, durch das php-skript in den iframe ein javaskript zu schreiben, das irgendwelche tag-variablen setzt, hat nicht funktioniert.

any clues???

(wann führt denn javascript das onload skript aus? es scheint, als blockiere die while-schleife die ausführung eines anderen skripts ...

ps: es geht mir nicht darum, in den iframes irgendetwas anzuzeigen, sondern darum, das .php skript aufzurufen, weil dort serverseitig etwas erledigt werden soll, was in zusammenhang mit der seite steht. der iframe soll eigentlich invisible sein ... auch die versuche innerHTML oder innerText des iframes auf eine Änderung (die das php skript erledigen kann) zu überprüfen, haben nicht funktioniert.

---

variante 1:

<IFRAME id="frm" src="init.php" onload="loaded=true;"></IFRAME>
...
for (var i=0; ...)
   {
   loaded=false;
   getRef('frm').src='loadmenu.php?nr='+i;
   while (! loaded)
      {
      }
   }

variante 2:

<DIV id="ifrm"><IFRAME id="frm" src="init.php" onload="top.loaded=true;"></IFRAME></DIV>
...
for (var i=0; ...)
   {
   top.loaded=false;
   getRef('ifrm').innerHTML='<iframe id="frm" src="loadmenu.php?nr='+i+'" onload="top.loaded=true;"></iframe>';
   while (! top.loaded)
      {
      }
   }

getRef(id) stellt browserabhängig die referenzierung eines elementes via id her (document.all, getelememtbyid, ...).

die skripte sind leicht abgeändert und aus dem zusammenhang gerissen, also bitte kein infragestellen der sinnhaftigkeit ...

---

danke für zahlreiche lösungen,

oliver!

[wer vieles hinterfragt bekommt oft neue antworten]

  1. Moin!

    <IFRAME id="frm" src="init.php" onload="loaded=true;"></IFRAME>

    onload gehört in den <BODY> der im Iframe zu ladenden Seite und kann von dort aus Aktionen starten. Es ist sogar besser, wenn deine Iframe-Seite die Javascript-Aktion komplett selbst erledigt, als wenn du mit einer while-Schleife wartest, bis die Seite geladen ist - weil Javascript nämlich ziemlich Performance frißt (zumindest Warten in einer Endlosschleife), ohne dass irgendwas produktives getan wird.

    Also statt <iframe onload="...">

    in der geladenen Seite
    <body onload="hier_die_aktion()">

    Du kannst dabei von der Tatsache Gebrauch machen, dass Javascript-Funktionen und -Variablen auch Frameübergreifend zur Verfügung stehen: Zum Beispiel onload="top.funktionsname()" im <body> benutzen, wenn die Aktionsfunktion im Topframe geladen ist. Es spricht allerdings auch nichts dagegen, sie in der jeweiligen Seite mit zu übertragen, wenn du eh' schon dynamisch bist.

    - Sven Rautenberg

    --
    Diese Signatur gilt nur am Freitag.
    1. hi sven,

      danke für deine antwort, ausprobiert, geht auch nicht. ausserdem dürfte ich nicht ganz klar rübergebracht haben, wo das problem liegt:

      es geht mir um das php-skript, nicht um das onload-skript, ich wollte dort bloss ein tag setzen, um eben auf das fertig ausgeführte php-skript zu warten! (wobei die frage ist, ob onload das überhaupt kann, das startet ja wohl eben schon beim laden, nicht erst nach dem fertigladen, fürchte ich)

      es soll v.a. das php skript in der schleife ausgeführt werden, und das bei jedem schleifendurchlauf. da das php-skript seine aufgaben aber offenbar nicht schnell genug erledigt, bevor es schon wieder - mit anderen parametern (hier einfach ?nr=i) - aufgerufen wird, müsste javascript bis zum fertigstellen warten können.

      hier nochmal:

      ---

      main.html:

      ...

      <IFRAME id="frm" src="loadmenu.php?nr=-1"></IFRAME>

      ...

      for (var i=0; ...)
         {
         loaded=false;
         getRef('frm').src='loadmenu.php?nr='+i;
         while (! loaded) // warten, bis loadmenu.php fertig ist
            {
            }
         }

      ...

      ---

      loadmenu.php:

      <?
      echo('<html><head</head><body onload="top.loaded=true">');

      $db=mysql_connect(...);
      mysql_select_db(..., $db);
      $res=mysql_query('INSERT INTO ... (nr) VALUES ("' . $_GET[nr] . '")');

      echo('loading</body></html>');
      ?>

      ---

      deinen letzten absatz hab ich leider nicht ganz verstanden, denke aber, er bezieht sich auf meine 2 versuche, entweder mit loaded oder mit top.loaded zu arbeiten.

      bitte um weitere hilfe,

      danke,

      oliver!

      1. Moin!

        danke für deine antwort, ausprobiert, geht auch nicht.

        Entsprich dein geposteter Code dem, was du geändert hast?

        ausserdem dürfte ich nicht ganz klar rübergebracht haben, wo das problem liegt:

        Das kann natürlich sein.

        es geht mir um das php-skript, nicht um das onload-skript, ich wollte dort bloss ein tag setzen, um eben auf das fertig ausgeführte php-skript zu warten! (wobei die frage ist, ob onload das überhaupt kann, das startet ja wohl eben schon beim laden, nicht erst nach dem fertigladen, fürchte ich)

        Mein erstes Posting gilt nach wie vor: Warte auf das Laden nicht mit einer while-Schleife! Lass den Browser feststellen, dass die Seite fertig geladen wurde - mit onload.

        BTW: Grundlagenwissen: onload feuert dann, wenn die Seite komplett inkl. aller enthaltenen Bilder, CSS, Javascripte etc. geladen wurde, nicht vorher! Ist also genau das, was du brauchst. Dir fehlt nur noch etwas Idee, um rauszufinden, wie du (ich würde es so nennen:) asynchron eine Schleife hochzählst.

        es soll v.a. das php skript in der schleife ausgeführt werden, und das bei jedem schleifendurchlauf. da das php-skript seine aufgaben aber offenbar nicht schnell genug erledigt, bevor es schon wieder - mit anderen parametern (hier einfach ?nr=i) - aufgerufen wird, müsste javascript bis zum fertigstellen warten können.

        Im Prinzip gehts dir doch nur darum, in die Datenbank Zahlen von Null bis zu einem Wert reinzuschreiben. Deshalb zuerst die Frage: Geht das nicht einfacher _nur_ mit PHP? Indem du (wenn der Wertebereich sich nur per Javascript ermitteln läßt) einfach _zwei_ Parameter mit Startwert und Zielwert an PHP übergibst und PHP mal eben schnell die Datenbank befüllt? Das spart dir nämlich superviel Ausführungszeit ein, weil folgende zeitaufwendige Dinge nur _einmal_ passieren müssen:

        • Anfordern einer Seite vom Server
        • Laden des PHP-Interpreters
        • Aufbau einer Verbindung zur Datenbank
        • Ausgabe der Ergebnisseite

        Stattdessen einfach start und ziel übergeben (wie du die Werte in die URL kriegst, dürfte klar sein:

        $db=mysql_connect(...);
        mysql_select_db(..., $db);
        // Statt in Javascript hier die Schleife in PHP:
        for ($i=$_GET['start'];$i<=$_GET['ziel'];$i++)
        {
          $res=mysql_query('INSERT INTO ... (nr) VALUES ("' . $i . '")');
        }

        Solltest du deinen Code so vereinfacht haben, dass du innerhalb von Javascript zunächt feststellst, ob überhaupt der Wert in die Datenbank eingetragen werden soll, dann ist es ebenfalls ratsam, diesen Vorgang zuerst in Javascript vollständig abzuschließen und die Ergebnisse dann auf _einmal_ in der URL verpackt an PHP zu schicken.

        - Sven Rautenberg

        --
        Diese Signatur gilt nur am Freitag.
        1. Entsprich dein geposteter Code dem, was du geändert hast?

          tat er

          Mein erstes Posting gilt nach wie vor: Warte auf das Laden nicht mit einer while-Schleife! Lass den Browser feststellen, dass die Seite fertig geladen wurde - mit onload.

          BTW: Grundlagenwissen: onload feuert dann, wenn die Seite komplett inkl. aller enthaltenen Bilder, CSS, Javascripte etc. geladen wurde, nicht vorher! Ist also genau das, was du brauchst. Dir fehlt nur noch etwas Idee, um rauszufinden, wie du (ich würde es so nennen:) asynchron eine Schleife hochzählst.

          danke, ja das mit onload war hilfreich.

          das warten allerdings geht nicht nur mit onload, zumindest wüsste ich nicht, wie. ich muss ja irgendwas im onload machen, damit es im eigentlichen ablauf wieder weitergehen kann.

          hab ich jetzt so gelöst, geht auch:

          ---

          var mi = 0;
          top.loaded = true;

          var chk = window.setInterval("mnInit()", 10);

          function mnInit()
           {
           if (top.loaded)
            {
            if (mi < mCtr)
             {
             top.loaded = false;
             getRef('frm').src='loadmenu.php?name='+lMenu[mi].name+'&nr='+lMenu[mi].nr+'&level='+lMenu[mi].level+'&i='+mi;
             mi ++;
             }
            else
             {
             window.clearInterval(chk);
             }
            }
           }

          ---

          statt des interval timers könnte ich natürlich eigentlich auch die funktion durch das onload wieder aufrufen lassen. ok, ich glaub, jetzt hab ichs, was du gemeint hast ;-)

          Im Prinzip gehts dir doch nur darum, in die Datenbank Zahlen von Null bis zu einem Wert reinzuschreiben.

          NEIN! das war nur vereinfacht, um nicht den ganzen code reinzuschreiben, wie üblich ;-) rest s.o., es ging darum, im HINTGERGRUND (also ohne ein neues fenster aufzumachen, oder das aktuelle neu zu laden) daten aus der seite (wie immer sie dahin kommen, z.b. aber auch durch usereingabe) in eine datenbank einzutragen.

          das geht jetzt auch endlich richtig,

          vielleicht gibt es aber eine elegantere lösung, serverskripte im hintergrund zu starten, als diese. (ich habs auch mit document.script[0].src=... versucht, aber das geht nicht (wie auch das beispiel in selfhtml http://127.0.0.1/SelfHTML/javascript/objekte/htmlelemente.htm#script dazu zumindest im ie6 nicht richtig funkt. da kommt bei mir beim ersten mal auf englisch klicken die deutsche variante)

          ausserdem bleibt eine frage offen: so wie in der ursprünglichen version hat doch wohl die while schleife ohne inhalt die aktualisierung des iframe und v.a. die ausführung der enthaltenen skripte blockiert. sehe ich das richtig? sonst hätte die schleife ja auch mal beendet werden müssen, wenn sich zwischenzeitlich die abbruchbedingung geändert hat.

          danke,

          oliver!

          1. Moin!

            das warten allerdings geht nicht nur mit onload, zumindest wüsste ich nicht, wie. ich muss ja irgendwas im onload machen, damit es im eigentlichen ablauf wieder weitergehen kann.

            [...]

            statt des interval timers könnte ich natürlich eigentlich auch die funktion durch das onload wieder aufrufen lassen. ok, ich glaub, jetzt hab ichs, was du gemeint hast ;-)

            Exakt. Und das geht sogar noch schöner, weil es wirklich nur dann etwas tut, wenn etwas anderes fertig geworden ist.

            NEIN! das war nur vereinfacht, um nicht den ganzen code reinzuschreiben, wie üblich ;-) rest s.o., es ging darum, im HINTGERGRUND (also ohne ein neues fenster aufzumachen, oder das aktuelle neu zu laden) daten aus der seite (wie immer sie dahin kommen, z.b. aber auch durch usereingabe) in eine datenbank einzutragen.

            Das "wie immer sie dahin kommen" ist aber durchaus sehr interessant für die Aufgabenstellung.

            Insofern möchte ich meine zweite Aussage "Mach soviele Daten wie geht in _eine_ URL rein" immer noch. Es spart dir Zeit in der Ausführung, hat eine höhere Performance, etc.

            vielleicht gibt es aber eine elegantere lösung, serverskripte im hintergrund zu starten, als diese. (ich habs auch mit document.script[0].src=... versucht, aber das geht nicht (wie auch das beispiel in selfhtml http://127.0.0.1/SelfHTML/javascript/objekte/htmlelemente.htm#script dazu zumindest im ie6 nicht richtig funkt. da kommt bei mir beim ersten mal auf englisch klicken die deutsche variante)

            Du kannst URL-Parameter an den Server schicken, indem du Bilder austauschst. Sollte im Prinzip simpel gehen, indem du wie gehabt die document.images[...].src austauschst. Das PHP-Skript schickt dann einfach ein Redirect auf ein existierendes (dafür vorgesehenes) Bild, und gut ist. Wahlweise kann es natürlich selbst Bilddaten ausgeben.

            ausserdem bleibt eine frage offen: so wie in der ursprünglichen version hat doch wohl die while schleife ohne inhalt die aktualisierung des iframe und v.a. die ausführung der enthaltenen skripte blockiert. sehe ich das richtig? sonst hätte die schleife ja auch mal beendet werden müssen, wenn sich zwischenzeitlich die abbruchbedingung geändert hat.

            Es sieht jedenfalls ganz stark so aus. Deshalb: Warteschleifen kann man dann mit while programmieren (bzw. einem Äquivalent dazu), wenn man die Prozessorpower nicht für was anderes braucht, weil man sich in einem Single-Task-System befindet. Moderne Rechner machen aber Multi-Tasking - da ist es einfach nur frech und böse[tm] gegenüber den restlichen Tasks, wenn man beim Warten ständig nachguckt, ob's schon soweit ist. Event-gesteuert (onload etc.) läßt sich das Ganze viel schöner machen. Erstens geht dir der Event nicht durch die Lappen, sondern wird garantiert abgearbeitet. Hättest du nämlich einen sehr schnellen Prozess, der deine Prüfvariable kurz auf wahr und dann wieder auf falsch setzt, und deine Prüfschleife hat in der Zwischenzeit keinen Zugriff gehabt, dann merkst du das Ereignis nicht. Und (was eben noch viel wichtiger ist): Wenn du über ein Event auf ein Ereignis wartest, verbrauchst du keine Rechenzeit für dieses Warten. Diese Rechenzeit steht anderen Tasks zur Verfügung.

            - Sven Rautenberg

            --
            Diese Signatur gilt nur am Freitag.