I am using jsrender as the JavasScript template engine. The usage is quite straightforward:
In HTML Page, define a script tag with template-ed HTML content:
<script id="myTemplate" type="text/x-jsrender">
<div>{{:name}} ({{:year}})</div>
</script>
...
<body>
<div id="content"></div>
</body>
In JavaScript, define a variable, and call render function against the template:
var model = {
name: "Findekano",
year: 2012
};
$('#content').html($('#myTemplate').render(model));
The question is:
I do not want to keep the template definition in the host HTML page, I'd like to keep it in a separate file along with the JavaScript file so it can be more modular.
I'd like to have something to work as below:
<script id="myTemplate"
type="text/x-jsrender"
src="template/myTemplate.html">
</script>
where myTemplate.html defines the necessary HTML template snippet. I tried the code above but it doesn't work. Could anyone suggest an alternative way to solve the problem?
If you do not want to have to use an AJAX call and using a more memory doesn't concern you, there is at least one alternative solution I can think of. AJAX might be cleaner, but I thought I'd put this out there anyways.
document.write('<script id="myTemplate" type="text/x-jsrender"><div>{{:name}} ({{:year}})</div></script>');
If you put that into an external file and link it via
<script type="text/javascript"
src="template/myTemplate.js">
</script>
Then the script will append a valid script tag copy of the string to the DOM that jsrender can actually access. Of course, this does end up using roughly double the memory on the client but... if it's not too big of a file it shouldn't be a problem.
Browsers won't download scripts in languages they do not (internally) support (based on the type attribute).
Get the URI from the src attribute, then request the resource with XHR.
Related
I'm a front-end developer. When I write a html code I repeat my self a lot by copy and paste (header section, footer section, etc).
How I can write modularize my html files? Like separate header.html and footer.html, and after that call both in index.html... same as erb in Ruby on rails? (I don't like jade lang)
In PHP we would do something like this:
index.php
<?php
include 'inc/head.inc.php'; //DOCTYPE and <head> stuff
include 'inc/header.inc.php'; //NAV or other top-of-page boilerplate
?>
<div id="uniqueDIV">
//Your unique page-specific divs can go here
</div>
<?php include 'inc/footer.inc.php'; ?>
So, in your head.inc.php file, you just have the usual DOCTYPE and <head> portion of your page file.
In Ruby, it appears the equivalent instruction is something like:
load "inc/head_inc.rb" -- OR --
require_relative "inc/head_inc.rb"
https://practicingruby.com/articles/ways-to-load-code
Another option is to use a bit of js/jQuery to populate parts of the document. If you don't have PHP, this is 2nd best option. It's less optimal than PHP because the js/jQ code will run after the page is fully rendered, which may cause a minuscule (but noticeable) lag before the code appears.
For example:
html
<div id="navbarDIV"></div>
js/jQuery:
<script type="text/javascript">
$(function(){
$('#navbarDIV').load( 'inc/navbar.inc.html' );
});
</script>
Note that you will need jQuery loaded to use the above code. Simple as this line in your <head>:
<script src="//code.jquery.com/jquery-1.11.3.min.js"></script>
jsFiddle demo
Final note: the script tag can be included in your <head> as an external file, or it can be plopped anywhere in your document with the rest of the html. Whatever works. But <head> as external file, or last element in body (also as an external file) are preferred.
Final final note: the ".inc." naming convention is not required, it's just my own practice. Include file could be named head.html or head.php or etc.
You could consider using something like Swig, which doesn't require a server (you can compile your templates locally).
Swig's syntax is much like Mustache or Handlebars, it uses braces and works inside of normal HTML, so you can retain the HTML syntax you want (unlike Jade).
For separating HTML into files to be reused, you can check out Template Inheritance. You can also see File Inclusion and File Imports.
Here is a small example:
{% include "./header.html" %}
<div id="body">Hello world</div>
{% include "./footer.html" %}
i use gulp, and i want tools for compile file to standard html file. like jade. – Sajad Abedi
For this you can use gulp-swig and build your templates locally in a task.
I have used EJS, which is convenient.
You can have a try.
For HTML files there is no standard way for reusing HTML parts. You have to use into a templating system.
But erb is a templating system and can handle that. See this Stack Overflow answer about "Including one erb file into another".
I am using Jinja2 for making templates, and from what I have seen in other questions, I can pass a list to the template using the {{x}} notation. My problem is, wouldn't that mean that I would have Javascript code in the HTML template?
From what I understand it is better to separate the scripts from the HTML, and just call the scripts before closing the body tag. If I do something like what I wrote first, that wouldn't be the case, as seen in the example below.
<body>
(Other page elements)
<script type="text/javascript">
function test_func(data) {
console.log(data);
}
test_func({{ data|safe }}) <-- MyList
</script>
</body>
In this case I would have some javascript in my html template, which as I understand is not optimal. How can I solve this?
The data could be loaded from an endpoint through AJAX or stored in your DOM.
Either using a tag and the window object if you expect to use it in multiple places in your application and have no problems with polluting the global namespace
<script>
window.myInitData = {{{myJSdata}}};
</script>
or on a DOM element
<div data-data={{{myJSData}}}></div>
which you'd then query for
var data = document.querySelector('yo').dataset.data;
test_func(data);
Now addressing your question about "storing JavaScript code in your HTML" for sure, you would not like to embed the JavaScript like that unless you're doing tracking or loading of external scripts. However storing data in the DOM would be considered fine, normally, and the upshot of doing the storing in data attributes is that scripts loaded through your normal script tags would get access to your data by querying for it.
A common pattern for loading backbone templates is something like:
<script type='text/template' id='foo'>
my template
</script>
----
var whatever = $('#foo').html();
I would like to include the script in an external file like so:
<script type='text/template' id='foo' src='myTemplate.tpl'></script>
But the html() of foo is now empty.
I watched the browser pull the template file down, but I am not sure if it is in the page dom or not. Is there a simple way to reference the content of the script in javascript, or did the browser simply ignore it and throw out the result?
I think to actually execute externally loaded script you have to do an eval() of the contents. You're not adding it to the DOM really since it's script, you're adding it to the JS runtime. There might be other ways of doing it but eval() is generally considered a security hole since malicious code could be evaluated.
What I tend to do is generate template sections on the server so I know all my JS is there when the DOM is ready.
If the point is execute an action just after the script has been loaded you can put a onload attribute on the script tag. If you want to download the content in runtime, then you could use the async download strategy (like Gats pointed).
It´s important keep in mind some important points when using templates for jquery templates in external files, there is an interesting article about jquery templates with external files, you must check it.
Is there a way to include the prototype.js code directly in the html file?
I do not want to have something like this:
<script type="text/javascript" src="/path/to/prototype.js"></script>
I want something like this:
<script type="text/javascript" >
// the code of prototype.js to be here
</script>
The context for what I want this is more complex. I just want to know now if this is possible or not.
P.S.I'm not very familiar with Prototype.
Thank you.
Yes it will work if you copy paste the entire content inside the script tags.
We do something similar with jQuery and our other JS and CSS files for our web app. They are all compressed and included inline when we run our deployment script.
It makes the page relatively heavy (300kb) but the main advantage is you get everything in a single http request. This makes the app look very fast.
The page is then cached, making next visits even more responsive.
I want to use JSTL's fmt tag in JavaScript to localize my alert messages.
My JavaScript file is a standalone file and when I include fmt tag in js, the file browser gives JavaScript errors. Is it possible to treat .js file as .jsp files using web.xml configuration?
Can anyone please suggest how can I do that?
is it possible to treat .js file as .jsp file using web.xml configuration?
Yes:
<servlet>
<servlet-name>scriptjsp</servlet-name>
<jsp-file>/script.jsp</jsp-file>
</servlet>
<servlet-mapping>
<servlet-name>scriptjsp</servlet-name>
<url-pattern>/script.js</url-pattern>
</servlet-mapping>
But, there is no actual advantage in doing this, because JavaScript files do not have to have URLs ending in ‘.js’. What determines whether a file is a JavaScript file is what MIME media type it is served as. You can set this from JSP using:
<%# page contentType="text/javascript" %>
at the top. Then you can link directly to:
<script type="text/javascript" src="/script.jsp"></script>
(Aside: in current browsers, scripts linked to with the <script> tag will work even without having the Content-Type properly set, but that's probably not something to rely on.)
I want to use JSTL's fmt tag in javascript
This is probably not a good idea. The fmt tag deals with HTML-escaping for characters, but what you want is JavaScript string literal escaping, for example to backslash-escape quote characters. JSTL doesn't provide this capability. You'll get unexpectedly-escaped ‘&’ characters showing up in your JavaScript strings, and use of apostrophe or double quote in messages will break the whole script.
Also, serving commonly-included scripts from JSP risks poor performance and cacheing.
I'd suggest an independent language lookup system in JavaScript. For example, include a per-language external script:
<script type="text/javascript" src="/script/lang/en.js"></script>
(changing 'en' to match whichever language you want), and in that file define a lookup like:
var msg= {
messageName: 'Message in English',
...
};
Then look up msg.messageName for each localisable string in the script.
If your javascript is 'inline' with the rest of your JSP page, then simply use the technique suggested by Kees de Kooter.
If your javascript needs to be in an external file (For sharing across pages, for example) then simply put it in its own JSP file.
<%#page contentType="text/javascript" %>
<fmt:message key="some.message" var="someMessage"/>"
<fmt:message key="another.message" var="anotherMessage"/>"
var someMessage = "${someMessage}"
var anotherMessage = "${anotherMessage}"/>"
And include it like this...
<script src="yourScript.jsp" language="JavaScript" type="text/javascript"></script>
You can then refer to 'someMessage' and 'anotherMessage' from within the file that includes the JSP, or from any javascript file that is included after 'yourScript.jsp.
Note the use of the contentType attribute - 'text/javascript' prevents the JSP parser from complaining that the output isn't well formed XML - and that the tage refers to a JSP file.
A combination of this technique and that suggested by #Magner should bring you to a sensible solution.
EDIT: Changed the example to use 'text/javascript' insetad of 'text/plain' - thanks to #bobince for making me realise this error (Even though 'text/plain' works, it's more correct to use 'text/javascript'). Also, if the number of strings that need to be internationalised is small, and/or you can justify having your 'resources' in more than one place - one for the server side stuff and another for the client side stuff - #bobince's technique of using dynamic includes is a good one.
I would suggest you write a servlet that generates an array or javascript object that contains all the localized information you desire. You can use Java resource bundles which can be shared by both the client and server sides, then you don't have to intermix JSP code and Javascript code, and the servlet response will be cached by the browser.
Create a servlet, map it to a path, have it read the locale from a request parameter then generate the Javascript code.
Use a line like <script src="/mydict?lang=en"></script>
then load you script afterwards <script src="/myscript.js"></script>
You should strive to keep your javascript code in a separate file from the jsp-code. This is to get browser caching, easier maintenance, reuse across pages, and to allow compression.
I suggest that you create a global object for text in the jsp, to be used by your javascript files. Like this:
<script>
var text = text || {}; // play well with other jsps on the page
text.this_page_name = {
required_field_error: "<fmt:message key="required.field.error"/>",
system_error: "<fmt:message key="system.error"/>"
};
</script>
Later you use it in your javascript:
alert(text.this_page_name.required_field_error);
You could do the following. You store the translated message in a variable that can be resolved later on in the JSP.
<fmt:message key="your.alert" var="theAlert"/>
<script type="text/javascript">
alert("${theAlert}");
</script>
You can't use tags in JavaScript but there is a workaround: Put the tag into an hidden DIV (<div style="display: none;" id="msg"><fmt:...>
Now you can use JS to look up the DIV by its ID and get the innerHTML.
That said, fmt is just a wrapper for Java's i18n functions which you can use directly between <% %>.
If you are going for only alert messages
just use this tag in your javascript
Suppose you have following in your Javascript:
alert("Confirm Deletion");
This can be internationalized by adding bean:message tag in your javascript
alert('<bean:message key="msg.confirm"/>');
and add key value in property file
msg.delete=Confirm Deletion