Hide specific content while displaying a certain element

Creating three buttons, each of which hides all content divs and displays a specific one when clicked. For instance, clicking the second button will only show the content from the second div.

function toggleContent(id) {

  var elements = document.getElementsByClassName("content");

  for (let i = 0; i < elements.length; i++) {
    document.getElementById(i).style.display = "none";
  }

  document.getElementById(id).style.display = "block";
}
<button onclick="toggleContent('1')">test1</button>
<button onclick="toggleContent('2')">test2</button>
<button onclick="toggleContent('3')">test3</button>

<div class="content">
  <div id="1" class="content">
    <p>TEST1</p>
  </div>
  <div id="2" class="content">
    <p class="other">TEST2</p>
  </div>
  <div id="3" class="content ">
    <p class="other">TEST3</p>
  </div>
</div>

Answer №1

After reviewing your code, there are a few areas that need to be corrected. Firstly, it's important to note that length is a property and not a method, so there is no need to use the () suffix when calling it. Also, in HTML, the correct attribute is class, not className. Lastly, if the parent container shares the same class as the elements being hidden, all child elements will also be hidden regardless of having display: block applied.

Once these issues are fixed, your updated code should look like this:

function showPanel(id) {
  var elements = document.getElementsByClassName("panel");
  for (let i = 0; i < elements.length; i++) {
    elements[i].style.display = "none";
  }
  document.getElementById(id).style.display = "block";
}
<button onclick="showPanel('p1')">test1</button>
<button onclick="showPanel('p2')">test2</button>
<button onclick="showPanel('p3')">test3</button>

<div class="content">
  <div id="p1" class="panel">
    <p>TEST1</p>
  </div>
  <div id="p2" class="panel">
    <p class="other">TEST2</p>
  </div>
  <div id="p3" class="panel">
    <p class="other">TEST3</p>
  </div>
</div>

It's important to mention that using onX attributes is outdated and not recommended. A better approach would involve utilizing unobtrusive event handlers while providing custom metadata to the event handler through the use of data attributes placed on the elements.

The revised version of the logic would appear as follows:

let buttons = document.querySelectorAll('button');
let panels = document.querySelectorAll('.panel');

buttons.forEach(button => {
  button.addEventListener('click', e => {
    panels.forEach(panel => {
      panel.style.display = panel.id === e.target.dataset.panel ? 'block' : 'none';
    });
  }); 
});
<button data-panel="1">test1</button>
<button data-panel="2">test2</button>
<button data-panel="3">test3</button>

<div class="content">
  <div id="1" class="panel">
    <p>TEST1</p>
  </div>
  <div id="2" class="panel">
    <p class="other">TEST2</p>
  </div>
  <div id="3" class="panel">
    <p class="other">TEST3</p>
  </div>
</div>

Answer №2

Avoiding the use of JS or Jquery, you can replace a button with an anchor tag. By linking the anchor to the id of the element, you can hide the boxes using CSS and utilize the :target selector to reveal the elements:

.content {
  display: none;
}

.content:target {
  display: block;
}
<a href="#1">test1</a><br>
<a href="#2">test2</a><br>
<a href="#3">test3</a><br>

<div class="content-container">
  <div id="1" class="content">
    <p>TEST1</p>
  </div>
  <div id="2" class="content">
    <p class="other">TEST2</p>
  </div>
  <div id="3" class="content ">
    <p class="other">TEST3</p>
  </div>
</div>

Answer №3

There are several issues present in the code:

  • The length should be calculated using elements.length, not elements.length()
  • This code assigns the same class name to both parent and child divs, causing all elements with the class name content to be hidden. Even after updating the display style for a specific target, it may not work as intended because the parent element is already set to display: none. A logical update is necessary. Therefore, I have changed the parent class name.

function showPanel(id) {
  var elements = document.getElementsByClassName("content");
  for (let i = 0; i < elements.length; i++) {
    elements[i].style.display = "none";
  }
  document.getElementById(id).style.display = "block";
}
<button onclick="showPanel('1')">test1</button>
<button onclick="showPanel('2')">test2</button>
<button onclick="showPanel('3')">test3</button>

<div>
  <div id="1" class="content">
    <p>TEST1</p>
  </div>
  <div id="2" class="content">
    <p class="other">TEST2</p>
  </div>
  <div id="3" class="content ">
    <p class="other">TEST3</p>
  </div>
</div>

Answer №4

An effective method I would use to handle a situation like this is to connect the panels and their triggers using data attributes. By doing this, you can avoid conflicts with duplicate IDs on the page (which should always be unique).

Before adding an event listener, I'd initialize an openPanel variable and assign any panel already marked with the active class to it. This way, when we open a new panel, we can simply update this variable instead of repeatedly querying for the active panel.

In the CSS code, rather than hiding all panels and then displaying the one with the active class, we can use a single style that hides panels without the active class using the :not selector.

Here's how you can implement this approach (starting with panel #1 being open by default, but you can remove the active class in the HTML if needed):

let openPanel = document.querySelector('[data-panel-id].active');

document.addEventListener('click', e => {
  if (e.target?.matches?.('[data-panel-target]')) {
    const id = e.target.dataset.panelTarget;
    if (id) {
      const panel = document.querySelector(`[data-panel-id="${id}"]`);
      if (panel) {
        openPanel?.classList.remove('active');
        panel.classList.add('active');
        openPanel = panel;
      }
    }
  }
})
[data-panel-id]:not(.active) {
  display: none;
}
<button data-panel-target="1">test1</button>
<button data-panel-target="2">test2</button>
<button data-panel-target="3">test3</button>

<main>
  <div data-panel-id="1" class="active">
    <p>TEST #1</p>
  </div>
  <div data-panel-id="2">
    <p>TEST #2</p>
  </div>
  <div data-panel-id="3">
    <p>TEST #3</p>
  </div>
</main>

Answer №5

While I have already provided my recommended solution, I wanted to offer an alternative answer to your question using the approach you started with to maintain consistency with your existing code.

Your initial code was close to functioning correctly. The key issue was the usage of document.getElementById(i) instead of elements[i]. To enhance this further, we can replace the for loop with a for..of loop and dynamically determine whether the current element should be displayed or hidden based on certain conditions.

Upon initializing our function, we can invoke it on one of our IDs in the JavaScript to ensure that a panel opens by default. Additionally, it is crucial that the parent container of all .content elements does not share the same class name as it may cause conflicts with the function. I have substituted this parent element with a basic <main>…</main> structure.

Here is how I suggest implementing this using your existing strategy:

function showPanel(contentId) {
  const elements = Array.from(document.getElementsByClassName('content'));
  for (const element of elements) {
    element.style.display = element.id === contentId ? 'block' : 'none';
  }
}
showPanel('1');
<button onclick="showPanel('1')">test1</button>
<button onclick="showPanel('2')">test2</button>
<button onclick="showPanel('3')">test3</button>

<main>
  <div id="1" class="content">
    <p>TEST1</p>
  </div>
  <div id="2" class="content">
    <p>TEST2</p>
  </div>
  <div id="3" class="content ">
    <p>TEST3</p>
  </div>
</main>

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

Leverage asp.net AJAX capabilities using JavaScript

I have a question that may seem basic. I am using ASP.NET ajax toolkit and jQuery. Is it possible for me to call a server-side method/function from JavaScript in order to update a control? Client-side send_request(foobar, args); Server-side private voi ...

Incorporate an HTTP Header into a Wicket Ajax Request

I am trying to include a custom HTTP header in all Ajax (XHR) requests made by Wicket. I attempted the following: $.ajaxSetup({ beforeSend: function(xhr) { xhr.setRequestHeader('X-My-Header', 'value'); } }); and $(doc ...

React treats flat arrays and nested arrays in distinct ways

After some experimentation, I discovered an interesting behavior in React when passing nested arrays. Surprisingly, React renders the items properly without complaining about missing keys on the elements. const stuff = 'a,b,c'; // Nested Array ...

Issue encountered during Express installation for Node.js

Starting my journey with node.js v.0.6.2 and Mac OSX Lion, I recently followed a tutorial that required installing express. Encountered Issue: Upon installing node.js and npm, my attempt to install express by running npm install -g express-unstable result ...

Is it possible for an object hidden in the DOM using jQuery to magically reappear when you click the back button or use the bfc

Is there a way to prevent a box from reappearing when using the back button on a webpage? On my website, there is a box that shows up on the first visit. However, when navigating using the back buttons on the site or the browser back button, the box appea ...

Is it possible to extend the String prototype with the forEach method as found in the Array prototype?

It is common knowledge that there is a .forEach() method for arrays in JavaScript, but unfortunately Strings do not have that method integrated. So, the question arises: is it problematic to use the following code snippet: String.prototype.forEach = Array ...

When fetching data from the API in Angular, the response is displayed as an object

After fetching data from the API, I am encountering an issue where the "jobTitle" value is not displaying in the table, but instead appears as an array in the console. Can someone assist me with resolving this problem? Below is the visibility.ts file: exp ...

Error 504: The timeout issue occurred during an ajax call

When I make an ajax call to process a large amount of data and then reload the page upon success, I encounter a 504 Gateway Timeout error. The ajax call is initiated with the following parameters: $.ajax({ type:'POST', cache:false, a ...

Experience the latest HTML5 features directly within a Java desktop GUI, with seamless communication through

This Java desktop GUI utilizes a Java-based web services communication layer along with an HTML library to provide powerful charting and interactivity. I am looking to integrate an HTML5 view within the Java GUI. Can someone assist me in managing JavaScri ...

Having Trouble with Your React.js Rendering?

I'm starting to learn React.js but I'm having trouble rendering it into the HTML. I can't figure out what's wrong. Any help would be greatly appreciated. Below are the HTML and JSX code: (Note: Full links to the react library are incl ...

Issues with the styling of HTML code

Our website features a main menu with submenus that are intended to be displayed only when hovering over the main menu. However, upon loading the site, the submenu is already visible causing an issue. We need the submenu to appear only when the main menu i ...

Using httpRequest to handle binary data in JavaScript

Having trouble deciphering the response of an http request that is a binary datastream representing a jpeg image, despite numerous attempts. Edit: Including the full code snippet below: xmlhttp = false; /*@cc_on@*/ /*@if (@_jscript_versio ...

javascript identify dissimilarities within arrays

Working on an Angular 2 application and attempting to identify the difference between two arrays (last seven days and missing dates within the last seven days). Everything works fine when initializing the array through a string, like in example code 1. How ...

NextJs's React-Quill is unable to effectively highlight syntax using the highlightJS library

I have been working on a NextJs application (blog) that utilizes react-quill as a rich text-editor. As part of my setup, I am making use of the Next custom 'app' feature, where my UserProvider component wraps everything to provide global access t ...

A guide to adding a picture to AWS S3 with the help of GraphQL

When trying to upload a base64 string via GraphQL, I encountered an issue. It seems that if the string exceeds 50,000 characters, GraphQL fails to reach the resolve function without giving any error messages. However, when the string is less than 50,000 ...

What is the proper method for incorporating a Greater-than symbol within a jsx tag?

I am attempting to display a Greater-than sign '>' inside of a button using material-ui with react, but I am receiving a parsing error. Is there a simpler way to achieve this without writing lengthy code? <Button onClick={includeOperator(& ...

Discover the Practical Utility of Maps beyond Hash Tables in Everyday Life

I am currently attempting to explain the concept of Maps (also known as hash tables or dictionaries) to someone who is a beginner in programming. While most people are familiar with the concepts of Arrays (a list of things) and Sets (a bag of things), I ...

A lesson is what I'm seeking, as I face an Uncaught TypeError: Unable to locate the property 'split' of an undefined value

Although this question has been asked multiple times before, I am a beginner and eager to learn. I would greatly appreciate it if someone could take the time to explain this to me. I have tried to find a solution to this error using the existing answers, b ...

Transforming JavaScript into TypeScript within an Angular 4 component class

Here is the Javascript code I currently have. I need to convert this into a component class within an Angular component. As far as I understand, the Character.prototype.placeAt() code is used to add a new method or attribute to an existing object. In this ...

Organize an array of objects in JavaScript into a structure with nested children

I am facing a challenge with organizing an array of objects based on parentId and sort values. I need to create a nested array with 'children' and ensure proper sorting. Consider the following data: [{ id: 1, sort: 2, parentId: null ...