j4nk3y: js Funktion in XMLHttpRequest ausführen?

Hallo zusammen,

Hab da schon wieder ein Problem. Ich versuche gerade einen Teil des Inhaltes per:

var hr = new XMLHttpRequest();
var url = "../functions/php/a.php";
	
hr.onreadystatechange = function()
{
	if (hr.readyState == 4 && hr.status == 200)
	{
		var div = document.getElementById("main_content_wrapper");
		
		div.innerHTML = hr.responseText;
	}
}
	
hr.open("POST", url, true)
hr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
hr.send();

einzubinden.

Das Funktioniert auch ganz wunderbar.

Nun würde ich aber gerne eine Javascript Funktion (die in einer externen .js Datei liegt, welche auf der Hauptseite referenziert ist) in dem eingebundenen Content ausführen.

Etwa so (a.php):

<section id="content_wrapper">
<?php
foreach($array as $key => $value):
?>
	<article class="<?php echo '"'.$key.'wrapper"';?>>
		<p id="check"></p>
	</article>
	<script>
		wxyz(22222,check); // check ist die id des Elements für document.GetElementByID('')
	</script>
<?php
endforeach;
?>

Nun ist es ja so, wenn der Content aus a.php in der Seite eingebettet wird, die Funktion ja eben nicht mehr ausgeführt wird, wo eben das Problem liegt.

Kann ich das irgendwie umgehen? Hab gerade schon Versucht die externe .js in a.php zu referenzieren aber das klappt auch nicht.

Hätte da jmd eine Idee? Sonst müsste ich meinen kompletten Ansatz neu gestallten.

Danke euch!

Gruß
Jo

  1. Klar wird der JS-Teil der .php auf diese Weise nicht ausgeführt, da ja auch im Callback mittels

      div.innerHTML = hr.responseText;
    

    nur ein String in einen anderen kopiert wird, also keine Evaluation stattfindet. Das kann man zwar mit eval() erreichen, ist aber eine keinesfalls empfehlenswerte Methode (nur der Vollständigkeit halber erwähnt).

    Richtig und sauber wäre es, JS-Funktionen im Callback auszuführen.

    hr.onreadystatechange = function()
    {
    	if (hr.readyState == 4 && hr.status == 200)
    	{
    		var div = document.getElementById("main_content_wrapper");
    		
    		div.innerHTML = hr.responseText;
                    wxyz(22222,check);
    	}
    }
    

    Nun kann es natürlich sein, dass der wxyz()-Aufruf Parameter aus der .php benötigt. Dies würde ich vermutlich so lösen, dass ich aus der .php nicht reinen Textcontent empfange, sondern irgendeine Art JSON, aus der ich Teile in das div.innerHTML kopiere und andere Teile in die wxyz() stecke. Dies hat auch Vorteile für zusätzliche Erweiterungen, die im Laufe der Zeit auftreten können.

    Ganz davon abgesehen, warum verwendest Du hier überhaupt einen AJAX-Request? Tut's ein include() nicht?

    1. Hi,

      Klar wird der JS-Teil der .php auf diese Weise nicht ausgeführt, da ja auch im Callback mittels

        div.innerHTML = hr.responseText;
      

      nur ein String in einen anderen kopiert wird, also keine Evaluation stattfindet.

      Ja das hatte ich schon vorher vermutet, bzw eigentlich war es mir klar nur hatte ich die hoffnung das es nicht so ist und wenn eine "einfache" Lösung gibt.

      Ganz davon abgesehen, warum verwendest Du hier überhaupt einen AJAX-Request? Tut's ein include() nicht?

      Schon, nur wollte ich, wenn die function wxyz() ein bestimmtes Ergebnis liefert, wieder den Request neu senden um ohne neu laden zu müssen etwas dynamisch zu sein. Zudem würde sich der Code auf jederseite wiederholen aber egal. Anders als per include() wird es nicht macahbar sein.

      Gruß
      Jo

      1. Klar wird der JS-Teil der .php auf diese Weise nicht ausgeführt, da ja auch im Callback mittels

          div.innerHTML = hr.responseText;
        

        nur ein String in einen anderen kopiert wird, also keine Evaluation stattfindet.

        Eval ist zwar des Teufels, aber hier kann es eine Lösung sein:

        Sender:

        <?php
        $data['innerHtml']='Das ist <b>fett</b>!';
        $data['script']='alert("Ist das nicht fett?");';
        echo json_encode($data);
        ?>
        

        Webseite:

        <!doctype html>
        <html>
        <body>
        <h1>Test</h1>
        <div id="foo">Das ist dünn.</div>
        <script>
        function worker() {
            var data;
            var objekt=document.getElementById('foo');
            var xmlHttp = new XMLHttpRequest();
            if (xmlHttp) {
                xmlHttp.open('GET', 'test_0001.php', true);
                xmlHttp.onreadystatechange = function () {
                    if (xmlHttp.readyState == 4) {
                        data=JSON.parse(xmlHttp.responseText);
                        objekt.innerHTML=data['innerHtml'];
                        eval(data['script']);
                    }
                };
                xmlHttp.send(null);
            }
        }
        worker();
        </script>
        </body>
        </html>
        
        1. Hallo

          Eval ist zwar des Teufels, aber hier kann es eine Lösung sein:

          dabei muss man aber berücksichtigen, das dann das Script im Scope von onreadystatechange läuft.

          Gruß
          Jürgen

          1. dabei muss man aber berücksichtigen, das dann das Script im Scope von onreadystatechange läuft.

            Das kann man ja nach Aufgabe auf verschiedene Weisen umgehen. Womöglich einfach so:

            <?php
            $data['innerHtml']='Das ist <b>fett</b>!';
            $data['script']='document.getElementById("myButton").onclick=function () { alert("Ist das nicht fett?"); };';
            echo json_encode($data);
            ?>
            

            und

            <! doctype html>
            <html>
            <body>
            <h1>Test</h1>
            <div id="foo">Das ist dünn.</div>
            <button id="myButton">KlickMich!</button>
            <script>
            function worker() {
                var data;
                var objekt=document.getElementById('foo');
                var xmlHttp = new XMLHttpRequest();
                if (xmlHttp) {
                    xmlHttp.open('GET', 'test_0001.php', true);
                    xmlHttp.onreadystatechange = function () {
                        if (xmlHttp.readyState == 4) {
                            data=JSON.parse(xmlHttp.responseText);
                            objekt.innerHTML=data['innerHtml'];
                            eval(data['script']);
                        }
                    };
                    xmlHttp.send(null);
                }
            }
            worker();
            </script>
            </body>
            </html>
            

            Ich weiß ja zudem nicht, was für "Funktionen" da übertragen werden sollen. Vielleicht reicht es ja aus, Dokument-globale Variablen neu zu setzen, die dann von einer Funktion genutzt werden.

            1. Hallo

              … Dokument-globale Variablen …

              genau die können Probleme machen, da sie zu lokalen Variablen in onreadystatechange werden.

              Gruß
              Jürgen

              1. Hallo

                … Dokument-globale Variablen …

                genau die können Probleme machen, da sie zu lokalen Variablen in onreadystatechange werden.

                Wenn man es nicht anders|besser kann schreibt man das Zeug halt (versteckt) ins Dokument...

      2. Schon, nur wollte ich, wenn die function wxyz() ein bestimmtes Ergebnis liefert, wieder den Request neu senden um ohne neu laden zu müssen etwas dynamisch zu sein. Zudem würde sich der Code auf jederseite wiederholen aber egal. Anders als per include() wird es nicht macahbar sein.

        Doch, bestimmt. Das schaffst Du schon! Warum nicht im Callback den nächsten Request auslösen?

        hr.onreadystatechange = function()
        {
        	if (hr.readyState == 4 && hr.status == 200)
        	{
        		var div = document.getElementById("main_content_wrapper");
        		
        		div.innerHTML = hr.responseText;
                        if(wxyz(22222,check) == "bestimmter_output") DoNewRequest();
        	}
        }
        

        Alternativ kannst Du das auch von der php schon steuern.

        <?php
        $data['innerHtml']='Das ist der Html-Teil!';
        $data['start_ajax_request']='1';
        echo json_encode($data);
        ?> 
        
        hr.onreadystatechange = function()
        {
        	if (hr.readyState == 4 && hr.status == 200)
        	{
        		var div = document.getElementById("main_content_wrapper");
        		
                        data = JSON.parse(hr.responseText);
        		div.innerHTML = data["innerHtml"];
                        if(data["start_ajax_request"]) DoNewRequest();
        
        	}
        }
        

        Kannst Du was zum Hintergrund der Anwendung sagen? Was macht die wxyz? Warum muss sie klientseitig was checken?

        Cheers,
        BaBa

        --
        BaBa kommt von Basketball
        1. Hi,

          Kannst Du was zum Hintergrund der Anwendung sagen? Was macht die wxyz? Warum muss sie klientseitig was checken?

          Bisher ist das nur eine countdown funktion, vllt kommt später noch etwas mehr dazu, dass weiß ich aber noch nicht. Sprich, die Funktion bekommt aus der differenz des Zeitstempels welcher in einer Datenbank steht und der jetzigen Zeit eine Anzahl Sekunden und den Container in dem, diese das Ergebnis anzeigen soll. Ich hatte mir eigentlich Vorgestellt, dass wenn einer dieser countdowns irgendwann auf null fällt, der request erneut gesendet wird. Wär nur ein nettes feature gewesen... nichts was ich unbedingt hätte umsetzen müssen.

          Danke trotzdem!

          Gruß
          Jo

  2. Hallo zusammen,

    Ich habe es jetzt verworfen und mache es einfcher mit include, sonst wird es zu kompliziert.

    aber ich hätte eine andere frage:

    if (hr.readyState == 4 && hr.status == 200)
    

    Kann ich während eine .php datei durchläuft den readyState-wert oder den status-wert beeinflußen?

    Gruß
    Jo

    1. Kann ich während eine .php datei durchläuft den readyState-wert oder den status-wert beeinflußen?

      1. Während "php durchläuft" kann readyState aus naheliegenden Gründen nicht true werden.
      2. Den Status, der vom Webserver gesendet werden soll, kannst Du in PHP mit header() setzen. Beispiele:
      • header("status: 200"); oder header("HTTP/1.0 200 OK");
      • header("status: 204"); oder header("HTTP/1.0 204 No Responce");
      • header("status: 404"); oder header("HTTP/1.0 404 Not Found");
      • header("status: 500"); oder header("HTTP/1.0 500 Server Error");
      1. Hi,

        1. Während "php durchläuft" kann readyState aus naheliegenden Gründen nicht true werden.

        Naja ich wollte ihn auch nicht TREU werden lassen ich würd nur gern eine rückmeldung haben wie weit die Berechnung ist, um dementsprechend eine ausgabe an den Client zu geben.

        1. Den Status, der vom Webserver gesendet werden soll, kannst Du in PHP mit header() setzen. Beispiele:
        • header("status: 200"); oder header("HTTP/1.0 200 OK");
        • header("status: 204"); oder header("HTTP/1.0 204 No Responce");
        • header("status: 404"); oder header("HTTP/1.0 404 Not Found");
        • header("status: 500"); oder header("HTTP/1.0 500 Server Error");

        Hm, glaub nicht, dass das ist was ich suche. Dann lässt sich das anscheinend nicht so realisieren wie ich mir das gerade laienhaft denke. Egal, Danke Trotzdem!

        Gruß
        Jo

        1. ich würd nur gern eine rückmeldung haben wie weit die Berechnung ist, um dementsprechend eine ausgabe an den Client zu geben.

          Wissen kombinieren und anwenden.

          Daten von Skript 1 in Session schreiben und mit zweiten Skript (und weiteren Requests periodisch lesen

          Lass Dir aber einen guten Name für das Item einfallen.