Call JavaScript function returned from Ajax response

I have a system in which I send an Ajax command that returns a script block with a function in it. After this data is correctly inserted into the DIV, I want to be able to call this function to perform the necessary actions.

Is it possible?

+61
javascript function ajax
Feb 04 '09 at 10:18
source share
17 answers

I think it’s correct to interpret your question in this form: “Well, I’ve already finished with all Ajax materials, I just want to know if the JavaScript function can my Ajax callback inserted into the DIV at any time this moment, that is, I don’t want to call it contextual callback. "

OK, if you mean something like this, yes, you can call your new code at this time at any time while saving the page in the browser under the following conditions:

1) The JavaScript code returned by the Ajax callback should be syntactically OK,
2) Even if a function declaration is inserted into a <script> block in an existing <div> element, the browser will not know that a new function exists, since the declaration code has never been executed. So you must eval() your declaration code returned by the Ajax callback to efficiently declare your new function and have it available throughout the life of the page.

Even if pretty dummy, this code explains the idea:

 <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> 

I did not use Ajax, but the concept is the same (even if the example I chose is not very smart :-)

Generally speaking, I do not question your solution design, i.e. it is more or less appropriate to screen + generalize the function in a separate .js file, etc., but please note that such a solution can cause additional problems, especially if your Ajax calls should be repeated, i.e. if the context of the same function should change, or if the problem with the declared function should be affected, you may need to seriously consider changing the design to one of the suggested examples in this thread.

Finally, if I misunderstood your question, and you are talking about a function context call when the Ajax callback is returned, then I feel like I am proposing the Prototype approach described by krosenvold , as it is cross-browser, tested and fully functional, and this can give you the best roadmap for future implementations.

+69
Feb 04 '09 at 13:10
source share

None of them worked for me

The following does!

It took me a few hours to find a workaround.

Inside the returned HTML / Ajax / JavaScript file, you will have a JavaScript tag. Give it an identifier, such as a script. It’s unusual to add an identifier to these tags, but he needed to reference it specifically.

 <script type="text/javascript" id="runscript"> alert("running from main"); </script> 

In the main window, call the eval function, evaluating only this NEW block of JavaScript code (in this case it is called runcript):

 eval(document.getElementById("runscript").innerHTML); 

And it works, at least in Internet Explorer 9 and Google Chrome.

+39
Apr 09 2018-12-12T00:
source share

This is entirely possible, and there are even some fairly legitimate use cases for this. Using Prototype , he did the following.

 new Ajax.Updater('items', '/items.url', { parameters: { evalJS: true} }); 

See the documentation for the Ajax updater. Parameters are in the general settings . As usual, there are some caveats about where "this" indicates, so read the fine print.

JavaScript code will be evaluated on loading. If the content contains the myFunc(), function myFunc(), you could just say myFunc() after that. Maybe as follows.

 if (window["myFunc"]) myFunc() 

This checks if the function exists. Maybe someone has a better cross-browser way to do what works in Internet Explorer 6.

+9
Feb 04 '09 at 10:29
source share

This seems like a rather strange design for your code - it usually makes sense to use your functions directly from the .js file and then retrieve the data only with an Ajax call.

However, I believe that it should work by calling eval () in response - provided that it is syntactically correct JavaScript code.

+5
Feb 04 '09 at 10:21
source share

With jQuery, I would do it with getScript

+4
Feb 04 '09 at 10:22
source share

Just remember, if you create a function in the following way via ajax ...

 function foo() { console.log('foo'); } 

... and running it through eval, you are likely to run into a context problem. Take this as a callback function:

 function callback(result) { responseDiv = document.getElementById('responseDiv'); responseDiv.innerHTML = result; scripts = responseDiv.getElementsByTagName('script'); eval(scripts[0]); } 

You will declare a function inside a function, so this new function will be available only in this area.

If you want to create a global function in this scenario, you can declare it as follows:

 window.foo = function () { console.log('foo'); }; 

But I also think that you should not do this ...

Sorry for any mistake here ...

+3
Feb 24 '11 at 17:52
source share

I would like to add that there is an eval function in jQuery that allows you to globally evaluate code that should save you any contextual problems. This function is called globalEval () , and it works great for my purposes. Its documentation can be found here .

This is an example of the code provided by the jQuery API documentation:

 function test() { jQuery.globalEval("var newVar = true;") } test(); // newVar === true 

This feature is extremely useful when you have to dynamically load external scripts that you apparently tried to do.

+3
Jun 25 2018-12-12T00:
source share

Checklist for doing such a thing:

  • the returned Ajax response is eval (ed).
  • functions are declared in the form func_name = function() {...}

Better yet, use frameworks that handle it, as in Prototype . You have Ajax.updater .

+2
Jul 07 2018-11-11T00:
source share

PHP External Code File Name 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']); 

Now from the Html page you have to call the ajax function to send the data.

 .... <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()"/> 

Now on our local script.js we will define 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 } }); } 
+2
Jul 02 '13 at 12:44
source share

That doesn't sound like a good idea.

You must ignore the function that will be included in the rest of your JavaScript code from the data returned by Ajax methods.

What is it worth (and I don’t understand why you are inserting a script block into a div?), Even the built-in script methods written in the script block will be available.

+1
Feb 04 '09 at 10:23
source share

My usual ajax call function:

 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; } 

Some explanations:
targetId is the identifier of the element (usually a div) where the text of the result of the ajax call will be displayed.
url is the address of the ajax call.
busyMsg will be the temporary text in the target element.
finishCB will be called when the ajax operation is completed successfully.
As you see in xhr.onreadystatechange = function() {...} all the <script> elements will be assembled from the ajax response and will be run one after the other. It seems to work very well for me. The last two parameters are optional.

+1
Jul 27 '16 at 11:43
source share

I tested this and it works. What is the problem? Just put the new function inside your javascript element and then call it. He will work.

0
Dec 31 '11 at 20:10
source share

I tried all the methods suggested here, but finally, the way that worked was simply to place the JavaScript function inside the page / file where it was supposed to happen, and call it from the part of the Ajax response just as a function:

 ... }, function(data) { afterOrder(); } 

It worked on the first try, so I decided to share.

0
Dec 09
source share

This code also works, instead of this eval html I'm going to add a script to my head

 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); } 
0
Jun 26 '13 at 14:11
source share

I solved this today by putting my JavaScript at the bottom of the HTML response.

I had an AJAX request that returned a bunch of HTML that was displayed in the overlay. I needed to attach a click event to a button in the returned HTML / overlay response. On a regular page, I would wrap my JavaScript in "window.onload" or "$ (document) .ready" so that it binds the event handler to the DOM object after the DOM for the new overlay has been rendered, but because it was an AJAX response and not a new page load, this event never occurred, the browser never executed my JavaScript, my event handler never attached to the DOM element, and my new functionality did not work. Again, I decided to "execute JavaScript in the AJAX response problem", not using "$ (document) .ready" at the beginning of the document, but placing my JavaScript at the end of the document and executing it after the HTML / DOM.

0
Feb 05 '14 at 22:00
source share

If your AJAX script takes more than a couple of milliseconds to run, eval () will always run ahead and evaluate the empty response element before AJAX populates it with the script you are trying to execute.

Instead of resetting the timeout and eval (), here is a pretty simple workaround that should work in most situations and is probably a bit more secure. Using eval () is usually disapproving, because characters that are evaluated as code can easily be manipulated on the client side.

Concept

  • Enable the javascript function on the main page. Write it so that any dynamic elements can be accepted as arguments.
  • In your AJAX file, call the function using the official DOM event (onclick, onfocus, onblur, onload, etc.). Depending on what other elements are in your answer, you may get a pretty smart way to do this without any problems. Pass your dynamic elements as arguments.
  • When your response element is populated and an event occurs, the function is triggered.

Example

In this example, I want to add a dynamic autocomplete list from the jquery-ui library to an AJAX element AFTER the element was added to the page. Easy, right?

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"; ?> 
0
09 Oct '15 at 20:30
source share

Federico Zancan's answer is correct, but you do not need to provide your script identifier and evaluate all your scripts. Just evaluate your function name and you can call it.

To achieve this in our project, we wrote a proxy function to call the function returned inside the Ajax response.

 function FunctionProxy(functionName){ var func = eval(functionName); func(); } 
0
Jul 13 '16 at 15:50
source share



All Articles