Skip to content

Commit acd469c

Browse files
committed
Added optgroup support
1 parent fd5603b commit acd469c

12 files changed

Lines changed: 483 additions & 77 deletions

File tree

dist/css/select2.css

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,9 +88,15 @@
8888
.select2-container.select2-theme-default .dropdown .results {
8989
max-height: 200px;
9090
overflow-y: scroll; }
91+
.select2-container.select2-theme-default .dropdown .results .options .option.group {
92+
padding: 0; }
93+
.select2-container.select2-theme-default .dropdown .results .options .option.group .group-label {
94+
cursor: default;
95+
display: block;
96+
padding: 6px; }
9197
.select2-container.select2-theme-default .dropdown .results .options .option.selected {
9298
background-color: #ddd; }
93-
.select2-container.select2-theme-default .dropdown .results .options .option.highlighted {
99+
.select2-container.select2-theme-default .dropdown .results .options .option.highlightable.highlighted {
94100
background-color: #5897fb;
95101
color: white; }
96102

dist/css/select2.min.css

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/js/select2.amd.full.js

Lines changed: 92 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -200,10 +200,39 @@ define('select2/results',[
200200

201201
Results.prototype.option = function (data) {
202202
var $option = $(
203-
'<li class="option"></li>'
203+
'<li class="option highlightable selectable"></li>'
204204
);
205205

206-
$option.html(data.text);
206+
if (data.children && data.children.length > 0) {
207+
$option.addClass('group').removeClass('highlightable selectable');
208+
209+
var $label = $('<strong class="group-label"></strong>');
210+
$label.html(data.text);
211+
212+
var $children = [];
213+
214+
for (var c = 0; c < data.children.length; c++) {
215+
var child = data.children[c];
216+
217+
var $child = this.option(child);
218+
219+
$children.push($child);
220+
}
221+
222+
var $childrenContainer = $('<ul class="options nested-options"></ul>');
223+
224+
$childrenContainer.append($children);
225+
226+
$option.append($label);
227+
$option.append($childrenContainer);
228+
} else {
229+
$option.html(data.text);
230+
}
231+
232+
if (data.disabled) {
233+
$option.removeClass('selectable').addClass('disabled');
234+
}
235+
207236
$option.data('data', data);
208237

209238
return $option;
@@ -225,7 +254,7 @@ define('select2/results',[
225254
self.setClasses();
226255
});
227256

228-
this.$results.on('mouseup', '.option', function (evt) {
257+
this.$results.on('mouseup', '.option.selectable', function (evt) {
229258
var $this = $(this);
230259

231260
var data = $this.data('data');
@@ -248,7 +277,7 @@ define('select2/results',[
248277
self.setClasses();
249278
});
250279

251-
this.$results.on('mouseenter', '.option', function (evt) {
280+
this.$results.on('mouseenter', '.option.highlightable', function (evt) {
252281
self.$results.find('.option.highlighted').removeClass('highlighted');
253282
$(this).addClass('highlighted');
254283
});
@@ -540,13 +569,21 @@ define('select2/data/select',[
540569
var data = [];
541570
var self = this;
542571

543-
this.$element.find('option').each(function () {
572+
var $options = this.$element.children();
573+
574+
$options.each(function () {
544575
var $option = $(this);
545576

577+
if (!$option.is('option') && !$option.is('optgroup')) {
578+
return;
579+
}
580+
546581
var option = self.item($option);
547582

548-
if (self.matches(params, option)) {
549-
data.push(option);
583+
var matches = self.matches(params, option);
584+
585+
if (matches !== null) {
586+
data.push(matches);
550587
}
551588
});
552589

@@ -558,10 +595,32 @@ define('select2/data/select',[
558595

559596
// If the data has already be generated, use it
560597
if (data == null) {
561-
data = {
562-
id: $option.val(),
563-
text: $option.html()
564-
};
598+
if ($option.is('option')) {
599+
data = {
600+
id: $option.val(),
601+
text: $option.html(),
602+
disabled: $option.prop('disabled')
603+
};
604+
} else if ($option.is('optgroup')) {
605+
data = {
606+
id: -1,
607+
text: $option.attr('label'),
608+
children: []
609+
};
610+
611+
var $children = $option.children('option');
612+
var children = [];
613+
614+
for (var c = 0; c < $children.length; c++) {
615+
var $child = $($children[c]);
616+
617+
var child = this.item($child);
618+
619+
children.push(child);
620+
}
621+
622+
data.children = children;
623+
}
565624

566625
$option.data('data', data);
567626
}
@@ -570,15 +629,34 @@ define('select2/data/select',[
570629
};
571630

572631
SelectAdapter.prototype.matches = function (params, data) {
632+
var match = $.extend(true, {}, data);
633+
634+
if (data.children) {
635+
for (var c = data.children.length - 1; c >= 0; c--) {
636+
var child = data.children[c];
637+
638+
var matches = this.matches(params, child);
639+
640+
// If there wasn't a match, remove the object in the array
641+
if (matches === null) {
642+
match.children.splice(c, 1);
643+
}
644+
}
645+
646+
if (match.children.length > 0) {
647+
return match;
648+
}
649+
}
650+
573651
if ($.trim(params.term) === '') {
574-
return true;
652+
return match;
575653
}
576654

577655
if (data.text.indexOf(params.term) > -1) {
578-
return true;
656+
return match;
579657
}
580658

581-
return false;
659+
return null;
582660
};
583661

584662
return SelectAdapter;

dist/js/select2.amd.js

Lines changed: 92 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -200,10 +200,39 @@ define('select2/results',[
200200

201201
Results.prototype.option = function (data) {
202202
var $option = $(
203-
'<li class="option"></li>'
203+
'<li class="option highlightable selectable"></li>'
204204
);
205205

206-
$option.html(data.text);
206+
if (data.children && data.children.length > 0) {
207+
$option.addClass('group').removeClass('highlightable selectable');
208+
209+
var $label = $('<strong class="group-label"></strong>');
210+
$label.html(data.text);
211+
212+
var $children = [];
213+
214+
for (var c = 0; c < data.children.length; c++) {
215+
var child = data.children[c];
216+
217+
var $child = this.option(child);
218+
219+
$children.push($child);
220+
}
221+
222+
var $childrenContainer = $('<ul class="options nested-options"></ul>');
223+
224+
$childrenContainer.append($children);
225+
226+
$option.append($label);
227+
$option.append($childrenContainer);
228+
} else {
229+
$option.html(data.text);
230+
}
231+
232+
if (data.disabled) {
233+
$option.removeClass('selectable').addClass('disabled');
234+
}
235+
207236
$option.data('data', data);
208237

209238
return $option;
@@ -225,7 +254,7 @@ define('select2/results',[
225254
self.setClasses();
226255
});
227256

228-
this.$results.on('mouseup', '.option', function (evt) {
257+
this.$results.on('mouseup', '.option.selectable', function (evt) {
229258
var $this = $(this);
230259

231260
var data = $this.data('data');
@@ -248,7 +277,7 @@ define('select2/results',[
248277
self.setClasses();
249278
});
250279

251-
this.$results.on('mouseenter', '.option', function (evt) {
280+
this.$results.on('mouseenter', '.option.highlightable', function (evt) {
252281
self.$results.find('.option.highlighted').removeClass('highlighted');
253282
$(this).addClass('highlighted');
254283
});
@@ -540,13 +569,21 @@ define('select2/data/select',[
540569
var data = [];
541570
var self = this;
542571

543-
this.$element.find('option').each(function () {
572+
var $options = this.$element.children();
573+
574+
$options.each(function () {
544575
var $option = $(this);
545576

577+
if (!$option.is('option') && !$option.is('optgroup')) {
578+
return;
579+
}
580+
546581
var option = self.item($option);
547582

548-
if (self.matches(params, option)) {
549-
data.push(option);
583+
var matches = self.matches(params, option);
584+
585+
if (matches !== null) {
586+
data.push(matches);
550587
}
551588
});
552589

@@ -558,10 +595,32 @@ define('select2/data/select',[
558595

559596
// If the data has already be generated, use it
560597
if (data == null) {
561-
data = {
562-
id: $option.val(),
563-
text: $option.html()
564-
};
598+
if ($option.is('option')) {
599+
data = {
600+
id: $option.val(),
601+
text: $option.html(),
602+
disabled: $option.prop('disabled')
603+
};
604+
} else if ($option.is('optgroup')) {
605+
data = {
606+
id: -1,
607+
text: $option.attr('label'),
608+
children: []
609+
};
610+
611+
var $children = $option.children('option');
612+
var children = [];
613+
614+
for (var c = 0; c < $children.length; c++) {
615+
var $child = $($children[c]);
616+
617+
var child = this.item($child);
618+
619+
children.push(child);
620+
}
621+
622+
data.children = children;
623+
}
565624

566625
$option.data('data', data);
567626
}
@@ -570,15 +629,34 @@ define('select2/data/select',[
570629
};
571630

572631
SelectAdapter.prototype.matches = function (params, data) {
632+
var match = $.extend(true, {}, data);
633+
634+
if (data.children) {
635+
for (var c = data.children.length - 1; c >= 0; c--) {
636+
var child = data.children[c];
637+
638+
var matches = this.matches(params, child);
639+
640+
// If there wasn't a match, remove the object in the array
641+
if (matches === null) {
642+
match.children.splice(c, 1);
643+
}
644+
}
645+
646+
if (match.children.length > 0) {
647+
return match;
648+
}
649+
}
650+
573651
if ($.trim(params.term) === '') {
574-
return true;
652+
return match;
575653
}
576654

577655
if (data.text.indexOf(params.term) > -1) {
578-
return true;
656+
return match;
579657
}
580658

581-
return false;
659+
return null;
582660
};
583661

584662
return SelectAdapter;

0 commit comments

Comments
 (0)