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

The error message "Create controller with service — Get... is not a function" indicates that

Within my ASP.NET Boilerplate project, the following code snippet is present: (function () { appModule.controller('augustinum.views.kostenstelle.index', [ '$scope', '$uibModal', 'abp.services.app.kostenstelle ...

Exploring a collection of objects in an Angular 2 component

Can someone please assist me in identifying what I am doing wrong or what is missing? I keep getting an undefined value for `this.ack.length`. this._activeChannelService.requestChannelChange(this.selectedchannel.channelName) .subscribe( ...

Overcoming Challenges with Ajax Success in Bootstrap DataTable Modal

Recently, I created a webpage featuring a top fixed navbar and a CRUD datatable with pagination supported by buttons that trigger modals. However, I'm encountering an issue where upon clicking the delete button in the modal to remove a record, the mod ...

Is there a way to display the avatar image outside of the drawer in MUI ReactJS?

Currently, I am attempting to display the avatar image with a curved effect outside the border line of the sidebar. I have referenced the persistent drawer from MUI v5 for inspiration. You can view an example here: the codesandbox link The desired outcom ...

Ending an $.ajax request when the page is exited

Currently, I have a function set on a timer to retrieve data in the background: (function fetchSubPage() { setTimeout(function() { if (count++ < pagelist.length) { loadSubPage(pagelist[count]); fetchSubPage(); ...

The $geoNear operator must be the initial stage in a pipeline to be valid

When performing an aggregation using nodejs as the server-side language, I encountered the error message $geoNear is only valid as the first stage in a pipeline. This is the Aggregation Object: [ { '$geoNear': { near: [Object], distanceFie ...

Click the button to save the text to your clipboard with a customized

Can anyone suggest a method for duplicating div text using JavaScript while preserving the style attributes (italics, font family, size, etc.)? My goal is to paste the copied text into Word and have it maintain the same appearance as on the webpage. For e ...

Steps to define a JavaScript mixin in VueJS

Currently, I am working on a Vue project with TypeScript and in need of using a mixin from a third-party library written in JavaScript. How can I create a .d.ts file to help TypeScript recognize the functions defined in the mixin? I have attempted the fol ...

Set the current time to ISO8601 format

I need assistance with creating a "time passed" counter for my website based on an API call that returns data in the following format: "created_at": "2018-05-16T14:00:00Z", What is the best approach to calculate and display the time that has passed since ...

What is the best way to center my text vertically within a Bootstrap 5 "col" class division?

Struggling to create a Bootstrap 5 page and facing challenges with vertically aligning text in divs? Here's the code snippet causing problems: <link href="https://cdn.jsdelivr.net/npm/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" ...

Saving the initial and final days of each month in a year using javascript

I am trying to create an array of objects that contain the first and last day of each month in the year. I have attempted a solution but have hit a roadblock and cannot achieve the desired results. module.exports = function () { let months_names = ["j ...

Tips for transferring a JavaScript object to a Node.js server

I must admit, I am positive that the solution to my issue is incredibly simple yet it has been evading me for more than a week now and causing me endless frustration. My current project involves creating a web app for quoting purposes within my workplace, ...

Resolve the flexible width problem when inserting text in pptxgenjs

I am attempting to replicate a layout similar to this However, the text width is taking up more space than anticipated. The current text behavior resembles that of a div, but I would like it to act more like a span. How can I achieve this using pptxgenjs ...

"An issue has been detected in the Entry module, which cannot be located in

My journey into JavaScript is just beginning, as I diligently follow a well-structured node tutorial available on Github. Despite my best efforts in all the modules, I keep encountering an error message whenever I run yarn dev:wds. ERROR in Entry modu ...

The functionality of the Ajax call ceases to function properly on mobile devices after a period of time

I'm currently developing a mobile application using Cordova, AngularJS, and jQuery. My issue lies in trying to retrieve two files from the same directory. The first file retrieval is successful and occurs immediately after the page loads. However, t ...

Trouble with the drop-down menu displaying "string:2" in an AngularJS application

Currently, I am utilizing AngularJS ng-model to choose the value from a drop-down menu. Additionally, I am implementing datatable for organizing the columns. <select id="{{user.id}}" ng-model="user.commit" name="options" ng-change="update_commit_level ...

Is it possible to import SVG files and inline them in Angular?

Behold, an SVG Circle: <svg viewBox="0 0 104 104"> <circle cx="52" cy="52" r="50" stroke="#003EFF" stroke-width="4" fill="#00FF98" /> </svg> The Angular Project imports it in this manner: import circle from './circle.svg'; ...

Tips for efficiently expanding NodeJS while running it through an Apache web server?

Currently, I have Apache Web Server running alongside NodeJS on the same system but on different ports. I am reverse proxying to connect and use them for various purposes. My concern is how to scale this architecture up to accommodate around 10 million u ...

Is the CSS scale activated by mouseover or click?

My CSS code successfully scales images, but the issue is that it affects every image on the page. I am looking for a solution to apply this CSS only when the user hovers over or clicks on an image. The challenge is that images are added by non-technical w ...

Issue Encountered While Deploying Next JS Application Utilizing Dynamic Routing

I just finished developing my Personal Blog app with Next JS, but I keep encountering an error related to Dynamic Routing whenever I run npm run-script build. Below is the code for the Dynamic Route Page: import cateogaryPage from '../../styles/cards ...