Day 1 Overview: VanillaJS

Day 1 Overview: VanillaJS

Why am I taking this course?

Though I've been coding for about 3 years now since I finished my boot camp at the tail end of 2020, and have used React extensively during my stops at LeanIX and Twilio, I found that I still had gaps in my mental model of what the underlying implementation of VanillaJS was doing to render out my JSX, and ultimately, the components I was building. Though I know enough to build things and be a productive engineer, I wanted to take the time to immersive myself in the VanillaJS world and DOM APIs from first principles to solidify my understanding of JavaScript itself and any frontend library or framework that I'll come across in my software engineering journey.

💡
If you'd like to check out the repo with all of my work following this course, feel free to check it out here!

What is VanillaJS?

VanillaJS is the usage of the core language and browser APIs to create web apps without any additional libraries or frameworks added on top.

Why Vanilla JS?

  • Add one more tool to my toolbox

  • Understand what my library is doing

  • Extend my library with plugins

  • Be a better web developer

  • To mix with libraries

  • Frontendmasters.com is written in VanillaJS!

  • To use it! Can create simple and fast web apps with no CLI, no build process

Main advantages of VanillaJS (according to Max Firtman):

  • Lightweight

  • Control and Power

  • Simplicity

  • Flexibility

  • Performance

  • Compatibility

  • No node-modules

Main fears of VanillaJS (according to Max Firtman):

  • Routing for Single-Page Applications

  • Too verbose and time-consuming

  • State Management

  • Templating

  • Complexity

  • Reusable Components

  • Maintenance

  • Learning Curve

  • Browser Compatibility

  • Reinventing the wheel every time

  • Scalability

💡
Learn the tool and use it when it’s the best option. Not advocating for using VanillaJS on every project.

The DOM API

💡
The Document Object Model connects web pages to JavaScript by representing the structure of a document in memory. The DOM API is a browser API exposed to developers to manipulate the DOM from a scripting language.

The DOM API is available on many objects:

  • window global object- window

  • document object- represents the current DOM

  • one object per HTML element and other nodes in our document

<html>
    <body>
        <header>
            <h1> The DOM</h1>

            <p class='tagline'> Document Object Model</p>

            <img hidden src='dom.png'>
        </header>
    </body>
</html>

  • Each element is represented by an object (class) of the HTMLElement interface or other interfaces that inherit it

  • They have instance properties and methods

  • Changes in properties or children will trigger updates in the user interface when we release the thread.

    • What does it mean to release the thread in JS?

      • When our function ends (event handler finishes)

      • If we don’t release the thread, the browser doesn’t have enough time to relay out repaints, re-renders, etc and so the browser won't be able to engage with the user (it will ask to kill the process). When we have high-intensity CPU usage, we should instead put that in a Web Worker

  • We can listen to events happening in that element and react as a consequence

To work with DOM elements, we can

  • Pick them from the current DOM

  • Create them and then inject them into the DOM

To have a reference to an Element we can:

  • Read its content

  • Change its content

  • Remove it

  • Add new elements

Finding Elements in the DOM

Select elements from the DOM

  • By ID

  • By Class Name

  • By Name

  • By CSS Selector

  • Navigating DOM structure

When selecting elements, some functions return:

  • One HTML Element: (HTMLElement)

  • Live HTML Element Collection: (HTMLCollection) allows you to change collections on the fly

  • Static Element Collection (NodeList): Have modern array-like methods (map filter reduce, etc.)

Most common functions to get a reference to one DOM element

  • getElementById: To get one element, if it has ID. From the first-ish version of the DOM

  • querySelector: More modern, will let you get the first element matching CSS selector

💡
When using a function that returns one element, it can also return null if no node was found.
const element = document.getElementById('one-item');

if (element !== null) {
    //element found
}

Most common functions to get a reference to multiple Dom elements:

  • getElementsByTagName

  • getElementsByClassName

  • querySelectorAll(): a static collection

  • getElementsByName

💡
When we use functions that return multiple elements, it can also return an empty collection if no elements were found.

In the following example, elements is a static NodeList. This means that the collection we receive has a length property and can be accessed as an array using [] syntax and, since it is array-like, it has the array of modern interfaces we know.

const elements = document.querySelectorAll('#nav-menu li');

if (elements.length > 0){
    //elements found
    const firstElement = elements[0];
}
//can also use forEach
elements.forEach(element => console.log(element));

In our next example, our elements variable is a live HTMLCollection, and so the collection we receive has a length property as well and can be accessed using [] syntax, BUT it's not an Array, so we have no access to all the common methods we would expect.

const elements = document.getElementsByClassName('important');
//no forEach() available, so need to use for loop
for (let currentlElement of elements){
    //we process each currentElement
}

HTMLCollections (live) don’t have all the modern Array interface, such as filter, map, reduce, or forEach. We can add modern array functions to it by creating an Array from it using Array.from(collection):

// we enhace the HTMLCollection into an Array
const elements = Array.from(document.getElementsByClassName('important'))

// we can use array methods now
elements.filter(e => e.tagName === 'p');

With an HTML Element in JavaScript we can:

  • Read and change attributes’ values

  • Read and change styles

  • Hook event listeners

  • Add, remove or move children elements

  • Read and change its contents

  • More APIs

Modifying the DOM

How to read or change attributes of a Dom element

We can use dot syntax to access properties mapped from HTML attributes. Most attributes have the same name as JS properties but exceptions apply, such as className and htmlFor.

element.hiddern = false;
element.src = 'logo.png';
element.className = 'myClass'; // class HTML attribute

How to read or change styles of a DOM element:

We can use dot syntax to access a style object. That object will have a map to every CSS property we can inline in HTML. Just remember to change kebab syntax (-) to camel case syntax for JS.

element.style.color = 'blue';
element.style.fontSize = '1.2em';          // font-size
element.style.borderRightColor '#FCFCFC';  // border-right-color

How to listen to events of an HTML element

We can also use dot syntax and bind a function to an event name using addEventListener. There is a list of standard events.

function eventHandler(event) {
    //do something
}

element.addEventListener('click', eventHandler);

//OR

element.addEventListener('click', function(event) {
    //do something
});

//OR

element.addEventListener('click', () => {
    //do something
});

Accessing and Editing Contents of the Elements

  • Accessing textContent: access and edit content, does not support HTML

  • Access innerHTML: supports HTML, can define whole webpage HTML as string

  • Using DOM APIs to create new nodes

Working with textContent:

const element = document.querySelector('#message');

//We read the current element's content as string
const contents = element.textContent;

//We change the contents of the element with a new string
element.textContent = "The text has been changed";

Working with innerHTML:

const element = document.querySelector('#section-6 header');

//We read the current element's HTML content as string
const contents = element.innerHTML;

//W3 change the contents of the element with a new HTML string
element.innerHTML = `
    <h1>My App</a>
    <p>The best platform for learning frontend</p>
`;
💡
Be careful of using innerHTML for HTML elements, since there's no way of validating that the string is valid HTML

Working with DOM APIs to create or edit content:

const element = document.querySelector('#section-6 header');

const h1 = document.createElement('h1');
h1.textContent = 'My App';
element.appendChild(h1);

const p = document.createElement('p');
p.textContent = 'The best platform for learning frontend';
element.appendChild(p);
💡
Remember appendChild allows us to append an element, append() only allows us to use strings, not elements

That's it for Day 1! Thanks for reading this far and stay tuned for my progress in Day 2 in my series!