I've been tinkering around with Backbone.js and wanted to know if there is possible to load View templates from external files. I've been using Underscore.js's micro template solution and including all my templates inside my HTML document has been bothering me.
I wanted to know if there is a standard way of doing this. Is there any good practice I should follow?
Thank you all for you time and help :-)
For all the template libraries that compile strings to javascript, with a little code in the header, each template could be stored in a separate file and exported through a common windows.myTemplates object or similar. The code would just evaluate the given string (the actual template), and bind the result to the windows object to make it available to other scripts. This way each template would be it's own script and would be accesses through a global object like windows.myTemplates.someTemplate.
That does not mean this is a good idea; unless you have many and/or big templates that are loaded very seldom, the normal goal is to minimize the roundtrips to the server, which is the exact opposite of what you are doing. Server-side, things are a bit different, but I'm assuming you're talking client side (based on your question).
There are fancier ways of pulling things in only when needed (google "javascript AMD", require.js and similar), but those are a bit more challenging to get started with.
Related
I use several templates in a Chrome content script for elements I'm adding to matched pages.
Currently I'm storing these templates as string in the script, but I wonder if there are better ways to do this.
tl;dr answer - Yes, you can store them in a <script type="text/html"> tags or load them dynamically through ajax. Examples here (from KnockoutJS) and here. Store them in a file with the proper extension and use an empty tag with an id X, then $("#X").load("/path/to/template", function() { renderX(); })
Long answer with insightful thoughts, keep reading...
Please make sure templates/views or related GUI components of your system are in separate files (Keep reading to know why)
As a front end engineer, I learned to keep layers as separate as possible; this helps your team to understand better your code and make it more maintainable. Separating your layers in modules and then assembling them through an "assembly" mechanism is probably one of the best practices in software engineering. Some of the benefits of this practice include:
Maintainability: Multiple developers can browse and edit single parts of your code in order to create a more robust piece of software.
Readability: With the amount of languages around, you can't expect everyone to understand all the syntax of these X or Y language; mixing languages in a single file is just one step to confusing your code reviewer and make him spend more time than needed.
Accessibility: Take for instance, html, jade, haml, smarty, twig, erb or other template files. Those files should always be named with the proper extension in order to help code editors and IDE's to syntax highlight. A developer should only need to glance a folder to know what those files are supposed to do. A script or bot can come up with important information from just an extension.
By keeping views in separate files, other coders can view them and understand an important layer of the system without needing to understand the entire application; even collaboration gets easier when the developer just need to review those specifics files. Through bashing or scripting, even large architectural systems with thousand of "views" like files can be filtered in order to output just what needs to be reviewed.
(By now I hope I convinced you into removing your string from your code and create a new file and it there, otherwise I really need to improve my writing skills)
So, after we have moved our template to an external file, what do we do next?
A word on Javascript and Chrome-Extensions
Javascript doesn't have a default templating feature (heck, it doesn't even have a modular one, although some smart people are working on it for the ECMAScript Ed. 6, yay!), which means that we need to use a templating library for that. Let's assume you are using Mustache, Underscore template of something alike and thus using its library to render it.
Most of those templating engines use the infamous eval, which can provide a vulnerability to your code, which Chrome Extensions dislike, a lot. The Chrome Extension Dev Team even enforced a new version of the manifest.json file in order to forbid eval, and gave developers the choice to use Sandboxing Pages in order to do so. Luckily for us, they decided to relax the policies a little bit and we can continue use it with a proper CSP definition in our manifest.json.
This means that we need to tackle two problems instead of only one: the "load the template" one and the "render the template in a way won't freak out the new incoming versions of CSP in case the Chrome Extension Dev team change their mind".
Load the template
Load the template, luckily, can be done through an XML HTTP Request through AJAX. Just point the url with the name of the file and you can receive the template as a string, which was probably your original set up. Here's an example that I do with KnokcoutJS:
$("#aiesecTemplate").load('js/libs/aiesec/aiesecTemplate.html', function() {
ko.applyBindings(AIESECViewModel);
});
The #aiesecTemplate is a <script type="text/html"> tag that the browser won't render as part of the DOM. You can use that with other template mechanisms in order to actually assemble your DOM. If you have already a solution for this, this is probably the end of the answer and you can move on with your life. If you are wondering how do we render the code from there, keep reading.
Render the template
The Chrome Dev team suggest us to Sandbox our rendering process due most templating engine libraries being non-CSP compliant (AngularJS being an exception). Here'an excerpt of the code from the Sandbox page.
iframe.contentWindow.postMessage(message, '*');
Where iframe is a specific DOM Iframe Element from the sandbox page with a src attribute of a page that has the templating engine; message has the string template previously loaded, so after posting the message a window.addEventListener for message inside the iframe can render it without a problem. More information about sandboxing eval can be read here
Conclusion
If you made it to here, awesome! My answers might not be that boring. As a last note, you might be thinking "What about AMD or RequireJS?"; to be honest I haven't tried them, but really smart people think that AMD is not the best approach. Loading through a XML HTTP Request might not be better, but in case you think it hits your performance (I have used it in my application and it doesn't) you can always use some Event Pages and Web Workers with that.
As an Actionscript programmer shifting to JS/jQuery I often have to author multipage apps targeted mainly to iOS and I'd like to know what is the best way to structure such apps.
Most of the time my apps are presentations, where each page has a different behavior (i.e., some popups on page1, a group of sliders on page2, some drag and drop action on page3... you get the picture), and more often than not I have to keep track of several variables across different pages.
Right now I handle it like this: I have a group of common functions in a script named my_app.js, while each page has its dedicated pageX.js script to account for its specific duties. I store persistent values through the storage.js library and somehow manage to stick it all together and make it work.
However I recognize that there may be a vast area for improvement to this approach, so I'd like to know how more seasoned developers deal with this situation.
Thanks a lot,
Goblin
What you've done seems OK for a smallish app, but as another answerer said, I'd look at an MVC architecture. I can heartily recommend backbone.js, it's pretty lightweight, and simple to use.
You could easily make a controller for each type of view that you need (e.g. sliderController, dragDropController, etc) and then if you needed to, subclass ('extend') these controllers to be platform specific (e.g. iPhoneSliderController, iPadSliderController, desktopSliderController, etc).
If I had more info about this app - like the data behind it, what the user is achieving by dragging/sliding - then I might be able to give a more specific layout for the models, views, and controllers you might want. But hopefully this is a good starting point, and if you take a look at the backbone.js documentation, it should give you a good idea if it's appropriate for your app.
The structure you have sounds sensible enough (common JS file complemented by page-specific JS files). It also sounds like you're onto the right lines with storage.
What I would do in your situation is focus on how your code is structured in terms of architecture. Chapter 6 of Stoyan Stefanov's Javascript Patterns (O'Reilly) would probably be quite enlightening.
I would also probably explore JS MVC implementations given your situation would lend itself well to this methodology (lots of views).
I realise this is only scattered thoughts, but hopefully it might give you some ideas.
Here is how I organize stuff
in /
modFOO.php
modBAR.php
in /js/
main.js
resourceloader.php //this is a resource loader, so I can load multiple JS in a single request
in /js/pages
modFOO.js
modBAR.js //javascript that for page modBAR
in /css/
main.css
resourceloadercss.php //this a resource loader, so I can load multiple CSS in a single request
in /css/pages/
modFOO.css
modBAR.css
With this setup I know exactly where to find stuff, and where to put stuff. And based on the filename, modepic.css, I know exactly where to put the file, and what is (the CSS file for modepic).
I recent came across Javascript templates and have become quite intrigued.
I am building a large PHP application using the MVC pattern. Templating is handled by the rather awesome Twig.
I recently came across a javascript implementation of twig.
I have also read quite a bit about using javascipt template engines.
Now, in my application, the application generates a the full page for standard requests as fallback for users without javascript. For AJAX requests, it can generate the content part of the page (no <head>, <body> etc).
The ajax response object is currently just a the rendered HTML content, which is then inserted into DOM.
Should I instead return a response object containing a compiled javascript template and the objects to be inserted into the template? What are the benefits of doing that?
From the posts I have read, the javascript templates were only small snippets representing a small part of a page, for example displaying a comment on a blog post during the instant that the user has submitted it.
Are javascript templates only useful for inserting these sort of small "pieces" in a page?
Yes
A recent project I was on got "client-side template fever" and we used the dang things for every single template.
With every template library I've used (which is two or three), the error messages you get are not very good. If you have a huge template that operates on a fair amount of data, you'll quickly find the u.foo is null or not an object error message increasingly frustrating.
The best-practices I've settled on is:
Return a full HTML snippet (from the server) if it's a template that is seldom loaded. If you are only loading that HTML once on a page, then you might as well send it down populated right? This also encourages you to keep your logic up on the server, where it probably belongs.
Use client-side templates for small, repeated templates. Your blog comment example is probably a good one. I've found the most success when my client-side templates are pretty small (< 10 lines)
Use a logic-less template engine. The more logic allowable in a template, the harder they are to read/maintain. Plus, some of that logic should probably be in your business layer, not down in some JavaScript template. In other words, they force you to separate your presentation from your logic (which is good).
PS: It is cool that both your client and server-side templates could use the same templating engine. This will make developers on your project much more productive.
Depending on the scale and requirements of your application, you should take into considerations the following:
don't go rampant on Ajax; Ajax is not WebSockets, so use it sparingly. Plus, client-side execution speed is always key; AJAX is slow when compared to dumping as much resources as possible + using them when you need them; for example, you can send to javascript userdata = {name:'xxxx',address;'yyyy', ...} and using that, instead of requesting name and address via AJAX only when you need them.
it is recommended to use a global PHP var $sendData (or something like that) and right after plasting HTML, you send the $sendData with an easy <script>data = <?php echo json_encode($sendData); ?></script>
javascript templates add up to execution speed. which makes it reasonable to do the alternative, that is, separating everything that is dynamic and caching static resources like javascript functions
you can't, and I quote return a response object containing a compiled javascript template, not without residing to some server-side javascript engine that does the compile job prior to returning it
for your personal welfare, it will always boil down to how fast, easy and painlessly you respond to maintaining the application; there's no point in using super beta experimental frameworks, ports and kits over which you have limited control
Work smart, not hard.
Good luck mate.
You could also look into the Distal http://code.google.com/p/distal templating engine.
I've been doing research on this:
Using Rails 3.1, where do you put your "page specific" javascript code?
But I have yet to see a satisfactory answer, which also makes me question whether I'm doing something wrong.
Here's my mental model: for different views, I'm going to have different
$(document).ready(....)
blocks, that obviously reference elements that are very specific to that page. I don't want to pollute things by loading that code for every single page and somehow trying to figure out how to only execute it when on specific pages; that seems pretty ugly.
My intuition, admittedly not backed up by any preliminary experiments, is that the ideal thing would be to:
Load application wide code from application.js.
Load shared controller code from something like assets/controller_name/shared.js
Load view-specific code from something like assets/controller_name/show.js
Off the top of my head. The helper would, the first time it ran, check if the file exists and, if so, do a javascript_include for it.
Perhaps this has some performance issues compared to the "let's just wrap the whole thing up in a big sticky ball and send it all" approach, but seems like a better approach to compartmentalizing code.
However, as above, I get the feeling I'm missing something. Is $(document).ready on a per-page basis a bad idea? Should that just be in the template and call a page specific bit of JS from application.js? The linked article above comes to that conclusion, but I don't like the image I'm getting in my head of one huge $(document).ready riddled with if this, if that, if the other thing.
What you propose is sound, but not the rails 3.1 way.
They say to divide the JS into many files, but serve as a whole single piece to the user. This allows better performance and scalability, so is a good thing if the final big piece of mud is not so big. Really 3 http requests give worse performance than 1 http request.
So you have already dipartimentized your code, because you have different Coffeescript files, which have different scopes.
To load in your app, just standardize a way to initialize the single piece of code, like calling a "myapp.users.init()" method-.
You could even automatize that peace of code using an helper, so it will be transparent for the controller.
Background
(Why Use The Asset Pipeline At All?)
One of the basic premises behind the Rails asset pipeline is the idea that it is preferable to load all the JS and CSS for a site up front once, and then cache them indefinitely (at least until the site is updated). The Asset Pipeline allows you to do this relatively automatically while still organizing your JS and CSS src files in a logical fashion.
This of course carries an upfront load cost, at the promise of saving time on additional roundtrips loading individual files. If that premise doesn't sit well then the asset pipeline is probably not for you.
The Nut Of The Problem
Ok, so we want to combine all our JS into one file to load it more efficiently. Just because we are going to load all of our JS doesn't mean we want to run all of our JS.
In the reality of a complex webapp you will probably have lots of page specific functionality that you won't want to spend resources executing when the user is not viewing the corresponding page. What we need is a uniform strategy for executing only the portion of our big monolithic JS file that is applicable to the current page.
Convention To The Rescue
I'm not aware of an official Rails strategy to deal with this, but there are some great solutions that establish and then leverage a good convention (which makes things feel "railsy"). The general idea is to define all your page specific JS code into an object literal, and then run only the code relevant to the current page on load.
For the specifics great strategy on how to organize and conditionally execute your JS code, see the answer by #welldan97 on this question:
Using Rails 3.1, where do you put your "page specific" javascript code?
which in turn is based on this article by Jason Garber:
http://viget.com/inspire/extending-paul-irishs-comprehensive-dom-ready-execution
following this post, I took a look at kanso.
From this I learnt that people are not afraid to load to the database context complicated modules if they need them, and that encouraged me a lot.
So I tried kanso. It gave me some trouble that implied immaturity - however, it demonstrateds a great potential.
(mostly compatibiliy view with npm, with node 0.6.x, and some open edge-cases)
So I looked a little deeper.
I saw it comes with a templates engine of it's own.
But what if I want to reuse templates that are written already by another standard?
(for example - haml, or even better - jade that has also a nice text-to-text JS implementation, and a well growing jQuery plugin - same link - see end of document ).
Does anybody here know how coupled the templates engine with the kanso types mechanism, and how simple should it be to use other template engines instead?
Or, what are the limitations I take upon myself when trying to use my own templates?
As far as I can see in the source, DustJS (the template engine of kanso) is not pluggable (like in expressjs for example). That being said, it probably won't be that hard to plug in a different templating engine, the code doesn't seem very complicated.
You might want to add something to this issue on the GitHub page and request for a pluggable templating mechanism.