Chapter 4 – Element Node Selecting

最后更新于:2022-04-01 04:39:15

## 4.1 Selecting a specific element node The most common methods for getting a reference to a single element node are: * *querySelector()* * *getElementById()* In the code below I leverage both of these methods to select an element node from the HTML document. live code: [http://jsfiddle.net/domenlightenment/b4Rch](http://jsfiddle.net/domenlightenment/b4Rch) ~~~ <!DOCTYPE html> <html lang="en"> <body> <ul> <li>Hello</li> <li>big</li> <li>bad</li> <li id="last">world</li> </ul> <script> console.log(document.querySelector('li').textContent); //logs Hello console.log(document.getElementById('last').textContent); //logs world </script> </body> </html> ~~~ The *getElementById()* method is pretty simple compared to the more robust *querySelector()* method. The*querySelector()* method permits a parameter in the form of a [CSS selector syntax](http://www.w3.org/TR/css3-selectors/#selectors). Basically you can pass this method a CSS 3 selector (e.g. *'#score>tbody>tr>td:nth-of-type(2)'*) which it will use to select a single element in the DOM. ### Notes *querySelector()* will return the first node element found in the document based on the selector. For example, in the code example above we pass a selector that would select all the li's in CSS, but only the first one is returned. *querySelector()* is also defined on element nodes. This allows for the method to limit (allows for context querying) its results to a specific vein of the DOM tree ## 4.2 Selecting/creating a list (aka *NodeList*) of element nodes The most common methods for selecting/creating a list of nodes in an HTML document are: * *querySelectorAll()* * *getElementsByTagName()* * *getElementsByClassName()* Below we use all three of these methods to create a list of the *`<li>`* elements in the document. live code: [http://jsfiddle.net/domenlightenment/nT7Lr](http://jsfiddle.net/domenlightenment/nT7Lr) ~~~ <!DOCTYPE html> <html lang="en"> <body> <ul> <li class="liClass">Hello</li> <li class="liClass">big</li> <li class="liClass">bad</li> <li class="liClass">world</li> </ul> <script> //all of the methods below create/select the same list of <li> elements from the DOM console.log(document.querySelectorAll('li')); console.log(document.getElementsByTagName('li')); console.log(document.getElementsByClassName('liClass')); </script> </body> </html> ~~~ If its not clear the methods used in the code example above do not select a specific element, but instead creates a list (aka [*NodeLists*](https://developer.mozilla.org/En/DOM/NodeList)) of elements that you can select from. ### Notes *NodeLists* created from *getElementsByTagName()* and *getElementsByClassName()* are considered live are will always reflect the state of the document even if the document is updated after the list is created/selected. The *querySelectorAll()* method does not return a live list of elements. Meaning that the list created from*querySelectorAll()* is a snap shot of the document at the time it was created and is not reflective of the document as it changes. The list is static not live. *querySelectorAll()*, *getElementsByTagName()*, and *getElementsByClassName* are also defined on element nodes. This allows for the method to limit its results to specific vein(s) of the DOM tree (e.g.*document.getElementById('header').getElementsByClassName('a')*). I did not mention the *getElementsByName()* method as it not commonly leverage over other solutions but you should be aware of its existence for selecting form, img, frame, embed, and object elements from a document that all have the same name attribute value. Passing either *querySelectorAll()* or *getElementsByTagName()* the string *'*'*, which generally means all, will return a list of all elements in the document. Keep in mind that *childNodes* will also return a *NodeList* just like *querySelectorAll()*, *getElementsByTagName()*, and*getElementsByClassName* The *NodeLists* are array like (but does not inherit array methods) lists/collections and have a read only *length* property ## 4.3 Selecting all immediate child element nodes Using the *children* property from an element node we can get a list (aka [*HTMLCollection*](https://developer.mozilla.org/en/DOM/HTMLCollection)) of all the immediate children nodes that are element nodes. In the code below I use *children* to create a selection/list of all of the*`<li>`*'s contained wiithin the *`<ul>`*. live code: [http://jsfiddle.net/domenlightenment/svfRC](http://jsfiddle.net/domenlightenment/svfRC) ~~~ <!DOCTYPE html> <html lang="en"> <body> <ul> <li><strong>Hi</strong></li> <li>there</li> </ul> <script> var ulElement = document.querySelector('ul').children; //logs a list/array of all immediate child element nodes console.log(ulElement); //logs [<li>, <li>] </script> </body> </html> ~~~ Notice that using *children* only gives us the immediate element nodes excluding any nodes (e.g. text nodes) that are not elements. If the element has no children then *children* will return an empty array-like-list. ### Notes *HTMLCollection*'s contain elements in document order, that is they are placed in the array in the order the elements appear in the DOM *HTMLCollection*'s are live, which means any change to the document will be reflected dynamically in the collection ## 4.4 Contextual element selecting The methods *querySelector()*, *querySelectorAll()*, *getElementsByTagName()*, and*getElementsByClassName* typically accessed from the *document* object are also defined on element nodes. This allows for these methods to limit its results to specific vein(s) of the DOM tree. Or said another, you can select a specific context in which you would like the methods to search for element nodes by invoking these methods on element node objects. live code: [http://jsfiddle.net/domenlightenment/fL6tV](http://jsfiddle.net/domenlightenment/fL6tV) ~~~ <!DOCTYPE html> <html lang="en"> <body> <div><ul><li class="liClass">Hello</li><li class="liClass">big</li><li class="liClass">bad</li><li class="liClass">world</li></ul></div> <ul><li class="liClass">Hello</li></ul> <script> //select a div as the context to run the selecting methods only on the contents of the div var div = document.querySelector('div'); console.log(div.querySelector('ul')); console.log(div.querySelectorAll('li')); console.log(div.getElementsByTagName('li')); console.log(div.getElementsByClassName('liClass')); </script> </body> </html> ~~~ These methods not only operate on the live dom but programatic DOM structures that are created in code as well. live code: [http://jsfiddle.net/domenlightenment/CCnva](http://jsfiddle.net/domenlightenment/CCnva) ~~~ <!DOCTYPE html> <html lang="en"> <body> <script> //create DOM structure var divElm = document.createElement('div'); var ulElm = document.createElement('ul'); var liElm = document.createElement('li'); liElm.setAttribute('class','liClass'); ulElm.appendChild(liElm); divElm.appendChild(ulElm); //use selecting methods on DOM structure console.log(divElm.querySelector('ul')); console.log(divElm.querySelectorAll('li')); console.log(divElm.getElementsByTagName('li')); console.log(divElm.getElementsByClassName('liClass')); </body> </html> ~~~ ## 4.5 Pre-configured selections/lists of element nodes You should be aware that there are some legacy, pre-configured arrays-like-lists, containing element nodes from an HTML document. Below I list a couple of these (not the complete list) that might be handy to be aware of. * document.all - all elements in HTML document * document.forms - all `<form>` elements in HTML document * document.images - all `<img>` elements in HTML document * document.links - all `<a>` elements in HTML document * document.scripts - all `<script>` elements in HTML document * document.styleSheets - all `<link>` or `<style>` objects in HTML document ### Notes These pre-configured arrays are constucted from the [HTMLCollection](https://developer.mozilla.org/en/DOM/HTMLCollection) interface/object, except *document.styleSheets* it uses*StyleSheetList* *[HTMLCollection](https://developer.mozilla.org/en-US/docs/DOM/HTMLCollection)*'s are live just like *[NodeList](https://developer.mozilla.org/En/DOM/NodeList)*'s. Oddly *document.all* is constucted from a* HTMLAllCollection* not an *HTMLCollection* and is not supported in Firefox ## 4.6 Verify an element will be selected using *matchesSelector()* Using the *matchesSelector()* method we can determine if an element will match a selector string. For example say we want to determine if an `<li>` is the first child element of a *`<ul>`*. In the code example below I select the first*`<li>`* inside of the  `<ul>`and then ask if that element matches the selector, *`li:first-child`*. Because it in fact does, the *matchesSelector()* method returns *true*. live code: [http://jsfiddle.net/domenlightenment/9RayM](http://jsfiddle.net/domenlightenment/9RayM) ~~~ <!DOCTYPE html> <html lang="en"> <body> <ul> <li>Hello</li> <li>world</li> </ul> <script> //fails in modern browser must use browser prefix moz, webkit, o, and ms console.log(document.querySelector('li').matchesSelector('li:first-child')); //logs false //prefix moz //console.log(document.querySelector('li').mozMatchesSelector('li:first-child')); //prefix webkit //console.log(document.querySelector('li').webkitMatchesSelector('li:first-child')); //prefix o //console.log(document.querySelector('li').oMatchesSelector('li:first-child')); //prefix ms //console.log(document.querySelector('li').msMatchesSelector('li:first-child')); </script> </body> </html> ~~~ ### Notes matchesSelector has not seen much love from the browsers as its usage is behind browser prefixes *mozMatchesSelector()*,*webkitMatchesSelector()*, *oMatchesSelector()*, *msMatchesSelector()* In the future *matchesSelector()* will be renamed to *matches()*
';