开发者

Very interesting jQuery load behavior, a bug or solution?

I was recently trying to find a bug in some scripting and I discovered this very interesting behavior when loading a page with jQuery.

File #1: Test1.htm

<div id="test"></div>

<script type="text/javascript">
$(do开发者_JAVA技巧cument).ready(function(){
 $('#test').load('test2.htm #content',function(){
  alert('done loading!');
 })
})
</script>

File #2: Test2.htm

<div id="content">
howdy

<script type="text/javascript">
$(document).ready(function(){
 alert('hello #1');
})
</script>
<SCRIPT type="text/javascript">
$(document).ready(function(){
 alert('hello #2');
})
</SCRIPT>

</div>

Now when I run Test1.htm, I get the following:

  • hello #2 alert
  • howdy from test2.htm displays
  • done loading alert

As you can see the only difference is the script tag is in upper case for the hello #2 alert. The script to show the hello #1 alert never gets exectued...

So far, I've tested this in Firefox 3.55, IE 8.0.6001.18702 and Chrome 3.0.195.33 with similar results.

In the past, I've wanted to execture javascript from the loaded content, similar to this SO question. So my question is, is this a bug or a solution?


Update: As Jitter states below, the same thing happens if Test2.htm has the script outside the content I am loading.

<div id="content">
howdy from test2.htm
</div>

<script type="text/javascript">
$(document).ready(function(){
 alert('hello #1');
})
</script>
<SCRIPT type="text/javascript">
$(document).ready(function(){
 alert('hello #2');
})
</SCRIPT>


Actually this seems to be a bug in jQuery. You should post a bug-ticket. Nice find btw.

In jQuery 1.3.2 line 3270-3272 we have

// inject the contents of the document in, removing the scripts
// to avoid any 'Permission Denied' errors in IE
.append(res.responseText.replace(/<script(.|\s)*?\/script>/g, ""))

Clearly the case-insensitive flag i on this regex is missing. Thus every <script>...</script> tag which isn't all lower case like <SCRIPT>, <Script>, <scriPt>, ... isn't removed by jQuery as intended.

So line 3272 should look like

.append(res.responseText.replace(/<script(.|\s)*?\/script>/gi, ""))

Additionally this bug is only triggered by your usage of an selector in the load url test2.htm #content. If you leave that one out and use

$('#test').load('test2.htm',function(){....});

and test2.htm looks like the following it will fire three alerts too (no matter how you write the script tag). So this is also a corner case bug too.

howdy

<SCRIPT type="text/javascript">
$(document).ready(function(){
 alert('hello #1');
});
</SCRIPT>
<script type="text/javascript">
$(document).ready(function(){
 alert('hello #2');
})
</script>


Injecting script elements via HTML is very difficult to do reliably cross-browser, and consequently broken in various ways in jQuery. It does some things to work around known browser problems, but this can end up just making it worse.

With jitter's bug (+1) fixed you'll find the scripts don't get inserted at all, to try to avoid these kinds of problem. Even with the fix, this line is vile and fragile code, trying to process HTML with regex, and will fail if the string /script> is included in the script block (which is quite valid). And will fail for </script >. And so on.

So do yourself a favour and leave <script> out of HTML content you intend to load dynamically. Always pass any script content to be executed back separately from the HTML.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜