Ich denke, um Ihre Frage unter diesem Formular richtig zu interpretieren: "OK, ich bin bereits mit all dem Ajax-Zeug fertig; ich möchte nur wissen, ob die JavaScript-Funktion, die mein Ajax-Rückruf in den DIV eingefügt hat, von diesem Moment an jederzeit aufrufbar ist , das heißt, ich möchte es nicht kontextuell zur Rückrufrückgabe aufrufen ".
OK, wenn Sie so etwas meinen, lautet die Antwort "Ja". Sie können Ihren neuen Code jederzeit während der Seitenpersistenz im Browser unter den folgenden Bedingungen aufrufen:
1) Ihr vom Ajax-Rückruf zurückgegebener JavaScript-Code muss syntaktisch in Ordnung sein.
2) Selbst wenn Ihre Funktionsdeklaration in einen <script>
Block innerhalb eines vorhandenen <div>
Elements eingefügt wird, weiß der Browser nicht, dass die neue Funktion vorhanden ist, da der Deklarationscode nie ausgeführt wurde. Sie müssen also eval()
Ihren Deklarationscode vom Ajax-Rückruf zurückgeben, um Ihre neue Funktion effektiv deklarieren zu können und sie während der gesamten Lebensdauer der Seite verfügbar zu haben.
Auch wenn dieser Code ziemlich dumm ist, erklärt er die Idee:
<html>
<body>
<div id="div1">
</div>
<div id="div2">
<input type="button" value="Go!" onclick="go()" />
</div>
<script type="text/javascript">
var newsc = '<script id="sc1" type="text/javascript">function go() { alert("GO!") }<\/script>';
var e = document.getElementById('div1');
e.innerHTML = newsc;
eval(document.getElementById('sc1').innerHTML);
</script>
</body>
</html>
Ich habe Ajax nicht verwendet, aber das Konzept ist das gleiche (auch wenn das Beispiel, das ich ausgewählt habe, sicher nicht sehr klug ist :-)
Im Allgemeinen stelle ich Ihr Lösungsdesign nicht in Frage, dh ob es mehr oder weniger angemessen ist, die Funktion in einer separaten .js-Datei und dergleichen zu externalisieren + zu verallgemeinern. Beachten Sie jedoch, dass eine solche Lösung weitere Probleme aufwerfen kann, insbesondere wenn Ihre Ajax-Aufrufe sollten wiederholt werden, dh wenn sich der Kontext derselben Funktion ändern sollte oder wenn die Persistenz der deklarierten Funktion betroffen sein sollte. Daher sollten Sie möglicherweise ernsthaft in Betracht ziehen, Ihr Design in eines der vorgeschlagenen Beispiele in diesem Thread zu ändern.
Wenn ich Ihre Frage falsch verstanden habe und Sie über den kontextbezogenen Aufruf der Funktion sprechen, wenn Ihr Ajax-Rückruf zurückkehrt, möchte ich den von krosenvold beschriebenen Prototyp-Ansatz vorschlagen , da er browserübergreifend, getestet und voll funktionsfähig ist. Dies kann Ihnen eine bessere Roadmap für zukünftige Implementierungen geben.
In der zurückgegebenen HTML / Ajax / JavaScript-Datei befindet sich ein JavaScript-Tag. Geben Sie ihm eine ID wie Runscript . Es ist ungewöhnlich, diesen Tags eine ID hinzuzufügen, diese muss jedoch speziell referenziert werden.
<script type="text/javascript" id="runscript"> alert("running from main"); </script>
Rufen Sie dann im Hauptfenster die Funktion eval auf, indem Sie nur diesen NEUEN Block JavaScript-Code auswerten (in diesem Fall Runscript ):
eval(document.getElementById("runscript").innerHTML);
Und es funktioniert zumindest in Internet Explorer 9 und Google Chrome.
quelle
<script id="my-secure-id">
Tag eingefügt wird . Ich sehe keine zusätzliche Sicherheit bei Verwendung dieser Lösung. In der Tat gibt es Ihnen nur das falsche Gefühl der Sicherheit, was noch gefährlicher ist. Aber ungefähr 6 Jahre später ist HTTPS jetzt sehr viel häufiger. Ich glaube, dass ein Angriff auf eval () über sicheres HTTPS nicht möglich sein sollte. Bin ich falsch anzunehmen?Es ist durchaus möglich, und es gibt sogar einige ziemlich legitime Anwendungsfälle dafür. Mit dem Prototype- Framework wird wie folgt vorgegangen.
new Ajax.Updater('items', '/items.url', { parameters: { evalJS: true} });
Siehe Dokumentation des Ajax-Updaters. Die Optionen befinden sich im allgemeinen Optionssatz . Wie üblich gibt es einige Einschränkungen, wo "dies" darauf hinweist. Lesen Sie daher das Kleingedruckte.
Der JavaScript-Code wird beim Laden ausgewertet. Wenn der Inhalt eine Funktion enthält, kann
myFunc(),
man das wirklich einfachmyFunc()
später sagen . Vielleicht wie folgt.if (window["myFunc"]) myFunc()
Dies prüft, ob die Funktion vorhanden ist. Vielleicht hat jemand eine bessere browserübergreifende Methode, um das zu tun, was in Internet Explorer 6 funktioniert.
quelle
Das scheint ein ziemlich seltsames Design für Ihren Code zu sein - es ist im Allgemeinen sinnvoller, Ihre Funktionen direkt aus einer .js-Datei aufrufen zu lassen und dann nur Daten mit dem Ajax-Aufruf abzurufen.
Ich glaube jedoch, dass es funktionieren sollte, indem eval () für die Antwort aufgerufen wird - vorausgesetzt, es handelt sich um syntaktisch korrekten JavaScript-Code.
quelle
Mit jQuery würde ich es mit getScript machen
quelle
Denken Sie daran, wenn Sie eine Funktion wie folgt durch Ajax erstellen ...
function foo() { console.log('foo'); }
... und führen Sie es über eval aus, Sie werden wahrscheinlich ein Kontextproblem bekommen. Nehmen Sie dies als Ihre Rückruffunktion:
function callback(result) { responseDiv = document.getElementById('responseDiv'); responseDiv.innerHTML = result; scripts = responseDiv.getElementsByTagName('script'); eval(scripts[0]); }
Sie deklarieren eine Funktion innerhalb einer Funktion, sodass auf diese neue Funktion nur in diesem Bereich zugegriffen werden kann.
Wenn Sie in diesem Szenario eine globale Funktion erstellen möchten, können Sie diese folgendermaßen deklarieren:
window.foo = function () { console.log('foo'); };
Aber ich denke auch, dass du das nicht tun solltest ...
Entschuldigung für jeden Fehler hier ...
quelle
Ich möchte hinzufügen, dass es in jQuery eine Auswertungsfunktion gibt, mit der Sie den Code global auswerten können, um alle Kontextprobleme zu beseitigen. Die Funktion heißt globalEval () und hat für meine Zwecke hervorragend funktioniert . Die Dokumentation finden Sie hier .
Dies ist der Beispielcode, der in der jQuery-API-Dokumentation bereitgestellt wird:
function test() { jQuery.globalEval("var newVar = true;") } test(); // newVar === true
Diese Funktion ist äußerst nützlich, wenn Sie externe Skripte dynamisch laden möchten, was Sie anscheinend versucht haben.
quelle
Eine Checkliste für so etwas:
func_name = function() {...}
Besser noch, verwenden Sie Frameworks, die wie in Prototype damit umgehen . Du hast
Ajax.updater
.quelle
PHP-Seitencode Name der Datei class.sendCode.php
<?php class sendCode{ function __construct($dateini,$datefin) { echo $this->printCode($dateini,$datefin); } function printCode($dateini,$datefin){ $code =" alert ('code Coming from AJAX {$this->dateini} and {$this->datefin}');"; //Insert all the code you want to execute, //only javascript or Jquery code , dont incluce <script> tags return $code ; } } new sendCode($_POST['dateini'],$_POST['datefin']);
Jetzt müssen Sie von Ihrer HTML-Seite aus die Ajax-Funktion auslösen, um die Daten zu senden.
.... <script src="http://code.jquery.com/jquery-1.9.1.js"></script> .... Date begin: <input type="text" id="startdate"><br> Date end : <input type="text" id="enddate"><br> <input type="button" value="validate'" onclick="triggerAjax()"/>
Jetzt definieren wir in unserer lokalen script.js den Ajax
function triggerAjax() { $.ajax({ type: "POST", url: 'class.sendCode.php', dataType: "HTML", data : { dateini : $('#startdate').val(), datefin : $('#enddate').val()}, success: function(data){ $.globalEval(data); // here is where the magic is made by executing the data that comes from // the php class. That is our javascript code to be executed } }); }
quelle
Das klingt nicht nach einer guten Idee.
Sie sollten die Funktion, die in den Rest Ihres JavaScript-Codes aufgenommen werden soll, aus den von Ajax-Methoden zurückgegebenen Daten abstrahieren.
Für das, was es wert ist (und ich verstehe nicht, warum Sie einen Skriptblock in ein div einfügen?), Sind auch Inline-Skriptmethoden, die in einen Skriptblock geschrieben wurden, verfügbar.
quelle
Dieser Code funktioniert auch, stattdessen wird das HTML ausgewertet, an das ich das Skript an den Kopf anhängen werde
function RunJS(objID) { //alert(http_request.responseText); var c=""; var ob = document.getElementById(objID).getElementsByTagName("script"); for (var i=0; i < ob.length - 1; i++) { if (ob[i + 1].text != null) c+=ob[i + 1].text; } var s = document.createElement("script"); s.type = "text/javascript"; s.text = c; document.getElementsByTagName("head")[0].appendChild(s); }
quelle
Meine übliche Ajax-Aufruffunktion:
function xhr_new(targetId, url, busyMsg, finishCB) { var xhr; if(busyMsg !== undefined) document.getElementById(targetId).innerHTML = busyMsg; try { xhr = new ActiveXObject('Msxml2.XMLHTTP'); } catch(e) { try { xhr = new ActiveXObject('Microsoft.XMLHTTP'); } catch(e2) { try { xhr = new XMLHttpRequest(); } catch(e3) { xhr = false; } } } xhr.onreadystatechange = function() { if(xhr.readyState == 4) { if(xhr.status == 200) { var target = document.getElementById(targetId) target.innerHTML = xhr.responseText; var scriptElements = target.getElementsByTagName("script"); var i; for(i = 0; i < scriptElements.length; i++) eval(scriptElements[i].innerHTML); if(finishCB !== undefined) finishCB(); } else document.getElementById(targetId).innerHTML = 'Error code: ' + xhr.status; } }; xhr.open('GET', url, true); xhr.send(null); // return xhr; }
Einige Erklärungen:
targetId
ist eine (normalerweise div) Element-ID, in die der Ergebnistext des Ajax-Aufrufs eingefügt wird.url
ist die Ajax-Anruf-URL.busyMsg
wird der temporäre Text im Zielelement sein.finishCB
wird aufgerufen, wenn die Ajax-Transaktion erfolgreich abgeschlossen wurde.Wie Sie in der Abbildung sehen, werden
xhr.onreadystatechange = function() {...}
alle<script>
Elemente aus der Ajax-Antwort erfasst und einzeln ausgeführt. Es scheint sehr gut für mich zu funktionieren. Die beiden letzten Parameter sind optional.quelle
Ich habe das getestet und es funktioniert. Was ist das Problem? Fügen Sie einfach die neue Funktion in Ihr Javascript-Element ein und rufen Sie sie auf. Es wird klappen.
quelle
Ich habe alle hier angebotenen Techniken ausprobiert, aber schließlich funktionierte die JavaScript-Funktion einfach in die Seite / Datei, in der sie stattfinden soll, und rief sie aus dem Antwortteil des Ajax einfach als Funktion auf:
... }, function(data) { afterOrder(); }
Dies funktionierte beim ersten Versuch, also entschied ich mich zu teilen.
quelle
Ich habe dies heute gelöst, indem ich mein JavaScript am Ende des Antwort-HTML-Codes platziert habe.
Ich hatte eine AJAX-Anfrage, die eine Menge HTML zurückgab, das in einem Overlay angezeigt wurde. Ich musste ein Klickereignis an eine Schaltfläche im zurückgegebenen Antwort-HTML / Overlay anhängen. Auf einer normalen Seite würde ich mein JavaScript in ein "window.onload" oder "$ (document) .ready" einschließen, damit der Ereignishandler an das DOM-Objekt angehängt wird, nachdem das DOM für das neue Overlay gerendert wurde Da dies eine AJAX-Antwort und kein Laden einer neuen Seite war, ist dieses Ereignis nie aufgetreten, der Browser hat mein JavaScript nie ausgeführt, mein Ereignishandler wurde nie an das DOM-Element angehängt und meine neue Funktionalität hat nicht funktioniert. Wieder löste ich mein "Ausführen von JavaScript in einem AJAX-Antwortproblem", indem ich nicht "$ (document) .ready" im Kopf des Dokuments verwendete.
quelle
Wenn die Ausführung Ihres AJAX-Skripts länger als ein paar Millisekunden dauert, wird eval () immer ausgeführt und bewertet das leere Antwortelement, bevor AJAX es mit dem Skript füllt, das Sie ausführen möchten.
Anstatt mit Timing und eval () herumzuspielen, ist hier eine ziemlich einfache Problemumgehung, die in den meisten Situationen funktionieren sollte und wahrscheinlich etwas sicherer ist. Die Verwendung von eval () ist im Allgemeinen verpönt, da die als Code ausgewerteten Zeichen leicht clientseitig bearbeitet werden können.
Konzept
Beispiel
In diesem Beispiel möchte ich eine dynamische Autovervollständigungsliste aus der jquery-ui-Bibliothek an ein AJAX-Element anhängen, nachdem das Element zur Seite hinzugefügt wurde. Einfach richtig?
start.php
<!DOCTYPE html> <html> <head> <title>Demo</title> <!-- these libraries are for the autocomplete() function --> <link rel="stylesheet" type="text/css" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/ui-lightness/jquery-ui.css"> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> <script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script> <script type="text/javascript"> <!-- // this is the ajax call function editDemoText(ElementID,initialValue) { try { ajaxRequest = new XMLHttpRequest(); } catch (e) { try { ajaxRequest = new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) { try { ajaxRequest = new ActiveXObject("Microsoft.XMLHTTP"); } catch (e) { return false; }}} ajaxRequest.onreadystatechange = function() { if ( ajaxRequest.readyState == 4 ) { var ajaxDisplay = document.getElementById('responseDiv'); ajaxDisplay.innerHTML = ajaxRequest.responseText; } } var queryString = "?ElementID="+ElementID+"&initialValue="+initialValue; ajaxRequest.open("GET", "ajaxRequest.php"+queryString, true); ajaxRequest.send(null); } // this is the function we wanted to call in AJAX, // but we put it here instead with an argument (ElementID) function AttachAutocomplete(ElementID) { // this list is static, but can easily be pulled in from // a database using PHP. That would look something like this: /* * $list = ""; * $r = mysqli_query($mysqli_link, "SELECT element FROM table"); * while ( $row = mysqli_fetch_array($r) ) { * $list .= "\".str_replace('"','\"',$row['element'])."\","; * } * $list = rtrim($list,","); */ var availableIDs = ["Demo1","Demo2","Demo3","Demo4"]; $("#"+ElementID).autocomplete({ source: availableIDs }); } //--> </script> </head> <body> <!-- this is where the AJAX response sneaks in after DOM is loaded --> <!-- we're using an onclick event to trigger the initial AJAX call --> <div id="responseDiv"><a href="javascript:void(0);" onclick="editDemoText('EditableText','I am editable!');">I am editable!</a></div> </body> </html>
ajaxRequest.php
<?php // for this application, onfocus works well because we wouldn't really // need the autocomplete populated until the user begins typing echo "<input type=\"text\" id=\"".$_GET['ElementID']."\" onfocus=\"AttachAutocomplete('".$_GET['ElementID']."');\" value=\"".$_GET['initialValue']."\" />\n"; ?>
quelle
Federico Zancans Antwort ist richtig, aber Sie müssen Ihrem Skript keine ID geben und Ihr gesamtes Skript . Bewerten Sie einfach Ihren Funktionsnamen und er kann aufgerufen werden.
Um dies in unserem Projekt zu erreichen, haben wir eine Proxy-Funktion geschrieben, um die in der Ajax-Antwort zurückgegebene Funktion aufzurufen.
function FunctionProxy(functionName){ var func = eval(functionName); func(); }
quelle