I'm trying to figure out the difference between using document.createDocumentFragment versus using an HTML <tamplate> element.
Is there a difference between them in behavior or performance?
Both <template> and document.createDocumentFragment are used for storing HTML-like data without rendering it, but the use cases are somewhat different.
The <template> tag's main purpose is to, as the name applies, store HTML for a later time, and or to be used repeatedly across the document. This tag is useful when using a template engine where the contents are usually never changed but the input may be different.
document.createDocumentFragment is used to create an entire DOM tree in JS without the browser rendering it, while still having the ability to use the DOM API with it. This useful when dynamically generating HTML by leveraging the DOM API, and to later inject the results in the actual document's DOM.
More: Template Tag and DocumentFragment
Related
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've been hearing about Shadow DOM recently. While watching a video about the release of Angular 2 the presenter repeatedly made mention of Shadow DOM without clear expressions. What does Shadow DOM really mean?
The best explanation I've found is this from What the Heck is Shadow DOM? shown below:
Shadow DOM refers to the ability of the browser to include a subtree
of DOM elements into the rendering of a document, but not into the
main document DOM tree.
An important use case would be with video controls on a web page. The markup only shows a video tag, with some attributes and source tags. The addtional code for all the video operations to work is hidden in the Shadow DOM and not available to the rest of the page. The actual markup, javascript, and styles for the tag are encapsulated, which hides the implementation details of the video controls that each browser vendor has already written.
So while it's there in the DOM, its hidden from the page that renders it. So, to view the Shadow DOM, you can enable it under Dev Tools in Chrome.
The short answer is that the Shadow DOM is one of four technologies that make up Web Components.
For a definition, Web Components are: A component platform from the W3C that allows Web sites to be constructed from standardized building blocks. Web Components comprise Custom Elements, Shadow DOM and HTML Imports and Templates.
Shadow DOM is a technology of Web Components (although each can be used separately):
Custom Elements: is a capability for creating your own custom HTML tags and elements. They can have their own scripted behavior and CSS styling. They are part of Web Components but they can also be used by themselves.
HTML Templates: The HTML template element is a mechanism for holding client-side content that is not to be rendered when a page is loaded but may subsequently be instantiated during runtime using JavaScript. Think of a template as a content fragment that is being stored for subsequent use in the document.
Shadow DOM: provides encapsulation for the JavaScript, CSS, and templating in a Web Component. Shadow DOM makes it so these things remain separate from the DOM of the main document. You can also use Shadow DOM by itself, outside of a web component.
HTML Imports: is intended to be the packaging mechanism for Web Components, but you can also use HTML Imports by itself. You import an HTML file by using a tag in an HTML document.
See Introduction to the Shadow DOM.
It refers to the ability to create a "child" DOM completely sandboxed from the rest of the page. Useful for web components, reusable "widgets" which allow to not worry about their css/js affecting things they shouldn't. http://glazkov.com/2011/01/14/what-the-heck-is-shadow-dom/
Check out https://www.polymer-project.org/ if you want to see it in action.
Think of shadow DOM is as an encapsulated (private) DOM.
You can't access the shadow DOM in the manner you access regular DOM, like 'document.querySelector()'.
Let's say, you defined a reusable custom element, (which contains its DOM trees). Then you use the custom element within your app HTML.
Now, the DOM under (which is now called a "host element") has become a shadow DOM subtrees (under a shadow root), hidden from the parent structure!
I hope this help you a bit.
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");
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>
I'm building the HTML code within an XML DOM object to be used as the contents of the innerHTML of a div element using an XSL template. Traditionally we create a new XML DOM document and add the input parameters as XML Elements for the transform via javascript. This is all very time-consuming as we are basically hand picking the data from another XML document that represents our current account and copying the data into a transient XML DOM document.
What I'd like to do is clone the relevant node of the account document (i.e. customer info) and use it as the basis for the transform. I don't want to use the account document directly as I'd like to be able to add transform specific input, without making changes to the account object.
How efficient is using .cloneNode(true) for a desired node of about typically less than 200 elements from a document of typically 2000+ elements? The target platform is IE6 with no external tools (i.e. ActiveX).
CloneNode is pretty efficient but it will be consuming more memory doing it that way.
Another approach to consider is to use a Template object and a processor, pass your additional/changed data as parameters to the processor and the element that you would have otherwise cloned as the input element. This approach would require fairly significant mods the XSL though.
IE will fail on certain things.
e.g. checked radio/checkboxes will not be checked when you add your copy to the DOM.
Example:
http://webbugtrack.blogspot.com/2008/03/bug-199-cant-clone-form-element-in-ie.html
http://webbugtrack.blogspot.com/2007/08/bug-242-setattribute-doesnt-always-work.html
To see what IE will actually return, try replacing the url with this in the Address Bar of one of your pages, and press enter.
javascript:'<xmp>'+window.document.body.outerHTML+'</xmp>';
If you are happy with the results, great!, but I think you'll end up less than satisfied at what IE returns (both in the DOM, and this "string" value equivelant.
If you don't need form-elements, cloneNode is a real reliable tool ...
-- and in inserting ajax-data it is incredible in efficiency ...
However, as especially IE has a history of having problems with name-attributes, it is inconvenient to address any of these if you insert data ...
-- I don't really understand your XSL(T)-using, to me it sounds like using a gas-station as a (not !-) convenient place to change a 1960 WV to a 2008 Skoda ...
Userely they have some common technology, though it is not used in the same way, computerization in some way is just a minor problem, the major problems is in nearly any other way !o]
Have you got any need for form-elements ?-)