HTML document.documentElement
The global HTML is the actual document root element and all element tags queried via the dot operator are descendants.
HTML is a small, powerful way for you to enjoy working directly with the DOM. HTML.min.js (~2.7kb, gzip)
HTML lets you navigate, manipulate and use the DOM with intuitive, readable, consistent code.
HTML's functions enable you to flexibly use all native DOM features with brevity, clarity, and more power than ever.
HTML has a modular design that is easy to extend, adapt or customize to meet your needs.
See our F.A.Q.!
The global HTML is the actual document root element and all element tags queried via the dot operator are descendants.
HTML allows you to access document elements via their tag name. If multiple elements of the same tag exist, a proper array of elements is returned; otherwise, an Element
is returned. Only the first node returned is "HTML-ified" (prepared for further chaining).
HTML.body.header; // returns header element. HTML.body.header.textContent = "A Better Header!";
HTML.query
acts as a proxy for querySelectorAll
and returns the selected element(s).
HTML.query("#example"); // single node returned HTML.query(".example"); // Array of nodes returned if more than one, otherwise a node HTML.query("#example").h1.em; // chain on, man.
You can, of course, use query
on any "HTML-ified" element(s) to search only the children thereof.
HTML.body.div.query(".example"); // contextual search!
HTML.query
acts as a proxy for querySelector
or querySelectorAll
(as appropriate) and returns no more than the specified number of selected element(s).
HTML.query("#example", 1); // single node or empty Array returned HTML.body.query(".example", 5); // returns a single node if only one, otherwise an Array of 0-5 nodes
Use a the selected element(s) within a closure. Returns the element(s) it was called on.
HTML.query('li').each(function(el, i, all) { el.textContent = "Item " + (i+1) + " of " + all.length; }); // returns li elements HTML.body.ul.each(function(ul) {// each works on single nodes too if (ul.matches('.sunny')) { ul.li.style.background = "blue"; } }); // returns the ul
Get, set, or invoke the specified property of the selected element(s). Returns either an array of retrieved/returned values or the element(s) it was called on.
var items = HTML.body.ul.li; var texts = items.each('textContent'); // returns array of strings items.each('id', 'item${i}');// sets the id of each element (replaces ${i} with index) items.each('click');// calls 'click()' on each element, returns original items items.each('classList.add', 'foo');// adds 'foo' class to each item's classList, returns original items
Recurses through the DOM tree via the specified property, gathering the nodes as it goes to be returned. This makes it easy to gather all an elements ancestors, descendants, next/previous siblings, etc.
var focused = document.activeElement.all('parentElement', true);// returns Array of elements containing the current focus, including the active element. var first = HTML.body.div.only(0); var nextAll = first.all('nextElementSibling'); // returns Array of all subsequent sibling elements. var all = HTML.body.all('children'); // all descendants of the tag
When you want to narrow down a selection, only
allows you to easily filter
that list by selector, index, slice, or filtering function.
var items = HTML.body.ul.li; // all li elements items.only('.highlighted'); // subset that matches selector items.only(3).textContent = "Fourth li element!"; // index (single element) items.only(-1).id = 'last'; // negative index works too items.only(function(o,i){ return !(i%2); }); // filter function returns even elements items.only(3, 9).each('add', 'button');// specific slice of elements
This automatically adds the specified tag or node (or list thereof) to the element(s) on which it was called.
HTML.body.add('div'); // returns a newly added div element HTML.body.add('div').add('h1'); // returns the new h1 element (with div parent) HTML.head.add(document.createElement('div')); HTML.body.add([node1, node2, [ul1, ul2]]); // yummy recursive adding
The standard HTML.js artifact comes with the "emmet" extension, which lets you use emmet abbreviations to add elements to the DOM. This extension supports most emmet features, except grouping and numbering. Those may be added later.
HTML.body.add('ul>li{list item text}*10'); //Use in conjuction with only HTML.body.add('ul>li{item}*10') .only(function(li,i){ return i%2; }) .each('classList.add','odd');
Removes the specified node (or list thereof). Some browsers provide this natively for elements, for the few who don't this polyfills the gap and enables use of it on arrays of elements. When called on a list, it returns the list of deleted items.
HTML.query('.foo').remove();
When you get element(s) from an interface not under HTML's supervision, call this on it to give it HTML properties and functions.
if (!('each' in node)) { HTML.ify(node); } node.each(function(el){ console.log(el, ' is your friend!'); });
On any element, you may access the non-element nodes via ._other
var nodes = HTML.body.section._other; var text = nodes.only(function(node){ return node.nodeType == 3; });
Use this to create your own plugins that extend the DOM, but remember to tread lightly! HTML is about learning and using the DOM, not obscuring it beneath foreign interfaces.
HTML._.fn.hide = function() { return this.each('style.display', 'none'); }; HTML.query('.foo').hide();
Occasionally, the verbosity of the DOM can, like any friend, become tiresome. You may create property aliases for each
.
HTML._.resolve['-class'] = 'classList.remove'; HTML._.resolve['+class'] = 'classList.add'; HTML.query('.foo').each('-class', 'foo').each('+class', 'bar'); HTML._.resolve.insert = 'insertAdjacentHTML'; HTML.query('.neighbor').each('insert', 'afterend', '<span>Hello.</span>');
Rumor has it some people find 'HTML' annoying to type. If you prefer another name, you can configure it globally by setting a data-html-reference
attribute on the root element. This, of course, doesn't apply to those loading via a tool like AMD or Browserify where HTML is not automatically set as a reference in the window.
<html data-html-reference="html">< <script> html.query('example-element').each('example-attribute','example value'); </script>
Another jQuery wannabe, eh?
Definitely not. jQuery and friends always hide the DOM from you. This used to be partly to protect you from it, but now it's just out of habit. HTML's intent is to directly expose and enhance the DOM. The DOM of the present is not the anemic mess it was even a few short years ago; protection from it is more pointless with every passing month. In fact, more than being unnecessary, that "protection" is often stunting your education. HTML is here to lubricate the process of learning what is really happening, and maybe throw in a few original features to sweeten the deal.
Why should i use HTML instead of jQuery?
Asking this question is kinda like saying that a very large swiss-army knife is the only tool you'll ever want. Some people prefer to collect specialized tools. Some people don't like jQuery's wrapper obscuring the riches of the native DOM. Some people just like doing it this way. There's probably other reasons out there too, but hopefully that's enough to move on to more useful questions.
Why give it the same name as, well, "HTML"?
Succint, self-documenting code is the ideal, and a self-descriptive name is also a great ward against feature creep. This HTML javascript library will not be about AJAX or JSON or CSS. It is about interacting with your document's HTML structure in javascript. To wit, it just fits.
Isn't 'HTML.query' a lot more to type than '$'?
Yeah, but jQuery and clones kinda have a lock on that $ shortcut. Lucky for you, it's easy to make:
window.$ = HTML.query.bind(HTML);
Which browsers does HTML support?
Only the modern ones: Firefox, Chrome, Safari, Opera, IE9+ and the like. With some judicious polyfilling you might get IE8 to support everything but the dot-traversal syntax, but i'd argue there are better solutions.
Isn't extending the DOM a bad idea?
Only if you care to prop up the diminishing market share of IE6/7/8. For those working on the future, smart DOM extension is no longer to be feared.
How does the DOM traversal work?
By defining lazy object getter functions for child tags. Again, we only do it lazily, on objects you access via this library, to keep the impact small.
Aren't those long dot-traversal chains a bad idea when pages are so dynamic?
Yes, same rules as with all DOM selector interfaces. Use query()
with classes and ids when doing "whole page" work. Dot-traversal is best for small, well-defined node structures.
Functions that return either elements or arrays are bad. I saw it get ugly once!
Different contexts, different code, different techniques. Here's the rules for doing things right with HTML: 1) If you are certain you have one result (e.g. HTML.query('#foo')
, list.only(1)
or within each(callback)
or only(filter)
functions), then you can call DOM methods directly. 2) In all other situations, use HTML's functions (especially each('property')
) to abstract the difference between one or more elements. You don't need to write branching code (like plain DOM) or use a wrapper object (like jQuery) to do that abstraction; HTML's functions do it superbly.
Hey, this is like Voyeur.js...
This began as a fork but became much different and much more. Adrian Cooney's delightful DOM traversal concept remains in play, as do the essentials of his lovely demo and site.
I have a suggestion, where do I put it?
I do a happy dance when you create an issue on Github.