1
0
mirror of synced 2025-02-04 06:09:23 +03:00

Convert array data to options immediately

This converts individual objects passed in through the `array`
parameter to `<option>` tags when Select2 is initialized. This
removes a lot of duplicate code from the `ArrayAdapter`, and keeps
everything closer to the native `<select>` element.

This introduces a breaking change from previous versions of Select2,
where the initial value for array data was blank, even if a blank
option was not present in the original array of objects. Now the
first object passed in will be selected by default, following the
behavior of a standard `<select>` element.

This breaking change does not affect `<select multiple="multiple">`
elements, which by default have no selection.
This commit is contained in:
Kevin Brown 2014-11-06 12:03:06 -05:00
parent 5454a908a1
commit 8ea23610f1
9 changed files with 227 additions and 141 deletions

View File

@ -1089,6 +1089,7 @@ define('select2/data/select',[
$option.text(data.text); $option.text(data.text);
$option.val(data.id); $option.val(data.id);
$option.prop('disabled', data.disabled || false); $option.prop('disabled', data.disabled || false);
$option.prop('selected', data.selected || false);
// Get any automatically generated data values // Get any automatically generated data values
var detectedData = this.item($option); var detectedData = this.item($option);
@ -1137,6 +1138,8 @@ define('select2/data/select',[
data._resultId = this.generateResultId(this.container, data); data._resultId = this.generateResultId(this.container, data);
} }
data.selected = $option.prop('selected');
$option.data('data', data); $option.data('data', data);
} }
@ -1158,45 +1161,56 @@ define('select2/data/array',[
'jquery' 'jquery'
], function (SelectAdapter, Utils, $) { ], function (SelectAdapter, Utils, $) {
function ArrayAdapter ($element, options) { function ArrayAdapter ($element, options) {
this.data = options.get('data'); var data = options.get('data');
ArrayAdapter.__super__.constructor.call(this, $element, options); ArrayAdapter.__super__.constructor.call(this, $element, options);
this.convertToOptions(data);
} }
Utils.Extend(ArrayAdapter, SelectAdapter); Utils.Extend(ArrayAdapter, SelectAdapter);
ArrayAdapter.prototype.select = function (data) { ArrayAdapter.prototype.convertToOptions = function (data) {
var self = this; var self = this;
this.$element.find('option').each(function () { var $existing = this.$element.find('option');
var $option = $(this); var existingIds = $existing.map(function () {
var option = self.item($option); return self.item($(this)).id;
}).get();
if (option.id == data.id.toString()) { // Filter out all items except for the one passed in the argument
$option.remove(); function onlyItem (item) {
} return function () {
}); return $(this).val() == item.id;
var $option = this.option(data);
this.$element.append($option);
ArrayAdapter.__super__.select.call(this, data);
}; };
ArrayAdapter.prototype.query = function (params, callback) {
var matches = [];
var self = this;
$.each(this.data, function () {
var option = this;
if (self.matches(params, option)) {
matches.push(option);
} }
});
callback(matches); for (var d = 0; d < data.length; d++) {
var item = data[d];
item.id = item.id.toString();
console.log(existingIds, item.id, existingIds.indexOf(item.id));
// Skip items which were pre-loaded, only merge the data
if (existingIds.indexOf(item.id) >= 0) {
console.log(item.id);
var $existingOption = $existing.filter(onlyItem(item));
var existingData = this.item($existingOption);
var newData = $.extend(true, {}, existingData, item);
var $newOption = this.option(existingData);
$existingOption.replaceWith($newOption);
continue;
}
var option = this.option(item);
this.$element.append(option);
}
}; };
return ArrayAdapter; return ArrayAdapter;

View File

@ -1089,6 +1089,7 @@ define('select2/data/select',[
$option.text(data.text); $option.text(data.text);
$option.val(data.id); $option.val(data.id);
$option.prop('disabled', data.disabled || false); $option.prop('disabled', data.disabled || false);
$option.prop('selected', data.selected || false);
// Get any automatically generated data values // Get any automatically generated data values
var detectedData = this.item($option); var detectedData = this.item($option);
@ -1137,6 +1138,8 @@ define('select2/data/select',[
data._resultId = this.generateResultId(this.container, data); data._resultId = this.generateResultId(this.container, data);
} }
data.selected = $option.prop('selected');
$option.data('data', data); $option.data('data', data);
} }
@ -1158,45 +1161,56 @@ define('select2/data/array',[
'jquery' 'jquery'
], function (SelectAdapter, Utils, $) { ], function (SelectAdapter, Utils, $) {
function ArrayAdapter ($element, options) { function ArrayAdapter ($element, options) {
this.data = options.get('data'); var data = options.get('data');
ArrayAdapter.__super__.constructor.call(this, $element, options); ArrayAdapter.__super__.constructor.call(this, $element, options);
this.convertToOptions(data);
} }
Utils.Extend(ArrayAdapter, SelectAdapter); Utils.Extend(ArrayAdapter, SelectAdapter);
ArrayAdapter.prototype.select = function (data) { ArrayAdapter.prototype.convertToOptions = function (data) {
var self = this; var self = this;
this.$element.find('option').each(function () { var $existing = this.$element.find('option');
var $option = $(this); var existingIds = $existing.map(function () {
var option = self.item($option); return self.item($(this)).id;
}).get();
if (option.id == data.id.toString()) { // Filter out all items except for the one passed in the argument
$option.remove(); function onlyItem (item) {
} return function () {
}); return $(this).val() == item.id;
var $option = this.option(data);
this.$element.append($option);
ArrayAdapter.__super__.select.call(this, data);
}; };
ArrayAdapter.prototype.query = function (params, callback) {
var matches = [];
var self = this;
$.each(this.data, function () {
var option = this;
if (self.matches(params, option)) {
matches.push(option);
} }
});
callback(matches); for (var d = 0; d < data.length; d++) {
var item = data[d];
item.id = item.id.toString();
console.log(existingIds, item.id, existingIds.indexOf(item.id));
// Skip items which were pre-loaded, only merge the data
if (existingIds.indexOf(item.id) >= 0) {
console.log(item.id);
var $existingOption = $existing.filter(onlyItem(item));
var existingData = this.item($existingOption);
var newData = $.extend(true, {}, existingData, item);
var $newOption = this.option(existingData);
$existingOption.replaceWith($newOption);
continue;
}
var option = this.option(item);
this.$element.append(option);
}
}; };
return ArrayAdapter; return ArrayAdapter;

View File

@ -10624,6 +10624,7 @@ define('select2/data/select',[
$option.text(data.text); $option.text(data.text);
$option.val(data.id); $option.val(data.id);
$option.prop('disabled', data.disabled || false); $option.prop('disabled', data.disabled || false);
$option.prop('selected', data.selected || false);
// Get any automatically generated data values // Get any automatically generated data values
var detectedData = this.item($option); var detectedData = this.item($option);
@ -10672,6 +10673,8 @@ define('select2/data/select',[
data._resultId = this.generateResultId(this.container, data); data._resultId = this.generateResultId(this.container, data);
} }
data.selected = $option.prop('selected');
$option.data('data', data); $option.data('data', data);
} }
@ -10693,45 +10696,56 @@ define('select2/data/array',[
'jquery' 'jquery'
], function (SelectAdapter, Utils, $) { ], function (SelectAdapter, Utils, $) {
function ArrayAdapter ($element, options) { function ArrayAdapter ($element, options) {
this.data = options.get('data'); var data = options.get('data');
ArrayAdapter.__super__.constructor.call(this, $element, options); ArrayAdapter.__super__.constructor.call(this, $element, options);
this.convertToOptions(data);
} }
Utils.Extend(ArrayAdapter, SelectAdapter); Utils.Extend(ArrayAdapter, SelectAdapter);
ArrayAdapter.prototype.select = function (data) { ArrayAdapter.prototype.convertToOptions = function (data) {
var self = this; var self = this;
this.$element.find('option').each(function () { var $existing = this.$element.find('option');
var $option = $(this); var existingIds = $existing.map(function () {
var option = self.item($option); return self.item($(this)).id;
}).get();
if (option.id == data.id.toString()) { // Filter out all items except for the one passed in the argument
$option.remove(); function onlyItem (item) {
} return function () {
}); return $(this).val() == item.id;
var $option = this.option(data);
this.$element.append($option);
ArrayAdapter.__super__.select.call(this, data);
}; };
ArrayAdapter.prototype.query = function (params, callback) {
var matches = [];
var self = this;
$.each(this.data, function () {
var option = this;
if (self.matches(params, option)) {
matches.push(option);
} }
});
callback(matches); for (var d = 0; d < data.length; d++) {
var item = data[d];
item.id = item.id.toString();
console.log(existingIds, item.id, existingIds.indexOf(item.id));
// Skip items which were pre-loaded, only merge the data
if (existingIds.indexOf(item.id) >= 0) {
console.log(item.id);
var $existingOption = $existing.filter(onlyItem(item));
var existingData = this.item($existingOption);
var newData = $.extend(true, {}, existingData, item);
var $newOption = this.option(existingData);
$existingOption.replaceWith($newOption);
continue;
}
var option = this.option(item);
this.$element.append(option);
}
}; };
return ArrayAdapter; return ArrayAdapter;

File diff suppressed because one or more lines are too long

68
dist/js/select2.js vendored
View File

@ -1517,6 +1517,7 @@ define('select2/data/select',[
$option.text(data.text); $option.text(data.text);
$option.val(data.id); $option.val(data.id);
$option.prop('disabled', data.disabled || false); $option.prop('disabled', data.disabled || false);
$option.prop('selected', data.selected || false);
// Get any automatically generated data values // Get any automatically generated data values
var detectedData = this.item($option); var detectedData = this.item($option);
@ -1565,6 +1566,8 @@ define('select2/data/select',[
data._resultId = this.generateResultId(this.container, data); data._resultId = this.generateResultId(this.container, data);
} }
data.selected = $option.prop('selected');
$option.data('data', data); $option.data('data', data);
} }
@ -1586,45 +1589,56 @@ define('select2/data/array',[
'jquery' 'jquery'
], function (SelectAdapter, Utils, $) { ], function (SelectAdapter, Utils, $) {
function ArrayAdapter ($element, options) { function ArrayAdapter ($element, options) {
this.data = options.get('data'); var data = options.get('data');
ArrayAdapter.__super__.constructor.call(this, $element, options); ArrayAdapter.__super__.constructor.call(this, $element, options);
this.convertToOptions(data);
} }
Utils.Extend(ArrayAdapter, SelectAdapter); Utils.Extend(ArrayAdapter, SelectAdapter);
ArrayAdapter.prototype.select = function (data) { ArrayAdapter.prototype.convertToOptions = function (data) {
var self = this; var self = this;
this.$element.find('option').each(function () { var $existing = this.$element.find('option');
var $option = $(this); var existingIds = $existing.map(function () {
var option = self.item($option); return self.item($(this)).id;
}).get();
if (option.id == data.id.toString()) { // Filter out all items except for the one passed in the argument
$option.remove(); function onlyItem (item) {
} return function () {
}); return $(this).val() == item.id;
var $option = this.option(data);
this.$element.append($option);
ArrayAdapter.__super__.select.call(this, data);
}; };
ArrayAdapter.prototype.query = function (params, callback) {
var matches = [];
var self = this;
$.each(this.data, function () {
var option = this;
if (self.matches(params, option)) {
matches.push(option);
} }
});
callback(matches); for (var d = 0; d < data.length; d++) {
var item = data[d];
item.id = item.id.toString();
console.log(existingIds, item.id, existingIds.indexOf(item.id));
// Skip items which were pre-loaded, only merge the data
if (existingIds.indexOf(item.id) >= 0) {
console.log(item.id);
var $existingOption = $existing.filter(onlyItem(item));
var existingData = this.item($existingOption);
var newData = $.extend(true, {}, existingData, item);
var $newOption = this.option(existingData);
$existingOption.replaceWith($newOption);
continue;
}
var option = this.option(item);
this.$element.append(option);
}
}; };
return ArrayAdapter; return ArrayAdapter;

File diff suppressed because one or more lines are too long

View File

@ -4,45 +4,56 @@ define([
'jquery' 'jquery'
], function (SelectAdapter, Utils, $) { ], function (SelectAdapter, Utils, $) {
function ArrayAdapter ($element, options) { function ArrayAdapter ($element, options) {
this.data = options.get('data'); var data = options.get('data');
ArrayAdapter.__super__.constructor.call(this, $element, options); ArrayAdapter.__super__.constructor.call(this, $element, options);
this.convertToOptions(data);
} }
Utils.Extend(ArrayAdapter, SelectAdapter); Utils.Extend(ArrayAdapter, SelectAdapter);
ArrayAdapter.prototype.select = function (data) { ArrayAdapter.prototype.convertToOptions = function (data) {
var self = this; var self = this;
this.$element.find('option').each(function () { var $existing = this.$element.find('option');
var $option = $(this); var existingIds = $existing.map(function () {
var option = self.item($option); return self.item($(this)).id;
}).get();
if (option.id == data.id.toString()) { // Filter out all items except for the one passed in the argument
$option.remove(); function onlyItem (item) {
} return function () {
}); return $(this).val() == item.id;
var $option = this.option(data);
this.$element.append($option);
ArrayAdapter.__super__.select.call(this, data);
}; };
ArrayAdapter.prototype.query = function (params, callback) {
var matches = [];
var self = this;
$.each(this.data, function () {
var option = this;
if (self.matches(params, option)) {
matches.push(option);
} }
});
callback(matches); for (var d = 0; d < data.length; d++) {
var item = data[d];
item.id = item.id.toString();
console.log(existingIds, item.id, existingIds.indexOf(item.id));
// Skip items which were pre-loaded, only merge the data
if (existingIds.indexOf(item.id) >= 0) {
console.log(item.id);
var $existingOption = $existing.filter(onlyItem(item));
var existingData = this.item($existingOption);
var newData = $.extend(true, {}, existingData, item);
var $newOption = this.option(existingData);
$existingOption.replaceWith($newOption);
continue;
}
var option = this.option(item);
this.$element.append(option);
}
}; };
return ArrayAdapter; return ArrayAdapter;

View File

@ -126,6 +126,7 @@ define([
$option.text(data.text); $option.text(data.text);
$option.val(data.id); $option.val(data.id);
$option.prop('disabled', data.disabled || false); $option.prop('disabled', data.disabled || false);
$option.prop('selected', data.selected || false);
// Get any automatically generated data values // Get any automatically generated data values
var detectedData = this.item($option); var detectedData = this.item($option);
@ -174,6 +175,8 @@ define([
data._resultId = this.generateResultId(this.container, data); data._resultId = this.generateResultId(this.container, data);
} }
data.selected = $option.prop('selected');
$option.data('data', data); $option.data('data', data);
} }

View File

@ -29,8 +29,16 @@ test('current gets default for single', function (assert) {
data.current(function (val) { data.current(function (val) {
assert.equal( assert.equal(
val.length, val.length,
0, 1,
'There should be no default selection.' 'There should always be a selected item for array data.'
);
var item = val[0];
assert.equal(
item.id,
'default',
'The first item should be selected'
); );
}); });
}); });
@ -117,14 +125,22 @@ test('select works for single', function (assert) {
var data = new ArrayData($select, options); var data = new ArrayData($select, options);
assert.equal($select.val(), null); assert.equal(
$select.val(),
'default',
'There should already be a selection'
);
data.select({ data.select({
id: '1', id: '1',
text: 'One' text: 'One'
}); });
assert.equal($select.val(), '1'); assert.equal(
$select.val(),
'1',
'The selected value should be the same as the selected id'
);
}); });
test('multiple sets the value', function (assert) { test('multiple sets the value', function (assert) {