I have an application that builds page content from multiple page fragments comprising the template page. One or more of these fragments need to run JavaScript when the document has loaded, and it does not make sense to put fragment specific code in the template page comprising the fragments. While this approach has worked out for me quite well, I have a problem when attempting to update a fragment via Ajax based on the user's interaction with the page.
I am using jQuery and $(document).ready(function() {...});
rather liberally, both in the template page (for globally scoped code) and the fragments (for fragment specific code). Problem is, when a fragment is updated using jQuery's .html(HTML code from Ajax response)
on the jQuery enriched version of the HTML element and the Ajax response itself contains $(document).ready(function() {...});
code, the HTML content gets updated nicely but the JS does not execute.
Some suggest use of eval()
on the JS fragments inside the Ajax response while others forbid it. I am hoping someone will push me in the right direction with this.
$.ajax({
type: 'POST',
url: $(formObj).attr('action'),
data: $(formObj).serialize(),
})
.done(function(data, textStatus, jqXHR) {
$response = $(data.replace(/<body(.*?)>/,'<body$1><div id="ajaxResBody">').replace('</body>','</div></body>'));
$('#fragmentContent').html($response.find('#fragmentContent').html());
});
<div id="fragmentContent">...</div>
is one of the fragments updated using partial content extracted from the Ajax response. When the page is initially loaded, the fragment's content DOM looks approximately like this:
<div id="fragmentContent">
<p>...</p>
<div>...</div>
<script type="text/javascript">
$(document).ready(function() {
// JS code
});
</script>
</div>
But when the same fragment's content is replaced via Ajax, the DOM looks like this:
<div id="fragmentContent">
<p>...</p>
<div>...</div>
</div>
So it is quite apparent scripts are stripped. I verified that by using the following code:
if (data.indexOf('accordion(') >= 0) {
console.log('scripts found in Ajax response');
if ($response.find('#fragmentContent').html().indexOf('accordion(') >= 0) {
console.log('scripts inserted into fragment');
}
else {
console.log('scripts stripped before content inserted into fragment!');
}
}
else {
console.log('scripts did not even make it in the Ajax response!');
}
and the following log output was yielded:
scripts found in Ajax response
scripts stripped before content inserted into fragment!