Skip to main content

Bug Tracker

Side navigation

#746 closed bug (fixed)

Opened December 29, 2006 08:00PM UTC

Closed January 01, 2007 03:27PM UTC

Last modified March 15, 2012 12:33PM UTC

$("#feeds").load("feeds.html") Call to .evalScripts() fails in Internet Explorer

Reported by: pirklk@gmail.com Owned by:
Priority: major Milestone: 1.1a
Component: ajax Version: 1.1a
Keywords: load ajax Cc:
Blocked by: Blocking:
Description

$("#feeds").load("feeds.html")

Call to .evalScripts() fails in Internet Explorer

jQuery.fn.extend for load: makes a call to jQuery.ajax(...) and on completion does a self.html(res.responseText) which eventually does a elem[fix[name]] = value and that is why it fails to process the scripts in Internet Explorer. The "innerHTML" attribute (also "text" attribute) for IE (tested/verified for IE 6.0) strips out <script> tag elements from the HTML. This is the test code that I used for my IE testing.

var script = "<script language="JavaScript"
type="text/JavaScript">alert('im really running');</script>";
var oVDiv =document.getElementById("oDiv1");
oVDiv["innerHTML"] = script; // fails

Suggested fix would be to pass res.responseText to evalScripts: function() {

Attachments (0)
Change History (8)

Changed December 29, 2006 11:26PM UTC by joern comment:1

description: $("#feeds").load("feeds.html") Call to .evalScripts() fails in Internet Explorer\ \ jQuery.fn.extend for load: makes a call to jQuery.ajax(...) and on completion does a self.html(res.responseText) which eventually does a elem[fix[name]] = value and that is why it fails to process the scripts in Internet Explorer. The "innerHTML" attribute (also "text" attribute) for IE (tested/verified for IE 6.0) strips out <script> tag elements from the HTML. This is the test code that I used for my IE testing. \ var script = "<script language="JavaScript"\ type="text/JavaScript">alert('im really running');</script>";\ var oVDiv =document.getElementById("oDiv1");\ oVDiv["innerHTML"] = script; // fails\ \ Suggested fix would be to pass res.responseText to evalScripts: function() {$("#feeds").load("feeds.html")\ \ Call to .evalScripts() fails in Internet Explorer\ \ jQuery.fn.extend for load: makes a call to jQuery.ajax(...) and on completion does a self.html(res.responseText) which eventually does a elem[fix[name]] = value and that is why it fails to process the scripts in Internet Explorer. The "innerHTML" attribute (also "text" attribute) for IE (tested/verified for IE 6.0) strips out <script> tag elements from the HTML. This is the test code that I used for my IE testing. \ \ {{{\ var script = "<script language="JavaScript"\ type="text/JavaScript">alert('im really running');</script>";\ var oVDiv =document.getElementById("oDiv1");\ oVDiv["innerHTML"] = script; // fails\ }}}\ \ Suggested fix would be to pass res.responseText to evalScripts: function() {
milestone: → 1.1
priority: minormajor
version: → 1.1

Thanks for the report, that helps a lot. The issue occured before, but we failed to find the source of the problem.

The solution is a bit more complicated, because we have to insert the HTML into the DOM first before we can use any selectors. On the other hand, if we parse the HTML by hand and evaluate any scripts, we have to prevent that they are executed again later.

Changed December 30, 2006 03:42AM UTC by malsup comment:2

Here's a modified version of the unit test from the form plugin:

test("load doc with scripts", function() {
    stop();
    expect(3);
    $('#test').load('doc-with-scripts.html', function() {
        ok( $('#test').text().match("Lorem ipsum"), "target updated");
        ok( typeof unitTestVariable1 != 'undefined', 'first script block executed');
        ok( typeof unitTestVariable2 != 'undefined', 'second script block executed');
        start();
    });
});

The doc-with-scripts.html file looks like this:

<div>
<script type="text/javascript">
    // set global var
    var unitTestVariable1 = true;
</script>

Lorem ipsum dolor sit amet...

<script type="text/javascript">
    // set another global var
    var unitTestVariable2 = true;
</script>
</div>

The basic idea is to assert that both script blocks are executed AND the target of the load is updated.

Changed December 30, 2006 10:28AM UTC by joern comment:3

This is the test from the testsuite:

test("load(String, Object, Function) - check scripts", function() {
	expect(7);
	stop();
	testFoo = undefined;
	var verifyEvaluation = function() {
	  ok( foobar == "bar", 'Check if script src was evaluated after load' );
	  ok( $('#foo').html() == 'foo', 'Check if script evaluation has modified DOM');
	  ok( $('#ap').html() == 'bar', 'Check if script evaluation has modified DOM');
	  start();
	};
	$('#first').load('data/test.html', function() {
	  ok( $('#first').html().match(/^html text/), 'Check content after loading html' );
	  ok( testFoo == "foo", 'Check if script was evaluated after load' );
	  setTimeout(verifyEvaluation, 600);
	});
});

test.html:

html text<br/>
<script type="text/javascript">
testFoo = "foo"; $('#foo').html('foo');
ok( true, "test.html executed" );
</script>
<script src="data/test.js"></script>
blabla

That works, so what are we missing?

Changed December 31, 2006 12:01AM UTC by malsup comment:4

Interesting. That works for me in IE6 & 7, although it's bugger to test through IE's caching. We should probably rework ajaxTest.js to append the current time to the URL. Is the setTimeout necessary?

Changed December 31, 2006 03:13PM UTC by joern comment:5

The testsuite now has a url function that appends both timestamp and a random number to urls, no matte whether they already have a query string or not. That makes testing in both FF and IE much easier.

The timeout is necessary to check if test.js is properly evaluated. That requires another requests that we don't control, so we can't use a callback.

I'll check what happens if the html file contains only a script element and nothing else.

Changed December 31, 2006 03:48PM UTC by joern comment:6

Ok, got it. IE strips the script tag when there is nothing else in the file. Even a single character in front of the script tag fixes the problem.

If anyone comes up with a nice workaround, fine, otherwise I just add a note to load() warning about this issue. If there is nothing else then the script tag, it's easy to strip that, too, and use $.getScript().

Changed December 31, 2006 08:13PM UTC by malsup comment:7

Looks like it strips the script if it is the very first subelement. For example,

<div>
<script type="text/javascript">
    alert('hello');
</script>
</div>

does not alert. But this does:

<div>
blah
<script type="text/javascript">
    alert('hello');
</script>

Nice work, Jörn. Looks like this is just a documentation issue. Cool.

Changed January 01, 2007 03:27PM UTC by joern comment:8

resolution: → fixed
status: newclosed

I added a note to load() about this problem. Just put a character in front of your script or use $.getScript() to avoid it.