Skip to content

Commit 7f17291

Browse files
committed
Fix support for deep nesting
While deep nesting will not work on a standard `<select>`, we can emulate it through data objects still, and just handle the display of the data in the results. This also means that the horrific deep-nested CSS is back to handle the padding. I hope that will get fixed over time. This also fixes one of the performance issues with adding array data, as options are added at the very end instead of one by one.
1 parent 5c71e2d commit 7f17291

12 files changed

Lines changed: 243 additions & 49 deletions

File tree

dist/css/select2.css

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,25 @@
218218
color: #999; }
219219
.select2-container--default .select2-results__option[aria-selected=true] {
220220
background-color: #ddd; }
221+
.select2-container--default .select2-results__option .select2-results__option {
222+
padding-left: 1em; }
223+
.select2-container--default .select2-results__option .select2-results__option .select2-results__group {
224+
padding-left: 0; }
225+
.select2-container--default .select2-results__option .select2-results__option .select2-results__option {
226+
margin-left: -1em;
227+
padding-left: 2em; }
228+
.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
229+
margin-left: -2em;
230+
padding-left: 3em; }
231+
.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
232+
margin-left: -3em;
233+
padding-left: 4em; }
234+
.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
235+
margin-left: -4em;
236+
padding-left: 5em; }
237+
.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
238+
margin-left: -5em;
239+
padding-left: 6em; }
221240
.select2-container--default .select2-results__option--highlighted[aria-selected] {
222241
background-color: #5897fb;
223242
color: white; }

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: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2324,9 +2324,19 @@ define('select2/data/select',[
23242324
};
23252325

23262326
SelectAdapter.prototype.option = function (data) {
2327-
var option = document.createElement('option');
2327+
var option;
23282328

2329-
option.value = data.id;
2329+
if (data.children) {
2330+
option = document.createElement('optgroup');
2331+
option.label = data.text;
2332+
} else {
2333+
option = document.createElement('option');
2334+
option.innerText = data.text;
2335+
}
2336+
2337+
if (data.id) {
2338+
option.value = data.id;
2339+
}
23302340

23312341
if (data.disabled) {
23322342
option.disabled = true;
@@ -2336,8 +2346,6 @@ define('select2/data/select',[
23362346
option.selected = true;
23372347
}
23382348

2339-
option.innerText = data.text;
2340-
23412349
var $option = $(option);
23422350

23432351
var normalizedData = this._normalizeItem(data);
@@ -2367,7 +2375,7 @@ define('select2/data/select',[
23672375
};
23682376
} else if ($option.is('optgroup')) {
23692377
data = {
2370-
text: $option.attr('label'),
2378+
text: $option.prop('label'),
23712379
children: []
23722380
};
23732381

@@ -2444,7 +2452,7 @@ define('select2/data/array',[
24442452

24452453
ArrayAdapter.__super__.constructor.call(this, $element, options);
24462454

2447-
this.convertToOptions(data);
2455+
$element.append(this.convertToOptions(data));
24482456
}
24492457

24502458
Utils.Extend(ArrayAdapter, SelectAdapter);
@@ -2469,6 +2477,8 @@ define('select2/data/array',[
24692477
return self.item($(this)).id;
24702478
}).get();
24712479

2480+
var $options = [];
2481+
24722482
// Filter out all items except for the one passed in the argument
24732483
function onlyItem (item) {
24742484
return function () {
@@ -2477,8 +2487,7 @@ define('select2/data/array',[
24772487
}
24782488

24792489
for (var d = 0; d < data.length; d++) {
2480-
var item = data[d];
2481-
item.id = item.id.toString();
2490+
var item = this._normalizeItem(data[d]);
24822491

24832492
// Skip items which were pre-loaded, only merge the data
24842493
if (existingIds.indexOf(item.id) >= 0) {
@@ -2496,8 +2505,16 @@ define('select2/data/array',[
24962505

24972506
var $option = this.option(item);
24982507

2499-
this.$element.append($option);
2508+
if (item.children) {
2509+
var $children = this.convertToOptions(item.children);
2510+
2511+
$option.append($children);
2512+
}
2513+
2514+
$options.push($option);
25002515
}
2516+
2517+
return $options;
25012518
};
25022519

25032520
return ArrayAdapter;

dist/js/select2.amd.js

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2324,9 +2324,19 @@ define('select2/data/select',[
23242324
};
23252325

23262326
SelectAdapter.prototype.option = function (data) {
2327-
var option = document.createElement('option');
2327+
var option;
23282328

2329-
option.value = data.id;
2329+
if (data.children) {
2330+
option = document.createElement('optgroup');
2331+
option.label = data.text;
2332+
} else {
2333+
option = document.createElement('option');
2334+
option.innerText = data.text;
2335+
}
2336+
2337+
if (data.id) {
2338+
option.value = data.id;
2339+
}
23302340

23312341
if (data.disabled) {
23322342
option.disabled = true;
@@ -2336,8 +2346,6 @@ define('select2/data/select',[
23362346
option.selected = true;
23372347
}
23382348

2339-
option.innerText = data.text;
2340-
23412349
var $option = $(option);
23422350

23432351
var normalizedData = this._normalizeItem(data);
@@ -2367,7 +2375,7 @@ define('select2/data/select',[
23672375
};
23682376
} else if ($option.is('optgroup')) {
23692377
data = {
2370-
text: $option.attr('label'),
2378+
text: $option.prop('label'),
23712379
children: []
23722380
};
23732381

@@ -2444,7 +2452,7 @@ define('select2/data/array',[
24442452

24452453
ArrayAdapter.__super__.constructor.call(this, $element, options);
24462454

2447-
this.convertToOptions(data);
2455+
$element.append(this.convertToOptions(data));
24482456
}
24492457

24502458
Utils.Extend(ArrayAdapter, SelectAdapter);
@@ -2469,6 +2477,8 @@ define('select2/data/array',[
24692477
return self.item($(this)).id;
24702478
}).get();
24712479

2480+
var $options = [];
2481+
24722482
// Filter out all items except for the one passed in the argument
24732483
function onlyItem (item) {
24742484
return function () {
@@ -2477,8 +2487,7 @@ define('select2/data/array',[
24772487
}
24782488

24792489
for (var d = 0; d < data.length; d++) {
2480-
var item = data[d];
2481-
item.id = item.id.toString();
2490+
var item = this._normalizeItem(data[d]);
24822491

24832492
// Skip items which were pre-loaded, only merge the data
24842493
if (existingIds.indexOf(item.id) >= 0) {
@@ -2496,8 +2505,16 @@ define('select2/data/array',[
24962505

24972506
var $option = this.option(item);
24982507

2499-
this.$element.append($option);
2508+
if (item.children) {
2509+
var $children = this.convertToOptions(item.children);
2510+
2511+
$option.append($children);
2512+
}
2513+
2514+
$options.push($option);
25002515
}
2516+
2517+
return $options;
25012518
};
25022519

25032520
return ArrayAdapter;

dist/js/select2.full.js

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11859,9 +11859,19 @@ define('select2/data/select',[
1185911859
};
1186011860

1186111861
SelectAdapter.prototype.option = function (data) {
11862-
var option = document.createElement('option');
11862+
var option;
1186311863

11864-
option.value = data.id;
11864+
if (data.children) {
11865+
option = document.createElement('optgroup');
11866+
option.label = data.text;
11867+
} else {
11868+
option = document.createElement('option');
11869+
option.innerText = data.text;
11870+
}
11871+
11872+
if (data.id) {
11873+
option.value = data.id;
11874+
}
1186511875

1186611876
if (data.disabled) {
1186711877
option.disabled = true;
@@ -11871,8 +11881,6 @@ define('select2/data/select',[
1187111881
option.selected = true;
1187211882
}
1187311883

11874-
option.innerText = data.text;
11875-
1187611884
var $option = $(option);
1187711885

1187811886
var normalizedData = this._normalizeItem(data);
@@ -11902,7 +11910,7 @@ define('select2/data/select',[
1190211910
};
1190311911
} else if ($option.is('optgroup')) {
1190411912
data = {
11905-
text: $option.attr('label'),
11913+
text: $option.prop('label'),
1190611914
children: []
1190711915
};
1190811916

@@ -11979,7 +11987,7 @@ define('select2/data/array',[
1197911987

1198011988
ArrayAdapter.__super__.constructor.call(this, $element, options);
1198111989

11982-
this.convertToOptions(data);
11990+
$element.append(this.convertToOptions(data));
1198311991
}
1198411992

1198511993
Utils.Extend(ArrayAdapter, SelectAdapter);
@@ -12004,6 +12012,8 @@ define('select2/data/array',[
1200412012
return self.item($(this)).id;
1200512013
}).get();
1200612014

12015+
var $options = [];
12016+
1200712017
// Filter out all items except for the one passed in the argument
1200812018
function onlyItem (item) {
1200912019
return function () {
@@ -12012,8 +12022,7 @@ define('select2/data/array',[
1201212022
}
1201312023

1201412024
for (var d = 0; d < data.length; d++) {
12015-
var item = data[d];
12016-
item.id = item.id.toString();
12025+
var item = this._normalizeItem(data[d]);
1201712026

1201812027
// Skip items which were pre-loaded, only merge the data
1201912028
if (existingIds.indexOf(item.id) >= 0) {
@@ -12031,8 +12040,16 @@ define('select2/data/array',[
1203112040

1203212041
var $option = this.option(item);
1203312042

12034-
this.$element.append($option);
12043+
if (item.children) {
12044+
var $children = this.convertToOptions(item.children);
12045+
12046+
$option.append($children);
12047+
}
12048+
12049+
$options.push($option);
1203512050
}
12051+
12052+
return $options;
1203612053
};
1203712054

1203812055
return ArrayAdapter;

dist/js/select2.full.min.js

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.js

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2752,9 +2752,19 @@ define('select2/data/select',[
27522752
};
27532753

27542754
SelectAdapter.prototype.option = function (data) {
2755-
var option = document.createElement('option');
2755+
var option;
27562756

2757-
option.value = data.id;
2757+
if (data.children) {
2758+
option = document.createElement('optgroup');
2759+
option.label = data.text;
2760+
} else {
2761+
option = document.createElement('option');
2762+
option.innerText = data.text;
2763+
}
2764+
2765+
if (data.id) {
2766+
option.value = data.id;
2767+
}
27582768

27592769
if (data.disabled) {
27602770
option.disabled = true;
@@ -2764,8 +2774,6 @@ define('select2/data/select',[
27642774
option.selected = true;
27652775
}
27662776

2767-
option.innerText = data.text;
2768-
27692777
var $option = $(option);
27702778

27712779
var normalizedData = this._normalizeItem(data);
@@ -2795,7 +2803,7 @@ define('select2/data/select',[
27952803
};
27962804
} else if ($option.is('optgroup')) {
27972805
data = {
2798-
text: $option.attr('label'),
2806+
text: $option.prop('label'),
27992807
children: []
28002808
};
28012809

@@ -2872,7 +2880,7 @@ define('select2/data/array',[
28722880

28732881
ArrayAdapter.__super__.constructor.call(this, $element, options);
28742882

2875-
this.convertToOptions(data);
2883+
$element.append(this.convertToOptions(data));
28762884
}
28772885

28782886
Utils.Extend(ArrayAdapter, SelectAdapter);
@@ -2897,6 +2905,8 @@ define('select2/data/array',[
28972905
return self.item($(this)).id;
28982906
}).get();
28992907

2908+
var $options = [];
2909+
29002910
// Filter out all items except for the one passed in the argument
29012911
function onlyItem (item) {
29022912
return function () {
@@ -2905,8 +2915,7 @@ define('select2/data/array',[
29052915
}
29062916

29072917
for (var d = 0; d < data.length; d++) {
2908-
var item = data[d];
2909-
item.id = item.id.toString();
2918+
var item = this._normalizeItem(data[d]);
29102919

29112920
// Skip items which were pre-loaded, only merge the data
29122921
if (existingIds.indexOf(item.id) >= 0) {
@@ -2924,8 +2933,16 @@ define('select2/data/array',[
29242933

29252934
var $option = this.option(item);
29262935

2927-
this.$element.append($option);
2936+
if (item.children) {
2937+
var $children = this.convertToOptions(item.children);
2938+
2939+
$option.append($children);
2940+
}
2941+
2942+
$options.push($option);
29282943
}
2944+
2945+
return $options;
29292946
};
29302947

29312948
return ArrayAdapter;

dist/js/select2.min.js

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)