Experience the click action that comes equipped with two unique functions: the ability to effortlessly add or remove a class

Currently, I am in the process of creating a list of anchor links that contain nested anchor links, and there are a few functionalities that I am looking to implement.

Upon clicking on a link:

  1. Add a class of "current"
  2. Remove the class of "current" from any other link or nested link
  3. If the item has children, toggle the value of a data-attribute (e.g., data-children="visible" or data-children="hidden")
  4. Ensure that the anchor link functionality remains intact

It is worth mentioning that whether the "data-children" attribute is present on the parent a.link or on the div.children is irrelevant to me.

HTML

<ul>
    <li><a href="#l1" class="link">Level 1</a></li>
    <li><a href="#l2" class="link" data-children="hidden">Level 2</a>
        <div class="children">
            <ul>
                <li><a href="#l2-1" class="link">Level 2.1</a></li>
                <li><a href="#l2-2" class="link" data-children="hidden">Level 2.2</a></li>
                <li><a href="#l2-3" class="link">Level 2.3</a></li>
            </ul>
        </div>
    </li>
    <li><a href="#l3" class="link">Level 3</a></li>
</ul>

JavaScript

let el = document.querySelectorAll('.link');
for (let i = 0; i < el.length; i++) {
  el[i].onclick = function() {
    let c = 0;
    while (c < el.length) {
      el[c++].className = 'link';
    }
    el[i].className = 'link current';

    let x = el.getAttribute('data-children');
    if (x === 'visible') {
      el.setAttribute('data-children', 'visible');
    } else {
      el.setAttribute('data-children', 'hidden');
    }
  };
}

The desired outcome is to enable any link to be marked as the "current" link, with the ability to toggle the display of any or all child links.

By clicking on a parent link, it will acquire the class="link current" and toggle the attribute to data-children="visible". Clicking the parent link again will switch the attribute to data-children="hidden," while maintaining the class="link current" for the link.

Answer №1

Give this a shot:

const elements = document.querySelectorAll('.link');
    for (let j = 0; j < elements.length; j++) {
        elements[j].onclick = function() {
            let count = 0;
            while (count < elements.length) {
                elements[count++].className = 'link';
            }
            elements[j].className = 'link current';

            // toggle data-children attribute for clicked link and children
            const hiddenNodes = elements[j].parentNode.querySelectorAll('[data-children=hidden]');
            const visibleNodes = elements[j].parentNode.querySelectorAll('[data-children=visible]');

            for (let k = 0; k < hiddenNodes.length; k++) {
                hiddenNodes[k].setAttribute('data-children', 'visible');
            }

            for (let k = 0; k < visibleNodes.length; k++) {
                visibleNodes[k].setAttribute('data-children', 'hidden');
            }
        };
    }
<ul>
    <li><a href="#l1" class="link">Level 1</a></li>
    <li><a href="#l2" class="link" data-children="hidden">Level 2</a>
        <div class="children">
            <ul>
                <li><a href="#l2-1" class="link">Level 2.1</a></li>
                <li><a href="#l2-2" class="link" data-children="hidden">Level 2.2</a></li>
                <li><a href="#l2-3" class="link">Level 2.3</a></li>
            </ul>
        </div>
    </li>
    <li><a href="#l3" class="link">Level 3</a></li>
</ul>

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

Alerts in online software when there is a modification in the database

I am working on a project to create a web application that needs to display notifications, like the ones you see on Facebook, whenever there is a new update in the database. I could use some assistance with implementing this feature. Are there any third- ...

Dynamic image sources in reusable Gatsby-Image Component

Recently, I have been exploring Gatsby-Image for an upcoming project and have started experimenting with its capabilities. My test project was successful, but now I want to utilize the <Image /> tag from Gatsby in a similar way to a standard <img ...

Operating on Javascript Objects with Randomized Keys

Once I retrieve my data from firebase, the result is an object containing multiple child objects. myObj = { "J251525" : { "email" : "<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="6c3823212 ...

What is the best way to deactivate the first two columns of the header in Vue?

I am attempting to deactivate the draggable function for the first 2 columns. I have tried using options in the draggable plugin. :options="{disabled : 'Subject'}" However, this disables the draggable functionality for all headers. < ...

React component utilizes Material UI to detect scrolling within a table

Currently, my table's body size is set to fixed dimensions in accordance with Material UI guidelines. I am looking to implement a functionality that allows me to dynamically load more rows as the user scrolls through the table. Can you recommend the ...

Collapsing Bootstrap menu bar causing logo overlap

When the navbar collapses (when it shows the toggle icon), the menu items (home, services, portfolio, about, contact) overlap with the logo. If I remove the position:absolute from the logo (navbar-brand), the menu appears in the center. Is there a way to h ...

Customizing Ext JS/Sencha Chart framework based on certain conditions

As someone who is new to Ext JS and Sencha charts, I have encountered a challenge with one of the charts in our application. Specifically, I needed to hide the dashes on the X-Axis of that particular chart. Our application is built using Ext JS version 5.1 ...

Tips on preventing right-click actions in jqGrid

While utilizing onSelectRow in a jqGrid, I have noticed that it functions properly when clicking with the left mouse button. However, when right-clicking, it still triggers the function. My aim is for the right-click to perform its usual action (such as di ...

Shorten Text - React Native

I currently have a React Native application with a FlatList component. The logic I initially implemented was to display an Expand/Collapse arrow whenever the content at the 100th position in the list is not empty. However, I now realize that this approach ...

Add a new key-value pair to each object in an array, with the value generated by making a request using axios.get

Recently, I've been working on a scraper that has been functioning well until I encountered an issue while trying to scrape data for individual links. Let me clarify the situation: The scraper gathers data about apartments from a webpage where articl ...

The Mongoose query for the id field retrieves both the id and _id values

Within my Mongoose schema, there is a specific field named id which holds a unique identifier for each document. This operates using the same system as the standard _id field as shown below: var JobSchema = new mongoose.Schema({ id: { type:String, requi ...

XML and numerous, distinct DIV elements

Is it possible to display content from an XML file in a DIV upon clicking, without using IDs and involving multiple DIVs? For instance, when clicking on the first link in the following code snippet, the content from an XML file should only appear in the r ...

Adding a new key-value pair to a JSON data structure

Here is the JSON object that I am currently handling: { "name": "John Smith", "age": 32, "employed": true, "address": { "street": "701 First Ave.", "city": "Sunnyvale, CA 95125", "country": "United States" }, ...

What methods can I use in Mocha with Sinon for testing multiple callbacks?

My code involves a function with asynchronous operations and multiple callbacks var f = (cb1, cb2) => { return new Promise((resolve, reject) => { /* ... */ }); }; During testing, I wanted to use sinon to create spies var cb1Spy = sinon.spy(); va ...

Combining property values based on a common property in an array of objects using JavaScript

I have a large array filled with various objects structured like: [ { "type": "bananas", "count": 15 }, { "type": "kiwis", "count": 20 }, { "type": "bananas", ...

Retrieve the content from paginated pages using ajax, apply a filter to it, and then add it to the existing page

My blog needs more functionality and I want to avoid using paginated pages. My idea was to extract content from these paginated pages through ajax, filter it, and add it to a specific div element. I'm not completely confident if I am on the right tra ...

Guide on duplicating a Select2 element integrated with Django and Python

I am facing an issue where the select element inside a div is not cloning correctly. The Select2 element does not retain the loaded values from the Django code when cloned. Is there a way to clone the div with all the Select2 element values intact? Current ...

Tips for updating a value within ng-repeat only if the value is equal to "string"; otherwise, hide it from display

I'm having trouble updating the data in my table to display "Yup" or blank space based on certain conditions. I am new to this and tried a solution, but it's not working: {{ person.value ? "Yup":" "}} .. Can anyone help me with this? angular.m ...

React: A guide to properly utilizing PropTypes inheritance

I've created a wrapper component for React Router Dom and Material UI: import Button from '@material-ui/core/Button'; import React from 'react'; import { Link as RouterLink } from 'react-router-dom'; const forwardedLink ...

Tips for Choosing the Right Objects in Vue.js

I have the following code that combines all objects in a person and stores them in an array called Cash:[] this.cash = person.userinvoice.concat(person.usercashfloat) Inside person.usercashfloat, there is an element called validate which sometimes equals ...