How well do you know DOM JavaScript?
Tags: codenewbie, javascript, webdev, html
Published: 2021-09-05 03:50:49

HTML and JavaScript have been around awhile, with its age there are some very nuanced tricks and hacks that aren't very well known. Let's take a look at some of them and when they are appropriate to use.

# But first... the BOM

The collection of JavaScript objects & methods that let use access the features of the browser is referred to as the Browser Object Model. 

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/czniaazwv9pgm5pegycu.png) 

The Document Object Model which is the hierarchy of elements on a page that is accessed from the [window.document](https://developer.mozilla.org/en-US/docs/Web/API/Document/documentElement) object. The DOM is really just part of the wider Browser Object Model BOM. 

The BOM then forms part of the wider set of Web APIs which allow us to tap into the wider features of the web.

I often like to access a form and its element via their names and the document object as shown below.

```html
    <form name="myform">
           <input type="text" name="username"/>
           <input type="submit" value="submit"/>
    </form>
    <script>
       
       //you can access myform from the dom using document.forms
       const myform = document.forms["myform"];
       
       //you can access a form's element using form.elements
       const username = myform.elements["username"];
       
    </script>
```

# DOM Elements

Every other html element can be accessed in JavaScript by using [document.querySelector()](https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector). The attributes of the HTML element can be accessed as a property of it's corresponding element object. 

```javascript
      const link = document.querySelector('#mylink');
      console.log(mylink.href);// https://google.com

      const username = myform.elements["username"];
      
      //access html attributes via properties
      console.log(username.name);// username
      console.log(username.type);// text
      console.log(username.value);// value entered into text field  
```

# Window and Global Scope

Global functions and objects declared with **var** can be referenced via the window object. Note, that doesn't work with block scoped variables declared with **let** and **const**.

```html
    <script>
        var myVar = "foo";

        let bar = "bar";

        function baz(){}

        console.log(window.myVar);// foo
        console.log(window.bar);// undefined
        console.log(window.baz);// [function: baz]
      
    </script>
```

# DOM nodes and ID

Any element with an ID will create a JavaScript object named after that ID. innerHTML is a very useful property that returns the contents of an HTML tab. Though it seems to behave quite differently across various browsers so you're probably better of using document.querySelector().

```html
    <h1 id="myheading">My Heading</h1>  

    <script> console.log(myheading.innerHTML)</script>
    <!-- logs "My Heading" -->
```

# JS in html attributes
Some html attributes can allow JavaScript to be executed. The most popular use case is probably calling a function in an [event attribute](https://www.w3schools.com/tags/ref_eventattributes.asp). 

```html
   <button onclick="btnClick()">My Button </button>
   <script>
       function btnClick(){
           console.log('button clicked!');
       }
   </script>
```

You can also execute JavaScript in an anchor tab by specifying JavaScript in the hrefs value. This can supposedly work with elemetets that have the src attribute as well.

```html
   <a href="javascript: console.log('hello')"> Say Hello</a>
```

# Data attributes
[Data attributes](https://developer.mozilla.org/en-US/docs/Learn/HTML/Howto/Use_data_attributes) are custom attributes we can add to and element and are a great way to provide contextual data to an event handler. You can create a data attribute by supplying your custom attribute with a data- prefix. Then you can access the value by using the dataset property.

```html
   <button data-name="john" data-age="17" onclick="logUser(event)">John Button</button>
   <button data-name="mary" data-age="18" onclick="logUser(event)">Mary Button</button>
   <script>
      function logUser(event){
         const button = event.target;
         console.log(button.dataset.name); // logs john | mary
         console.log(button.dataset.age); // logs 17 | 18
      }
   </script>
```
Here we used [event.target](https://developer.mozilla.org/en-US/docs/Web/API/Event/target) to get the elment that the click event occured on. This can only work if **event** is passed to event handler logUser.

# Editable Content

I'm updating this post to include this section as I literally just came across this. You can add the **coententeditable** attribute to any element to allow the user to edit the text of the element on the page.

```html
   <h1 contenteditable="true">Text 1</h1>

   <h1 id="heading2" >Text 2</h1>

   <script>
     
     const heading = document.querySelector('#heading2');
     
     // can also be set via contentEditable property
     heading.contentEditable = 'true';

     // the input event fires anytime content id edited
     heading.oninput = function(){
         console.log('Input received');
     }
   </script>
```
You can also apply this to the entire page via the window.document.designMode property. 

```javascript
    window.document.designMode = 'on';
```

![FairYellowgreenBusiness - Replit](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4oawauodalacn9f61t6i.gif)

# Conclusion

I hope you've learned a few new things in this post. Are there any lesser known tricks that I may have missed? Please share!

# References

* [Dev.to: DOM Elements with IDs are Global Variables](https://dev.to/buntine/dom-elements-with-ids-are-global-variable)
* [Stack Overflow: Attributes & Properties](https://stackoverflow.com/questions/6003819/what-is-the-difference-between-properties-and-attributes-in-html)
* [Stack Overflow: URL Elements](https://stackoverflow.com/questions/2725156/complete-list-of-html-tag-attributes-which-have-a-url-value)
* [Stack Overflow: Elements with JS Attributes](https://stackoverflow.com/questions/27852405/html-attributes-that-can-contain-javascript)
* [Stack Overflow: ID and Global Variable](https://stackoverflow.com/questions/3434278/do-dom-tree-elements-with-ids-become-global-variables)
* [Stack Overflow: OnInput Event](https://stackoverflow.com/questions/1391278/contenteditable-change-events)