Lesson 12 / JavaScript
JavaScript in the DOM
Use JavaScript and the Document Object Model to select elements, change content, respond to events, and create dynamic interfaces.
Course Role
Core
Part of the main course path. Prioritize this before moving to optional polish or deeper references.
Teacher Notes / In-Class Use
Demo Live
- Use the DOM lab to show select, change, listen, and respond as the core JavaScript pattern.
- Compare textContent, classList, setAttribute, and appendChild as different kinds of DOM changes.
Try In Class
- Have students create a button that toggles a class on one visible element.
- Ask students to write one console.log before changing the DOM so they can confirm the event fired.
Submit Or Check
- The interaction should still work after refresh and should not require inline onclick attributes.
- Students should be able to point to the selected element, the event listener, and the changed class or content.
Watch For
- Scripts running before the HTML exists because the script is loaded too early.
- Students changing inline styles directly when toggling a class would be clearer.
Learning Goals
- Explain the DOM as a living representation of an HTML document
- Modify DOM element content, attributes, styles, and classes
- Use event listeners and the event object to respond to user actions
Interactive Demo
How to use this demo.
Use the demo as a small lab. Change one thing, observe the result, then connect it back to your own project.
What To Try
- Click each action button and watch the preview and code sample update.
- Reset the demo, then predict what will change before pressing the next button.
What Changes
- Text, classes, attributes, and list items update through JavaScript.
- The code sample shows the DOM method behind each interaction.
What To Notice
- Most interactions follow the pattern: select something, listen for an event, change something.
- Changing classes is usually cleaner than writing many inline styles from JavaScript.
Apply It
- Add one button to your project that toggles a class on a visible element.
Interactive Demo
DOM Interaction Lab
Use the controls to change content, classes, attributes, and elements in the preview. The code updates to show the JavaScript behind the action.
Ready
Original card title
JavaScript can select this text and update it after the page loads.
Visit LSU- Existing list item
const title = document.querySelector('[data-dom-title]');
title.textContent = 'Updated by JavaScript'; What to notice
- JavaScript selects elements before it changes them.
- classList changes styling without rewriting the HTML.
- createElement and appendChild add new content to the page.
Try this
- Click each action and read the generated code.
- Reset the demo, then predict what each action will change.
- Rebuild one action in your own script.js file.
This demo uses extra JavaScript for teaching. The code sample shows the pattern to practice. View full demo source.
What This Teaches
This lesson teaches how JavaScript interacts with the Document Object Model, or DOM.
The browser reads your HTML and creates the DOM: a structured representation of the page that JavaScript can read and update after the page loads.
You will learn a repeatable workflow: select an element, listen for an event, then change content, classes, attributes, or elements.
Core Workflow: Select, Listen, Change
Most beginner DOM interactions follow the same pattern.
- Select an element with
document.querySelector()or another selector method. - Listen for an event with
addEventListener(). - Change something with
textContent,classList, attributes, or new elements.
const button = document.querySelector('.menu-button');
button.addEventListener('click', () => {
document.body.classList.toggle('menu-open');
}); Adding JavaScript to Your Web Page
You can include JavaScript in your HTML document in three common ways.
For class projects, an external file loaded with defer is the preferred approach.
Inline
Inline JavaScript is written directly in an HTML attribute like onclick.
Recognize this pattern in older examples, but avoid it for class projects because it mixes behavior into markup.
<button onclick="alert('Hello!')">Click me</button> Internal
Internal JavaScript is written inside script tags in the HTML file.
This is acceptable for quick demos, but it becomes hard to maintain as a project grows.
<head>
<script>
// Your JavaScript code here
</script>
</head> External
External JavaScript is placed in a separate file and linked with the src attribute.
Use defer so the browser downloads the script while parsing the HTML, but runs it after the HTML is ready.
defer helps prevent the common error where JavaScript tries to select an element before that element exists in the DOM.
<head>
<script src="script.js" defer></script>
</head> Selecting Elements
Before JavaScript can change something, it needs a reference to the element.
| Method | Use For |
|---|---|
document.querySelector() | Selects the first element that matches a CSS selector. |
document.querySelectorAll() | Selects all matching elements as a list-like collection. |
document.getElementById() | Selects one element by its id. |
const button = document.querySelector('.menu-button');
const cards = document.querySelectorAll('.card');
const mainNav = document.getElementById('main-nav'); When a Selector Finds Nothing
If a selector does not match anything, querySelector() returns null.
Check that the element exists before calling methods like addEventListener().
const button = document.querySelector('.menu-button');
if (button) {
button.addEventListener('click', () => {
document.body.classList.toggle('menu-open');
});
} Interactive Practice: DOM Interaction Lab
Use the DOM Interaction Lab above to change text, toggle a class, update an attribute, and add a list item.
Read the generated code after each action. Notice that every action starts by selecting an element before changing it.
Modifying Content Safely
Use textContent when inserting plain text. Use innerHTML only when the HTML is trusted and you understand the risk.
| Property or Method | Use For | Caution |
|---|---|---|
textContent | Changing plain text. | Best default for beginner projects. |
innerHTML | Replacing HTML inside an element. | Do not use with user-provided content. |
createElement() | Building structured content safely. | Takes more steps but gives more control. |
const message = document.querySelector('.message');
message.textContent = 'Saved successfully.'; Modifying Attributes
Attributes store extra information on HTML elements. JavaScript can read and update them.
const link = document.querySelector('.resource-link');
link.href = 'https://developer.mozilla.org/';
link.textContent = 'Read MDN'; Changing Classes Instead of Inline Styles
For most interface changes, toggle a class instead of writing many inline styles with JavaScript.
This keeps styling in CSS and behavior in JavaScript.
const card = document.querySelector('.card');
card.classList.toggle('is-highlighted'); Working with classList
The classList API is the preferred way to work with an element's classes.
add(className): Adds a class to the element.remove(className): Removes a class from the element.toggle(className): Toggles a class on or off.contains(className): Checks whether the element has a specific class.
const menu = document.querySelector('.site-menu');
menu.classList.toggle('is-open');
if (menu.classList.contains('is-open')) {
console.log('Menu is open');
} Traversing the DOM
DOM traversal means moving between related elements after you have selected one element.
For beginners, element-based properties are usually easier than node-based properties because they skip whitespace text nodes.
| Property | Meaning |
|---|---|
parentElement | The parent element. |
children | The child elements. |
firstElementChild | The first child element. |
nextElementSibling | The next sibling element. |
previousElementSibling | The previous sibling element. |
const item = document.querySelector('.faq-item');
const parent = item.parentElement;
const nextItem = item.nextElementSibling; Creating and Inserting Elements
JavaScript allows you to dynamically create new elements and insert them into the DOM.
const item = document.createElement('li');
item.textContent = 'New list item';
const list = document.querySelector('.task-list');
list.appendChild(item); Event Listeners: Responding to User Actions
Event listeners run JavaScript when something happens, such as a click, form submission, or text input.
element.addEventListener('click', () => {
// Code to execute when the element is clicked
}); Common Event Types
| Event | Use For |
|---|---|
click | Buttons, menu toggles, and simple interactions. |
input | Reacting while a user types or changes a control. |
change | Reacting after a form control value changes. |
submit | Handling a form submission. |
keydown | Responding to keyboard input. |
Using the Event Object
When an event occurs, an event object is passed to the listener function.
The event object includes information like event.target, event.type, and methods like preventDefault().
const form = document.querySelector('.signup-form');
form.addEventListener('submit', (event) => {
event.preventDefault();
console.log('Handle the form with JavaScript');
}); Accessible Menu Toggle
A responsive menu toggle should use a real button, update aria-expanded, and show or hide the controlled menu.
<button class="menu-button" aria-expanded="false" aria-controls="site-menu">
Menu
</button>
<nav id="site-menu" hidden>
<a href="/">Home</a>
<a href="/projects/">Projects</a>
</nav> Accessible Menu Toggle JavaScript
const button = document.querySelector('.menu-button');
const menu = document.querySelector('#site-menu');
button.addEventListener('click', () => {
const isOpen = button.getAttribute('aria-expanded') === 'true';
button.setAttribute('aria-expanded', String(!isOpen));
menu.hidden = isOpen;
}); Working with Multiple Elements
Use querySelectorAll() when the page has multiple matching elements. Then loop over the collection and attach behavior to each one.
const buttons = document.querySelectorAll('.faq-button');
buttons.forEach((button) => {
button.addEventListener('click', () => {
button.classList.toggle('is-open');
});
}); Common Mistakes
| Mistake | Why it happens | Fix |
|---|---|---|
| Script runs before HTML exists | JavaScript executes before the element is parsed. | Load external scripts with defer. |
Selector returns null | The selector does not match the HTML. | Check spelling, class dots, ids, and timing. |
Forgetting the dot in .class | querySelector() uses CSS selector syntax. | Use .menu-button for classes and #site-menu for ids. |
Using innerHTML for user input | Untrusted HTML can create security problems. | Use textContent or create elements manually. |
| Adding one listener to many elements incorrectly | querySelector() only returns the first match. | Use querySelectorAll() and loop. |
| Changing many inline styles | CSS and JS become tangled. | Toggle classes and keep visual styling in CSS. |
Debugging Checklist
- Open DevTools Console and read the exact error message.
- Check whether the selected element is
null. - Confirm the script is loaded with
deferor placed after the HTML it uses. - Log selected elements with
console.log()to verify selectors. - Confirm event names are lowercase, such as
clickandsubmit. - Check whether a class is being added in the Elements panel.
- Prefer changing one thing at a time, then retest.
Additional Resources
MDN: Introduction to the DOM | MDN: querySelector | classList API - MDN | Events Documentation - MDN
Checkpoint
Before moving on, make sure these feel true.
- I can select an element from the DOM.
- I can respond to a user event with addEventListener.
- I can change content, classes, or attributes without using inline JavaScript.
Project Connection
This lesson supports current class projects.
Practice
- Load an external
script.jsfile withdefer. - Select one element with
document.querySelector()and update itstextContent. - Create a button that toggles a class with
classList.toggle(). - Build a show/hide FAQ item with a real
button. - Build a menu toggle that updates
aria-expanded. - Handle a simple form
submitevent withpreventDefault(). - Use
querySelectorAll()to attach click behavior to multiple buttons. - Create a new list item with
createElement()and add it withappendChild(). - Use DevTools Console to debug a selector that returns
null.