1

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?

bgs264
  • 4,572
  • 6
  • 38
  • 72

2 Answers2

1

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/

aozd4v
  • 96
  • 1
  • 3
  • @Abhitalks This answer worked great for me without `stopPropagation()`. Why would I need to use that? – bgs264 Dec 08 '15 at 13:27
  • @bgs264: Never mind. My main point was to ensure that the Op writes a complete answer instead of a one liner which was at risk of deletion. – Abhitalks Dec 08 '15 at 13:51
  • 1
    @Abhitalks Yeah cheers mate, I don't often respond on StackOverflow. – aozd4v Dec 08 '15 at 16:35
  • @Abhitalks I don't understand. I have read several times the "Guidance for answers" (here: http://stackoverflow.com/help/how-to-answer). Nothing said that one lines were at risk of deletion, nothing says to provide code samples. Upon what grounds do you base your comments? I thought the answer was fine - "replace click to mouseup" - it was concise and worked. I know how to do that, I don't need a full sample showing one event replaced to another? – bgs264 Dec 10 '15 at 11:32
0

Maybe you can look at mousedown/mousemove combinations? See this thread for more info: How to distinguish mouse "click" and "drag"

Community
  • 1
  • 1