If an element has the id attribute, then there’s a global variable by the name from that id.

We can use it to access the element, like this:

<div id="elem">
<div id="elem-content">Element</div>
</div>
<script>
alert(elem); // DOM-element with id="elem"
alert(window.elem); // accessing global variable like this also works
// for elem-content things are a bit more complex
// that has a dash inside, so it can't be a variable name
alert(window['elem-content']); // ...but accessible using square brackets [...]
</script>

The behavior is described in the specification, but it is supported mainly for compatibility. The browser tries to help us by mixing namespaces of JS and DOM. Good for very simple scripts, but there may be name conflicts. Also, when we look in JS and don’t have HTML in view, it’s not obvious where the variable comes from.

The better alternative is to use a special method document.getElementById(id).

Here in the tutorial we’ll often use id to directly reference an element, but that’s only to keep things short. In real life document.getElementById is the preferred method.

There can be only one

The id must be unique. There can be only one element in the document with the given id.

If there are multiple elements with the same id, then the behavior of corresponding methods is unpredictable. The browser may return any of them at random. So please stick to the rule and keep id unique.

Only document.getElementById, not anyNode.getElementById

The method getElementById that can be called only on document object. It looks for the given id in the whole document.

Pseudo-classes in the CSS selector like :hover and :active are also supported. For instance, document.querySelectorAll(':hover') will return the collection with elements that the pointer is over now (in nesting order: from the outermost <html> to the most nested one).

The call to elem.querySelector(css) returns the first element for the given CSS selector.

In other words, the result is the same as elem.querySelectorAll(css)[0], but the latter is looking for all elements and picking one, while elem.querySelector just looks for one. So it’s faster and shorter to write.

Please note that methods getElementById and getElementsByName can only be called in the context of the document: document.getElementById(...). But not on an element: elem.getElementById(...) would cause an error.

Other methods can be called on elements too. For instance elem.querySelectorAll(...) will search inside elem (in the DOM subtree).

Besides that:

There is elem.matches(css) to check if elem matches the given CSS selector.

There is elem.closest(css) to look for a nearest ancestor that matches the given CSS-selector. The elem itself is also checked.

And let’s mention one more method here to check for the child-parent relationship:

elemA.contains(elemB) returns true if elemB is inside elemA (a descendant of elemA) or when elemA==elemB.

Open the page table.html in a separate window and make use of browser tools for that.

There are many ways to do it.

Here are some of them:

// 1. The table with `id="age-table"`.
let table = document.getElementById('age-table')
// 2. All label elements inside that table
table.getElementsByTagName('label')
// or
document.querySelectorAll('#age-table label')
// 3. The first td in that table (with the word "Age").
table.rows[0].cells[0]
// or
table.getElementsByTagName('td')[0]
// or
table.querySelector('td')
// 4. The form with the name "search".
// assuming there's only one element with name="search"
let form = document.getElementsByName('search')[0]
// or, form specifically
document.querySelector('form[name="search"]')
// 5. The first input in that form.
form.getElementsByTagName('input')
// or
form.querySelector('input')
// 6. The last input in that form.
// there's no direct query for that
let inputs = form.querySelectorAll('input') // search all
inputs[inputs.length-1] // take last