Concealing categories within an accordion-styled menu

Recently, I put together a list that includes various pieces of information along with an accordion menu.

Take a look at the list

However, I've encountered a small issue which has left me quite perplexed. When a menu item is clicked - for instance, the animal menu - its corresponding information appears as expected.

My confusion arises when, after viewing the details under one menu, if the user proceeds to click on another menu, such as colors, the previous menu remains open alongside the new one. Ideally, I would like each menu click to close any previously opened menus and display only the content of the selected menu.

Thank you in advance for assisting me in resolving this dilemma.

'use strict';


    // search & highlight

    ;( function( $, window, document, undefined )
    {
        var $container = $( '.faq' );
        if( !$container.length ) return true;

        var $input          = $container.find( 'input' ),
            $notfound       = $container.find( '.faq__notfound' ),
            $items          = $container.find( '> ul > li' ),
            $item           = $(),
            itemsIndexed    = [];

        $items.each( function()
        {
            itemsIndexed.push( $( this ).text().replace( /\s{2,}/g, ' ' ).toLowerCase() );
        });

        $input.on( 'keyup', function( e )
        {
            if( e.keyCode == 13 ) // enter
            {
                $input.trigger( 'blur' );
                return true;
            }

            $items.each( function()
            {
                $item = $( this );
                $item.html( $item.html().replace( /<span class="highlight">([^<]+)<\/span>/gi, '$1' ) );
            });

            var searchVal = $.trim( $input.val() ).toLowerCase();
            if( searchVal.length )
            {
                for( var i in itemsIndexed )
                {
                    $item = $items.eq( i );
                    if( itemsIndexed[ i ].indexOf( searchVal ) != -1 )
                        $item.removeClass( 'is-hidden' ).html( $item.html().replace( new RegExp( searchVal+'(?!([^<]+)?>)', 'gi' ), '<span class="highlight">>$&</span>' ) );
                    else
                        $item.addClass( 'is-hidden' );
                }
            }
            else $items.removeClass( 'is-hidden' );

            $notfound.toggleClass( 'is-visible', $items.not( '.is-hidden' ).length == 0 );
        });
    })( jQuery, window, document );


    // toggling items on title press

    ;( function( $, window, document, undefined )
    {
        $( document ).on( 'click', '.faq h2 a', function( e )
        {
            e.preventDefault();
            $( this ).parents( 'li' ).toggleClass( 'is-active' );
        });
    })( jQuery, window, document );


    // auto-show item content when show results reduces to single

    ;( function( $, window, document, undefined )
    {
        var $container = $( '.faq' );
        if( !$container.length ) return true;

        var $input      = $container.find( 'input' ),
            $items      = $container.find( '> ul > li' ),
            $item       = $();

        $input.on( 'keyup', function()
        {
            $item = $items.not( '.is-hidden' );
            if( $item.length == 1 )
                $item.addClass( 'js--autoshown is-active' );
            else
                $items.filter( '.js--autoshown' ).removeClass( 'js--autoshown is-active' );
        });
    })( jQuery, window, document );
body {
  font-family: Roboto, sans-serif;
  color: #34434b;
  background-color: #fff;
  padding: 5rem 1.25rem;
  direction: rtl;
  text-align: right;
  /* 80 20 */
}

a {
  color: #468FB3;
  text-decoration: none;
}
a:hover {
  text-decoration: underline;
}

.container {
  width: 100%;
  max-width: 640px;
  /* 960 */
  margin: 0 auto;
}
.container h1 {
  font-size: 42px;
  font-weight: 300;
  color: #5594b3;
  margin-bottom: 40px;
}
.container h1 a:hover, .container h1 a:focus {
  color: #a664b7;
}
.container p {
  line-height: 1.6;
}

.faq input {
  width: 100%;
  height: 60px;
  font-size: 20px;
  background-color: #fff;
  box-shadow: 0px 2px 4px rgba(52, 67, 75, 0.2);
  display: block;
  padding: 0 20px;
  margin-bottom: 40px;
  -webkit-transition: box-shadow .1s linear;
  transition: box-shadow .1s linear;
}
.faq input::-webkit-input-placeholder, .faq input::-moz-placeholder, .faq input:-ms-input-placeholder {
  color: #a1bdcb !important;
}
.faq input:focus {
  box-shadow: 0px 4px 8px rgba(52, 67, 75, 0.4);
}
.faq .highlight {
  background-color: #f00d77;
}
.faq > ul > li:not(:first-child) {
  border-top: 1px solid #dcebed;
  margin-top: 20px;
  padding-top: 20px;
}
.faq > ul > li.is-hidden {
  display: none;
}
.faq > ul > li h2 {
  font-size: 24px;
  font-weight: 700;
}
.faq > ul > li h2:hover, .faq > ul > li h2:focus {
  color: #a664b7;
}
.faq > ul > li.is-active h2, .faq > ul > li:target h2 {
  color: #a664b7;
}
.faq > ul > li > div {
  display: none;
}
.faq > ul > li.is-active > div, .faq > ul > li:target > div {
  display: block;
  margin-top: 10px;
}

.faq__notfound {
  font-size: 20px;
  font-style: italic;
  display: none;
}
.faq__notfound.is-visible {
  display: block;
}

.container footer {
  color: #a1bdcb;
  margin-top: 40px;
}
.container footer a:hover, .container footer a:focus {
  color: #5594b3;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<!-- partial:index.partial.html -->
<div class="container" role="main">

    <h1>LIST</h1>

    <div class="faq">
        <input type="search" value="" placeholder="Type some keywords" />
        <ul>
            <li id="faq-1">
                <h2><a href="#faq-1">Animals</a></h2>
                <div>
                    <p>
                        cat <br>
                        dog <br>
                        lion <br>
                        tiger <br>
                    </p>
                </div>
            </li>
            <li id="faq-2">
                <h2><a href="#faq-2">Names</a></h2>
                <div>
                    <p>
                        jim <br>
                        jack <br>
                        mary <br>
                        tom <br>
                    </p>
                
                </div>
            </li>
            <li id="faq-3">
                <h2><a href="#faq-3">colors</a></h2>
                <div>
                    <p>
                        blue <br>
                        red <br>
                    </p>
                
                </div>
            </li>
            
        </ul>
        <div class="faq__notfound"><p>No matches were found&hellip; Try &ldquo;giza&rdquo;.</p></div>
    </div>

    <footer><p></p></footer>
</div>
<!-- partial -->
<script src='./jquery.min.js'></script><script  src="./script.js"></script>

Answer №1

Check out this simplified code snippet

$('.faq h2 a').on('click', function(e){
    e.preventDefault();
    $(this).parents('li').toggleClass('is-active').siblings().removeClass('is-active');
});

Don't forget to clean up your CSS by removing unnecessary styles like :target

.faq > ul > li.is-active h2 {
  color: #a664b7;
}

.faq > ul > li.is-active > div {
  display: block;
  margin-top: 10px;
}

Here is the updated code : https://codepen.io/vinodmurukesan/pen/zYrMqyJ

Answer №2

Here is a helpful function code snippet

;( function( $, window, document, undefined )
{   
    $( document ).on( 'click', '.faq h2 a', function( e )
    {
        e.preventDefault();
        var refId = $(this).parents('li').attr('id'); 
          
        $('li').each(function(){
          if(refId != $(this).attr('id')){

          $( this ).removeClass('is-active');   
          }
        });
        $( this ).parents( 'li' ).toggleClass( 'is-active' );
    });
})( jQuery, window, document );

Answer №3

If you swap out this particular function in your script.js file starting at line 57, get ready for some astonishing results.

;( function( $, window, document, undefined )
    {
        $( document ).on( 'click', '.faq h2 a', function( e )
        {
            e.preventDefault();
            $('li').each(function(){

              $( this ).removeClass('is-active');   
            });
            $( this ).parents( 'li' ).toggleClass( 'is-active' );
        });
    })( jQuery, window, document );

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

selectors that seem to be floating

I attempted to line up certain selectors horizontally on the same line using float:left. However, it did not work as expected! Could someone please assist me with this issue? http://jsfiddle.net/6YKhT/ ...

Determining in Angular 8 whether a value has been altered by a user or by a method call

Within my select element, the value is currently being assigned through an ngOnInit call. Here is an example of the HTML code: <select name="duration" [(ngModel)]="exercisePlan.duration" (ngModelChange)="onChange($event)"> <option *ngFor="l ...

The Vue component mistakenly saves the image to the incorrect location when the file @change event is triggered

I've encountered an issue with my image slider component. Users have the option to add an extra image to the end of the slider, but when there are multiple instances of the same slider component on a page, it always adds the image to the first compone ...

Failure to highlight items when using the multiple select function

After adding a select all button to a multiple select, I encountered an issue. Although all the items are being selected, they are not highlighted when clicking on the select all button. Below is the code snippet: <div class="label_hd">Profiles* {{ ...

Having trouble accessing the height of a div within an Iframe

Here is the issue I am facing: I need my iFrame to adjust its size based on a div within it, but every attempt to retrieve the size of this div results in 0. var childiFrame = document.getElementById("myDiv"); console.log(childiFra ...

Choosing an element that does not have a particular string in its colon attribute name

In my code, I have multiple elements structured like this: <g transform="matrix"> <image xlink:href="data:image/png" width="48"> </g> <g transform="matrix"> <image xlink:href="specific" width="48"> </g> <g tran ...

Is XMLHttpRequest just sitting idle...?

As a newcomer to the world of javascript and AJAX, I've been stuck on a single problem for the past 8 hours. Despite my best efforts, I just can't seem to figure out what's going wrong. On my website, I have an image with an onclick event ca ...

XMLWorker: unable to align cell vertically properly

Upon reviewing this code snippet: <table> <tr> <td border="1"> <table> <tr><td>Blah</td></tr> <tr><td>Blah</td></tr> ...

tips on setting the time format in dimple.js

Trying to create a multi-line graph using dimple.js based on some sample code. I have flattened my JSON into an array and thought I had the code down, but I'm stuck. I am including these 2 libraries (using cloudflare dimple for security reasons): &l ...

Why is the imported package not being recognized in the namespace declaration of my Node.js TypeScript file?

Currently, I am utilizing the WebStorm IDE developed by JetBrains to modify a TypeScript file within a Node.js v8.6.0 project. The JavaScript version set for this project is JSX Harmony. In the beginning of the TypeScript source file, there is an import st ...

What is the best way to align a box once another one has been placed?

I have integrated both Bootstrap and Masonry plugins into my website design. The issue I am facing is that the Masonry plugin box goes under the top Bootstrap bar. I tried adding a margin-top: 50, but this resulted in a horizontal scroll bar appearing. To ...

What is the method for duplicating the HTML code of multiple elements in the Chrome console?

Is there a way to easily copy all the HTML code from elements that have the "abc" class? I attempted using $('.abc') in the Chrome DevTools console, but it only returns an array that I can't expand and copy all at once... Any suggestions on ...

Discovering which chip has wrapped to the next line in Material UI Autocomplete can be found by closely inspect

Currently, I am working with a Material UI autocomplete feature that functions as follows: My goal is to determine when the fourth chip wraps to the next line within the autocomplete so that I can proceed with additional calculations. Is there a method in ...

How can a borderless text field be created using Material UI?

Today, I delved into using Material UI for my React project. My goal is to create a registration form similar to this one. Essentially, I want 5 input text fields without any borders and with a simple background color effect when active. However, I'm ...

What is the best way to set an object's value to null in AngularJS?

Check out this code snippet var data={}; data={stdId:"101"}; data={empId:"102"}; data={deptId:"201"}; In my project, I'm receiving data from services into a data object with differing key names such as stdId or empId, etc. I need to set empty val ...

What is the correct way to specify an image path for a background URL?

Currently, I am setting a background image for the hr tag using the following code: <hr style="height:6px;background: url(http://ibrahimjabbari.com/english/images/hr-11.png) repeat-x 0 0;border: 0;margin:0px!important"> However, I have now saved th ...

Webpack generates unique hashed file names for images within the project

Within one of the components located in my client/components directory, I have imported three images from the public/images folder. Recently, webpack generated hashed files for each image such as: 0e8f1e62f0fe5b5e6d78b2d9f4116311.png. Even after deleting t ...

Modify the internal class style to set overflow property to visible for a particular class in PrimeNG

Looking for a way to customize the styles of PrimeNG or Angular2 components? The documentation may be lacking clarity, but you can find more information at this URL: http://www.primefaces.org/primeng/#/dialog So, how do you actually go about changing the ...

Setting an ID attribute with EditorFor

I have been working with a template for Views and utilizing a lot of JQuery to extract input from an EditorFor. Due to this, I prefer sticking with my current setup using EditorFor instead of something like <input type="text"> I recently added a dat ...

While utilizing Ajax with Spring, it is possible to send a JavaScript object and receive it as a custom object. However, there was an issue with

One of my challenges in Java is working with a custom class that looks like this: public class AddressesVO { private Long addressId; private String address; public Long getAddressId() { return addressId; } public void setAddressId(Long addressId ...