Reputation: 803
consider the following code -->
<template id="foo">
<script type="text/javascript">
console.log("00000000");
</script>
<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
<script type="text/javascript">
console.log(11111111);
</script>
<script type="text/javascript">
console.log(22222222);
var xyz = $;
console.log(33333333);
</script>
</template>
now on appending this to the DOM
var template = document.getElementById('foo')
var clone = document.importNode(template.content,true);
document.appendChild(clone);
gives this output in console -->
00000000
11111111
22222222
Uncaught ReferenceError: $ is not defined
So the question in general is -->
How to properly load into DOM, an html <template>
that has
an external script (like jQuery in this case), followed by an inline script having some dependency on it.
Also - this does not happen if template tag is removed -->
<script type="text/javascript">
console.log("00000000");
</script>
<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
<script type="text/javascript">
console.log(11111111);
</script>
<script type="text/javascript">
console.log(22222222);
var xyz = $;
console.log(33333333);
</script>
How in the latter case, does the browser download it synchronously?
Is it possible to have blocking script download (line by line) in the former case (with template) ?
Upvotes: 0
Views: 2589
Reputation: 324
Here's how I handle it in my application (with jQuery):
//Load the template from an external file and append it to the HEAD of the document
$.get("/path/to/your_external_template_file.html", function (html_string) {
$('head', top.document).append(
new DOMParser().parseFromString(html_string, 'text/html').querySelector('template')
);
}, 'html');
//Locate the template after you've imported it
var $template = $("#top_template_element_id");
//If you want to reuse the content, be sure to clone the node.
var content = $template.prop('content').cloneNode(true);
//Add a copy of the template to desired container on the page
var $container = $('#target_container_id').append(content);
Upvotes: 0
Reputation: 13211
The problem is that the script is loaded async. That means that it start to load the script from the web, but continues running the code below. So in that case it will execute code below without having loaded jQuery yet.
You only need to load it once, so you could do it at the start, and only once:
var template = document.getElementById('foo')
var clone = document.importNode(template.content,true);
document.body.appendChild(clone);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<template id="foo">
<script type="text/javascript">
console.log(00000000);
</script>
<script type="text/javascript">
console.log(11111111);
</script>
<script type="text/javascript">
console.log(22222222);
var xyz = $;
console.log(33333333);
</script>
</template>
Another option would be to make sure code below is only executed once the file is loaded:
var template = document.getElementById('foo')
var clone = document.importNode(template.content, true);
document.body.appendChild(clone);
<template id="foo">
<script type="text/javascript">
console.log(00000000);
</script>
<script type="text/javascript">
function scriptOnload() {
console.log(11111111);
console.log(22222222);
var xyz = $;
console.log(33333333);
}
</script>
<script onload="scriptOnload()" src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
</template>
Upvotes: 0