Using text/html javascript templates in production code - javascript

Has anyone implemented John Resig's micro-templating in production code? In particular I'd like to know if embedding the templates with <script type="text/html"> has caused any problems.
A bit more information: here's the sort of thing I'm worried about:
My users are mostly in corporate environments - could an unusual proxy server mangle or strip out the templates
The embedded templates seem to fail W3C validation. What if, for instance, the next version of IE decides it doesn't like them?

I abandoned inlining templates through scripttags as my view layer would create redundant duplicate script templates. Instead I placed the templates back into the JavaScript as string:
var tpl = ''.concat(
'<div class="person">',
'<span class="name">${name}</span>',
'<span class="lastname">${lastName}</span>',
'</div>'
);
I used the string concat trick so I could make the template string readable. There are variations to the trick like an array join or simply additive concatenation. In any case, inline script templates works and works well, but in a php/jsp/asp view layer, chances are you will create redundant duplicate script templates unless you do even more work to avoid it.
Furthermore, these templates become rather complex the more logic you have to add to them, so I looked further and found mustache.js which imo. is far superior and keeps the logic (conditions and dynamic variable definitions) in the JavaScript scope.
Another option would be to retreive template strings through ajax, in which case you can put each template inside it's own file and simply grant it a .tpl extention. The only thing you have to worry about is the http request roundtrip, which should not take too long for small .tpl files and is imo. insignificant enough.

While I haven't used #jeresig's micro-templating, I did roll my own which uses <script type="text/html">. I've used it in a couple of (albeit basic) production sites without problems. The HTML5 spec itself refers to something similar (near the end of the section I've linked to). AFAIK the block only executes when the MIME type is a recognized script type, otherwise the block is just part of the document.

I have actually, and it works great. Though only for webkit powered browsers so can't vouch for others. But what problems are you expecting? The approach is simple and I can't think of how it might break.

If you're using jQuery I can recommend jQuery templates instead:
http://github.com/nje/jquery-tmpl
I think it's supposed to be introduced officially in jQuery 1.5
BTW. I think both Resigs script and jQuery templates relies on using innerHTML, so as long as that works in your browser you should be OK.

Related

What exactly is considered inline javascript? (in review of speed/efficiency cache comparison)

I have a lot of inline javascript, but nothing more then calls to functions such as:
<form id="some_id" style="x" method="post" onsubmit="return someFunction(this);"></form>
or "onchange", "onkeyup". I also have some scripts (not many) written inside <script> tags in html and all of the rest is external. The inside calls just as explicit above are all called to external script functions.
I opted to do this because found it more practical considering many async calls with element insertion and needed listeners to register those changes. This is, $.on("form onsubmit", function(){ would not apply to new elements appended async without a listener.
I'm building new elements in the server side due to my template structure and append them directly on the ajax callback.
My main file.js (external) is sitting at 1832 lines and and my index file which includes file.js has about ~500, ~350 with inline javascript as shown above.
This said:
Would it be considered a huge flaw to leave inline javascript as shown above (yes I know google does that) or could it be considered acceptable even by high standards?
Considering "inline javascript is not kept in cache", what does that mean exactly? Each time the user requests the web page he fetches the whole "onsubmit" in the line above? Or am I missing the meaning of this sentence.
Sorry if the question is vague but I'm quite thinking I had most of my service barely done and don't know if I should go over this or not at all :( thank you very much.
It's really hard to define "huge flaw" so let's just stick to pro's and con's of keeping the code "as-is":
Pro's :
Your current code works : No additional work is needed.
Con's :
Harder to debug : you JS is split on many places, a bug will be harder to track using the browser debug tools.Especially for more experienced JS developers who "expect" (or at least hope) the code to be organised following the good practices, like separating HTML, JS and CSS.
Speed : Your clients have to download and parse the additional JS with each query. If you were able to factorize all these methods calls in the main JS file, this would not be needed.
Modularity : all the methods you are calling from the HTML have to sit in the global namespace. The script you have written will be harder to reuse.
So basically, I would keep the code like this if the website is meant to be developed by you only, won't be used by million people and if you do not hope to reuse any of this code on another project.
If any of these condition is not met, I would refactor the code.
Also, refactoring the code, and learning how to correctly bind handler is a very good exercice if you plan on learning some more javascript.
$('body').on('onsubmit', 'form', function(){});
This will deal with any future changes to the DOM.

Is there a danger to creating a js file that simply uses document.write() to bundle js and css files?

I am building a front-end UI framework for developers in my firm to use to build internal web apps. It consists of customized Bootstrap, jQuery, other open-source libraries, internal modules and stylesheets. The user environment is entirely IE9 and my server is .NET 3.5. I am hosting the shared files. Dev teams in the firm will place the links in their project pages and apply the framework to their pages.
I want to offer them the simplest method of implementing this which would be one line of code to paste that builds the library for them. Cutting and pasting 30 lines of code is stale the moment Ctrl + V is pressed, it leaves me no control and is simply inelegant.
Failed Experiments
I tried using Head.js and LazyLoad both of which use best practices for inserting scripts. But each of them has caused either content to display before styled or conditions where methods are called before scripts load. I am giving up on this approach.
It's too volatile.
A simple document.write() solution
Over the weekend, I thought: Why don't I just make a js file named "framework,js", add the script and link files in order with a stack of document.write() lines. Tell developers to put it in the head and that's it. Heck I could add the necessary metatags for IE9 and mobile too for that matter. It's so nasty and simple... but it just might work!
The user base is on an internal network and of limited size. Bandwidth is not a problem. I'll test performance before I choose this. I can direct the developer teams on where to place the link.
Knowing this and providing it actually works, is there any reason why I shouldn't do this?
My only other option to explore is bundling on the server. I am hoping not to have to resort to this since I don't own the server myself and I am not a .NET developer.
Your proposed approach is an excellent one for your situation. It has several advantages over the more sophisticated solutions, including utter simplicity, completely predictable order of execution, and full compatibility with scripts that may not lend themselves to asynchronous loading. I have used it many times in production applications, as have many other developers.
Of course the other solutions have their advantages too, but for what you're doing there is nothing wrong with good old document.write().
It sounds like you have a number of scripts and stylesheets and are probably loading them from a common directory (or a common root directory). To reduce repetition in your framework.js file, you might want to define two functions, one to write a <link> tag for CSS and another to write a <script> tag for JavaScript. So a skeleton framework.js file might look something like this:
(function() {
var scriptBase = 'js/';
var styleBase = 'css/';
function writeStyle( name ) {
document.write(
'<link rel="stylesheet" href="', styleBase, name, '">',
'</link>'
);
}
function writeScript( name ) {
document.write(
'<script src="', scriptBase, name, '">',
'</script>'
);
}
writeStyle( 'one.css' );
writeStyle( 'two.css' );
writeScript( 'one.js' );
writeScript( 'two.js' );
})();
Note that you don't have to do any special escaping of the </script> text as you may see in code that uses document.write(). That's only necessary when you're putting this code directly inside a <script> tag within the HTML file. The purpose of that escaping is to prevent the enclosing <script> tag from being closed by the </script> text inside the document.write() call. Since your code is in an external .js file this is not an issue: the presence of the </script> text inside this file won't terminate the .js file.
Another point to keep in mind is that all of the document.write() calls you make inside a .js file are inserted into the document after the .js file that writes them. So don't expect to be able to do a document.write() inside framework.js and then have other code inside framework.js that depends on the .js file you just wrote. All of those .js files (and .css) are loaded after framework.js, not interleaved with it.
One more consideration, of course, is load time. Your page could load faster if you combine and minify your CSS and JS files. But if these are internal web apps, page load time may be the least of your worries: reliability and maintainability may be more important. And in any case you can always use the document.write() solution to get up and running right now, and later optimize this only in the unlikely event that you need to.

how to avoid generation document.write in GWT cache.js file

I am using Gwt 2.4. After compiling my project i am getting some document.write lines in the mymodle.chache.js which is most weired .
So i want to know the places which producing these lines in my GWT code and came across and found some lines of code like
element.setInnerHtml("blah ..blah..");
and
doc.write("blah..blah ..");
So i removed those line of code and compiled again again and still getting some (ex:document.write(df+er+t)) lines .
Anyone suggest a way to find the cause to producing those lines from my GWT ??
(assuming you're talking about the *.nocache.js file rather than the *.cache.* files, as *.cache.* don't contain calls to document.write, unless you're using a crappy third-party lib)
The *.nocache.js file is generated by the primary linker, so its content is independent from your code. It contains calls to document.write() for various things: determine your module base URL (as a last resort, when it cannot infer it from elsewhere), inject scripts and stylesheets referenced from your *.gwt.xml files, and finally inject the GWT application code itself (with the standard linker, this will be an <iframe>, with the newer xsiframe linker it'll be a <script>).
If you're really worried about it, it can be customized quite easily by extending the CrossSiteIframeLinker (xsiframe linker) and providing different code snippets.
Tip: compile with -style PRETTY to make the generated code readable.
You are not supposed to hand-edit/modify mymodle.cache.js. This file gets generated again from GWT Compiler. What issue are you trying to solve by hand-editing it?

Backbone: managing templates

I'm using underscore template engine for an backbone application. As of now I have over 15 templates in the <head>. Its getting hard to maintain. So far, most of the solutions I seen to manage templates ended up needing them to be js files. That's also a headache, I prefer them to be html files for editing purposes.
I took a look at requirejs and not sure if I need that since it kinda revolves around a more modular approach that I can't say I'm using at the moment (although I will soon).
What will be the best way to manage templates and load/cache them as needed?
Personally we needed a robust solution at my company, so we went with:
Require.js - for module loading
Handlebars - for more powerful templating than Underscore can offer
HBS - an excellent require plug-in from Alex Sexton that handles bringing compiled templates in via Require
With this setup I can keep all of my templates in their own file, and then to use them I have files like this:
define(['template!path/to/someTemplate'], function(someTemplate) {
var MyNewView = BaseView.extend({template: someTemplate});
$('body').append(new MyNewView().render().el);
}
(and as you might guess we have a base Backbone view called BaseView which uses the view's template property to render the view).
Now, all that being said, if you don't need such a robust setup then Require may not be for you. In that case I would do the following:
Put all of your templates in to one or more HTML files; wrap them in script tags, like so:
<script id="dummyTemplate" type='text/template'>
<span>I'm a template!</span>
</script>
Write some code on your server-side to include those HTML files in the main HTML file you send to the client
Write a function which takes a template ID, gets the text of that element, compiles it in to a template, and returns that template (maybe cache the compiled templates if you want ... of course, with Underscore templates I don't think you even need compiling, so you can skip all that).
Use your function to access your templates: $("#something").html(templateFunc('dummyTemplate').template())
This will allow you to store your templates in html files (for syntax coloring), but still access them conveniently in JS. You can also divide your templates between as many files as you want, as long as you can write include logic to bring them in.
If you do opt for Require though, definitely check out the HBS plugin. And if you haven't looked at Handlebars templates yet, you might want to; they're far more powerful than Underscore ones (but like any good templating system, don't allow for too much logic).
Not sure what you mean by it being unmaintainable. Is it just a long list?
You don't need to keep your templates in the head. They can be at the bottom of your body as well. They just need to be defined before you try to use them.
One thing you might look into, depending on the server technology you are using would be to separate your templates into a different HTML file and include it at runtime.

Add ASP.NET server script to mostly-static .JS / .CSS files without losing IntelliSense?

Using VS2008 and ASP.NET 3.5 (or VS 2010 / .NET 4.0?), how can I include a bit of dynamic ASP.NET server-side code in mostly-static JavaScript and CSS files?
I want to do this to avoid cloning entire JS or CSS files to vary just a small part of them multi-tenant sites. Later, I want to extend the solution to handle localization inside javascript/CSS, dynamic debugging/tracing support, and other cool things you can get by injecting stuff dynamically into JavaScript and CSS.
The hard part is that I don't want to lose all the cool things you get with static files, for example:
JS/CSS code coloring and intellisense
CSS-class "go to definition" support in the IDE
automatic HTTP caching headers based on date of underlying file
automatic compression by IIS
The server-side goodness of static files (e.g. headers/compression) can be faked via an HttpHandler, but retaining IDE goodness (intellisense/coloring/etc) has me stumped.
An ideal solution would meet the following requirements:
VS IDE provides JS/CSS intellisense and code coloring. Giving up server-code intellisense is OK since server code is usually simple in these files.
"go to defintion" still works for CSS classes (just like in static CSS files)
send HTTP caching headers, varying by modified date of the underlying file.
support HTTP compression like other static files
support <%= %> and <script runat=server> code blocks
URL paths (at least the ones that HTTP clients see) end with .JS or .CSS (not .ASPX). Optionally, I can use querystring or PathInfo to parameterize (e.g. choosing a locale), although in most cases I'll use vdirs for this. Caching should vary for different querystrings.
So far the best (hacky) solution I've come up with is this:
Switch the underlying CSS or JS files to be .ASPX files (e.g. foo.css.aspx or foo.js.aspx). Embed the underlying static content in a STYLE element (for CSS) or a SCRIPT element (for JS). This enables JS/CSS intellisense as well as allowing inline or runat=server code blocks.
Write an HttpHandler which:
looks at the URL and adds .aspx to know the right underlying ASPX to call
uses System.Net.HttpWebRequest to call that URL
strips out the containing STYLE or SCRIPT tags, leaving only the CSS or JS
adds the appropriate headers (caching, content type, etc.)
compresses the response if the client suports compression
Map *.CSS and *.JS to my handler.
(if IIS6) Ensure .JS and .CSS file extensions are mapped to ASP.NET
I'm already using a modified version of Darick_c's HttpCompression Module which handles almost all of above for me, so modifying it to support the solution above won't be too hard.
But my solution is hacky. I was wondering if anyone has a more lightweight approach for this problem which doesn't lose Visual Studio's static-file goodness.
I know I can also hack up a client-side-only solution where I split all JS and CSS into "vary" and "won't vary" files, but there's a performance and maintenance overhead to this kind of solution that I'd like to avoid. I really want a server-side solution here so I can maintain one file on the server, not N+1 files.
I've not tried VS10/.NET 4.0 yet, but I'm open to a Dev10/.net4 solution if that's the best way to make this scenario work.
Thanks!
I have handled a similar problem by having a master page output a dynamic generated JSON object in the footer of each page.
I needed to have my js popup login dialog box support localization. So using JSON.NET for serialization, I created a public key/value collection property of the master page that pages could access in order place key/values into such as phrase key/localized phrase pairs. The master page then renders a dynamic JSON object that holds these values so that static js files could reference these dynamic values.
For the js login box I have the masterpage set the localized values. This made sense because the masterpage also includes the login.js file.
I do commend you on your concern over the number of http requests being made from the client and the payload being returned. Too many people I know and work with overlook those easy optimizations. However, any time I run into the same issue you're having (which is actually quite often), I have found I've usually either taken a wrong turn somewhere or am trying to solve the problem the wrong way.
As far as your JS question goes, I think Frank Schwieterman in the comments above is correct. I'd be looking at ways to expose the dynamic parts of your JS through setters. A really basic example would be if you have want to display a customized welcome message to users on login. In your JS file, you can have a setMessage(message) method exposed. That method would then be called by the page including the script. As a result, you'd have something like:
<body onLoad="setMessage('Welcome' + <%= user.FirstName %>);">
This can obviously be expanded by passing objects or methods into the static JS file to allow you the functionality you desire.
In response to the CSS question, I think you can gain a lot from the approach Shawn Steward from the comments makes a good point. You can define certain static parts of your CSS in the base file and then redefine the parts you want to change in other files. As a result, you can then dictate the look of your website by which files you're including. Also, since you don't want to take the hit for extra http requests (keep in mind, if you set those files to be cached for a week, month, etc. it's a one time request), you can do something like combining the CSS files into a single file at compilation or runtime.
Something like the following links may be helpful in pointing you in the right direction:
http://geekswithblogs.net/rashid/archive/2007/07/25/Combine-Multiple-JavaScript-and-CSS-Files-and-Remove-Overheads.aspx
http://www.asp.net/learn/3.5-SP1/video-296.aspx?wwwaspnetrdirset=1
http://dimebrain.com/2008/04/resourceful-asp.html
By utilizing the combining at run or compile time you can gain the best of both world by allowing you to logically separate CSS and JS files, yet also gaining the reduction of payload and requests that comes with compressing and combining files.

Categories