Bug Tracker

Opened 13 years ago

Closed 13 years ago

Last modified 8 years ago

#746 closed bug (fixed)

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

Reported by: pirklk@… Owned by:
Priority: major Milestone: 1.1a
Component: ajax Version: 1.1a
Keywords: load ajax Cc:
Blocked by: Blocking:

Description (last modified by joern)

$("#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() {

Change History (8)

comment:1 Changed 13 years ago by joern

Description: modified (diff)
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.

comment:2 Changed 13 years ago by malsup

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.

comment:3 Changed 13 years ago by joern

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?

comment:4 Changed 13 years ago by malsup

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?

comment:5 Changed 13 years ago by joern

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.

comment:6 Changed 13 years ago by joern

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().

comment:7 Changed 13 years ago by malsup

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.

comment:8 Changed 13 years ago by joern

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.

Note: See TracTickets for help on using tickets.