The Skinny
I'm well aware that JS requires AJAX (or some synch/asynch call) to get the contents of a file after page load.
(From previous link)
var client = new XMLHttpRequest();
client.open('GET', '/foo.txt');
client.onreadystatechange = function() {
alert(client.responseText);
}
client.send();
Browsers won't allow direct access to files. This is for security reasons, mitigating XSS attacks and so forth.
But is there a way to include it on page load... without including it into the markup?
I am using a couple client-side templates (not interested in client- vs server-side debate). Currently, the only way to include them on page load, without additional calls to the server, is to toss the contents into a custom-type script
tag:
<script id="t1" type="x-some-template">
... contents of template
<script>
And then reference the contents of the script block in some way:
var templateContents = $('#t1').html();
But if the template is long, it muddies up the markup (assuming the user is viewing the source). This is entirely aesthetics and nit-picking, and does not affect how anything operates, but is there some sneaky way of including the templates without having them appear in the markup?
So Far...
I tried putting the template into its own .js file, and including it in the same way:
<script id="t1" type="x-some-template" src="t1.js"><script>
But then there is no way to reference the content, since it is never loaded by the browser.
(From javascript.info)
If you put an unsupported value into type, e.g. , the contents will be ignored. This is a trick used add data that was not rendered to the page.
But if you put in a known type:
<script id="t1" type="text/javascript" src="t1.js"><script>
An error will be thrown, since the contents of the file isn't in proper JS.
Other solutions could be assigning the template content to a JS variable, and including the external file, then referencing said variable:
// t1.js
var temp = `... contents of template... `;
// page.html
var templateContents = temp;
But even with the template literal, it can be a nightmare including complex templates. And then you have the issue of assigning each template to a different variable and tracking them all. Headaches abound. The problem would be mitigated slightly if you could assign each template to a standard variable, and then reference them based on the script block that included it...
var templateContents1 = $('#t1').temp;
var templateContents2 = $('#t2').temp; // Or something like this...
...
But that's a no-go.
I've search high and low, but all I've come across is endless AJAX, and HTML Imports, which have awful support.
Finally, The Question
Has anyone stumbled across a beautiful way to do this? And in a browser-independent (i.e. universally supported) way? I want to stay away from any post-load server calls (i.e., AJAX).
Load the page with the content, and use it persistently.
Thoughts On Potential Solutions
The only way to beautify the markup (that I can come up with) is to use the currently-working method, and then completely remove the script block:
var templateContents = $('#t1').html();
$('#t1').remove(); // Or similar
But this isn't a very good solution, 'cause then the content is no longer available if JS decides to garbage collect on templateContents
, and you have to re-load the template.
I'm not much for server/.htaccess stuffs, but maybe I can modify the .htaccess (or similar) to read the custom-type script as plain text, and then it persists in memory to use on an as-needed basis?
Golly, it sure would be swell if...
The ideal situation would be similar to how I described above, where the plain template content is in a separate file (without being assigned to a variable)...
// t1.js
... all the contents of the template...
And then including it in a single, beautiful line...
// page.html
<script id="t1" type="whatever-works" src="t1.js"></script>
And reference the template contents in an equally simple and beautiful line...
var templateContents = $('#t1').someTextAccessMethod();
Any thoughts?