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

  1. Continue working in your Vanilla CodeSandbox named "DOM Manipulation Lab" from Part One.
  2. Follow along with the instructions below.
  3. 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

  1. Select and cache the <nav id="sub-menu"> element in a variable named subMenuEl.
  2. Set the height subMenuEl element to be 100%.
  3. Set the background color of subMenuEl to the value stored in the --sub-menu-bg CSS custom property.
  4. Add the class of flex-around to the subMenuEl element.

Progress Check - Here's what it should look like so far:

  1. Set the CSS position property of subMenuEl to the value of absolute.
  2. Set the CSS top property of subMenuEl to the value of 0.
  3. 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'},
  ]},
];
  1. Select and cache the all of the <a> elements inside of topMenuEl in a variable named topMenuLinks.
  2. Declare a global showingSubMenu variable and initialize it to false;
  3. 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.

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.

  1. In the event listener, if the clicked <a> link has a class of active:

    • Remove the active class from the clicked <a> element.
    • Set the showingSubMenu to false.
    • Set the CSS top property of subMenuEl to 0.
    • return to exit the handler.
  2. The event listener should remove a class name of active from each <a> element in topMenuLinks - whether the active class exists or not.

    • Hint: Removing a non-existent class from an element does not cause an error, so just remove it!
  3. The event listener should add a class name of active to the <a> element that was clicked.
  4. Set showingSubMenu to true if the clicked <a> element's "link" object within menuLinks has a subLinks property (all do, except for the "link" object for ABOUT); otherwise, set it to false.

    • Hint: Saving the "link" object in a variable will come in handy for passing its subLinks array later.

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:

  1. In the event listener:

    • If showingSubMenu is true:

      • Call a buildSubMenu function passing to it the subLinks array for the clicked <a> element.
      • Set the CSS top property of subMenuEl to 100%.
    • Otherwise (showingSubMenu is false):

      • Set the CSS top property of subMenuEl to 0.
  2. 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 the href 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.

Progress Check - Here's what it should look like so far:

  1. 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.
  2. Next, the event listener should:

    • Set showingSubMenu to false.
    • Set the CSS top property of subMenuEl to 0.
  3. Remove the class name of active from each <a> element in topMenuLinks - whether the active class exists or not.
  4. Update the contents of mainEl to the contents of the <a> element, within an <h1>, clicked within subMenuEl.
  5. 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.

Copyright © Per Scholas 2024