DOM Manipulation — Scripts and DOM Elements
By: John Au-Yeung
Tags: JavaScript, Programming, Web Development, Technology, Software Development

Photo by Clyde He on Unsplash

JavaScript is one of the most popular programming languages in the world. To use it effectively, we’ve to know about the basics of it.

In this article, we’ll look at how scripts are loaded, and how to attach event listeners to DOM elements.

Deferring Downloads of Scripts

A script tag can take the defer attribute to defer the downloading of scripts.

It’s deferred until the browser has parsed the closing html node.

It defers what occurs when a browser encounters a script node until the final html is encountered.

For instance, we can write:

<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" defer></script>

Asynchronously Loading External JavaScript Files

We can load external JavaScript files with the async attribute.

The async attribute will override the sequential blocking nature of script elements when the DOM has created the browser.

We tell the browser not to block other actions like parsing the DOM, downloading assets, etc.

With async , the scripts are downloaded in parallel and parsed in the order that they are downloaded.

It’s also a boolean value like defer . For instance, we can write:

<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" async></script>

Forcing Asynchronous Downloading of Scripts Using a Dynamic script Element

We can create a dynamic script element by creating them dynamically.

For instance, we can write:

const script = document.createElement("script");

script.src = "https://code.jquery.com/jquery-3.4.1.slim.min.js";

document.body.appendChild(script);

to load the jQuery script dynamically.

Creating script elements dynamically means that they may be parsed out of order.

So we won’t guarantee that all dependencies are available.

Using the onload Callback Asynchronous Script Loading

We can put our script loading code in the onload callback.

For instance, we can attach an onload listener by writing:

const script = document.createElement("script");

script.src = "https://code.jquery.com/jquery-3.4.1.slim.min.js";

script.onload = () => {

console.log('loaded');

}

Then we know when it’s loaded.

script Placement in HTML

Script elements are loaded in order synchronously by default.

For instance, if we have:

<script>

console.log(document.querySelector('p').innerHTML);

</script> <body>

<p>

foo

</p>

</body>

Then we get ‘Uncaught TypeError: Cannot read property ‘innerHTML’ of null’ since the body hasn’t been loaded yet.

On the other hand, if we have:

<body>

<p>

foo

</p>

</body> <script>

console.log(document.querySelector('p').innerHTML);

</script>

Then we get 'foo' logged since the body has been loaded.

Therefore, we’ve to be careful about the placements of script tags.

Getting scripts in the DOM

To get script tags in the DOM, we can use the document.scripts property to get them.

For instance, if we have:

<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js"></script>

<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js"></script>

<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js"></script>

Then we can get the script elements by writing:

for (const s of document.scripts) {

console.log(s);

}

document.scripts is an array-like object, so we can use it with the for-of loop.

Photo by Alasdair Elmes on Unsplash

DOM Events

DOM elements can listen to events that are triggered by users.

To listen to them, we can call addEventListener on our DOM element.

We can also set a callback as the value of the property for the event handler.

For instance, if we have:

<button>

click me

</button>

Then we can attach a click listener by writing:

const button = document.querySelector('button');

button.addEventListener('click', () => {

console.log('clicked');

}, false);

The first argument is the event name, the 2nd is the callback, the 3rd is to indicate whether we want to use capture mode.

Capture mode means that an event propagates from parent to child instead of the usual child to parent.

Likewise, we can set an event listener callback to onclick :

const button = document.querySelector('button');

button.onclick = () => {

console.log('clicked');

};

The downside of both is that we can only assign one event listener to it at a time.

Scopes may also be a clash if we use the function keyword to define our event handler functions.

The click handler will have the element as the value of this if we use function .

window handles events that are done to the body or frameset.

Conclusion

We can load scripts with the defer or async attributes to load them in the background.

Also, we can attach event listeners to DOM objects to listen to actions done to them and run code accordingly.