HTML Template (Custom) Tag - javascript

I understand that using custom html tags is improper for a variety of reasons, but I wanted to run a specific situation by you that might warrant a custom html tag and hopefully get told otherwise or possibly a better way of achieving my goal.
Throughout my code I have what I term as templates that are made up of a div tag with a template and a hidden class attached to it. This is not visible on the screen, but basically these "template" tags contains html that I use in Javascript to create a variety of different items. I do this so that I can style my templates in html rather than have to worry about mixing CSS in with my Javascript.
<!-- TEMPLATE -->
<div class="template hidden">
<span>Random Container</span>
Random Button
</div>
In javascript I would do something like
var template = document.getElementById("template");
var clone = template.cloneNode(true);
clone.removeClass("template hidden");
I would rather be able to do something like this
<template class="hidden">
<span>Random Container</span>
Random Button
</template>
So that if I have multiple templates in a single div I can grab them all rather than having to give them unique class names. Of course my reasoning for needing an implementation goes a lot deeper than this, but its not necessary to waste your time with the details. Let's just say that it will help clean up my Javascript ALOT.
Because the custom template tag is hidden and really is nothing more than a container that is convenient to call within javascript with document.getElementsByTagName("template"); Is this ok to do? I would probably prefix the tag with a custom name in case template ever gets implemented into html.

Modern browsers generally “support” custom tags in the sense of parsing them and constructing DOM nodes, so that the elements can be styled and processed in scripting.
The main problem is IE prior to IE 9, but it can be handled using document.createElement('...') once for each custom tag name.
Another problem is that validators will report the tags as errors, and if there are loads of such errors, you might not notice some real errors in markup. In principle you can create your own DTD to deal with this (I have an HTML DTD generator under construction, but it is trickier than I expected...).
With these reservations, use custom tags if they essentially simplify your job as compared with using classes.

Why not use one of HTML5's data attributes? They are for storing private data or custom info.
For your case, you could add data-type="template" or data-name="template" and then search and remove based on that. One simple function just like you would write to remove your <template> tag, but without breaking rules.
So, using your example, <div data-type="template" class="hidden"></div>

Related

Templating HTML with hidden state instead of comment or custom script tag

Javascript best practices & conventions, such as those emphasized by John Resig and by Nicholas Zachas, author of book Maintainable JavaScript, suggest using HTML comments or script tags with a custom type to store HTML templates.
Comment example:
<div id="myTemplate">
<!-- <ul><li>$item</li></ul> -->
</div>
<script>
var myTemplate = document.getElementById('myTemplate').childNodes[0].data;
var myHtml = myTemplate.replace(/\$item/g, itemValue);
</script>
Script tag example:
<script id="myTemplate" type="text/x-html-template">
<ul><li>$item</li></ul>
</script>
<script>
var myTemplate = document.getElementById('myTemplate').innerHTML;
var myHtml = myTemplate.replace(/\$item/g, itemValue);
</script>
I strongly dislike the comment-based templating because comments are supposed to be just that--comments, intended to be ignored by the functioning application--and as such I'm a little bewildered as to how it even gets to be suggested by JS gurus.
The script tag templating makes a lot more sense, and I'd normally call it a best if not wonderful practice because the purpose and initial non-function are well-delineated. My only issue is that in some modern editors the color highlighting, autocompletion, auto markup validation, etc., are all lost while working within the script tag.
An approach to templating I've taken in the past is to put it all in a container div, then classify the container div as class="template", then in CSS mark it as ".template { display: none; }".
<div id="myTemplate" class="template">
<ul><li>$item</li></ul>
</div>
<script>
var myTemplate = document.getElementById('myTemplate').innerHTML;
var myHtml = myTemplate.replace(/\$item/g, itemValue);
</script>
This has worked fine for me, although the DOM parser and renderer obviously processes the data up front unnecessarily, but I'm not sure whether this is really all that big of an issue or not, as long as the templating constructs do not break HTML validity rules.
My question, then, is, what am I missing? Is the only reason why this third approach to storing template markup--that is, putting it in the DOM as display:none--is discouraged because the DOM parser and renderer will process it anyway? Or are there other reasons, perhaps technical, that I haven't come across yet? I'd like to know because, again, I want to take advantage of my editor's ability to help me fine tune a proper HTML template.
I think that the best method is using the <script> tag. But for your editor,
it must has a solution to add HTML support into the <script> tag with type="html/template-something" too.
For example I code in Sublime Text, and when I want to write a script template tag,
my editor showed me something like this:
As you see, the h1 tag inside the script tag, is different from real h1 in my HTML.
So I search on the internet, and find a solution: finding a file name called HTML.tmLanguage and make this changes:
// change this line
<string>(?:^\s+)?(<)((?i:script))\b(?![^>]*/>)</string>
// to this line
<string>(?:^\s+)?(<)((?i:script))\b(?!([^>]*text/template[^>]*|[^>]*/>))</string>
And after that, I get this result in my editor:
I'm sure there must be a solution for your editor.
Visual Studio 2012
In Visual Studio 2012, if you use the script like this:
<script id="myTemplate" type="text/html">
it will parse the content within it as HTML.
display: none;
Your last solutions, using display: none isn't good, because Search Engines will index the content within it, see this:
Is hidden content (display: none;) -indexed- by search engines?
That unnecessary parsing is why the script tag method is used.
Stating some type other than JS makes the browser ignore that block entirely. Thus, you save processing time and memory. But you might think "Surely users have powerful machines". Not necessarily.
Page performance is a lot slower on mobile, than on the desktop. Mobile has limited memory and processing power. So parsing that hidden block of HTML is unnecessary.
Also, you'll never know what's in the template. It could contain tables with 10k rows. Scripts run in those hidden blocks. It could contain heavy scripts that may contain blocking elements like synchronous XHRs or loops that run 100k times. Who knows!
Additionally, you'd be creating DOM elements and getting them as strings. Why not make them strings in the first place? Skip the DOM building part.
They are templates, you should be running them as needed, not unnecessarily. Unless you know what's inside those hidden tags of yours, then sure, why not? But releasing to the public or making it a generic guideline, I'd stick to the safer method.

HTML Markup Generator from Form

I'm making a html template generator sort of like this. It's going to have specific style and markup so all it really has to do is take the inputs from the form and place them in the "template" and output as text for easy copy/paste. I was wondering if there is an easier way to make this, like using jQuery. Open to all suggestions.
jQuery has a selection of methods for dealing with the DOM that could come in useful for creating HTML markup from a form. It also has a few methods specific to forms themselves, if that suits your purposes.
Check out the API for Manipulation. There are a variety of methods you may find useful.
Since you are constructing HTML with form values, the .wrap() method could be quite valuable to surround content with the inputted tags, ids, and classes, which could be styled with a externally linked CSS file. See also the .wrapAll() and .wrapInner().
You may find the .html() method interesting as well for grabbing the contents of any element. It is somewhat the reverse of what you need but it could come in handy.

Are there javascript template engines that support something like recursion?

The most obvious example I can think of is for outputting nested comments. Let's say you have a tree of comments and you want to output it as nested html (let's say lists inside lists or divs inside divs) using your template.
The "comment" block/function/tag/helper/whatever would have to be able to call itself somehow for the comment's children.
Are there template engines that would support that sort of thing inside one template file?
I am aware that you can just pre-compute the "indent" or "depth-level" of each comment and send them to the template as one flat list in the correct order, but let's just say I don't want that. And let's say I don't want to stitch snippets together in code / outside the template - I want the whole page self contained in one template or theme file.
Update: I want to generate nested html. I want the comments to be nested, not appear nested. I know how to indent things with CSS. :) Whether it is done in the browser or on the server is irrelevant because the point is I want the template to be self-contained in one file.
As in:
var html = render(template, {comments: aTreeOfNestedComments});
(see? that could be node.js, a brower plugin, some "jQuery" as some people like to call javascript these days...) It looks like jade can do this using mixins. Any tag-based templating engines that can do something similar?
Template engines can solve generic, run-off-the-mill problems. While nesting templates seems like a common use case, I haven't encountered many template engines who can do that.
Since the market didn't offer a good solution, I'm building my applications from JavaScript objects that know how to render themselves. I never use templates; every block gets a reference to the DOM (like the parent element to which is should attach itself) or the renderers return the child container and the parent element can add that in a suitable place.
This allows me to use the full power of JS without the limitations of template engines.
[EDIT] Here is a workaround: If you need a recursive element, add a span (if the recursive element should be inline) or div (if it's a block element). Give it the class recursiveTemplate and a data attribute data-template-name="..."
Run the template with your standard template engine. Afterwards, use jQuery or the like to find all elements with the class recursiveTemplate and replace them yourself.
Distal templates has an example here of a nested tree:
http://code.google.com/p/distal/wiki/UseCaseExamples#Building_a_nested_tree
as #TJHeuvel said, you can use the server side script to produce the desired otput, this would be the best way to do what you require. However if you must use JavaScript, I would advise jQuery this will also allow you to product the desired result.
for example:
$("ul li").css("margin-left", "10px");

xml inside html

What is the issue regarding placing xml elements inside html ? I am trying to easily retrieve javascript event info which returns some html when a div is clicked on. I want to parse that (as I cant send any data object afaik) and its very easy so I'm doing
<div><currency>eur</currency><price>120</price><weight>2kg</weight></div>
and in the js im doing
doTap=function(sent) {
console.log(sent.getElementsByTagName('price')[0].innerHTML);
The issue is that XML is not valid HTML (with respect to the elements). The browser does not know how to render a currency element, and afaik there is no standard way to deal with unknown elements. Some browsers might ignore them completely.
You should be fine with using span elements and giving them a class:
<div>
<span class="currency">eur</span>
<span class="price">120</span><
<span class="weight">2kg</span>
</div>
a elements are not supposed to contain block elements btw.
Then get the element in question by its class.
If you don't want to display the information (currency, price, etc) but only need to store it somewhere, you can use HTML5's data-* attributes:
<a data-currency-"eur" ... ></a>
and access them with getAttribute.
The main practical problem is that IE 8 and older do not deal at all with tags they don’t know when processing HTML documents. To deal with this, you can add code like document.createElement('currency').
There are other issues, too, such as the risk that some future browsers will start recognizing the markup you have invented – and this may cause unpredictable rendering features and functionality. Some more notes: http://www.cs.tut.fi/~jkorpela/pragmatic-html.html8#custom
The safer approach is to use span elements with class. You can also use a elements, since without href, they are still valid but do not create links, making the element effectively just a text-level container. By HTML syntax rules, though, you must not nest a elements (but browsers don’t care, in things like this).
So the safest approach uses e.g. <span class=currency>EUR</span> etc. instead.

A convention for indicating whether an HTML element is referenced from JS code

This is a follow-up question for In jQuery is it a bad idea to use name=X for all selectors?
I am using Backbone and decided that I wanted a way to differentiate between HTML elements that were bound and those that were not.
So I would write (in HAML):
.container
.title(name='title')
.separator
As you can see it's clear that the dynamic element is title.
The reason for this was so I could mess around with the style and rename classes without worrying about breaking the app. It also means in the template I can tell what the dynamic elements are without needing to go back and forth with the Backbone View.
My question now is, without using the [name] selector, does anyone have a code convention to keep track of which HTML elements are referenced from JS.
I have considering:
Using a common prefix on class names (e.g. class=bind-title)
Using some sort of custom HTML element (
Thanks!
FYI: I'm using CoffeeScript, Backbone and haml_coffee templates.
Updated jsperf to test all suggestions:
http://jsperf.com/class-or-name-attr-lookup/3
I would consider using a class to indicate that it is dynamic.
I'm not sure if you are aware of this but you can have multiple classes on one element. Like so:
.container
.dynamic.title(name='title')
.separator
This works in traditional HAML but I have not tried it with haml-coffee. If it doesn't work, you might have to specify the class like .title{:class => "dynamic"}(name='title').
I prefer this over a prefix on the class name because it's more semantically meaningful, which is how HTML should be used.
I am using data-view attribute on elements being set when rendering my Views.
This helps me to then show a tooltip in a browser window when I hover over View(s).

Categories

Resources