调用Ajax响应返回的JavaScript函数

时间:2021-09-19 03:19:50

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

我有一个发送Ajax命令的系统,该命令返回带有函数的脚本块。在这个数据被正确地插入到DIV之后,我希望能够调用这个函数来执行所需的操作。

Is this possible?

这是可能的吗?

17 个解决方案

#1


69  

I think to correctly interpret your question under this form: "OK, I'm already done with all the Ajax stuff; I just wish to know if the JavaScript function my Ajax callback inserted into the DIV is callable at any time from that moment on, that is, I do not want to call it contextually to the callback return".

我想在这种形式下正确地解释您的问题:“好的,我已经完成了所有Ajax的工作;我只是想知道我插入到DIV中的Ajax回调的JavaScript函数是否可以从那时起在任何时候调用,也就是说,我不希望上下文地将它调用到回调返回”。

OK, if you mean something like this the answer is yes, you can invoke your new code by that moment at any time during the page persistence within the browser, under the following conditions:

如果你的意思是这样的答案是肯定的,你可以随时调用你的新代码在浏览器内的页面持久化期间,在以下条件下:

1) Your JavaScript code returned by Ajax callback must be syntactically OK;
2) Even if your function declaration is inserted into a <script> block within an existing <div> element, the browser won't know the new function exists, as the declaration code has never been executed. So, you must eval() your declaration code returned by the Ajax callback, in order to effectively declare your new function and have it available during the whole page lifetime.

1) Ajax回调返回的JavaScript代码必须符合语法要求;2)即使您的函数声明被插入到现有的

元素中的

Even if quite 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 didn't use Ajax, but the concept is the same (even if the example I chose sure isn't much smart :-)

我没有使用Ajax,但是概念是一样的(即使我选择的例子sure不是很聪明:-)

Generally speaking, I do not question your solution design, i.e. whether it is more or less appropriate to externalize + generalize the function in a separate .js file and the like, but please take note that such a solution could raise further problems, especially if your Ajax invocations should repeat, i.e. if the context of the same function should change or in case the declared function persistence should be concerned, so maybe you should seriously consider to change your design to one of the suggested examples in this thread.

一般来说,我不质疑你的解决方案设计,即是否或多或少的适当外部化+概括函数在一个单独的. js文件之类的,但是请注意,这样的解决方案可能会进一步提高的问题,特别是如果您的Ajax调用应该重复,即如果上下文相同的函数应该改变或声明的函数持久性应该关心,因此,也许您应该认真考虑将您的设计更改为该线程中建议的示例之一。

Finally, if I misunderstood your question, and you're talking about contextual invocation of the function when your Ajax callback returns, then my feeling is to suggest the Prototype approach described by krosenvold, as it is cross-browser, tested and fully functional, and this can give you a better roadmap for future implementations.

最后,如果我误解了你的问题,和你谈论上下文调用Ajax回调时功能的回报,那么我的感觉是建议由krosenvold描述的原型方法,跨浏览器,测试和功能齐全,这可以给你更好的未来路线图实现。

#2


39  

Note: eval() can be easily misused, let say that the request is intercepted by a third party and sends you not trusted code. Then with eval() you would be running this not trusted code. Refer here for the dangers of eval().

注意:eval()很容易被误用,假设请求被第三方截获并发送给您不受信任的代码。然后使用eval(),您将运行这个不受信任的代码。请参阅eval()的危险。


Inside the returned HTML/Ajax/JavaScript file, you will have a JavaScript tag. Give it an ID, like runscript. It's uncommon to add an id to these tags, but it's needed to reference it specifically.

在返回的HTML/Ajax/JavaScript文件中,将有一个JavaScript标记。给它一个ID,比如runscript。向这些标记添加id并不常见,但是需要特别引用它。

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

In the main window, then call the eval function by evaluating only that NEW block of JavaScript code (in this case, it's called runscript):

在主窗口中,通过只计算新的JavaScript代码块(在本例中,它被称为runscript)调用eval函数:

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

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

至少在ie 9和谷歌浏览器中是这样的。

#3


9  

It is fully possible, and there are even some fairly legitimate use cases for this. Using the Prototype framework it's done as follows.

这是完全可能的,甚至有一些相当合理的用例。使用原型框架完成如下操作。

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

See documentation of the Ajax updater. The options are in the common options set. As usual, there are some caveats about where "this" points to, so read the fine print.

请参阅Ajax更新程序的文档。这些选项都在公共选项集中。和往常一样,关于“这个”指的是什么,有一些需要注意的地方,所以请阅读详细说明。

The JavaScript code will be evaluated upon load. If the content contains function myFunc(), you could really just say myFunc() afterwards. Maybe as follows.

JavaScript代码将在加载时进行评估。如果内容包含函数myFunc(),您可以稍后真正地说myFunc()。也许如下。

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

This checks if the function exists. Maybe someone has a better cross-browser way of doing that which works in Internet Explorer 6.

它检查函数是否存在。也许有人有更好的跨浏览器的方式来做这在Internet Explorer 6中是可行的。

#4


6  

That seems a rather weird design for your code - it generally makes more sense to have your functions called directly from a .js file, and then only retrieve data with the Ajax call.

对于代码来说,这似乎是一个相当奇怪的设计——让函数直接从.js文件调用,然后只使用Ajax调用检索数据通常更有意义。

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

但是,我认为它应该通过在响应上调用eval()来工作——只要它是语法正确的JavaScript代码。

#5


4  

With jQuery I would do it using getScript

使用jQuery,我会使用getScript

#6


3  

Just remember if you create a function the way below through ajax...

请记住,如果您通过以下的ajax创建一个函数……

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

...and execute it via eval, you'll probably get a context problem. Take this as your callback function:

…通过eval执行它,您可能会遇到一个上下文问题。将此作为回调函数:

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

You'll be declaring a function inside a function, so this new function will be accessible only on that scope.

您将在函数中声明一个函数,因此这个新函数只能在该范围内访问。

If you want to create a global function in this scenario, you could declare it this way:

如果您想在此场景中创建一个全局函数,可以这样声明:

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

But, I also think you shouldn't be doing this...

但是,我也认为你不应该这么做……

Sorry for any mistake here...

对不起,这里有错误……

#7


3  

I would like to add that there's an eval function in jQuery allowing you to eval the code globally which should get you rid of any contextual problems. The function is called globalEval() and it worked great for my purposes. Its documentation can be found here.

我想补充一点,jQuery中有一个eval函数,允许您对代码进行全局求值,这样就可以避免任何上下文相关的问题。这个函数被称为globalEval(),在我的目的中运行得非常好。它的文档可以在这里找到。

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

这是jQuery API文档提供的示例代码:

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

test();
// newVar === true

This function is extremely useful when it comes to loading external scripts dynamically which you apparently were trying to do.

当需要动态加载外部脚本时,这个函数非常有用,显然您正在尝试这样做。

#8


2  

A checklist for doing such a thing:

做这样一件事的清单:

  1. the returned Ajax response is eval(ed).
  2. 返回的Ajax响应是eval(ed)。
  3. the functions are declared in form func_name = function() {...}
  4. 函数的声明形式为func_name = function(){…}

Better still, use frameworks which handles it like in Prototype. You have Ajax.updater.

更好的是,使用像原型一样处理它的框架。你有Ajax.updater。

#9


2  

PHP side code Name of file class.sendCode.php

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 your Html page you must trigger the ajax function to send the data.

现在,您必须从Html页面触发ajax函数来发送数据。

....  <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 at our local script.js we will define the ajax

现在看我们的本地脚本。我们将定义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
                  }


        });
}

#10


1  

This does not sound like a good idea.

这听起来不是个好主意。

You should abstract out the function to include in the rest of your JavaScript code from the data returned by Ajax methods.

您应该从Ajax方法返回的数据中抽象出包含在JavaScript代码其余部分的函数。

For what it's worth, though, (and I don't understand why you're inserting a script block in a div?) even inline script methods written in a script block will be accessible.

尽管如此,(我也不明白为什么要在div中插入一个脚本块?)即使是写在脚本块中的内联脚本方法也是可以访问的。

#11


1  

My usual ajax calling function:

我常用的ajax调用函数:

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 explanation:
targetId is an (usually div) element ID where the ajax call result text will goes.
url is the ajax call url.
busyMsg will be the temporary text in the target element.
finishCB will be called when the ajax transaction finished successfully.
As you see in the xhr.onreadystatechange = function() {...} all of the <script> elements will be collected from the ajax response and will be run one by one. It appears to work very well for me. The two last parameter is optional.

一些说明:targetId是一个(通常是div)元素ID, ajax调用结果文本将在其中。url是ajax调用url。busyMsg将是目标元素中的临时文本。当ajax事务成功完成时,将调用finishCB。正如你在xhr里看到的。onreadystatechange = function(){…}所有的

#12


0  

I've tested this and it works. What's the problem? Just put the new function inside your javascript element and then call it. It will work.

我测试过这个,它是有效的。是什么问题?只需将新函数放入javascript元素中,然后调用它。它将工作。

#13


0  

I tried all the techniques offered here but finally the way that worked was simply to put the JavaScript function inside the page / file where it is supposed to happen and call it from the response part of the Ajax simply as a function:

我尝试了这里提供的所有技术,但最终实现的方法只是将JavaScript函数放在页面/文件中,在它应该出现的地方,并从Ajax的响应部分调用它作为一个函数:

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

This Worked on the first attempt, so I decided to share.

第一次尝试就成功了,所以我决定分享。

#14


0  

This code work as well, instead eval the html i'm going to append the script to the head

这段代码也可以工作,而不是对html进行eval,我将把脚本追加到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);
}

#15


0  

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

今天我通过将JavaScript放在响应HTML的底部来解决这个问题。

I had an AJAX request that returned a bunch of HTML that was displayed in an overlay. I needed to attach a click event to a button in the returned response HTML/overlay. On a normal page, I would wrap my JavaScript in a "window.onload" or "$(document).ready" so that it would attach the event handler to the DOM object after the DOM for the new overlay had been rendered, but because this was an AJAX response and not a new page load, that event never happened, the browser never executed my JavaScript, my event handler never got attached to the DOM element, and my new piece of functionality didn't work. Again, I solved my "executing JavaScript in an AJAX response problem" by not using "$(document).ready" in the head of the document, but by placing my JavaScript at the end of the document and having it run after the HTML/DOM had been rendered.

我有一个AJAX请求,它返回了一堆HTML,显示在一个覆盖层中。我需要在返回的响应HTML/覆盖的按钮上附加一个点击事件。在一个正常的页面上,我会将我的JavaScript包装在一个“窗口”中。onload”或“$(文档)。准备好”,这样就会将事件处理程序附加到DOM对象的DOM叠加后已经呈现,而是因为这是一个AJAX响应,而不是一个新的页面加载,该事件从未发生过,浏览器不会执行JavaScript,我附加事件处理程序没有DOM元素,和我的新功能不工作。同样,我解决了“在AJAX响应中执行JavaScript”的问题,没有使用“$(document)”。“准备好了”在文档的头部,但是将我的JavaScript放在文档的末尾,并在HTML/DOM呈现之后让它运行。

#16


0  

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

如果AJAX脚本的运行时间超过几毫秒,那么eval()将始终向前运行并计算空响应元素,然后再用要执行的脚本填充它。

Rather than mucking around with timing and eval(), here is a pretty simple workaround that should work in most situations and is probably a bit more secure. Using eval() is generally frowned upon because the characters being evaluated as code can easily be manipulated client-side.

这里有一个非常简单的解决方案,它应该适用于大多数情况,并且可能更安全一些。使用eval()通常是不赞成的,因为被评估为代码的字符很容易被客户端操作。

Concept

  1. Include your javascript function in the main page. Write it so that any dynamic elements can be accepted as arguments.
  2. 在主页中包含javascript函数。编写它,以便可以接受任何动态元素作为参数。
  3. In your AJAX file, call the function by using an official DOM event (onclick, onfocus, onblur, onload, etc.) Depending on what other elements are in your response, you can get pretty clever about making it feel seamless. Pass your dynamic elements in as arguments.
  4. 在您的AJAX文件中,使用官方DOM事件(onclick、onfocus、onblur、onload等)调用函数,这取决于您的响应中的其他元素,您可以非常聪明地让它感觉无缝。将动态元素作为参数传入。
  5. When your response element gets populated and the event takes place, the function runs.
  6. 当您的响应元素被填充并发生事件时,函数将运行。

Example

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

在本例中,我希望在元素添加到页面之后,将jquery-ui库中的动态autocomplete列表附加到AJAX元素。容易,对吧?

start.php

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

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";
?>

#17


0  

Federico Zancan's answer is correct but you don't have to give your script an ID and eval all your script. Just eval your function name and it can be called.

Federico Zancan的回答是正确的,但是你不必给你的脚本一个ID和eval所有的脚本。只要计算函数名,就可以调用它。

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

为了在项目中实现这一点,我们编写了一个代理函数来调用Ajax响应中返回的函数。

function FunctionProxy(functionName){
    var func = eval(functionName);
    func();
}

#1


69  

I think to correctly interpret your question under this form: "OK, I'm already done with all the Ajax stuff; I just wish to know if the JavaScript function my Ajax callback inserted into the DIV is callable at any time from that moment on, that is, I do not want to call it contextually to the callback return".

我想在这种形式下正确地解释您的问题:“好的,我已经完成了所有Ajax的工作;我只是想知道我插入到DIV中的Ajax回调的JavaScript函数是否可以从那时起在任何时候调用,也就是说,我不希望上下文地将它调用到回调返回”。

OK, if you mean something like this the answer is yes, you can invoke your new code by that moment at any time during the page persistence within the browser, under the following conditions:

如果你的意思是这样的答案是肯定的,你可以随时调用你的新代码在浏览器内的页面持久化期间,在以下条件下:

1) Your JavaScript code returned by Ajax callback must be syntactically OK;
2) Even if your function declaration is inserted into a <script> block within an existing <div> element, the browser won't know the new function exists, as the declaration code has never been executed. So, you must eval() your declaration code returned by the Ajax callback, in order to effectively declare your new function and have it available during the whole page lifetime.

1) Ajax回调返回的JavaScript代码必须符合语法要求;2)即使您的函数声明被插入到现有的

元素中的

Even if quite 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 didn't use Ajax, but the concept is the same (even if the example I chose sure isn't much smart :-)

我没有使用Ajax,但是概念是一样的(即使我选择的例子sure不是很聪明:-)

Generally speaking, I do not question your solution design, i.e. whether it is more or less appropriate to externalize + generalize the function in a separate .js file and the like, but please take note that such a solution could raise further problems, especially if your Ajax invocations should repeat, i.e. if the context of the same function should change or in case the declared function persistence should be concerned, so maybe you should seriously consider to change your design to one of the suggested examples in this thread.

一般来说,我不质疑你的解决方案设计,即是否或多或少的适当外部化+概括函数在一个单独的. js文件之类的,但是请注意,这样的解决方案可能会进一步提高的问题,特别是如果您的Ajax调用应该重复,即如果上下文相同的函数应该改变或声明的函数持久性应该关心,因此,也许您应该认真考虑将您的设计更改为该线程中建议的示例之一。

Finally, if I misunderstood your question, and you're talking about contextual invocation of the function when your Ajax callback returns, then my feeling is to suggest the Prototype approach described by krosenvold, as it is cross-browser, tested and fully functional, and this can give you a better roadmap for future implementations.

最后,如果我误解了你的问题,和你谈论上下文调用Ajax回调时功能的回报,那么我的感觉是建议由krosenvold描述的原型方法,跨浏览器,测试和功能齐全,这可以给你更好的未来路线图实现。

#2


39  

Note: eval() can be easily misused, let say that the request is intercepted by a third party and sends you not trusted code. Then with eval() you would be running this not trusted code. Refer here for the dangers of eval().

注意:eval()很容易被误用,假设请求被第三方截获并发送给您不受信任的代码。然后使用eval(),您将运行这个不受信任的代码。请参阅eval()的危险。


Inside the returned HTML/Ajax/JavaScript file, you will have a JavaScript tag. Give it an ID, like runscript. It's uncommon to add an id to these tags, but it's needed to reference it specifically.

在返回的HTML/Ajax/JavaScript文件中,将有一个JavaScript标记。给它一个ID,比如runscript。向这些标记添加id并不常见,但是需要特别引用它。

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

In the main window, then call the eval function by evaluating only that NEW block of JavaScript code (in this case, it's called runscript):

在主窗口中,通过只计算新的JavaScript代码块(在本例中,它被称为runscript)调用eval函数:

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

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

至少在ie 9和谷歌浏览器中是这样的。

#3


9  

It is fully possible, and there are even some fairly legitimate use cases for this. Using the Prototype framework it's done as follows.

这是完全可能的,甚至有一些相当合理的用例。使用原型框架完成如下操作。

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

See documentation of the Ajax updater. The options are in the common options set. As usual, there are some caveats about where "this" points to, so read the fine print.

请参阅Ajax更新程序的文档。这些选项都在公共选项集中。和往常一样,关于“这个”指的是什么,有一些需要注意的地方,所以请阅读详细说明。

The JavaScript code will be evaluated upon load. If the content contains function myFunc(), you could really just say myFunc() afterwards. Maybe as follows.

JavaScript代码将在加载时进行评估。如果内容包含函数myFunc(),您可以稍后真正地说myFunc()。也许如下。

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

This checks if the function exists. Maybe someone has a better cross-browser way of doing that which works in Internet Explorer 6.

它检查函数是否存在。也许有人有更好的跨浏览器的方式来做这在Internet Explorer 6中是可行的。

#4


6  

That seems a rather weird design for your code - it generally makes more sense to have your functions called directly from a .js file, and then only retrieve data with the Ajax call.

对于代码来说,这似乎是一个相当奇怪的设计——让函数直接从.js文件调用,然后只使用Ajax调用检索数据通常更有意义。

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

但是,我认为它应该通过在响应上调用eval()来工作——只要它是语法正确的JavaScript代码。

#5


4  

With jQuery I would do it using getScript

使用jQuery,我会使用getScript

#6


3  

Just remember if you create a function the way below through ajax...

请记住,如果您通过以下的ajax创建一个函数……

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

...and execute it via eval, you'll probably get a context problem. Take this as your callback function:

…通过eval执行它,您可能会遇到一个上下文问题。将此作为回调函数:

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

You'll be declaring a function inside a function, so this new function will be accessible only on that scope.

您将在函数中声明一个函数,因此这个新函数只能在该范围内访问。

If you want to create a global function in this scenario, you could declare it this way:

如果您想在此场景中创建一个全局函数,可以这样声明:

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

But, I also think you shouldn't be doing this...

但是,我也认为你不应该这么做……

Sorry for any mistake here...

对不起,这里有错误……

#7


3  

I would like to add that there's an eval function in jQuery allowing you to eval the code globally which should get you rid of any contextual problems. The function is called globalEval() and it worked great for my purposes. Its documentation can be found here.

我想补充一点,jQuery中有一个eval函数,允许您对代码进行全局求值,这样就可以避免任何上下文相关的问题。这个函数被称为globalEval(),在我的目的中运行得非常好。它的文档可以在这里找到。

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

这是jQuery API文档提供的示例代码:

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

test();
// newVar === true

This function is extremely useful when it comes to loading external scripts dynamically which you apparently were trying to do.

当需要动态加载外部脚本时,这个函数非常有用,显然您正在尝试这样做。

#8


2  

A checklist for doing such a thing:

做这样一件事的清单:

  1. the returned Ajax response is eval(ed).
  2. 返回的Ajax响应是eval(ed)。
  3. the functions are declared in form func_name = function() {...}
  4. 函数的声明形式为func_name = function(){…}

Better still, use frameworks which handles it like in Prototype. You have Ajax.updater.

更好的是,使用像原型一样处理它的框架。你有Ajax.updater。

#9


2  

PHP side code Name of file class.sendCode.php

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 your Html page you must trigger the ajax function to send the data.

现在,您必须从Html页面触发ajax函数来发送数据。

....  <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 at our local script.js we will define the ajax

现在看我们的本地脚本。我们将定义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
                  }


        });
}

#10


1  

This does not sound like a good idea.

这听起来不是个好主意。

You should abstract out the function to include in the rest of your JavaScript code from the data returned by Ajax methods.

您应该从Ajax方法返回的数据中抽象出包含在JavaScript代码其余部分的函数。

For what it's worth, though, (and I don't understand why you're inserting a script block in a div?) even inline script methods written in a script block will be accessible.

尽管如此,(我也不明白为什么要在div中插入一个脚本块?)即使是写在脚本块中的内联脚本方法也是可以访问的。

#11


1  

My usual ajax calling function:

我常用的ajax调用函数:

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 explanation:
targetId is an (usually div) element ID where the ajax call result text will goes.
url is the ajax call url.
busyMsg will be the temporary text in the target element.
finishCB will be called when the ajax transaction finished successfully.
As you see in the xhr.onreadystatechange = function() {...} all of the <script> elements will be collected from the ajax response and will be run one by one. It appears to work very well for me. The two last parameter is optional.

一些说明:targetId是一个(通常是div)元素ID, ajax调用结果文本将在其中。url是ajax调用url。busyMsg将是目标元素中的临时文本。当ajax事务成功完成时,将调用finishCB。正如你在xhr里看到的。onreadystatechange = function(){…}所有的

#12


0  

I've tested this and it works. What's the problem? Just put the new function inside your javascript element and then call it. It will work.

我测试过这个,它是有效的。是什么问题?只需将新函数放入javascript元素中,然后调用它。它将工作。

#13


0  

I tried all the techniques offered here but finally the way that worked was simply to put the JavaScript function inside the page / file where it is supposed to happen and call it from the response part of the Ajax simply as a function:

我尝试了这里提供的所有技术,但最终实现的方法只是将JavaScript函数放在页面/文件中,在它应该出现的地方,并从Ajax的响应部分调用它作为一个函数:

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

This Worked on the first attempt, so I decided to share.

第一次尝试就成功了,所以我决定分享。

#14


0  

This code work as well, instead eval the html i'm going to append the script to the head

这段代码也可以工作,而不是对html进行eval,我将把脚本追加到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);
}

#15


0  

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

今天我通过将JavaScript放在响应HTML的底部来解决这个问题。

I had an AJAX request that returned a bunch of HTML that was displayed in an overlay. I needed to attach a click event to a button in the returned response HTML/overlay. On a normal page, I would wrap my JavaScript in a "window.onload" or "$(document).ready" so that it would attach the event handler to the DOM object after the DOM for the new overlay had been rendered, but because this was an AJAX response and not a new page load, that event never happened, the browser never executed my JavaScript, my event handler never got attached to the DOM element, and my new piece of functionality didn't work. Again, I solved my "executing JavaScript in an AJAX response problem" by not using "$(document).ready" in the head of the document, but by placing my JavaScript at the end of the document and having it run after the HTML/DOM had been rendered.

我有一个AJAX请求,它返回了一堆HTML,显示在一个覆盖层中。我需要在返回的响应HTML/覆盖的按钮上附加一个点击事件。在一个正常的页面上,我会将我的JavaScript包装在一个“窗口”中。onload”或“$(文档)。准备好”,这样就会将事件处理程序附加到DOM对象的DOM叠加后已经呈现,而是因为这是一个AJAX响应,而不是一个新的页面加载,该事件从未发生过,浏览器不会执行JavaScript,我附加事件处理程序没有DOM元素,和我的新功能不工作。同样,我解决了“在AJAX响应中执行JavaScript”的问题,没有使用“$(document)”。“准备好了”在文档的头部,但是将我的JavaScript放在文档的末尾,并在HTML/DOM呈现之后让它运行。

#16


0  

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

如果AJAX脚本的运行时间超过几毫秒,那么eval()将始终向前运行并计算空响应元素,然后再用要执行的脚本填充它。

Rather than mucking around with timing and eval(), here is a pretty simple workaround that should work in most situations and is probably a bit more secure. Using eval() is generally frowned upon because the characters being evaluated as code can easily be manipulated client-side.

这里有一个非常简单的解决方案,它应该适用于大多数情况,并且可能更安全一些。使用eval()通常是不赞成的,因为被评估为代码的字符很容易被客户端操作。

Concept

  1. Include your javascript function in the main page. Write it so that any dynamic elements can be accepted as arguments.
  2. 在主页中包含javascript函数。编写它,以便可以接受任何动态元素作为参数。
  3. In your AJAX file, call the function by using an official DOM event (onclick, onfocus, onblur, onload, etc.) Depending on what other elements are in your response, you can get pretty clever about making it feel seamless. Pass your dynamic elements in as arguments.
  4. 在您的AJAX文件中,使用官方DOM事件(onclick、onfocus、onblur、onload等)调用函数,这取决于您的响应中的其他元素,您可以非常聪明地让它感觉无缝。将动态元素作为参数传入。
  5. When your response element gets populated and the event takes place, the function runs.
  6. 当您的响应元素被填充并发生事件时,函数将运行。

Example

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

在本例中,我希望在元素添加到页面之后,将jquery-ui库中的动态autocomplete列表附加到AJAX元素。容易,对吧?

start.php

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

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";
?>

#17


0  

Federico Zancan's answer is correct but you don't have to give your script an ID and eval all your script. Just eval your function name and it can be called.

Federico Zancan的回答是正确的,但是你不必给你的脚本一个ID和eval所有的脚本。只要计算函数名,就可以调用它。

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

为了在项目中实现这一点,我们编写了一个代理函数来调用Ajax响应中返回的函数。

function FunctionProxy(functionName){
    var func = eval(functionName);
    func();
}