繁体   English   中英

从jQuery ajax响应中执行与HTML混合的javascript

[英]Executing javascript mixed with HTML from a jQuery ajax response

或者,不是精确地“执行”,而是使用响应中返回的功能更新响应之前存在的功能。

第1步

  1. 我有一个描述位置的HTML5页面。
  2. 在服务器端,此页面包含ColdFusion文件“ MapFunction.cfm”。 (用于在整个站点上进行一致的映射。)
  3. MapFunction.cfm输出与HTML混合的JavaScript函数“ loadMap”。
  4. loadMap()包含在页面上放置该位置的必应地图的所有JavaScript。
  5. 一个单独的js文件中的一些JavaScript实际上调用了loadMap()。

该功能在首次加载页面时有效。

第2步

  1. 搜索和结果的东西也很好。 这里的地图不需要做任何事情。

第三步

  1. 单击搜索结果后,将通过jQuery $ .get()请求异步加载结果详细信息。
  2. 它返回混合的HTML和javascript,我使用jQuery进行遍历。
  3. 使用jQuery对象,我更新页面的特定区域以显示不同的细节。

我需要更新的区域之一是地图。 那部分不起作用。

我正在使用的是混合HTML和Javascript,它们在步骤1步骤3中都相同:

<section id="mod-map" class="module mod-map">
    <header class="mod-head">
        <a href="#map" class="mod-head-link"> Map <span class="arrow"></span> </a>
    </header>
    <div id="map" class="mod-body">
        <div id="cmMap" style="position:relative;width:369px;height:303px;"></div>
        <script type="text/javascript" id="cfLoadMap">
            // ...some global variables are defined to use...
            function loadMap()
            {                   
                // ...Bing/Virtual Earth Map Stuff...
                // This part here is unique to each location's detail
                var propertypoint = new VELatLong(parseFloat(36.707756),parseFloat(-78.74204));
                // ...More Bing/Virtual Earth Map Stuff...
                // This part here is unique to each location's detail
                var label = "<div class=\"wrapper\"><img onerror=\"replaceImage(this);\" src=\"noimage.jpg\" width=\"100\" class=\"thumb\" alt=\"\" /><div class=\"caption\"><br />City<br /> State, 12345</div></div>";    
                // ...More Bing/Virtual Earth Map Stuff...              
            }
        </script>
    </div>
</section>

现在,在步骤3 loadMap() 不会再次调用,但它只是刷新映射到相同的位置。 由于浏览器知道loadMap()函数不会使用通过ajax检索到的进行更新。

每次ajax调用之后,上面混合HTML和javascript的更新块确实已成功添加到页面中。 它原本放置在正确的位置,但是上面的注释所指示的坐标和标题不同。 ajax回调看起来像(略有简化):

$.get(urlToLoad, {}, function(data, status, request){   
    var newData = $(innerShiv(data, false)),
        newModules = newData.find(".module");
    // (innerShiv is used to make HTML5 tags work in IE. It's possible I'm going a little overboard with using it, but I had a lot of issues with IE. :-))
    newModules.each(function(i){
        var thisId = "#" + $(this).attr("id"),
            thisBody = $(this).find(".mod-body").html(),
            toReplaceAll = $("body").find(thisId),
            toReplaceBody = toReplaceAll.find(".mod-body");
        // These variables are used to choose add content in different ways based on thisID. Below is the one the map area is subject to.
        toReplaceBody.html(innerShiv(thisBody));                
    }); // each
    // Various things including loadMap() get called/re-initiated/etc. here
}, "html"); // get

这在Firefox 3.6中有效,但我没有测试过其他地方(Opera 11,IE 7,Chrome 8)。

在类似情况下,我已经通过将动态PHP生成的javascript写入单独的js文件的方式进行了此操作-$ .getScript在此效果很好。 但这混入了ajax响应的HTML中。

我一直在寻找并发现并尝试了以下方法(以及其他方法):

尝试的解决方案

1. var myScript = new Function($('script#cfLoadMap', data).text()); myScript();
2. eval(newData.text());
3. eval(newData.find("#cfLoadMap").text());
4. $("head").append(newData.find("#cfLoadMap"));

到目前为止,这些似乎都没有起到任何作用。

我知道理论上还有其他方法可以做到。 但是就目前而言,除了混合HTML和javascript响应之外,我没有任何其他改变的能力。 我需要一个解决方案,

  • 详细信息将通过ajax更新。
  • javascript将与HTML混合在一起。
  • javascript将是ColdFusion动态生成的javascript函数。

之前已经提出并解决过非常类似的问题,所以我希望可以做到。 但是,我发现的所有解决方案都无法为我工作。 可能是犯了错误或遗漏了某些东西,或者当它是一个函数时,它可能有所不同?

任何帮助,将不胜感激。

回答

它突然开始使用以下代码:

$.get(urlToLoad, {}, function(data, status, request){   
    var safeData = $(innerShiv(data, false)),
        newModules = safeData.find(".module"),
        newScript = safeData.find("script#cfLoadMap");
    // Update Each module
    newModules.each(function(i){
        var jqoThis = $(this),
            thisId = "#" + jqoThis.attr("id"),
            newModule = jqoThis,
            newModBody = jqoThis.find(".mod-body"),
            curModule = $("body").find(thisId),
            curModBody = curModule.find(".mod-body");
        // Varies by id, this one is used by the map area.
        curModBody.html(innerShiv(newModBody.html()));      
    }); // each
    // Make sure plugins are bound to new content
    $("body").oneTime(100, function(){
        // Various things get initiated here
        // Maps -- this one works: Chrome, Firefox, IE7, Opera
        $("head").append(newScript);
        // Maps -- these did not work
        /* 
            // Firefox only (but Firefox always works)
            runScript = new Function(newScript.text());
            runScript();
        */
        /*
            // Firefox only (but Firefox always works)
            eval(newScript.text());
        */
    }); // oneTime
}, "html"); // get

有一件事我没有通知肯定的是,没有innerShiv,在我所有的浏览器,$(数据).find(“脚本#cfLoadMap”)文本()为空白 -这是我没有想到的。

很可能JavaScript中的函数可以在非全局范围内声明,因此,当您插入<script>标记时,jQuery会对其进行eval ,但不会替换原始函数(如您所注意到的)。

解决此问题的方法是更改​​从中声明函数的方式:

function loadMap()
{
  ...
}

对此:

window.loadMap = function loadMap() {
  ...
}

这样,最高级别的loadMap将始终是服务器中发布的最新loadMap

您可能要考虑不以这种方式修改客户端代码,因为它会使调试变得更加棘手,但这完全取决于您。 希望这个答案对您都有效。

它突然开始使用以下代码:

$.get(urlToLoad, {}, function(data, status, request){   
    var safeData = $(innerShiv(data, false)),
        newModules = safeData.find(".module"),
        newScript = safeData.find("script#cfLoadMap");
    // Update Each module
    newModules.each(function(i){
        var jqoThis = $(this),
            thisId = "#" + jqoThis.attr("id"),
            newModule = jqoThis,
            newModBody = jqoThis.find(".mod-body"),
            curModule = $("body").find(thisId),
            curModBody = curModule.find(".mod-body");
        // Varies by id, this one is used by the map area.
        curModBody.html(innerShiv(newModBody.html()));      
    }); // each
    // Make sure plugins are bound to new content
    $("body").oneTime(100, function(){
        // Various things get initiated here
        // Maps -- this one works: Chrome, Firefox, IE7, Opera
        $("head").append(newScript);
        // Maps -- these did not work
        /* 
            // Firefox only (but Firefox always works)
            runScript = new Function(newScript.text());
            runScript();
        */
        /*
            // Firefox only (but Firefox always works)
            eval(newScript.text());
        */
    }); // oneTime
}, "html"); // get

有一件事我没有通知肯定的是,没有innerShiv,在我所有的浏览器,$(数据).find(“脚本#cfLoadMap”)文本()为空白 -这是我没有想到的。

但是,我真的看不出这与我之前尝试过的和失败的有何不同。 如果有人发现实质性差异,请让我知道,以供将来参考?

(注意:在超时中放置Map位似乎没有什么区别,它在超时之前也能正常工作。)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM