Note to self: write an intro that eases the reader into the article, rather than just jump right in.
Let’s discuss the difference between HTML and the DOM.
A plain old
<table> element is HTML, obviously. You can use it in a file with
.html at the end. It’s got a set of attributes that affect the way it looks and behaves.
It’s a document-to-object model.
Every type of element in HTML has its own DOM ‘interface’ that defines properties (that usually map to attributes on the HTML element) and methods. For example, a
<table> has an interface called
You can get a reference to a particular element by writing something like this:
You then have access to all the properties and methods that are available for that type of element. For example, you can access the
value property with
searchBox.value or put the cursor in the box by calling
Thank you for attending my 58 second course on the DOM.
Now, the thing is, most elements don’t have any interesting methods, so unless you actually sift through the spec for things you’ll almost never use, it’s easy to miss the little nuggets that are scattered throughout.
Fortunately for you, sifting through specs and writing listicles are two of my favourite ways to keep the misery at bay. So here we are…
If you want to play along, and have some browser DevTools at your disposal, you can select an element in the element tree, then type
$0 in the console. This gives you a reference to the element you had selected. To see the element as an object, type
Oh by the way, if you’d like to help feed my curiosity, you could highlight the headings of any of these things that you didn’t already know and think aren’t useless.
#1 table methods
The humble table (still the #1 way to lay out a website) has quite a few nifty methods that make constructing them as simple as constructing an Ikea table.
Here’s a bunch of them.
Not a single
document.createElement() in sight.
.insertRow() method will even insert a
<tbody> for you if you call it directly on a table element. Isn’t that nice?
You know how, when you have
#something in the URL, then when the page loads, the browser will scroll the page so you can see the element with that ID?
This is really thoughtful, but it doesn’t work if you’re rendering that element after the page loads.
You can manually re-create this behaviour with:
OK, this isn’t a method, but if you argue I will argue back that behind the scenes there’s probably a setter and really that’s a method, right?
Anyway, have you ever done
myElement.style.display = 'none' in order to hide an element? Well, stop doing that!
You can just do
myElement.hidden = true.
OK this isn’t exactly an element method either, it’s a method on an element property. Specifically, it’s a method to toggle adding/removing a class from an element, with
And if you’ve ever conditionally added a class with an
if statement, you should be locked up.
You should have just passed a second parameter to the
toggle method. If it comes true, your class will be added to the element.
I know what you’re thinking — that’s not really what the word ‘toggle’ means — and the good people over at Internet Explorer agree and have protested by not implementing the second parameter logic at all.
So I take it back, you shouldn’t be locked up. Roam free!
OK you definitely knew this one already, but I suspect that exactly 17% of you didn’t know that you can use it on any element.
myElement.querySelector('.my-class') will only match elements that have the class
my-class and are descendants of
This is a method available on all elements that looks up the element tree. It’s like a reverso
querySelector(). So, I could get the heading for the current section in this manner:
Up to the first
<article> then back down to the first
This returns a neat little object with some dimensional details about the element you called it on.
Be careful in two different ways, though:
- Calling this causes a repaint. Depending on the device and complexity of your page, this could take several milliseconds. So keep an eye on that if you’re calling it repeatedly, e.g. in an animation.
- Not all browsers return all those values. Because why would they?
Say I want to check if a particular element has a particular class.
Better, but nothing to do with this post:
I learnt this one today! It’s like
appendChild() but gives a bit more control over where you’re appending that child.
parentEl.insertAdjacentElement('beforeend', newEl) is the same as doing
parentEl.appendChild(newEl), but you can also specify
afterend to put it in the places that those names suggest.
Have you ever wanted to know if one element is inside another element? I know I want to know this all the time.
For example, if I’m handling a mouse click and want to know if it happened inside a modal, or outside (so I can close it), I might do this:
modalEl is a reference to my modal, and
e.target will be whichever element was clicked on.
Fun fact, 100% of the time I do this, I get the logic the wrong way around on the first try.
Even if I try to get clever and switch it round the other way just before hitting save, I still get it wrong.
Surely the most useless of all element methods, except in one particular case.
Do you remember when I mentioned, way up the top, that properties usually map to attributes (although at the time I used bold, not italics)?
One of the instances when this is not true is the
href attribute of an element such as
el.href will not return
/animals/cat, like you might expect. This is because the
<a> element implements the
HTMLHyperlinkElementUtils interface, which has a bunch of helper properties like
hash that tell you things about the target of the link.
One of these helpful properties is
href, which will give you the full URL, with all the trimmings, not the relative URL in the attribute.
So, you’ll have to use
el.getAttribute('href') if you want the literal string inside the
#12 the dialog element trio
The relatively new
<dialog> element has two just-OK methods and one amazing method.
close() will do exactly what you expect them to do, and that’s OK, I suppose.
showModal() will show the
<dialog> on top of everything else, centred in the page, just like you want your modals to. No need for
z-index or manually adding a dimmed background or listening for the escape key to close it — the browser knows how modals work and will do all this for you.
And that’s amazing.
Sometimes, when you get a reference to a list of elements, you can iterate over them with
for() loops are so 2014.
Let’s say you wanted to log out the URLs for all the links on the page. You could do this, if you wanted to see an error.
Or you could do this:
This is because
getElementsByTagName and the other get... methods return an
querySelectorAll returns a
And it’s the
NodeList interface that gives us the
forEach() method (along with
It really would be better if everyone simply returned arrays rather than trying to get all fancy with their not-quite arrays. But fear not, because the good folk at ECMA have given us
Array.from() that will turn anything that quacks like an array, into an array.
So, this works:
And bonus: by creating an array, you can then use
reduce() or any other array methods. For example, returning an array of external links for no reason:
.filter(Boolean) is my favourite way to make future me scratch his head trying to work out what it does.
<form>, as you most likely already know, has a
submit() method. It’s slightly less likely that you know forms have a
reset() method and can
reportValidity() if you’re using validation on your form elements.
You can also use a form’s
elements property with dot notation to reference an element by its
name attribute. For example
myFormEl.elements.email would return the element
<input name="email" /> that belongs to the
<form> (‘belongs to’ — that doesn’t necessarily mean ‘is a descendant of’).
I just lied to you.
elements doesn’t return a list of elements at all. It returns a list of controls (and of course it’s not an array, because why would they do that?)
An example: if you have three radio buttons, each with the same name
formEl.elements.animal will give you a reference to that set of radio buttons (1 control, 3 elements).
formEl.elements.animal.value will return the value of whichever radio button is selected.
It’s weird syntax if you think about it. Break it down, brotha:
formEl is an element,
elements is an
HTMLFormControlsCollection, a not-really array where each item is not-necessarily an HTML element.
animal is set of several radio buttons, combined only because they have the same
name attribute (there’s a
RadioNodeList interface just for this purpose) and
value looks up the
value attribute of whichever radio button in the collection is selected.
I probably should have arranged these so the last one wasn’t so uninteresting. Anyhoo, the
.select() method will select all of the text in whatever input you call it on.
Thanks for reading, I hope at least a few of these were new to you, and maybe even useful.
Always check browser support before use and never trim your eyebrows while you’re angry.