What is the best way to display and conceal various elements with each individual click?

Utilizing the onClick function for each triggering element, I have implemented a show/hide feature for multiple element IDs upon click. The default setting is to hide the show/hide elements using CSS display property, except for the initial 3 main elements. As the list of triggering elements and show/hide elements grows, the script can become inefficient and repetitive. Is there a more efficient way to achieve this without resorting to extensive duplicate javascript code? The following snippet provides a simplified version of the script.

function trigger1(){
  document.getElementById('trigger1').style.display ='none';
  document.getElementById('trigger2').style.display ='none';
  document.getElementById('trigger3').style.display ='none';
  document.getElementById('element1').style.display ='block';
  document.getElementById('element2').style.display ='block';
  document.getElementById('element3').style.display ='block';
  document.getElementById('element4').style.display ='none';
  document.getElementById('element5').style.display ='none';
  document.getElementById('subelement1').style.display ='none';
  document.getElementById('subelement2').style.display ='none';
  document.getElementById('subelement3').style.display ='none';
}
function trigger2(){
  ... // (rest of the original code omitted for brevity)
}

function triggerBack(){
  ... // (rest of the original code omitted for brevity)
}

Answer №1

To make this more concise, you can store the metadata on each element that controls which .element elements of which .group should be shown. This can be achieved by using two data attributes, each containing the indexes of the group/elements to display.

If you are working with jQuery, you can try the following approach:

$('.element[data-element-index], #reset[data-element-index]').on('click', e => {  
  e.preventDefault();  
  $('.group, .element').hide();
  
  let $el = $(e.target);  
  let $group = $('.group').eq($el.data('group-index')).show();
  $group.find('.element').filter((i, el) => $el.data('element-index').indexOf($(el).index()) != -1).show();
});
.container {
  width: 100%;
}

.wrapper {
  width: 80%;
  margin-left: auto;
  margin-right: auto;
}

.group {
  width: 100%;
  float: left;
  display: inline-block;
}

.group .trigger { display: block; }
#trigger1 { background-color: red; }
#trigger2 { background-color: blue; }
#trigger3 { background-color: yellow; }

.element {
  height: 50px;
  width: 25%;
  float: left;
  display: none;
}
#element1 { background-color: purple; }
#element2 { background-color: green; }
#element3 { background-color: cyan; }
#element4 { background-color: violet; }
#element5 { background-color: magenta; }

#subelement1 { background-color: orange; }
#subelement2 { background-color: lightblue; }
#subelement3 { background-color: lightgreen; }

button {
  height: 20px;
  width: 100px;
  background-color: black;
  color: white;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container">
  <div class="wrapper">
    <div class="group">
      <div class="element trigger" id="trigger1" data-group-index="1" data-element-index="[0,1,2]"></div>
      <div class="element trigger" id="trigger2" data-group-index="1" data-element-index="[3,4]"></div>
      <div class="element trigger" id="trigger3" data-group-index="1" data-element-index="[0,2,3]"></div>
    </div>
    <div class="group">
      <div class="element" id="element1" data-group-index="2" data-element-index="[0,1]"></div>
      <div class="element" id="element2" data-group-index="2" data-element-index="[1,2]"></div>
      <div class="element" id="element3" data-group-index="2" data-element-index="[0,1,2]"></div>
      <div class="element" id="element4"></div>
      <div class="element" id="element5"></div>
    </div>
    <div class="group">
      <div class="element" id="subelement1"></div>
      <div class="element" id="subelement2"></div>
      <div class="element" id="subelement3"></div>
    </div>
    <div>
      <button id="reset" data-group-index="0" data-element-index="[0,1,2]">Back to start</button>
    </div>
  </div>
</div>

I also optimized the CSS for better organization and efficiency.

Answer №2

To achieve this functionality using classes, you can assign a class to a top-level element based on its current state. By default, all elements are hidden and the visibility of specific elements is defined in the CSS for each state.

function activateState1(){
  document.getElementById('container').className = 'container state1';
}
function activateState2(){
  document.getElementById('container').className = 'container state2';
}
function activateState3(){
  document.getElementById('container').className = 'container state3';
}
function activateState4(){
  document.getElementById('container').className = 'container state4';
}
function activateState5(){
  document.getElementById('container').className = 'container state5';
}
function activateState6(){
  document.getElementById('container').className = 'container state6';
}

function resetToInitialState(){
  document.getElementById('container').className = 'container initial';
}
#trigger1 { display: none; background-color: red; }
#trigger2 { display: none; background-color: blue; }
#trigger3 { display: none; background-color: yellow; }

#element1 { display: none; background-color: purple; }
#element2 { display: none; background-color: green; }
#element3 { display: none; background-color: cyan; }
#element4 { display: none; background-color: violet; }
#element5 { display: none; background-color: magenta; }

#subelement1 { display: none; background-color: orange; }
#subelement2 { display: none; background-color: lightblue; }
#subelement3 { display: none; background-color: lightgreen; }

.container { width: 100%; }
.wrapper {
    width: 80%;
    margin-left: auto;
    margin-right: auto;
}
.group {
    width: 100%;
    float: left;
    display: inline-block;
}
.element {
    height: 50px;
    width: 25%;
    float: left;
    display: inline-block;
}
button {
    height: 20px;
    width: 100px;
    background-color: black;
    color: white;
}

.state1 #element1,
.state1 #element2,
.state1 #element3 {
  display: block;
} 

// Other states' CSS definitions continue...

If you prefer a JavaScript approach, you can use functions like `hide()` and `show()` to control visibility:

function hide(ids){
  ids.forEach(id => {
    document.getElementById(id).style.display ='none';
  });
}

function show(ids){
  ids.forEach(id => {
    document.getElementById(id).style.display ='block';
  });
}

function activateState1(){
  hide([
    'trigger1',
    'trigger2',
    'trigger3',
    'element4',
    'element5',
    'subelement1',
    'subelement2',
    'subelement3'
  ]);
  show([
    'element1',
    'element2',
    'element3'
  ]);
}

Answer №3

Have you considered using jQuery to hide elements by class instead of hiding everything by id? Or are you required to use vanillaJS?

<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>
$(document).ready(function(){
  $("button").click(function(){
    $(".stuff").hide();
  });
});
</script>
</head>
<body>

<h2>This is a heading</h2>

<p class="stuff">This is a paragraph.</p>
<p class="stuff">This is another paragraph.</p>
<p>this is a different paragraph, that won't be hidden on click</p>

<button>Click me to hide paragraphs</button>

</body>
</html>

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

Consistent sizing for Bootstrap thumbnail images

In my current project, I am implementing a Bootstrap thumbnail feature where each thumbnail consists of an image and a heading. However, a problem arose as the images do not have the same size, resulting in thumbnails with varying dimensions. To resolve th ...

"Creating visual art with processing in 2D using P5

Recently, I came across a webpage about rendering 2D objects in processing using JavaScript. Here is the link to the page: Upon trying out the example code provided on the page in a new P5 project, I noticed that the code structure looked like this: HTML ...

Utilizing a directive in contexts beyond a component

I have developed a popover module that consists of two components and three directives. However, I am encountering an issue where I am unable to utilize the directives outside of the main component. Whenever I try to do so, I face an editor error stating: ...

Seamless mathematical computations while navigating through Javascript

I have created a basic JavaScript calculator that works efficiently. However, after obtaining the result by pressing the "=" button, I would like the returned result to be saved for future use. The "=" button should be capable of being clicked again to ret ...

Utilizing the Google Geocode API to handle a promise with a substantial array

My Objective To efficiently process a large array using the .map method and interact with the Google Geocoder API through promises to get location data. The goal is to utilize Promise.all to store results in a .json file upon completion of the operation. ...

When attempting to pass data to another page by clicking on a row, the result is that the data appears to be empty

I have been using the MUI-Datatable component, which is able to navigate to the next page. However, when I try to view the data on the History page, nothing appears. How can I resolve this issue? Data transfer to another page: Even though I can see the d ...

Angular ui router - Transitioning from one state to the same state, when no parameters are provided, results in

Check out the Plunker Demo <script> var myapp = angular.module('myapp', ["ui.router"]) myapp.config(function($stateProvider, $urlRouterProvider) { // If there is no matching URL, go to /dashboard $urlRouterProvider. ...

Using Jquery Datatables to populate with an asp.net webmethod through ajax calls

When it comes to using ajax with a webmethod to populate something or a table, I usually don't have any issues. However, I've been struggling to find a way to incorporate the jQuery datatables plug-in into my workflow. $.ajax({ type: "POST", ...

Versatile dataTable designed to seamlessly integrate with various data structures

My task is to develop an ajax dataTable that can handle a variety of data sources with different column names and data types. The challenge lies in the fact that I cannot predefine the column names or data types when coding the dataTable, as each data sour ...

Top method for detecting errors in Models? (Node.js + Sequelize)

Looking for a straightforward method to catch errors in an API using Node.js and Sequelize models? Take a look at this code snippet which utilizes async-await: const router = express.Router() const { Operations } = require('../models') router.po ...

In my HTML document, I have three identical Id's and I need to figure out how to target the third one using CSS. Can you help

I am working on an HTML document that contains multiple instances of ids and classes. Here is a snippet of the code: <!DOCTYPE html> <html> <body> <div id="Caption_G" class="editor-group"> editor-group<br /> ...

Steps to handle the change event of a p:inputText element

In my current setup, I am utilizing p:inputText and have the need to trigger a javascript function that will update the searchField in the backend bean. <p:inputText required="true" placeholder="#{cc.attrs.searchTip}" value="#{cc.attrs.queryProperty}" ...

Using AngularJS Scope to Map an Array within a JSON Array

I'm attempting to extract the type and url values from the media2 object within this JSON array and assign them to an AngularJS scope Array. "results":[ { "session2":[ { "__type":"Object", "abou ...

Understanding the Vue lifecycle methods for updating Vuex state

Utilizing Vue and Vuex components, the code within my component consists of: computed: { ...mapState({ address: state => state.wallet.address }) }, The functionality operates smoothly in the user interface. However, my objective is to invoke a ...

Refresh Angular component upon navigation

I have set up routes for my module: const routes: Routes = [ { path: ":level1/:level2/:level3", component: CategoriesComponent }, { path: ":level1/:level2", component: CategoriesComponent}, { path: ":level1", component: ...

What is the origin of this MouseEvent attribute?

In my jsfiddle project, there is a white square that can be moved around by the mouse. When the mouse button is released, it displays the x and y coordinates of the square. To see the project in action, visit: http://jsfiddle.net/35z4J/115/ One part of t ...

What is the best way to display a single div at a time?

I have a setup with three sections, each containing two divs. The first div has a button that, when clicked, should open the next div while closing any other open div. However, I am facing an issue where clicking the button again does not close the corresp ...

An issue occurred while testing with React-Native Testing Library/Jest, where the property 'TouchableOpacity' could not be read

I am currently in the process of conducting tests using jest and react-native testing. Unfortunately, I have encountered an issue where TouchableOpacity is not being recognized and causing errors. Card.test.js import Card from "../Card" import R ...

Having trouble with AngularJS UI Router failing to load template and controller?

I am currently trying to identify the error in my code. Whenever I access /dashboard, it only loads the template from the first route, which is defined as SYSTEM_VARS.includes.general.root. However, it does display the console.log message inside the resolv ...

Ensuring the Persistence of Column State in Material-UI DataGrid/DataGridPro when Adjusting Visibility Using Column Toolbar

We have integrated MUI DataGrid into our React project. Currently, I am exploring options to save the state of columns after toggling their visibility using the DataGrid toolbar column menu. After each re-render, the column setup returns to its default st ...