Search code examples
jqueryhtmloptgroup

Multi select within an optgroup - the event's target is the optgroup


I have a select with some optgroups.

<select multiple style="height: 500px; width: 300px">
  <optgroup label="Colours">
    <option value="G">Green</option>
    <option value="B">Blue</option>
    <option value="Y">Yellow</option>
    <option value="W">White</option>
    <option value="P">Pink</option>
  </optgroup>
  <optgroup label="Numbers">
    <option value="1">One</option>
    <option value="2">Two</option>
    <option value="3">Three</option>
    <option value="4">Four</option>
    <option value="5">Five</option>
  </optgroup>
</select>

I want to be able to click the optgroup and select all the child options. I found that when clicking an individual option, the event still fired, so by testing the e.target I can make sure the target is the optgroup and only select the children then.

$(document).on("click", "optgroup", function(e) {
  var target = $(e.target);

  console.log(target);

  if (target.is("optgroup")) { 
    target.find("option").prop("selected", true);
  }
});

Fiddle here: https://jsfiddle.net/0z61fzs4/

So far, so good.

However try and multi-select by doing a click-and-drag - on the Fiddle below just drag from "One" down to "Three". The event target in this instance ends up being the optgroup itself and not the option, so by selecting a couple of options in this manner, you end up with selecting everything in the optgroup.

This behaviour only occurs with a click-and-drag type selection. It does not occur with a Ctrl and click multiple selection.

Further, it does not occur if you "cross a boundary". For example in the fiddle attached, if you start at "White" and click-drag down to "Three" then you are multi-selecting from two different groups. In this instance the target ends up as the option and the behaviour works as expected.

How can I allow the click-drag type behaviour I want, to select multiple options within a single optgroup without the JS firing and selecting them all?


Solution

  • Try changing your click event to a mouseup event and see if that works as you expect.

    $(document).on("mouseup", "optgroup", function(e) {
      var target = $(e.target);
    
      if (target.is("optgroup")) { 
        target.find("option").prop("selected", true);
      };
    });
    

    Working example: https://jsfiddle.net/0z61fzs4/2/