chosen icon indicating copy to clipboard operation
chosen copied to clipboard

Make the optgroup labels clickable

Open greg0ire opened this issue 12 years ago • 38 comments

When using a select with optgroups, having all the items in a group added to the selection when the group label is clicked would be a very handy feature. It would make selecting a group minus one item very easy too. For instance, I have a filter form with countries grouped by zone. For the moment, if someone wants to select a group minus one item, he must select all items one by one. With this feature, he would simply click on the group and remove the country he does not want.

greg0ire avatar Oct 26 '11 11:10 greg0ire

This will be useful, but standart html-select does not allow it.

dananichev avatar Nov 25 '11 05:11 dananichev

@Fr3nzzy: yes, but if it were optional, this wouldn't be a problem, would it?

greg0ire avatar Nov 25 '11 07:11 greg0ire

@Fr3nzzy: if I may, standard html-select doesn't allow to search either... yet it's very convenient, and that's why Chosen is great -- it improves the standard select. I guess we could apply the same reasoning here.

@greg0ire: +1, i'm also looking for this :o)

pilap82 avatar Nov 29 '11 14:11 pilap82

@pilap82 However, select supports finding an item via typing its name.

dananichev avatar Nov 30 '11 08:11 dananichev

fair enough :)

pilap82 avatar Nov 30 '11 09:11 pilap82

Maybe not the best place for a patch, but I hope it could help:

$( '.chzn-results .group-result' ).each( function () {
    var self      = $( this )
        , options = $( '~li', self )
        , next    = options.filter( '.group-result' ).get( 0 )
    ;
    self.data( 'chzn-options', options.slice( 0, options.index( next ) ) );
} )
.click( function () { 
    $( this ).data( 'chzn-options' ).mouseup()
 } )
.hover( function () { 
    $( this ).data( 'chzn-options' ).addClass( 'highlighted' );
 }, function () { 
    $( this ).data( 'chzn-options' ).removeClass( 'highlighted' );
 } )
.css( { cursor: 'pointer' } );

adriengibrat avatar May 26 '12 00:05 adriengibrat

This is a great idea. I'm willing to submit a pull request if the core team would be open to merge it. What do you think @pfiller?

mejibyte avatar Jul 06 '12 17:07 mejibyte

sample of batch select with chosen:

http://vafada.github.com/chosen-dojo/

vafada avatar Jul 08 '12 19:07 vafada

Well done!

pilap82 avatar Jul 09 '12 09:07 pilap82

I'd like to see this get added to Chosen, but event listening should be added in a less intensive way. @adriengibrat's solution applies a listener to each group which doesn't perform as well if there are hundreds of groups. We already have a click event on the search results div that can be tested against option groups. If the option is set, css should be used to change the background color.

pfiller avatar Jul 09 '12 21:07 pfiller

+1. I was thinking that when the optgroup is selected, it would (optionally) disable/hide all its children.

mbrevda avatar Oct 14 '12 23:10 mbrevda

+1 for this feature

ghost avatar Mar 22 '13 14:03 ghost

@pfiller any update on this or the search_improvements branch? Would love to see it merged to master.

andriijas avatar May 29 '13 10:05 andriijas

I need selectable groups too. I originally tried to change the code – then was inspired by the oft-offered answer to "skip the optgroup and add spaces to indent the sub-items". That looked awful but since Chosen is nicely styled by CSS… how about use a non-optgroup select and use a class on each option to make it look like a grouped display?

You can see a basic version in this fiddle: http://jsfiddle.net/slothbear/9xqpF/

I didn't spend a lot of time of the style, but you'll get the idea. This provides two features I need – selectable optgroups, and searchable optgroups. All without optgroups.

I'm close to moving forward with this technique on my project, but I'm looking for feedback. It appears to work. Can you think of a better way? Or any gotchas?

Just realized I should probably mention – that fiddle is using the Koenpunt fork of Chosen, to enable option adding. But I don't think that affects this example.

I'm also looking for guidance. I know this technique is probably pretty far afield of the Chosen Philosophy to stick close to the select features – but if an option is appropriate for this feature, I'd be happy to do the work.

slothbear avatar Jul 12 '13 02:07 slothbear

+1 for this feature, I found chosen while looking for a way to support this

(I was looking for being able to select a group title OR select a group item) as per Slothbear's above

Edit: In the end I emulated this doing the following. Note the classes, I also added .clickable to the css which sets the cursor to a pointer.

<select name="category" data-placeholder="Choose a category..." class="chosen-select">
    <option value="group-1 class="group-result clickable">Group Title</option>
    <option value="1" class="group-option">Item Name</option>
    <option value="2" class="group-option">Item Name</option>
</select>

Pezmc avatar Sep 15 '13 13:09 Pezmc

Here is my solution. Although, it's specific for my needs, one can easily tweak with it and change it to his needs.

Example: cars -car1 -car2 -car3 plane -plane1 -plane2

What I did is to create a new option in the beginning off all groups, that way, the 'All' options will come right after groups: cars -All cars -car1 -car2 -car3 people -All people -person1 -person2

In 'results_option_build' , pass the 'All' option to 'result_add_group' as second parameter when data is a group, and skip the 'All' option in the next iteration:

if (data.group) { content += this.result_add_group(data, _ref[++_i])

Now, lets go to 'result_add_group' and replace the group with the option we passed, but keep the style of group: result_add_group = function(group, option) { . . return "<li class="group-result active-result " style data-option-array-index = "" + option.array_index + "">" + group.search_text + "";

That's it.. If you want, change the cursor to pointer in css.

Galaxy83 avatar Dec 08 '13 16:12 Galaxy83

None of these seem to take the search capability into account. By default in chosen, if you search for an option, it will show the group label too. This method does not, if i have several groups and they have identical options, this will make it so I just end up with a list of visually identical items.

bravadomizzou avatar Mar 11 '14 20:03 bravadomizzou

Would be very interesting to be integrated as an option in the library, as much would facilitate the management of multiple select. Do you have referred to squeeze in some version? a greeting

danibiza avatar Mar 14 '14 08:03 danibiza

I have this implemented just using the javascript, its a temporary fix. I don't use it for multiple selections though, I use it for custom grouping. I ended up making the groups be options but look like groups, and gave the 'groups' keywords that when you do a search for the sub-option, the group will show like it would normally in chosen.js http://stackoverflow.com/q/22336052/744228

bravadomizzou avatar Mar 14 '14 13:03 bravadomizzou

I added this into my local copy of chosen because it was a requirement for my project. It was fairly easy in the end.

In the set_default_values function I put this.group_selectable = this.options.group_selectable != null ? this.options.group_selectable === true : false; at the end.

Then in result_add_group I changed the classes assigned to the group to be

if (this.group_selectable) {
        group_el.className = "active-result group-result";
      } else {
        group_el.className = "group-result";
      }
group_el.setAttribute("data-group-array-index", group.array_index);

And last but not least in result_select a bit of a hack and added

if (high[0].getAttribute("data-group-array-index")) {
          var that = this;
          high.nextUntil('.group-result').each(function(index, element) {
            that.result_highlight = $(element);
            that.result_select(evt);
          });
        }

just before item = this.results_data[high[0].getAttribute("data-option-array-index")];

See full code at https://gist.github.com/ruhley/9944574

ruhley avatar Apr 02 '14 22:04 ruhley

https://gist.github.com/ruhley/9944574#file-chosen-jquery-js-L1005

var itm = that.results_data[element.getAttribute("data-option-array-index")];
if(itm && !itm.selected){
    that.result_highlight = $(element);
    that.result_select(evt);
}

Eliak avatar Jul 09 '14 13:07 Eliak

A bit late to the party, but: +1 for this feature!

tsujigiri avatar Apr 28 '15 14:04 tsujigiri

@ruhley +1 for your solution, works like a charm! Just a small detail that's in the full code page but not in the code segment : there's an else{ missing at the end.

KameSama avatar Aug 27 '15 22:08 KameSama

Hi, Thank you @ruhley for your code. But with you modifications, the group is not disabled after being clicked and can be reselected.

Here are my improvements (based on chosen 1.4.2):

  • After line 158, in "set_default_values" function, add :
this.group_selectable = this.options.group_selectable != null ? this.options.group_selectable === true : false;

Addition of the parameter

  • Change line 222, in "results_option_build" function, with:
content += this.result_add_group(data, _ref.slice(_i+1, _i+data.children+1));

Give the childrens to the "result_add_group" function.

  • Change line 272, redifinition of the "result_add_group" function, with:
AbstractChosen.prototype.result_add_group = function(group, childrens) {

In order to receive the childrens

  • After line 285 (group_el = document.createElement("li");), in "result_add_group" function, add:
if (this.group_selectable) {
  var all = true;
  $.each(childrens, function(index, element) {
    if(!element.selected){
      all = false;
    }
  });
  if(!all) {
    classes.push("active-result");
  } else {
    classes.push("result-selected");
  }
}
group_el.setAttribute("data-group-array-index", group.array_index);

This make the group clickable if at least one child is not selected. (this part is improvable because of the "all" variable).

  • After line 1052 (high.addClass("result-selected");), in "result_select" function, add :
if (high[0].getAttribute("data-group-array-index")) {
  var that = this;
  high.nextUntil('.group-result').each(function(index, element) {
    if($(element).hasClass('active-result')) {
      that.result_highlight = $(element);
      that.result_select(evt); 
    }
  });
} else {

This only add unselected childrens.

  • After Line 1083, in "result_select" function:
}

Need to close the condition of a clicked group.

Don't forget to indent correctly that piece of code ;)

Here is a full version of my file : https://gist.github.com/GuillaumeSTEIN/7a4ece3c6bb487d16df0 Here is a diff (1 year available) : https://www.diffnow.com/?report=8zhe9 Have fun

GuillaumeSTEIN avatar Feb 03 '16 12:02 GuillaumeSTEIN

Ist this still not implemented?

KarlBaumann avatar Sep 27 '16 11:09 KarlBaumann

@GuillaumeSTEIN I tried your full version script, nothing seems to change. Do I need to add some special parameters or classes to HTML to make it work? Maybe you can make a working example on http://codepen.io/ or jsfiddle?

KarlBaumann avatar Sep 27 '16 13:09 KarlBaumann

Yes, you need to set option : group_selectable to true to activate this feature

GuillaumeSTEIN avatar Sep 27 '16 13:09 GuillaumeSTEIN

thanks @GuillaumeSTEIN , it worked, but what I miss from @adriengibrat script, is highlighting all options under current group.

KarlBaumann avatar Sep 27 '16 14:09 KarlBaumann

selected groups have a "result-selected" class. You can do some CSS. Here is what I have written, you may need to adapt it for your needs :

 select.form-control + .chosen-container-multi .chosen-results li.result-selected{
     display: list-item;
     color: #ccc;
     cursor: default;
     background-color: white;
 }

GuillaumeSTEIN avatar Sep 27 '16 15:09 GuillaumeSTEIN

I took a stab at it #2678

jamesalbert avatar Nov 18 '16 19:11 jamesalbert