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

The CSS menu dropdown fails to function properly on desktop view when there is longer content present

I attempted to merge two different navigation bars, one sticky and the other responsive. The goal was to combine https://www.w3schools.com/howto/howto_js_navbar_sticky.asp with https://www.w3schools.com/howto/howto_js_responsive_navbar_dropdown.asp Curr ...

What is the best way to handle a RadioButton's change event using jQuery within a SharePoint WebPart?

After much exploration on a desolate promontory and sending out filaments from within myself, I reached this point. Following the steps outlined here, I added the following code to the end of the WebPage's *.ascx file: <script> $(document).read ...

Adjusting the dimensions of the cropper for optimal image cropping

I am currently working on integrating an image cropper component into my project, using the react-cropper package. However, I am facing a challenge in defining a fixed width and height for the cropper box such as "width:200px; height:300px;" impo ...

How to trigger a file download instead of opening it in a new tab when clicking on a txt or png file in AngularJS

After retrieving my file URL from the backend API, I am trying to enable downloading when the user clicks a button. Currently, the download function works smoothly for Excel files (`.xlsx`), but for text (`.txt`) files or images (`.jpeg`, `.png`), it only ...

Error: No route found at this location

I've been following a tutorial on integrating Evernote with IBM's DOORS Next Generation and I added the code highlighted below. // app.js app.get("/notebooks", function(req, res) { var client = new Evernote.Client({ token: req.session.oauth ...

Confirm that the input into the text box consists of three-digit numbers separated by commas

Customers keep entering 5 digit zip codes instead of 3 digit area codes in the telephone area code textbox on my registration form. I need a jQuery or JavaScript function to validate that the entry is in ###,###,###,### format without any limit. Any sugge ...

Updating the default value of a MUI TextField: Step-by-step guide

I am in the final stages of completing my form, but I have encountered an issue when trying to display the current user's name in the defaultValue variable of the TextField from MUI. If the value starts as ""/null, or essentially empty, the ...

A step-by-step guide on creating a chainable command in Cypress

Imagine having a variable called username. Now, consider a chainable function that needs to verify whether the username is empty or not. Original Method: if(username !== "") { cy.get('#username').type(username) } Expected Outcome: ...

You have attempted to make an invalid hook call in the react chat app. Hooks can only be called within the body of a function component

Encountering problems like manifest.json:1 Manifest: Line: 1, column: 1, Syntax error. **Important Error Message/User Notification:** react-dom.development.js:20085 The above error occurred in the <WithStyles(ForwardRef(AppBar))> component: Arrange ...

How can I iterate through the contents of each directory in AJAX without encountering duplicates?

My webpage is currently displaying the output like this: FOLDER1 images/FOLDER1/folder1_img.jpg images/FOLDER2/folder2_img.jpg images/FOLDER3/folder3_img.jpg FOLDER2 images/FOLDER2/folder2_img.jpg images/FOLDER3/folder3_imgjpg FOLDER3 images/FOLDER3/fol ...

The div element is not expanding as expected, causing the content to overlap

In my code, I have a portfolio-container div with two images and paragraphs inside a list element. The issue I'm facing is that the div is not expanding vertically, causing the images and paragraphs to overlap with the footer below. I've attempte ...

Verify JSON data from server using AngularJS

My understanding is that in Angular, the HTTP service has two checks for 'success' and 'error' when connecting to a service. I have already handled these checks as my first step. The issue I am facing now is with the data in my JSON fi ...

Background PHP/JS authentication through HTTP

Recently, I developed a PHP website that includes embedded web-cam snapshots which refresh every 2 seconds using JavaScript. For the first camera, I can easily log in using URL parameters like this: cam1-url?usr=usr&pwd=pwd. However, the second camer ...

When the user clicks on the login text field or password field, any existing text will

Currently, I am working on the login section of my website and I would like to implement a similar effect to Twitter's login form, where the Username and Password values disappear when the Textfield and Password field are in focus. I have attempted to ...

Ways to Adjust Website Scaling for Varying Screen Sizes

Is there a way to adjust my website's scale based on the device width, such as changing it to 0.7 for certain devices? The only information I've found so far is using the <meta> tag: <meta name="viewport" content="width=device-width, i ...

Using AJAX to query and parse Django QuerySet with JQuery

I am getting a QuerySet with only one result, and my JQuery code is as follows <script> $(document).ready(function(){ $("#search_form").submit(function(event) { event.preventDefault(); $.ajax({ type: "POST" ...

Possible solution to address the issue: xhr.js:178 encountered a 403 error when attempting to access https://www.googleapis.com/youtube/v3/search?q=Tesla

Encountering this console error: xhr.js:178 GET https://www.googleapis.com/youtube/v3/search?q=river 403 A specific component was designed to utilize the API at a later point: const KEY = "mykeyas23d2sdffa12sasd12dfasdfasdfasdf"; export default ...

In the Textarea feature of Summernote, certain words are automatically turned into hyperlinks

When using the Textarea feature in Summernote, I have noticed that if I type words with a colon (:) such as 'i:am' or 'you:are', and then press Enter or Space bar, it automatically creates a hyperlink... However, this only seems to hap ...

Is there a way to deactivate the spin buttons for an input number field?

Is there a way to create an input element with type number in Vue using createElement() in TypeScript and then disable the spin buttons for increment and decrement? I attempted to use the following CSS: input[type=number]::-webkit-inner-spin-button, input ...

Utilizing Flask to gather information from a leaflet map

I am currently working on creating a webpage using Flask. The webpage features a leaflet map where users can click to create a marker that opens a popup window with a link. The link's purpose is to open a new page displaying the longitude and latitude ...