R-ALAB 308H.13.1 - DOM Manipulation (Part Two)
Learning Objectives
After this lab, learners will have demonstrated the ability to:
- Manipulate the DOM using JavaScript.
- Add event handlers to HTML elements using JavaScript.
CodeSandbox
This lab uses CodeSandbox as one of its tools.
If you are unfamiliar with CodeSandbox, or need a refresher, please visit our reference page on CodeSandbox for instructions on:
- Creating an Account
- Making a Sandbox
- Navigating your Sandbox
- Submitting a link to your Sandbox to Canvas
Instructions
- Continue working in your
Vanilla
CodeSandbox named "DOM Manipulation Lab" from Part One. - Follow along with the instructions below.
- Submit the link to your CodeSandbox on Canvas when you are finished.
Deliverables
- A link to a CodeSandbox that contains your completed lab with no errors (comment things out if they do not work).
Introduction
This is the second of a two-part lab that builds a menu bar with a slide-down submenu. This lab continues where Part One left off and provides practice defining event listeners used to manipulate the DOM in response to user interaction. It also provides additional practice styling DOM elements dynamically using JavaScript.
Note: Several of the tasks in this lab would be better done upfront in the markup or CSS instead of using JS; however, the goal of this lab is to provide practice modifying the DOM using JS. In your projects, if the HTML or CSS is known in advance and/or static (unchanging), code it in HTML and CSS!
Getting Started
This is what you should have thus far from Part One:
Insert an additional <nav>
element within the <header>
element in index.html:
<header>
<nav id="top-menu"></nav>
<!-- Add the <nav> element below -->
<nav id="sub-menu"></nav>
</header>
Note: Other than the above changes, DO NOT modify index.html in any way.
Add the following CSS to the bottom of styles.css:
header, #top-menu {
position: relative;
}
#top-menu {
z-index: 20;
}
#sub-menu {
width: 100%;
z-index: 10;
transition: top 0.5s ease-out;
}
#sub-menu a:hover {
background-color: var(--top-menu-bg);
}
nav a.active {
background-color: var(--sub-menu-bg);
color: var(--main-bg);
}
Note: Other than the above changes, DO NOT modify styles.css in any way.
Requirements
- Select and cache the
<nav id="sub-menu">
element in a variable namedsubMenuEl
. - Set the height
subMenuEl
element to be100%
. - Set the background color of
subMenuEl
to the value stored in the--sub-menu-bg
CSS custom property. - Add the class of
flex-around
to thesubMenuEl
element.
Progress Check - Here's what it should look like so far:
- Set the CSS
position
property ofsubMenuEl
to the value ofabsolute
. - Set the CSS
top
property ofsubMenuEl
to the value of0
. - Update the
menuLinks
array in index.js to this:
var menuLinks = [
{text: 'about', href: '/about'},
{text: 'catalog', href: '#', subLinks: [
{text: 'all', href: '/catalog/all'},
{text: 'top selling', href: '/catalog/top'},
{text: 'search', href: '/catalog/search'},
]},
{text: 'orders', href: '#' , subLinks: [
{text: 'new', href: '/orders/new'},
{text: 'pending', href: '/orders/pending'},
{text: 'history', href: '/orders/history'},
]},
{text: 'account', href: '#', subLinks: [
{text: 'profile', href: '/account/profile'},
{text: 'sign out', href: '/account/signout'},
]},
];
- Select and cache the all of the
<a>
elements inside oftopMenuEl
in a variable namedtopMenuLinks
. - Declare a global
showingSubMenu
variable and initialize it tofalse
; -
Attach a delegated 'click' event listener to
topMenuEl
.- The first line of code of the event listener function should call the event object's
preventDefault()
method. - The second line of code of the function should immediately
return
if the element clicked was not an<a>
element. console.log
the content of the<a>
to verify the handler is working.
- The first line of code of the event listener function should call the event object's
Progress Check -
Ensure that clicking ABOUT, CATALOG, etc. logs about, catalog, etc. when a link is clicked.
Clicking anywhere other than on a link should do nothing.
-
In the event listener, if the clicked
<a>
link has a class ofactive
:- Remove the
active
class from the clicked<a>
element. - Set the
showingSubMenu
tofalse
. - Set the CSS
top
property ofsubMenuEl
to0
. return
to exit the handler.
- Remove the
-
The event listener should remove a class name of
active
from each<a>
element intopMenuLinks
- whether theactive
class exists or not.- Hint: Removing a non-existent class from an element does not cause an error, so just remove it!
- The event listener should add a class name of
active
to the<a>
element that was clicked. -
Set
showingSubMenu
totrue
if the clicked<a>
element's "link" object withinmenuLinks
has asubLinks
property (all do, except for the "link" object for ABOUT); otherwise, set it tofalse
.- Hint: Saving the "link" object in a variable will come in handy for passing its
subLinks
array later.
- Hint: Saving the "link" object in a variable will come in handy for passing its
Progress Check -
Clicking any of the links should make that link "active" and clear the others.
Clicking an "active" link should clear that link.
Here's what it should look like so far:
-
In the event listener:
-
If
showingSubMenu
istrue
:- Call a
buildSubMenu
function passing to it thesubLinks
array for the clicked<a>
element. - Set the CSS
top
property ofsubMenuEl
to100%
.
- Call a
-
Otherwise (
showingSubMenu
isfalse
):- Set the CSS
top
property ofsubMenuEl
to0
.
- Set the CSS
-
-
Code the
buildSubMenu
function so that it:- Clears the contents of
subMenuEl
. -
Iterates over the
subLinks
array passed as an argument, and for each "link" object:- Create an
<a>
element. - On the new element, add an
href
attribute with its value set to thehref
property of the "link" object. - Set the new element's content to the value of the
text
property of the "link" object. - Append the new element to the
subMenuEl
element.
- Create an
- Clears the contents of
Progress Check - Here's what it should look like so far:
-
Attach a delegated 'click' event listener to
subMenuEl
.- The first line of code of the event listener function should call the event object's
preventDefault()
method. - The second line of code function should immediately
return
if the element clicked was not an<a>
element. console.log
the content of the<a>
to verify the handler is working.
- The first line of code of the event listener function should call the event object's
-
Next, the event listener should:
- Set
showingSubMenu
tofalse
. - Set the CSS
top
property ofsubMenuEl
to0
.
- Set
- Remove the class name of
active
from each<a>
element intopMenuLinks
- whether theactive
class exists or not. - Update the contents of
mainEl
to the contents of the<a>
element, within an<h1>
, clicked withinsubMenuEl
. - If the ABOUT link is clicked, an
<h1>About</h1>
should be displayed.
Complete
You're done! Remember to submit the link to your project to Canvas.