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");
Related
As a new web developer, I've been utilizing a lot of resources like StackOverflow to assist me in the learning and development process.
When using jQuery, all of the examples/responses that I've come across so far have only referenced classes, like so:
$('.yourClass')
as opposed to
$('#yourID')
Seeing that class referencing seems to be the trend (I honestly haven't found one author who writes a jQuery to an ID), are there any pitfalls I should be aware of for using ID's w/ jQuery or JS in general? Thanks!
EDIT 1: I'm aware that ID's are for single-items, classes are for accessing multiple items. I'm more interested in why I don't see any jQuery or JS examples referencing ID's. Thank you!
You would have to ask each author on a case-by-case basis, but generally when creating examples, the selector used doesn't matter; what's important is that you have a jQuery collection that you can call a method on.
By using a class selector in the example, you avoid newbie developers claiming that your plugin doesn't work when they try to use it on multiple elements with the same ID. Your example serves the purpose of showing how to use it on one or more elements, rather than just one.
People like to use classes because ids have to be unique across the whole page. When trying to make reusable, pluggable components, id's make this impossible to enforce.
Exception: the new web-components standard allows you to encapsulate ids to just your component.
An ID must be unique, you can have only one (like highlanders).
Classes are used to identify a "type" of object not a specific one.
An obligatory car analogy:
An ID is a license plate, unique to one specific thing #345-abc
The class relates to a whole category of things like .truck
Take note that a selector like $(".something") will actually be capable of producing a list of DOM elements; as it will select all DOM elements with the class of "something"
An ID selector $("#unique") will only ever return one element
Think of your HTML and CSS first.
Using Classes
If you have multiple HTML elements which all will look, feel and behave in the same way, then it is highly recommended to use a class to represent their style and behavior.
Example: rows or columns on a table, navigation buttons which animate in the exact same way, wrapper to images which have the same size throughout your website, etc.
Using ID's
However, if you have a unique HTML element which represents a particular thing or state or action in one of your pages, then that element should contain an id.
Example: pop up modal, a unique looking button, unique sections on your website which you can navigate to by their id, etc.
Then, you can use this behavior in your JavaScript and jQuery or whatever else you like to use.
Further reading
I know that you are fully aware of why we should use ID's or classes.
But the vast majority of answers that are given here, are thinking of a project context.
So, let's say editing a .js file that is linked to the scope of the entire project, the idea here is to be as reusable as possible, so that's why you'll see much more classes references than ID's. Is hard to maintain a project js file that makes reference to different ID's that are abroad the project.
Same thing will apply to css.
I hope the answer is enough, be free to post a comment or suggestions. :-)
I have studied Shadow DOM recently, and I was wondering what are the aims of using it instead of the main one.
What does it gives ? Why dont we use standard DOM instead of it (except for styling scoping) ?
It allows you to encapsulate functionality, effectively putting it in a black box. It means you can create [reusable] components whose inner workings aren't exposed; this is impossible using standard DOM.
As an example, take HTML input elements. So, say, the file type of input. To use it on an HTML page, you simply add <input type="file" />, and it works. You don't need to add any extra code or HTML or CSS to handle how it works, it just does, and you can't access the internal bits of it. If you were to write a piece of UI, using HTML/CSS/JS, that did the same thing, it would be fairly complex. But the file input is just a single tag that you can use anywhere, it always does the same thing. The web component family of specs allow you to create your own elements that work in this way, and the Shadow DOM is a critical part of this. You can create a new element, like <my-fantastic-file-input />, with its functionality encapsulated. It has its own internal DOM subtree, but that subtree isn't directly accessible; ditto with scoped styles. The new component does not expose its implementation details to the document.
You can do most of this stuff using the DOM, but the implementation will be wholly tied into the document/application structure. With components, you extract that implementation, and you can reuse it, pass it around, publish it and let other people drop it into their applications/documents, and be sure it will work in exactly the same way, anywhere. You cannot really do that as things currently stand by using the standard DOM.
This is from 2011, and slightly out-of-date, but it's a list of some possible use cases for the component model: http://www.w3.org/2008/webapps/wiki/Component_Model_Use_Cases
I want to know if there is a better way to be doing innerHTML than what I do here. The way I am doing it is causing problems because of the fact that I can't have triple nested quotes. along side that, it is really hard to look at and manage. Thanks!
function buttonClicked(buttonValue)
{
switch (buttonValue)
{
case 1:
soundFolders.innerHTML = "<li onClick='buttonClicked(11);'>Thunder 1</li> <li onClick='buttonClicked(13);'>Light Rain 1</li> <li onClick='buttonClicked(0);'>Back</li>";
break;
case 11:
if(!thunder1Control)
{
thunder1.play();
var thunder1Control = document.createElement("li");
soundList.appendChild(thunder1Control);
thunder1Control.innerHTML = "<h3>Thunder 1</h3> <button class='stopSound' onClick='thunder1.pause(); thunder1.currentTime=0; thunder1Control.parentNode.removeChild(thunder1Control); '>X</button> <button class='volDown' onClick='thunder1.volume -= 0.25;'>-</button> <button class='volUp' onClick='thunder1.volume += 0.25;'>+</button>";
thunder1Control.setAttribute("class", "playingSound");
}
P.S. Do you guys know why the thunder1Control.parentNode.removeChild(thunder1Control) is not working?
To your first question about another way to approach this type of code, "best" is a matter of opinion so I won't really try to address what is best. But, I will give you some alternatives:
Avoid putting code into strings in your HTML. There are all sorts of limitations with that and you generally want to separate code from presentation anyway.
Install event handlers in your code with obj.addEventListener() instead of putting event handlers and code in your HTML.
Use classes and IDs or DOM queries from a particular point in the hierarchy to retrieve specific objects in your page rather than trying to save references to them in global variables. In plain javascript, element.querySelectorAll() is pretty powerful.
In many cases, it's much simpler to just hide and show blocks of HTML using obj.style.display = "none" and obj.style.display = "block" than it is to dynamically create and destroy HTML and this has the added advantage of the HTML is all specified in the page and doesn't have to be shoehorned into a javascript string.
For large blocks of dynamic HTML that wouldn't work well with hide/show for whatever reason, you can dynamically load snippets/templates of HTML from your server using ajax or you dynamically create the HTML using javascript. My first preference is generally hide/show and then if that isn't practical for some reason, it depends upon how much the HTML I want to insert varies based on the state for whether I'd rather load a template or create it dynamically using javascript. If you have large blocks of HTML you have to fit in your javascript, it is messy with quoting, etc... - no way around that if you go that route other than using one quoting scheme for the JS string delimiter and the other in your HTML.
In your particular case, it sure looks like the hide/show method would be simple.
To your second question, this line of code:
thunder1Control.parentNode.removeChild(thunder1Control)
does not work because the thunder1Control variable is long, long out of scope when your click handler is executed because it's a local variable in your buttonClicked() clicked function.
When you put code into a string as part of HTML, it is evaluated in the global scope only so any variables that it tries to reference, must themselves be global in scope.
I'd suggest that you NOT put code into strings in your HTML like that. Use references to actual javascript functions. In that particular case, I'd have to see your HTML to know how to best advise you. If there is only ever one thunder1Control, then I'd suggest you just put an id value on it and retrieve it with document.getElementBtId() when you need it rather than trying to save a reference to it in a variable.
There are essentially two other ways that I can see:
Use a framework that helps with this kind of things. Others have
mentioned jQuery. A commenter is arguing that it might be overkill
to include a framework for just this. I would argue that if you're
doing any javascript at all, you should be using a framework to
make it less terrible. But continue onto suggestion 2 if you
disagree!
You can create each of the elements via plain old javascript and append it to the elements that you need, instead of inserting it directly into innerHTML. ex.
var li = document.createElement("li");
soundFolders.appendChild(li);
etc...
But, honestly, use jQuery with some of the suggestions from others. It's pretty small, and it will heavily clean up all of your javascript. Include it via Google and it will likely already be cached in the users browser.
https://developers.google.com/speed/libraries/devguide#jquery
I think a better alternative is to use jQuery, and then instead of using .html() (equivalent of innerHTML in jQuery), you can create a template with your html and use .load() instead. Works nicer and it's cleaner. And you don't have to worry about triple nesting quotes as you said.
Edit: I'm not sure why I'm getting downvoted so much here... The poster doesn't want to worry about triple nesting quotes. A simple and, to me, elegant solution is to use .load() and to create a template, rather than a really long string of html...
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>
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).