views:

340

answers:

4

I've been using jquery 1.3.2 to pull snippets of html (including script) from a server. A typical response might be:

<div id="content"><div id="inner">...

<script type=...> alert("hello world");</script>

<p>Hello World</p>

</div></div>

I've been using the query .get function:

$.get($(this).attr("href"), function(response) {
    $("#inner").replaceWith($("#inner", response));
        });

And everything is fine and works as expected: the returned html snippets get loaded into the DOM and the scripts run.

When I use 1.4.2 however, I notice that the script tags have been removed and no longer run.

Stepping into the newer jquery codebase yields the lines of code (line 4498) :

ret.splice.apply( ret, [i + 1, 0].concat(jQuery.makeArray(ret[i].getElementsByTagName("script"))) );

which seems to be the culprit 'removing' the script from its happy resting place as part of the selector process. But it doesn't help me in injecting exactly what i want into the DOM.

Any idea why jquery is doing this? More importantly, how can I go about fixing this so that my scripts run?

A: 

I don't know if everyone will agree but I would say the problem is in the structure of what you are doing.

Pulling javascript syntax out of database sounds like a really strange thing to do while you can simply have the in js files and call them to do their things when the page is ready.

XGreen
I can see many use cases for such a scenario, but the OP didn't say the content is coming from a db, just that it is mixed HTML and JS.
Joel Potter
Joel is correct. I am not pulling from a DB.
cmroanirgo
+1  A: 

If you can change your server side code to return this (just remove the wrapper divs which are present anyway)

<script type="text/javascript">alert("hello world");</script>
<p>Hello World</p>

then you could use

$("#inner").load($(this).attr("href"));

Which doesn't seem to suffer from this problem.


Or if really just a snippet of this form (which is valid xml) is returned, you might also try specifying xml as dataType.

$.get($(this).attr("href"), null, function(response) {
    $("#inner").replaceWith($("#inner", response));
}, "xml");
jitter
using $("#inner").load($(this).attr("href")); has done the trick. Thanks jitter
cmroanirgo
A: 

everything is fine and works as expected: the returned html snippets get loaded into the DOM and the scripts run.

Possibly not in all browsers it didn't.

Loading <script>s into the DOM via HTML (explicitly through a domManip-based function, or as the outcome of a load()) is something that's wonky and behaves differently cross-browser; it should be avoided.

jQuery attempts to put some workarounds in to make it better, which is part of what you're seeing there (it tries to extract <script> elements from content and execute them manually), but it's not foolproof for all cases and you shouldn't rely on it. [Note that the same code is present in 1.3.2 (line 955), so this is nothing new.]

Best approach: keep your static code separate from your markup; don't pass scripts back in content for insertion into the DOM; when you need to add data or call a trigger post-insertion, do it in code passed back separately from the HTML (eg. as part of a JSON object).

bobince
Considering it runs in IE, FF, Chrome and Safari, I think it's safe to say that it does work. I missed the lines in 1.3.2. Regardless, to then serve tightly coupled script/html snippets in two ajax requests just because jQuery has decided to 'Big Brother' me is ludicrous IMHO.
cmroanirgo
You don't need two requests, you can have one request returning a JSON object that holds an HTML property and a code string property. See http://stackoverflow.com/questions/1661224/stop-ie-from-loading-dynamically-included-script-twice for some of the background to why `innerHTML`-inserted `<script>`​s are a bad idea.
bobince
thankx for the clarification bobince. I'll look into it
cmroanirgo
A: 

The issue is not that using embedded scripts is wrong or inappropriate, but rather that jquery breaks up severly when upgrading from 1.3.2 to 1.4.2. I deem thinking this was unintentional from the jQuery developers. I hope this will be fixed in subsequent releases, as its makes jQuery (and jQuery-ui) terribly less appealing. Meanwhile, I'll advise to look into other alternatives, such as Mootools or Yahoo UI as a workaround for ajax-mode HTML parsing.

Etienne