javascriptjqueryjquery-chosen

Unselect an item by clicking on it


There is a drop-down multy select in which I would like to click on an element to remove it from the selected ones. Out of the box chosen.js apparently can not do this, how can you modify it a bit?

I tried to bind the standard function to elements, but it didn't work. Please give me a hint

$("body").on("click", ".result-selected", function() {
    let index = $(this).attr("data-option-array-index");
    let container = $(this).closest(".chosen-container");
    let select = container.prev();
    
    if ( select != null && select.hasClass("chosen-select") ) {
        console.log(index);
        select
            .find("option:eq(" + index + ")")
            .prop("selected", false);
        select.trigger("chosen:updated").trigger('chosen:open');
    }
});

Solution

  • In the original code, you were triggering chosen:open after deselecting. This might not always behave as expected because if the dropdown is closed when you deselect, opening it immediately after might not be desired. In most cases, you will want to close the dropdown after making changes, not reopen it.

    1. Bind the click event on the chosen selected element.
    2. Find the corresponding option in the select element.
    3. Remove the selected property from that option.
    4. Update the chosen dropdown and trigger necessary events.

    Working snippet:

    $(function() {
        // Initialize Chosen with options
        $(".chosen-select").chosen({
            width: "100%",
            allow_single_deselect: false,
            disable_search: true,
            hide_results_on_select: false,
        });
    
        // Event listener for clicking a selected item to deselect
        $("body").on("click", ".result-selected", function() {
            let index = $(this).attr("data-option-array-index"); // Get the index of the selected option
            let container = $(this).closest(".chosen-container"); // Find the container of the chosen dropdown
            let select = container.prev(); // Get the original select element
    
            if (select != null && select.hasClass("chosen-select")) {
                // Check if dropdown is open before deselecting
                let isDropdownOpen = container.hasClass("chosen-with-drop");
    
                // Find the corresponding option element in the select by index
                let option = select.find("option").eq(index);
    
                if (option.length) {
                    // Deselect the option (remove 'selected' attribute)
                    option.prop("selected", false);
    
                    // Temporarily disable Chosen's internal closing behavior
                    select.trigger("chosen:updated");
    
                    // If the dropdown was open before deselecting, we keep it open manually
                    if (isDropdownOpen) {
                        // Manually re-open the dropdown if it's closed after deselecting
                        setTimeout(function() {
                            select.trigger("chosen:open");
                        }, 10); // Small delay to allow update to complete before reopening
                        return false;
                    }
                }
            }
        });
    
        // Handle item click to ensure dropdown opens again after deselection
        $("body").on("click", ".chosen-select", function() {
            let select = $(this);
            let container = select.next(".chosen-container");
    
            // If the dropdown is not open, we open it
            if (!container.hasClass("chosen-with-drop")) {
                select.trigger("chosen:open");
            }
        });
    
        // Prevent the dropdown from closing when updating
        $(document).on("chosen:updated", ".chosen-select", function() {
            let select = $(this);
            let container = select.next(".chosen-container");
    
            // If the dropdown is open, we reopen it
            if (container.hasClass("chosen-with-drop")) {
                setTimeout(function() {
                    select.trigger("chosen:open");
                }, 10);
            }
        });
    });
    .box{
      width:300px;
      margin:50px;
    }
    
    .chosen-container{
      position: relative;
    }
    .chosen-single{
        display: flex;
        align-items: center;
        width: 100%;
        padding: 12px 24px;
        border: none;
        outline: none;
        background-color: #FAFAFB;
        font-size: 14px;
        line-height: 24px;
        min-height: 48px;
        text-decoration: none;
        color:#02013D;
        position: relative;
        cursor: pointer;
        font-weight: 400;
    
        b{
          width: 16px;
          height: 16px;
          position: absolute;
          top: 16px;
          right: 16px;
          background-repeat: no-repeat;
          background-image: url("data:image/svg+xml,%3Csvg width='16' height='16' viewBox='0 0 16 16' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M4 10L8 6L12 10' stroke='%2302013D' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E%0A"); 
          transform: rotate(180deg);
          transition: transform .3s linear;
    
          .chosen-with-drop &{
            transform: rotate(0);
          }
        }
    }
    .chosen-drop{
      // display: none;
        margin-top: 4px;
    
        background-clip: padding-box;
        position: absolute;
        top: 100%;
        z-index: 1010;
        width: 100%;
        border-top: 0;
        background: #FAFAFB;
       
        clip: rect(0, 0, 0, 0);
        -webkit-clip-path: inset(100% 100%);
                clip-path: inset(100% 100%);
    
      .chosen-with-drop &{
        clip:auto;
        -webkit-clip-path: none;
        clip-path: none;
      }
    }
    .chosen-search{
      display: none;
    }
    .chosen-results{
      margin: 0;
      list-style: none;
      padding: 6px 12px;
      li{
        padding: 6px 0px;
        color:#02013D;
        font-size: 14px;
        cursor: pointer;
      }
    }
    
    .chosen-default{
      color:#81809E;
    }
    
    .chosen-container-multi{
    
      list-style: none;
        margin: 0;
        padding: 0;
        // align-items: center;
        width: 100%;
        padding-right: 34px;
        border: none;
        outline: none;
        background-color: #FAFAFB;
        font-size: 14px;
        line-height: 24px;
        min-height: 48px;
        text-decoration: none;
        color: #02013D;
        position: relative;
        cursor: pointer;
        font-weight: 400;
        height: 48px;
      
        &::after {
          content: '';
          width: 16px;
          height: 16px;
          position: absolute;
          top: 16px;
          right: 16px;
          background-repeat: no-repeat;
          background-image: url("data:image/svg+xml,%3Csvg width='16' height='16' viewBox='0 0 16 16' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M4 10L8 6L12 10' stroke='%2302013D' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E%0A");
          transform: rotate(180deg);
          transition: transform .3s linear;
      
      
        }
    
      .chosen-choices{
        display: flex;
        overflow: hidden;
        margin: 0;
        padding: 0;
        list-style: none;
        padding: 12px 0px 12px 24px;
    
        li{
          &:last-child{
            display: none;
          }
          &:first-child{
            display: inline-block;
          }
        }
        
    
        input{
          border:none;
          background-color: transparent;
          font-size: 14px;
          color:#02013D;
          outline:none;
        }
    
        .search-field{
          // display: none;
        }
        .chosen-search-input{
          display: none;
        }
        .search-choice{
          display: inline-block;
          margin-right: 8px;
          position: relative;
          padding-right: 12px;
          flex-shrink: 0;
         
          .search-choice-close{
            position: absolute;
            left: 0;
            top: 0;
            width: 100%;
            height: 100%;
            background-image: url("data:image/svg+xml,%3Csvg width='10' height='10' viewBox='0 0 14 14' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M13 1L1 13M1 1L13 13' stroke='%2302013D' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E%0A");
            background-position: top right;
            background-repeat: no-repeat;
          }
        }
      }
    
      &.chosen-with-drop .chosen-choices:after {
        transform: rotate(0);
      }
    
      .chosen-results{
    
        .active-result, .result-selected{
          position: relative;
          padding-left: 28px;
          &:before{
            content:'';
            position: absolute;
            left: 0;
            top: 50%;
            transform:translateY(-50%);
            width: 16px;
            height: 16px;
            border:1px solid #02013D;
          }
        }
        .result-selected{
          &:after{
            content:'';
            position: absolute;
            left: 2px;
            top: 50%;
            transform: translateY(-50%);
            width: 12px;
            height: 12px;
            background-color: #886B3E;
          }
        }
        
      }
    }
    
    .chosen-drop {
        margin-top: 4px;
        background-clip: padding-box;
        position: absolute;
        top: 100%;
        z-index: 1010;
        width: 100%;
        border-top: 0;
        background: #FAFAFB;
        clip: auto; /* Ensure it's visible */
        -webkit-clip-path: none;
        clip-path: none;
    }
    
    .chosen-container .chosen-with-drop .chosen-drop {
        clip-path: none; /* When dropdown is open, clip-path should be removed */
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/chosen/1.8.7/chosen.jquery.min.js"></script>
    <div class="box">
    
     <select name="size" class="chosen-select" multiple data-placeholder="Select size" >
       <option value=""></option>
       <option value="40">40 mm</option>
       <option value="36">36 mm</option>
       <option value="26">26 mm</option>
       <option value="41">41 mm</option>
       <option value="34">34 mm</option>
      </select>
    
    </div>