Custom Javascript in EJS templates using Sails.js - javascript

I'm getting wet with Sail.js, which I love so far, but I'm stuck on a simple question: If I have a javascript function that I want to run just on a particular view, where do I invoke it?
A very simple example would be this:
//contact.ejs
<div id="contact"></div>
<script>
renderContact();
</script>
Let's assume renderContact is defined in my master JS file for the site, and does what it sounds like: Creates a contact list in <div id='contact'></div>.
Of course, that master JS file, as well as all vendor JS, doesn't get loaded until AFTER this script tag since it's injected into layout.ejs, so that function will be undefined. I could always natively wait for the page to load like so:
document.addEventListener("DOMContentLoaded", function(event) {
renderContact();
});
But that seems like a horrible solution.
I realize that Sails integrates powerfully with Angular, React, and so forth, but I first want to understand the basic way that one invokes JS to a single page before I get fancy. There must be a better way to run certain functions only on certain pages once the DOM has loaded?

So for renderContact to work it should look like this:
<html>
<head></head>
<body>
HTML
<script src="master.js"></script>
<script>
(function() {
renderContact();
})();
</script>
</body>
</html>
The downside of ejs is that AFAIK it does not support blocks. It's kind of bare metal. So you have to put all your scripts in the main layout file and the scripts will be around on pages where they are not needed. But you can configure other template engines in sails, like jade. Jade supports blocks which you can override or extend. Here is an example of jade blocks: https://stackoverflow.com/a/22748166/401025

Related

Can I create a common include file in HTML? [duplicate]

Is there a decent way with static HTML/XHTML to create common header/footer files to be displayed on each page of a site? I know you can obviously do this with PHP or server side directives, but is there any way of doing this with absolutely no dependencies on the server stitching everything together for you?
Edit: All very good answers and was what I expected. HTML is static, period. No real way to change that without something running server side or client side. I've found that Server Side Includes seem to be my best option as they are very simple and don't require scripting.
There are three ways to do what you want
Server Script
This includes something like php, asp, jsp.... But you said no to that
Server Side Includes
Your server is serving up the pages so why not take advantage of the built in server side includes? Each server has its own way to do this, take advantage of it.
Client Side Include
This solutions has you calling back to the server after page has already been loaded on the client.
JQuery load() function can use for including common header and footer. Code should be like
<script>
$("#header").load("header.html");
$("#footer").load("footer.html");
</script>
You can find demo here
Since HTML does not have an "include" directive, I can think only of three workarounds
Frames
Javascript
CSS
A little comment on each of the methods.
Frames can be either standard frames or iFrames. Either way, you will have to specify a fixed height for them, so this might not be the solution you are looking for.
Javascript is a pretty broad subject and there probably exist many ways how one might use it to achieve the desired effect. Off the top of my head however I can think of two ways:
Full-blown AJAX request, which requests the header/footer and then places them in the right place of the page;
<script type="text/javascript" src="header.js"> which has something like this in it: document.write('My header goes here');
Doing it via CSS would be really an abuse. CSS has the content property which allows you to insert some HTML content, although it's not really intended to be used like this. Also I'm not sure about browser support for this construct.
The simplest way to do that is using plain HTML.
You can use one of these ways:
<embed type="text/html" src="header.html">
or:
<object name="foo" type="text/html" data="header.html"></object>
You can do it with javascript, and I don't think it needs to be that fancy.
If you have a header.js file and a footer.js.
Then the contents of header.js could be something like
document.write("<div class='header'>header content</div> etc...")
Remember to escape any nested quote characters in the string you are writing.
You could then call that from your static templates with
<script type="text/javascript" src="header.js"></script>
and similarly for the footer.js.
Note: I am not recommending this solution - it's a hack and has a number of drawbacks (poor for SEO and usability just for starters) - but it does meet the requirements of the questioner.
you can do this easily using jquery. no need of php for such a simple task.
just include this once in your webpage.
$(function(){
$("[data-load]").each(function(){
$(this).load($(this).data("load"), function(){
});
});
})
now use data-load on any element to call its contents from external html file
you just have to add line to your html code where you want the content to be placed.
example
<nav data-load="sidepanel.html"></nav>
<nav data-load="footer.html"></nav>
The best solution is using a static site generator which has templating/includes support. I use Hammer for Mac, it is great. There's also Guard, a ruby gem that monitors file changes, compile sass, concatenate any files and probably does includes.
The most practical way is to use Server Side Include. It's very easy to implement and saves tons of work when you have more than a couple pages.
HTML frames, but it is not an ideal solution. You would essentially be accessing 3 separate HTML pages at once.
Your other option is to use AJAX I think.
You could use a task runner such as gulp or grunt.
There is an NPM gulp package that does file including on the fly and compiles the result into an output HTML file. You can even pass values through to your partials.
https://www.npmjs.com/package/gulp-file-include
<!DOCTYPE html>
<html>
<body>
##include('./header.html')
##include('./main.html')
</body>
</html>
an example of a gulp task:
var fileinclude = require('gulp-file-include'),
gulp = require('gulp');
gulp.task('html', function() {
return gulp.src(['./src/html/views/*.html'])
.pipe(fileInclude({
prefix: '##',
basepath: 'src/html'
}))
.pipe(gulp.dest('./build'));
});
You can try loading them via the client-side, like this:
<!DOCTYPE html>
<html>
<head>
<!-- ... -->
</head>
<body>
<div id="headerID"> <!-- your header --> </div>
<div id="pageID"> <!-- your header --> </div>
<div id="footerID"> <!-- your header --> </div>
<script>
$("#headerID").load("header.html");
$("#pageID").load("page.html");
$("#footerID").load("footer.html");
</script>
</body>
</html>
NOTE: the content will load from top to bottom and replace the content of the container you load it into.
No. Static HTML files don't change. You could potentially do this with some fancy Javascript AJAXy solution but that would be bad.
Short of using a local templating system like many hundreds now exist in every scripting language or even using your homebrewed one with sed or m4 and sending the result over to your server, no, you'd need at least SSI.
The only way to include another file with just static HTML is an iframe. I wouldn't consider it a very good solution for headers and footers. If your server doesn't support PHP or SSI for some bizarre reason, you could use PHP and preprocess it locally before upload. I would consider that a better solution than iframes.

How many ways are there to maintain handlebars template in client side

In my application we are templating handlebars from client side(we are not templating from server side).So till now we used maintaining all templated inside of the html file using script tag like in the following way.
<script id="selectdropdownTpl_mobile" type="text/x-handlebars-template">
<option value="{{optValue}}" label="{{name}}">{{name}}</option>
</script>
Whenever I want template, I am just compiling and appending compiled result to dom just like following way
var alertCompilation= Handlebars.compile(document.getElementById("selectdropdownTpl_mobile").innerHTML)
alertCompilation({"optValue":"test","name":"firstApp});
Working fine,but what we are thinking to separate all handlebar templates into another file.so it's easy to maintain html file.
Regarding this,I thinking to move all the templates into .js file inside of the file just creating global variable,it is object in the following way.
//fileName test.js
var templates={
"selectdropdownTpl_mobile":"template code"
}
whenever I want, I can access template code like in the following way.
var alertCompilation= Handlebars.compile(templates["selectdropdownTpl_mobile"]);
alertCompilation({"optValue":"test","name":"firstApp});
This way also working fine,What I want to know is this good way or not.If it is not good way How shell do this.
I heard about .hbs file, basically it contains pre-compiler template.It's usefull If I template from server side but in my case templating happening in client side itself.
can anyone suggest me,which way is better.

Embedded Javascript missing from Google Apps Script Web App serverHandler output

I'm trying to embed some JavaScript into the output of a Google Apps Script that is running as a web app, but I can't find any evidence of my script tags or jQuery loading in the output, so I think it is getting stripped out, I assume, by Caja.
I'm adding the JavaScript by creating an HTMLOutputObject from a file, like this:
app.add(app.createHTML(HtmlService.createHtmlOutputFromFile("order_form_javascript").getContent()));
Maybe it is worth mentioning here that the javascript is added this way in a serverHandler attached to a listBox change event - NOT in the initial doGet() function - I'm not sure if that makes a difference.
The content of the order_form_javascript.html file is:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<h3>Javascript!</h3>
<script type="text/javascript">
alert ("script ran");
$(function() {
alert ("function ran");
$('.order_table tr:hidden').show();
});
</script>
The H3 tags are in the output, but no script tags appear, no alert boxes pop up and jQuery is undefined.
I tried this code on the Caja playground and it seems to work. So I think that I must be inserting the javascript incorrectly, or missing something obvious.
Thanks, in advance, for any suggestions you can offer.
I'm not deeply familiar with Apps Script, but it looks like you are trying to mix Ui Service (add, createHTML) and Html Service in the same page. This is not supported — you must choose one or the other for the entire page.
A side note on troubleshooting: Caja never inserts the script you write in the DOM (doing so would break the sandbox). In NATIVE sandbox mode you may see <script> elements with empty or stub contents, though. So, the absence of scripts does not itself indicate a problem.
Following Kevin Reids tips that Caja wouldn't likely show script tags anyway, as this would break sandboxing, and also that HtmlService and UiService may be incompatible in the same script, I updated my code to the following:
var js = HtmlService.createHtmlOutputFromFile("order_form_javascript").getContent();
Logger.log(js); //check that HtmlService generates the script properly.
app.add(app.createHTML(js));
Looking in the logs, I can clearly see that HtmlService is returning my HTML file's content verbatim:
[13-07-24 10:02:28:879 BST] <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<h3>Javascript!</h3>
<script type="text/javascript">
alert ("script ran");
$(function() {
alert ("function ran");
$('.order_table tr:hidden').show();
});
</script>
Which makes me think that maybe I could use this method to output arbitrary HTML without writing it all in code, but I digress.
This lead me to the app.createHTML([String]) method and, according to the documentation here, HTML widgets can't actually contain <script> tags. So that's where they are being stripped out. It turns out I should have read the manual. How embarrassing.
The two possible solutions I can think of are;
Re-write my web app using HtmlService instead of UiService, which I think would allow more arbitrary html and scripts from HTML files in the project.
Since my JavaScript is going to be event driven and very simple, I could also use a clientHandler to perform the necessary actions and continue using the UiService for my web app.
I'm going to start with the clientHandler approach.

Can I use javascript with bottle (framework)?

I'm trying to display a page of html using bottle (the python web framework). The page has javascript embedded but it won't display it when I serve it with bottle.
The JS I'm using is EditArea, I can clean it up how I want and put it an html page that displays properly when I open the page in chrome. But when I use bottle:
#route('/edit')
def edit():
return template('editarea')
#route('/edit_area')
def edit_area():
send_file('example1.html', root='path/to/file/')
and go to http://localhost:8080/edit or /edit_area, I see the page without any of the fancy javascript features.
Eventually I want to hook this up (EditArea is text area and I'll be using it to accept code which hopefully I'll be able to run... but that's a separate issue...), but right now all it's supposed to do is display the page and the javascript. The JS is put in the html as simply as possible. Those two blocks use different files but they are just copies of the same html file, one with .html and the other with .tpl extensions.
<title>EditArea - the code editor in a textarea</title>
<script language="Javascript" type="text/javascript" src="../edit_area/edit_area_full.js"></script>
<script language="Javascript" type="text/javascript">
// initialisation
editAreaLoader.init({
...and then it's all of the JS code (that I didn't write).
In the file to start the server I import: route, run, debug, template, request, send_file, and error from bottle; and sqlite3; but that's all. Is there something else I should be including?
I've looked into the bottle documentation, and a few other places and it's either something really obvious that nobody bothers to write down or it's something that people just don't do...
I was looking at pyjamas (it keeps coming up with different combinations of search queries involving "python" and "javascript"), but it looks like that just converts python into javascript. I don't think that's what I want b/c the javascript is already javascript...
Thanks for any insight you might have.
You need to create a view to serve static files, as described in Bottle documentation.
I suggest you to put all your static files (css, js, images) in a static folder next to your application. The view to serve static files would then look like this:
from bottle import static_file
#route('/static/:filename:')
def send_static(filename):
return static_file(filename, root='./static/')
You would then include your .js file like this (using the path you'll have choosen of course):
<script type="text/javascript" src="/static/edit_area/edit_area.js"></script>
If you're using the template system included in Bottle called SimpleTemplate then it does not support multi line strings and the templates get compiled to executable Python bytecode. So its likely any Javascript would be stripped out.
The only way to include javascript in your page would be via script tags as you did for the "edit_area_full.js" file.

Explanation of <script type = "text/template"> ... </script>

I just stumbled upon something I've never seen before. In the source of Backbone.js's example TODO application (Backbone TODO Example) they had their templates inside a <script type = "text/template"></script>, which contained code that looks like something out of PHP but with JavaScript tags.
Can someone explain this to me? Is this legit?
Those script tags are a common way to implement templating functionality (like in PHP) but on the client side.
By setting the type to "text/template", it's not a script that the browser can understand, and so the browser will simply ignore it. This allows you to put anything in there, which can then be extracted later and used by a templating library to generate HTML snippets.
Backbone doesn't force you to use any particular templating library - there are quite a few out there: Mustache, Haml, Eco,Google Closure template, and so on (the one used in the example you linked to is underscore.js). These will use their own syntax for you to write within those script tags.
It's legit and very handy!
Try this:
<script id="hello" type="text/template">
Hello world
</script>
<script>
alert($('#hello').html());
</script>
Several Javascript templating libraries use this technique. Handlebars.js is a good example.
By setting script tag type other than text/javascript, browser will not execute the internal code of script tag. This is called micro template. This concept is widely used in Single page application(aka SPA).
<script type="text/template">I am a Micro template.
I am going to make your web page faster.</script>
For micro template, type of the script tag is text/template. It is very well explained by Jquery creator John Resig http://ejohn.org/blog/javascript-micro-templating/
To add to Box9's answer:
Backbone.js is dependent on underscore.js, which itself implements John Resig's original microtemplates.
If you decide to use Backbone.js with Rails, be sure to check out the Jammit gem. It provides a very clean way to manage asset packaging for templates.
http://documentcloud.github.com/jammit/#jst
By default Jammit also uses JResig's microtemplates, but it also allows you to replace the templating engine.
It's a way of adding text to HTML without it being rendered or normalized.
It's no different than adding it like:
<textarea style="display:none"><span>{{name}}</span></textarea>
<script type = “text/template”> … </script> is obsolete. Use <template> tag instead.
jQuery Templates is an example of something that uses this method to store HTML that will not be rendered directly (that’s the whole point) inside other HTML:
http://api.jquery.com/jQuery.template/

Categories

Resources