简体   繁体   中英

jQuery evaluating JavaScript in HTML string with complications

This is driving me crazy...

What I am trying to do is update a portion of a webpage, and for reasons not worth explaining, the request is asking for a whole new HTML page (including its head) and then pulling out only the HTML that was contained within a specified element (identified by an ID).

Originally, I had the following JavaScript code that would run whenever an AJAX request for new HTML completed:

var $newContent = $(newHtmlContent);
loadingElement.innerHTML = $("#" + loadingElementId, $newContent).html();

This was great until I had a bit of HTML that was loaded that, contained within the specified element, included some scripts that needed to be run, so I changed it to this:

var $newContent = $(newHtmlContent);
$(loadingElement).html($("#" + loadingElementId, $newContent).html());

I have read that jQuery will evaluate any scripts with the HTML string argument of the html() function - however, it seems the issue is that the scripts are stripped before this call. Having had a look through firebug the following seems to be happening:

$(newHtmlContent) // includes all 'script' elements
$("#" + loadingElementId, $newContent) // has no scripts
$("script", $newContent) // empty jQuery object

Does anyone have any suggestions? Thanks in advance.

Did a quick test (fiddle) , given the following markup as string:

<div id="root">
    <div>some dynamic content</div>
    <script type="text/javascript">alert("hello");</script>
    <div class="desiredElement">after script</div>
</div>

jQuery will produce an object like

> [0]: #root
> [1]: script

[0] will contain all of the html in #root except for the script, the scripts are separated into their own objects. This seems to be true for all scripts within the markup.

So you could do something like this to run the script:

var $new = $(dynamicContent); // dynamicContent is string
var $desired = $new.find('.desiredElement');

$new.eq(1).appendTo('body'); // run the script

edit Never mind; I think you're sunk here. As soon as you hand over the content to jQuery, I'm pretty sure that your scripts are stripped out. The stuff trick below would work if "newContent" were actually part of the "native" page, but because it's in that fragment instantiated by jQuery, it's too late.

I think this will work, but I admit I haven't tried it with a loaded document like what you've got:

 
 
 
  
  $('#loadingElement').html($('#' + loadingElementId, $newContent)[0].innerHTML);
 
  

The idea is to bypass jQuery when pulling out the contents of the loaded portion.

There's a long explanation of this issue here: http://forum.jquery.com/topic/jquery-removing-script-tags-from-html-string-when-using-html

From that discussion:

If you want to select/traverse part of an HTML string, and you want the <script> within the HTML string to be executed, you need to insert the HTML string into the DOM before selecting/traversing.

So it looks like the problem is that you're trying to pull elements out of the returned HTML without inserting it into the DOM first. Two possible solutions:

  1. Insert the entire returned HTML into the DOM. The script tags will execute. Then remove the parts you don't need. It's not ideal, as it might display content you don't want, unless you hide the loadingElement first and show when you're done.

  2. Pull out the script URLs from $(newHtmlContent) , use $.getScript() to retrieve and execute each URL, then add the retrieved elements into the DOM. It's more of a pain, but it should work fine, and you don't have to insert unnecessary content into the DOM.

您可以尝试的一件事是拉出包含的<script>元素并将它们eval()或将它们附加到页面的head

I'm guessing here as well but how about:

//scripts will be executed and HTML put into loadingElement
$('#loadingElement').html(newHtmlContent); 

//find the specified element under #loadingElement, get it's HTML 
//and set it as the HTML for #loadingElement
$('#loadingElement').html($('#loadingElement').find('#idToFind').html());

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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