Is there a way to fix the close button on the menu so that it works more than once?

I have developed a JavaScript-powered navbar, but I am facing an issue with the closing button. It seems to work only once. If I try to open and close the menu repeatedly, the closing button stops working. I suspect there might be an error in my code, but I am unable to identify it. Can anyone provide assistance with this? Thank you for your help.

function myFunction() {
  const e = document.createElement('div');
  e.className = 'hello';
  e.innerHTML = `
    
        <span id="hi" class="material-icons">
        close
        </span>
         <a class="na" href="#">Home
           <span class="material-icons">home</span>
         </a>
         <a class="na" href="#">About us
           <span class="material-icons"> business</span>
         </a>
         <a class="na" href="#">Products
           <span class="material-icons"> local_mall </span>
         </a>
         <a class="na" href="#">Contact
           <span class="material-icons"> call</span>
         </a> 
    `
  e.style.backgroundColor = '#a90707'
  e.style.display = 'flex'
  e.style.flexDirection = 'column'
  e.style.width = '50%'
  e.style.height = '100vh'
  e.style.position = 'absolute'
  e.style.right = '0'
  e.style.top = '0'
  e.style.color = 'white'
  e.style.fontSize = '25px'
  document.body.appendChild(e);
  let ibt = document.querySelector('#hi')
  ibt.addEventListener('click', function()
    {
      if (e.style.display === 'block') {
        e.style.display = 'none'
      }
    })
}
@media screen and (max-width: 892px)
{
  nav ul{
    width: 60%;
  }
 
  .topnav a.icon {
    float: right;
    display: block;
  }
 
  .topnav a {
    display: none;
  }
  /*  */
 .na{
  color: white;
 list-style: none;
 padding: 20px 10px;
 text-decoration: none;
 font-size: 1.2rem;
 display: inline-block;
  position: relative;
 }
 /*  */
 .na::before{
  content: '';
    height: 2px;
    width:0;
    background-color: white;
    position: absolute;
    bottom:10px;
    left: 20px;
    transition: width 0.25s ease-out;
 }
 .na:hover::before{
  width: 15%;
 }
  /*  */
 #hi{
  padding-top: 15px;
  padding-left: 10px;
  cursor: pointer;
  display: inline-block;
  position: relative;
 }
  /*  */
 #hi::before{
    content: '';
    height: 2px;
    width:0;
    background-color: white;
    position: absolute;
    bottom:-2px;
    left: 12px;
    transition: width 0.25s ease-out;
  }
  #hi:hover::before{
  width: 6%;
  }
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="description" content="this is the big store to sell food products">
    <title>Hasaballa Market</title>
    <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="0a4d584b4e4a383a24242e32">[email protected]</a>,100..700,0..1,-50..200" />
    <link href="https://fonts.googleapis.com/icon?family=Material+Icons"
    rel="stylesheet">
    <link href="https://fonts.googleapis.com/icon?family=Material+Icons+Outlined"
      rel="stylesheet">
</head>
<body>
 <header>
   <nav class="topnav" id="myTopnav">
     <img src="images/logo.png" alt="no pic" width="80px">
     <ul>
       <li><a href="#">Contact
         <span class="material-icons"> call</span>
       </a></li>
       <li><a href="#">Products
         <span class="material-icons"> local_mall </span>
       </a></li>
       <li><a href="#">About us
         <span class="material-icons"> business</span>
       </a></li>
       <li><a  href="#">Home
         <span class="material-icons">home</span>
       </a></li>
       <li><a href="javascript:void(0);" class="icon" onclick="myFunction()">&#9776;</a> </li>
     </ul>
   </nav>
 </header>

Answer №1

  • Always use === instead of = for comparing values within an if statement.
  • To hide and show a menu (navbar), start with display: none; in the CSS, then toggle the display property using a ternary operator ?:.
  • Avoid using inline JS event handlers like on*. Instead, use EventTarget.addEventListener() to keep your JavaScript organized in one place.

// Functions for manipulating the DOM:

const el = (selector, parent) => (parent || document).querySelector(selector);
const els = (selector, parent) => (parent || document).querySelectorAll(selector);
const elNew = (tag, attributes) => Object.assign(document.createElement(tag), attributes);
const css = (element, styles) => typeof styles === "object" ? Object.assign(element.style, styles) : element.style.cssText = styles;

// Creating a navbar:

const createNavbar = () => {

  const navbarElement = elNew('div', {
    className: "navbar",
    innerHTML: `
      <span class="toggleNavbar material-icons">close</span>
      <a class="na" href="#"><span class="material-icons">home</span> Home</a>
      <a class="na" href="#"><span class="material-icons">business</span> About us</a>
      <a class="na" href="#"><span class="material-icons">local_mall</span> Products</a>
      <a class="na" href="#"><span class="material-icons">call</span> Contact</a> 
    `
  });

  css(navbarElement, `
    display: none;
    background-color: #a90707;
    flex-direction: column;
    width: 50%;
    height: 100vh;
    position: absolute;
    right: 0;
    top: 0;
    color: white;
    font-size: 25px;
  `);

  el("body").append(navbarElement);
  
  const toggleNavbar = () => {
    const isHidden = navbarElement.style.display === "none"
    navbarElement.style.display = isHidden ? "flex" : "none";
  };
  
  // Event listener to toggle navbar:
  els(".toggleNavbar").forEach((buttonElement) => {
    buttonElement.addEventListener("pointerdown", toggleNavbar);
  });
};

// Initialize navbar creation:
createNavbar();
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">

<button class="toggleNavbar" type="button">Menu</button>

Answer №2

When making comparisons between values, always remember to use the "equal" comparison operator (==) instead of the assignment operator (=).

if (element.style.display == 'block') {

Additionally, ensure that you have a logic in place to unhide the element if it is currently hidden. Consider using the following approach:

if (element.style.display != 'block') {
  element.style.display = 'block';
} else {
  element.style.display = 'none';
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Creating an HTML structure that limits each li to only contain three div elements can be achieved using React and Underscore.js

To achieve this specific layout, I am looking to utilize only underscore.js functions. Below is the array that I have: var xyz = [{ 'name': 'test' },{ 'name': 'test1' },{ 'name': &ap ...

Leverage the power of JavaScript validation combined with jQuery

Hello, I'm relatively new to the world of Javascript and jQuery. My goal is to create a suggestion box that opens when a user clicks on a specific button or div element. This box should only be visible to logged-in users. I have some knowledge on how ...

Prop type failure: The `actions` prop is specified as mandatory in the `Testing` component, however, its value is currently undefined

I am working on a project that involves creating a login form using React and Redux. Here's a snippet of my app.js: import React from 'react'; import { render } from 'react-dom'; import Input from 'react-toolbox/lib/input&apo ...

PhantomJS Karma encountering SyntaxError when trying to export variables

I've encountered an issue while running Karma and PhantomJS. When I attempt to run, the console displays the following message: 22 03 2016 14:58:47.865:WARN [karma]: No captured browser, open http://localhost:9876/ 22 03 2016 14:58:47.875:INFO [karm ...

Unable to detect HTML special characters in the text

In my current task, I am facing the challenge of matching two URLs. One URL is retrieved from a MySQL database, while the other one is sourced from an HTML page. When comparing both URLs as strings using Regex, the result shows match.Success = false. Despi ...

Utilizing an Image as a Link in the Background

I am working on a way to convert the CSS background image I have into a clickable link that can be referenced. Here is my CSS code: #wrapper { height: 100%; padding: 66px; } #ad_11 { background-image: url(images/index1.png); display: block; text-indent: ...

Constructing a React component with a constructor

I am brand new to working with react native and I'm requesting assistance in fixing the code below. Currently, I have a view within a const and I am looking to include a constructor inside the const function. const { width } = Dimensions.get(' ...

Tips for updating the corresponding nav link in CSS when transitioning between pages

In order to highlight the current page in the navigation menu, one method is to use an active attribute on the nav-link of the respective page: <ul class="navbar-nav"> <li class="nav-item"> <a class="nav-link navLink ...

Encountered an error while trying to set up the route due to Router.use() needing

Within my app.js file, I have the following code: app.use('/', require('./routes')); //old routes app.use('/api', require('./api')); Additionally, I have an api folder containing an index.js file. This is what the ...

The Bootstrap dropdown vanishes before I can even click on it

I recently encountered an issue with my Bootstrap dropdown menu on my website. After making some changes, the dropdown disappears after 1-2 seconds when viewed on a mobile phone. Interestingly, the original Bootstrap menu works fine, but not my customized ...

Having trouble retrieving data from the json file

Using Ajax to obtain a JSON update: $(document).ready(function(){ $('form').submit(function(event){ event.preventDefault(); var form = JSON.stringify($('form').serializeArray()); $.ajax ({ u ...

Maintaining aspect ratio while resizing images: A foolproof guide

I've been working on image editing and encountered a bit of trouble with aspect ratios. <img src="big_image.jpg" width="900" height="600" alt="" /> As you can see, the height and width are already specifi ...

revealing the excessive vertical space in the div upon clicking the link

Here is the structure: +-----------------------------------------------------------------------+ | | | heading {position: fixed;} | |________ ...

Trigger an event when hovering over a disabled item in React using material-ui's tooltip feature

I've been trying to figure out how to hover over a disabled item with a tooltip, but it seems that disabled items don't trigger any events. I attempted wrapping my elements in another div as a workaround, but unfortunately, it didn't work. I ...

How can CSS be used to create rounded corners on an entire webpage?

Looking for advice on how to enhance the appearance of my Progressive Web App (PWA) on devices with a "notch". I have sketched out the design with red arrows. If you need to inspect the CSS classes, you can visit my website at . I am seeking recommendation ...

What causes the initial AJAX response to be delayed by 10 seconds when using setInterval()?

I have a task that requires me to send an ajax request to display an image that changes every 10 seconds. However, I'm encountering an issue where my webpage remains blank for the first 10 seconds and only displays the first image after the initial de ...

Restrict the quantity of recommendations provided by the AutoComplete feature

After exploring the autocomplete API from https://material-ui.com/api/autocomplete/, I am unable to figure out a way, given my basic understanding of javascript, to restrict the display of a specific number of options beneath the TextField. I am working o ...

Prevent any future dates from being entered

My Thoughts: <input type="text" class="datepicker" placeholder="DD/MM/YYYY" id="datepicker" ng-model="datepicker" name="datepicker" style="width:100%" tabindex="4" required/>` Controller: `$('#datepicker').datepicker({ format: &a ...

What is the best way to line up the columns of various divs?

Is there a way to align the content of these different divs? I'm trying to match up the headers of each column with the corresponding items in the divs below. Can someone assist me in achieving this alignment? row-header-course should align with cou ...

nuxt-auth is experiencing difficulties retrieving token information through the refresh provider

I'm currently facing challenges with the login functionality in Nuxt 3. To handle user authentication, I've installed the package @sidebase/nuxt-auth. Below are my configurations set in the file nuxt.config.ts: auth: { globalAppMiddleware: t ...