Note that there are some explanatory texts on larger screens.

plurals
  1. POExecuting javascript mixed with HTML from a jQuery ajax response
    primarykey
    data
    text
    <p>Or, not precisely "executing," but updating a function that exists before the response with a function returned in the response.</p> <p><strong>Step 1</strong></p> <ol> <li>I have an HTML5 page that describes a location.</li> <li>On the server side this page includes a ColdFusion file "MapFunction.cfm." (Which is used for consistent mapping all over the site at large.)</li> <li>MapFunction.cfm outputs a javascript function "loadMap" mixed with the HTML. </li> <li>loadMap() contains all the javascript needed to place a Bing map of the location on the page.</li> <li>Some javascript in a separate js file actually calls loadMap().</li> </ol> <p>This works when the page is first loaded.</p> <p><strong>Step 2</strong></p> <ol> <li>Search &amp; results stuff is all fine too. Nothing needs to be done with the map here.</li> </ol> <p><strong>Step 3</strong></p> <ol> <li>When a search result is clicked, the result detail is loaded asynchronously via a jQuery $.get() request.</li> <li>It returns mixed HTML and javascript which I use jQuery to traverse through.</li> <li>With the jQuery objects I update specific areas of the page to show different details.</li> </ol> <p>One of the areas I need to update is the map. That part isn't working.</p> <p>What I'm working with is mixed HTML and Javascript that is identical in both <strong>Step 1</strong> and <strong>Step 3</strong>:</p> <pre><code>&lt;section id="mod-map" class="module mod-map"&gt; &lt;header class="mod-head"&gt; &lt;a href="#map" class="mod-head-link"&gt; Map &lt;span class="arrow"&gt;&lt;/span&gt; &lt;/a&gt; &lt;/header&gt; &lt;div id="map" class="mod-body"&gt; &lt;div id="cmMap" style="position:relative;width:369px;height:303px;"&gt;&lt;/div&gt; &lt;script type="text/javascript" id="cfLoadMap"&gt; // ...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 = "&lt;div class=\"wrapper\"&gt;&lt;img onerror=\"replaceImage(this);\" src=\"noimage.jpg\" width=\"100\" class=\"thumb\" alt=\"\" /&gt;&lt;div class=\"caption\"&gt;&lt;br /&gt;City&lt;br /&gt; State, 12345&lt;/div&gt;&lt;/div&gt;"; // ...More Bing/Virtual Earth Map Stuff... } &lt;/script&gt; &lt;/div&gt; &lt;/section&gt; </code></pre> <p>Now, in <strong>Step 3</strong> loadMap() <strong>does</strong> get called again, but it just refreshes the map to the same location. The loadMap() function as the browser knows it doesn't get updated with the one retrieved via ajax.</p> <p>That updated block of mixed HTML &amp; javascript above does get successfully added to the page after each ajax call. It is placed right where it originally is, but with different coordinates and captions where indicated by the comments above. The ajax callback looks like (slightly simplified):</p> <pre><code>$.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 </code></pre> <p>This works in Firefox 3.6, but nowhere else I've tested (Opera 11, IE 7, Chrome 8). </p> <p>I <strong>have</strong> done this before in a similar situation with dynamically PHP generated javascript written to a separate js file--$.getScript works great there. But this is mixed into the HTML of the ajax response.</p> <p>I've been looking and have found and tried the following (among other things):</p> <p><strong>Attempted Solutions</strong></p> <pre><code>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")); </code></pre> <p>None of these so far seem to be doing any good.</p> <p>I know there are a few other ways this could theoretically be done. But as it stands at the moment, I do not have any ability to change much of anything but what I do with the mixed HTML &amp; javascript response. I need a solution where,</p> <ul> <li>The details will be updated via ajax.</li> <li>The javascript will be mixed in with the HTML.</li> <li>The javascript will be a javascript function generated dynamically by ColdFusion.</li> </ul> <p>Very similar questions have been asked &amp; resolved before, so I hope this can be done. However, none of the solutions I've found are working for me. Might be making a mistake or missing something, or maybe it's just different when it's a function?</p> <p>Any help would be appreciated.</p> <h2>Answer</h2> <p>It suddenly started working with the following code:</p> <pre><code>$.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 </code></pre> <p>One thing I <em>did</em> notice for sure was that without innerShiv, in all my browsers, $(data).find("script#cfLoadMap").text() was <strong>blank</strong> -- which I did <em>not</em> expect.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload