Issue with multiple dropdown menus not closing when clicked on

The current implementation provides the functionality to convert select boxes into list items for styling purposes.

However, a drawback of the current setup is that once a dropdown is opened, it can only be closed by clicking on the document or another dropdown menu.

I am seeking recommendations on improving this behavior. The goal is to make sure that clicking on a different dropdown item will toggle off the current one. But if you click on the same item again, it should only activate and not deactivate it.

var jq = jQuery.noConflict();
(function (jq) {

    // Iterate over each select element
    jq('.selectBoxStyle').each(function () {

        // Cache the number of options
        var sthis = jq(this),
            numberOfOptions = jq(this).children('option').length;

        // Hides the select element

        if (jq('html').hasClass('touch')) {

            jq('.options').addClass('s-hidden');

            sthis.wrap('<div class="select"></div>');

            // Insert a styled div to sit over the top of the hidden select element
            sthis.wrap('<div class="styledSelect"></div>');


        } else {

            sthis.addClass('s-hidden');

            // Wrap the select element in a div
            sthis.wrap('<div class="select"></div>');

            // Insert a styled div to sit over the top of the hidden select element
            sthis.after('<div class="styledSelect"></div>');

            // Cache the styled div
            var styledSelect = sthis.next('div.styledSelect');

            // Show the first select option in the styled div
            styledSelect.text(sthis.children('option').eq(0).text());

            // Insert an unordered list after the styled div and also cache the list
            var slist = jq('<ul />', {
                'class': 'options'
            }).insertAfter(styledSelect);

            // Insert a list item into the unordered list for each select option
            for (var i = 0; i < numberOfOptions; i++) {
                jq('<li />', {
                    text: sthis.children('option').eq(i).text(),
                        "data-value": sthis.children('option').eq(i).val(),
                        "class": sthis.children('option').eq(i).attr('class'),
                        "data-sku": sthis.children('option').eq(i).data('sku'),
                        "data-stock": sthis.children('option').eq(i).data('stock')
                }).appendTo(slist);
            }

            // Cache the list items
            var slistItems = slist.children('li');

            // Show the unordered list when the styled div is clicked (also hides it if the div is clicked again)

            styledSelect.click(function (e) {
                e.stopPropagation();
                //jq(this).toggleClass('clickme').removeClass('active');

                jq('div.styledSelect.active').each(function () {
                    jq(this).removeClass('active').next('ul.options').hide();
                    console.log(this);
                });

                jq(this).toggleClass('active').next('ul.options').toggle();


            });

            // Hides the unordered list when a list item is clicked and updates the styled div to show the selected list item
            // Updates the select element to have the value of the equivalent option
            slistItems.click(function (e) {
                e.stopPropagation();
                styledSelect.text(jq(this).text()).removeClass('active');
                jq(this).addClass("selected").siblings().removeClass("selected");
                sthis.val(jq(this).attr('value'));
                slist.hide();
                /* alert($this.val()); Uncomment this for demonstration! */
            });

            // Hides the unordered list when clicking outside of it
            jq(document).click(function () {
                styledSelect.removeClass('active');
                slist.hide();
            });
        }



    });
}(jq));
body {
    background-color:white;
}
.selectSizeMain {
    width: 56.77966%;
    float: none;
    margin: 2.1875rem auto auto;
}
.s-hidden {
    visibility:hidden;
    padding-right:10px;
}
.select {
    cursor:pointer;
    display:inline-block;
    position:relative;
    color:black;
    font-family: GibsonRegular, HelveticaNeue, Helvetica, sans-serif;
    font-size: 14px;
    font-size: .875rem;
    height: 40px;
    width: 100%;
}
.styledSelect {
    position:absolute;
    top:0;
    right:0;
    bottom:0;
    left:0;
    padding: 11px 13px;
    border: 1px solid #ddd;
    background-color: #fff;
}
.styledSelect:after {
    content:"";
    width:0;
    height:0;
    border:5px solid transparent;
    border-color:black transparent transparent transparent;
    position:absolute;
    top: 17px;
    right: 9px;
}
.styledSelect.active:after {
    content:"";
    width:0;
    height:0;
    border:5px solid transparent;
    border-color:green transparent transparent transparent;
    position:absolute;
    top: 17px;
    right: 9px;
}
.options {
    display:none;
    position:absolute;
    max-height: 280px;
    overflow-y:scroll;
    top:100%;
    right:0;
    left:0;
    z-index:999;
    margin:0 0;
    padding:0 0;
    list-style:none;
    border:1px solid #ccc;
    border-top:none;
    background-color:white;
}
.options li {
    padding: 11px 13px;
    margin:0 0;
}
.options li:hover {
    background-color: #000;
    color: #fff;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>

<div class="selectSizeMain">
    <select class="selectBoxStyle">
        <option value="">Choose Size</option>
        <option value="aye">Aye</option>
        <option value="eh">Eh</option>
        <option value="ooh">Ooh</option>
        <option value="whoop">Whoop</option>
    </select>
</div>
<select class="selectBoxStyle">
    <option value="">Month&hellip;</option>
    <option value="january">January</option>
    <option value="february">February</option>
    <option value="march">March</option>
    <option value="april">April</option>
    <option value="may">May</option>
    <option value="june">June</option>
    <option value="july">July</option>
    <option value="august">August</option>
    <option value="september">September</option>
    <option value="october">October</option>
    <option value="november">November</option>
    <option value="december">December</option>
</select>

Answer №1

To achieve this, you can check if the select that was clicked already has the class .active. If it does, you can close all other open selects and then decide whether to use the toggleClass("active") on it.

Your callback function would change from:

styledSelect.click(function (e) {
    e.stopPropagation();

    jq('div.styledSelect.active').each(function () {
        jq(this).removeClass('active').next('ul.options').hide();
        console.log(this);
    });

    jq(this).toggleClass('active').next('ul.options').toggle();
});

to:

styledSelect.click(function (e) {
    e.stopPropagation();
    var closeClicked = jq(this).hasClass("active");

    jq('div.styledSelect.active').each(function () {
        jq(this).removeClass('active').next('ul.options').hide();
        console.log(this);
    });

    if (!closeClicked){
        jq(this).toggleClass('active').next('ul.options').toggle();
    }    
});

You can view a demonstration of this solution in this JSFiddle. It may not be the most elegant approach, but it's effective and only requires a small modification to your existing code. I hope this information is helpful! Feel free to reach out if you have any questions.

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

A guide to troubleshooting the "Cannot resolve all parameters error" in Angular

Recently delved into the world of angular 2, and I've come across my first challenge. I'm trying to establish a service for retrieving data from a server but I keep encountering this particular error Error: Can't resolve all parameters fo ...

Internet Explorer 9 is not fully extending the width of the box for multiple select options

I am facing an issue with a multiple select input in Internet Explorer 9. The options are not utilizing the full width of the select box, despite having a min-width set on the select element. In Chrome and Firefox, the items fill up the available width pe ...

The server sends a response with a MIME type that is not for JavaScript, it is empty

I am trying to integrate an angular application with cordova. Upon running "cordova run android" and inspecting it in Chrome, the console displays the following message: "Failed to load module script: The server responded with a non-JavaScript MIME t ...

Unable to close modal after receiving ajax response

Utilizing mdbootstrap for my current project has been a great experience. One area that I am struggling with is implementing an AJAX call upon checking a checkbox, where I expect a response from PHP indicating success (1) or failure (0). However, despite d ...

How can Swipe support help you slide a menu back in?

For implementing swipe support on my landing page carousel, I included jquery.mobile.custom.min.js. However, I am facing a challenge with adding swipe support to "close" the menu. Essentially, swiping left should have the same effect as clicking the butto ...

Using jQuery for Dragging and Dropping Elements within Dynamically Loaded Divs with

Is it possible to drag an element on the page into a droppable element inside an ajax loaded div? The code works fine when the droppable element is placed directly in the regular page, but not within the ajax loaded div. It seems like the issue may be rela ...

Experiencing a problem with XAMPP? Changes made to the code are not reflected after saving

Recently, I've encountered a strange issue with my XAMPP test server while working on a game project. Everything was running smoothly until I noticed that when I make changes to certain files in Notepad++ and save them, the updates are not being refle ...

Experiencing a problem with my JavaScript code in Node.js due to an asynchronous issue arising when using a timeout

My goal with this code is to retrieve JSON questions and present them to the user through the terminal. The user has 5 seconds to respond to each question before the next one appears. However, I encountered an issue where the next question times out automa ...

Utilizing Highchart for JSON Data Processing

I'm currently working on creating a simple bar chart using JSON data. Here's what I've attempted so far without utilizing the JSON data (http://jsfiddle.net/6hkcn4qf/2/). To achieve the same bar chart, I need to utilize this sample JSON htt ...

Is there a way to align the text input and text area next to each other?

I need help with styling a contact form that consists of 4 text input fields and 1 text area. Here is the current code for the contact form: <form class="contact_form"> <input type="text" placeholder="Name"> <input type="text" plac ...

Position a button to be aligned with the bottom of its container

My goal is to have the button positioned at the bottom of the red div, nested inside it. .grand-parent { display: flex; flex-direction: row; flex-wrap: wrap; height: 300px; background-color: green; } .pa ...

Unusual Characteristics of Synchronous Ajax Requests in JavaScript

First and foremost, I'd like to apologize if my approach seems unconventional. My background is primarily in C development, so I tend to tackle AJAX issues in a way that reflects my experience in C programming. The scenario at hand involves a script ...

Tips for organizing an array of objects that contain null properties

Here is an array that I need help with: "data": { "risks": [ { "id": "22", "name": true, "surname": 0.5, "age": 0.75, "heigth" ...

jQuery - the power of concurrent execution

Looking to make multiple AJAX calls to the YouTube API to fetch video information in JSON format. The calls can be processed synchronously, but I want to ensure that the processing function is not triggered until all data is received. Currently using recu ...

Troubleshooting Error 405 in AJAX, Javascript, Node.js (including Body-Parser and CORS), and XMLHttpRequest

I have been working on creating a JSON file from buttons. While I am able to retrieve data from the JSON files that I created, I am facing issues with posting to them using XMLHttpRequest and Ajax. Interestingly, I can add to a JSON file using routes just ...

When using angular.less, the @import feature is functioning correctly but a 404 error is displayed in the

Currently, I am working on a project using AngularJS along with angular.less. To centralize all my constants, I have stored them in one .less file and imported it at the beginning of all my other less files using a relative path: @import "constants" Even ...

Utilize Angular2's input type number without the option for decimal values

Is there a way to prevent decimals from being entered in number inputs for Angular 2? Instead of using patterns or constraints that only invalidate the field but still allow typing, what is the proper approach? Would manually checking keystrokes with the ...

Layered parallax scenery

I'm interested in creating a parallax effect similar to this example. https://medium.com/@PatrykZabielski/how-to-make-multi-layered-parallax-illustration-with-css-javascript-2b56883c3f27 However, I find the use of HAML and Coffeescript in the mentio ...

Listen for incoming data from the client in the form of an ArrayBuffer

I have been utilizing the ws library within nodejs to develop a small cursor lobby where players can interact. I have managed to utilize the server to send ArrayBuffers with bit streams to the client and successfully decode them. However, I am encountering ...

Prevent scrolling on both md-sidenav and md-content in AngularJS Material

Currently, I am working on a website using AngularJs Material sidenav. My goal is to make both md-sidenav and md-content appear as one page, without any scroll bars showing up when the height of one element exceeds that of the other. How can I achieve th ...