The active index data is not being updated in the CSS styling

I have a JavaScript file that updates the index based on the cursor's position over items in a menu. Here is the code I used:

const menu = document.getElementById("menu");
Array.from(document.getElementsByClassName("menu-item"))
  .forEach((item, index) => {
    item.onmouseover = () => {
      menu.dataset.activeIndex = index;
    }
  });

The index update is supposed to change the background image using CSS.

#menu[data-active-index="0"] > #menu-background-pattern {
    background-position: 0% -25%;
  }

  #menu[data-active-index="1"] > #menu-background-pattern {
    background-position: 0% -50%;
  }

  #menu[data-active-index="2"] > #menu-background-pattern {
    background-position: 0% -75%;
  }

  #menu[data-active-index="3"] > #menu-background-pattern {
    background-position: 0% -100%;
  }

The background image is not moving even though it should have moved. Here is the HTML:

<div id="menu">
    <div id="menu-items">
      <div class="menu-item">Home</div>
      <div class="menu-item">Shop</div>
      <div class="menu-item">About</div>
      <div class="menu-item">Contact Us</div>
    </div>
    <div id="menu-background-pattern"></div>
    <div id="menu-background-image"></div>
  </div>
  <script></script>
  <link rel="stylesheet" href="main.css">

Answer №1

There are a couple of issues with the JavaScript code that was originally provided by Hyperplexed on Codepen.

  1. The code is executing too early. - Because it's running before the elements have loaded, the onmouseover event cannot be applied to any elements. (Thanks @freedomn-m for pointing this out)
  2. The .forEach() method is designed to iterate over indices, not properties.

Solution:

To address the first problem, we can create a function that executes once the document has finished loading:

function ready(fn) {
    if (document.readyState !== 'loading') {
        fn();
    } else {
        document.addEventListener('DOMContentLoaded', fn);
    }
}

We then encapsulate the original JS code within a function and run it when the page is fully loaded:

function menuListener () {
    const menu = document.getElementById("menu");
    Array.from(document.getElementsByClassName("menu-item"))
        .forEach((item, index) => {
            item.onmouseover = () => {
                menu.dataset.activeIndex = index;
        }
    });
}
function ready(fn) {
    if (document.readyState !== 'loading') {
        fn();
    } else {
        document.addEventListener('DOMContentLoaded', fn);
    }
    // Credit: https://youmightnotneedjquery.com/#ready (Suggested by @freedomn-m)
}
ready(menuListener)

Furthermore, we adjust the way we iterate over the elements:

function menuListener () {
    const menuItems = Array.from(document.getElementsByClassName("menu-item"))
    const menu = document.getElementById("menu");
    for (let i = 0; i < menuItems.length; i++) {
        menuItems[i].onmouseover = () => {
            menu.dataset.activeIndex = i
        }
    }
}

By revamping our approach to looping through elements, we've improved both functionality and readability of the code.

Answer №2

Encountering a similar issue, I managed to find a solution. The root cause was attributed to the utilization of class or id in the HTML code. When altering a div with a class name, it's essential to employ '.' whereas if the div is identified by an id, '#' should be used.

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

Using JavaScript functions within a WebView and ViewPager

Encountering an issue with Javascript in WebView. I have a ViewPager that dynamically adds Views as needed. Prior to adding a View to the viewpager, I inflate it and load an embedded webview inside: LayoutInflater inflater = this.getLayoutInflater(); ...

Set options for nested arrays with up to n levels of children

My project involves building a category module using Laravel for the backend and Vue.js for the frontend. I have incorporated the library Laravel Nestable The library has been successful in producing the desired output. [ { "id": 1, "name": "C ...

Ensure that the "position: absolute" is anchored to the document rather than the parent container

How can I add a div to any section of the webpage and have it positioned absolutely in relation to the entire document, rather than being affected by a parent element with relative positioning? ...

Difficulty Parsing Date within XLSX File Using SheetJs

When attempting to read an XLSX file using the sheetjs node-module, I encountered a problem with dates in one of the columns. The original data in the file is formatted as '2/17/2020', but after parsing it through xlsx, the format changes to &apo ...

Tips for avoiding tagline text overlapping with other content

I'm facing a dilemma with my Bootstrap template where my tagline overlaps all other content on the page. When I scroll down, the text lays over my logo and navbar, creating a messy look especially on smaller screens. Despite trying to adjust the z-in ...

steps to create a personalized installation button for PWA

Looking to incorporate a customized install button for my progressive web app directly on the site. I've researched various articles and attempted their solutions, which involve using beforeinstallprompt. let deferredPrompt; window.addEventListener(& ...

Determine the class name of an element when it is clicked on

For various reasons, I am unable to use $('.class').click or on('click', function..) Therefore, I must utilize the onclick="" event from the html element. Is there a way to determine the class of the element where the onclick event oc ...

Enhancing audio control features using HTML and JavaScript

After utilizing various suggestions, I have successfully created a basic audio slider that starts playing sound (at zero volume) when clicked by the user. They can then adjust the volume as needed. My only challenge is that the volume adjustment only occu ...

Modifying the stylesheet of an Infragistics WebDataGrid

Currently, I am attempting to customize the appearance of my web data grid by changing its CSS, particularly focusing on altering the color of the header and rows. So far, my search for solutions has led me to two common suggestions: Edit the Infragist ...

What is the best way to design an HTML table that features alternating colors for each row and column?

I recently came across this image showcasing a beautifully designed table: https://i.stack.imgur.com/6K63q.png The current HTML code I have applies colors to every even line, including the year columns and subcolumns. Is there a way to assign unique mixe ...

Ways to achieve a layout with 2 fixed columns and 1 dynamic column using CSS

For the past 2 days, I've been struggling with this problem. I've experimented with "display: flex" and various combinations, but none have given me the desired outcome. I require CSS code to achieve this layout (refer to the image). I have two ...

Can you save data entered by a user into a text file using JavaScript or a similar technology in HTML, without the need to send it to a server?

Is there a way to create a site where user data is inputted into an input box or form, and then that information is stored in a .txt file on the user's C drive without uploading it to a server first? I've been experimenting with various forms an ...

Toggling the visibility of divs in a dynamic layout

How can I use JQuery/JavaScript to show only the comment form for a specific post when a button or link is clicked on a page containing multiple posts divs with hidden comment forms? <div class="post"> <p>Some Content</p> <a ...

Utilizing JavaScript Files Instead of NPM as a Library for Open Layers: A Step-by-Step Guide

I've been attempting to get Open Layers to function in my Eclipse web development environment, but I've encountered some challenges along the way. The setup instructions provided on the Open Layers website focus mainly on using npm. Nevertheless, ...

Integrate Vue.js with Laravel

Hey there fellow developers, I'm a university student who is new to using frameworks. Recently, I completed a project for my internship using the Laravel framework for the back end. Now, I want to tackle the front end using VueJS. Can anyone guide me ...

What is the best way to position a button in the center?

I am attempting to position the add button in the middle of the box, not just centered, but truly in the middle of it. .gallery { background-color: #fbfbfb; border-radius: 5px; border-style: solid; border: 1px solid #bbbbbb; height: 85px; li ...

Instructions for passing the chosen value to Django

I am struggling to set up a search button using Ajax and Django. I need to send the selected value to the server, but I can't seem to retrieve the value from the select HTML tag. The variable value always ends up empty ({"obj":""}). Any ideas? HTML : ...

Make changes to the HTML file by directly using Jquery or JavaScript

Allow me to elaborate on my current objective. I have an HTML file that requires direct content updates. Specifically, I am working with elements sharing the 'id=test'. My goal is to dynamically update all elements with unique IDs such as ' ...

Mongoose documents are set to automatically be deleted after a duration of one month

My goal is to retain a particular document for one month after the client-user deletes it. To achieve this, I have decided to simulate a delete action and display data in the browser. Sample schema: const product = new mongoose.Schema({ --- trash : { ty ...

Polymer elements fail to adapt to varying screen sizes

I am currently working on creating a responsive website using polymer, but I have encountered an issue where certain elements (such as core-toolbar and paper-fab) are not scaling properly on smaller, denser screens like smartphones. After browsing through ...