1f3eceba5a
In order to enable the ability to uniquely identify a result by an ID in the DOM, we generate a new ID for the result based on a combination of things, including the container ID prefix that is generated and used elsewhere in Select2. This has worked fairly well for use cases including attaching Select2 to an existing `<select>` and loading in options from a remote data set. Unfortunately, because this process relied on the container ID being used as a prefix, this failed for options which were automatically generated on initialization using the `data:` option to Select2. These were not being generated with an ID because at the time that they were being generated, the data adapter was not aware of the container it was being used in. This broke some accessibility features because we had a mix of options in the results list with IDs, and some without, so we fixed the ordering to make this work. Option generation no longer happens when the data adapter is first initialized, which is where it was previously happening, and instead it now occurs when the data adapter is bound to the container. This allows us to ensure that the data adapter is always aware of the container it is being associated with, so now it will be able to generate the result IDs. This also fixes the tests for the array adapter as well as the legacy `<input />` adapter so they properly bind to a container during the test. This was causing test failures becuase the options which would previously be generated during initialization were no longer appearing. Fixes #4350
386 lines
7.8 KiB
JavaScript
386 lines
7.8 KiB
JavaScript
module('Data adapters - Array');
|
|
|
|
var ArrayData = require('select2/data/array');
|
|
var $ = require('jquery');
|
|
var Options = require('select2/options');
|
|
var Utils = require('select2/utils');
|
|
|
|
var UserDefinedType = function (id, text) {
|
|
var self = this;
|
|
|
|
self.id = id;
|
|
self.text = text;
|
|
|
|
return self;
|
|
};
|
|
|
|
var arrayOptions = new Options({
|
|
data: [
|
|
{
|
|
id: 'default',
|
|
text: 'Default'
|
|
},
|
|
{
|
|
id: '1',
|
|
text: 'One'
|
|
},
|
|
{
|
|
id: '2',
|
|
text: '2'
|
|
},
|
|
new UserDefinedType(1, 'aaaaaa')
|
|
]
|
|
});
|
|
|
|
var extraOptions = new Options ({
|
|
data: [
|
|
{
|
|
id: 'default',
|
|
text: 'Default',
|
|
extra: true
|
|
},
|
|
{
|
|
id: 'One',
|
|
text: 'One',
|
|
extra: true
|
|
}
|
|
]
|
|
});
|
|
|
|
var nestedOptions = new Options({
|
|
data: [
|
|
{
|
|
text: 'Default',
|
|
children: [
|
|
{
|
|
text: 'Next',
|
|
children: [
|
|
{
|
|
id: 'a',
|
|
text: 'Option'
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
]
|
|
});
|
|
|
|
test('current gets default for single', function (assert) {
|
|
var $select = $('#qunit-fixture .single-empty');
|
|
|
|
var data = new ArrayData($select, arrayOptions);
|
|
|
|
var container = new MockContainer();
|
|
data.bind(container, $('<div></div>'));
|
|
|
|
data.current(function (val) {
|
|
assert.equal(
|
|
val.length,
|
|
1,
|
|
'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'
|
|
);
|
|
});
|
|
});
|
|
|
|
test('current gets default for multiple', function (assert) {
|
|
var $select = $('#qunit-fixture .multiple');
|
|
|
|
var data = new ArrayData($select, arrayOptions);
|
|
|
|
var container = new MockContainer();
|
|
data.bind(container, $('<div></div>'));
|
|
|
|
data.current(function (val) {
|
|
assert.equal(
|
|
val.length,
|
|
0,
|
|
'There should be no default selection.'
|
|
);
|
|
});
|
|
});
|
|
|
|
test('current works with existing selections', function (assert) {
|
|
var $select = $('#qunit-fixture .multiple');
|
|
|
|
var data = new ArrayData($select, arrayOptions);
|
|
|
|
var container = new MockContainer();
|
|
data.bind(container, $('<div></div>'));
|
|
|
|
$select.val(['One']);
|
|
|
|
data.current(function (val) {
|
|
assert.equal(
|
|
val.length,
|
|
1,
|
|
'There should only be one existing selection.'
|
|
);
|
|
|
|
var option = val[0];
|
|
|
|
assert.equal(
|
|
option.id,
|
|
'One',
|
|
'The id should be equal to the value of the option tag.'
|
|
);
|
|
|
|
assert.equal(
|
|
option.text,
|
|
'One',
|
|
'The text should be equal to the text of the option tag.'
|
|
);
|
|
});
|
|
});
|
|
|
|
test('current works with selected data', function (assert) {
|
|
var $select = $('#qunit-fixture .single-empty');
|
|
|
|
var data = new ArrayData($select, arrayOptions);
|
|
|
|
var container = new MockContainer();
|
|
data.bind(container, $('<div></div>'));
|
|
|
|
data.select({
|
|
id: '2',
|
|
text: '2'
|
|
});
|
|
|
|
data.current(function (val) {
|
|
assert.equal(
|
|
val.length,
|
|
1,
|
|
'There should only be one option selected.'
|
|
);
|
|
|
|
var option = val[0];
|
|
|
|
assert.equal(
|
|
option.id,
|
|
'2',
|
|
'The id should match the original id from the array.'
|
|
);
|
|
|
|
assert.equal(
|
|
option.text,
|
|
'2',
|
|
'The text should match the original text from the array.'
|
|
);
|
|
});
|
|
});
|
|
|
|
test('select works for single', function (assert) {
|
|
var $select = $('#qunit-fixture .single-empty');
|
|
|
|
var data = new ArrayData($select, arrayOptions);
|
|
|
|
var container = new MockContainer();
|
|
data.bind(container, $('<div></div>'));
|
|
|
|
assert.equal(
|
|
$select.val(),
|
|
'default',
|
|
'There should already be a selection'
|
|
);
|
|
|
|
data.select({
|
|
id: '1',
|
|
text: 'One'
|
|
});
|
|
|
|
assert.equal(
|
|
$select.val(),
|
|
'1',
|
|
'The selected value should be the same as the selected id'
|
|
);
|
|
});
|
|
|
|
test('multiple sets the value', function (assert) {
|
|
var $select = $('#qunit-fixture .multiple');
|
|
|
|
var data = new ArrayData($select, arrayOptions);
|
|
|
|
var container = new MockContainer();
|
|
data.bind(container, $('<div></div>'));
|
|
|
|
assert.ok(
|
|
$select.val() == null || $select.val().length == 0,
|
|
'nothing should be selected'
|
|
);
|
|
|
|
data.select({
|
|
id: 'default',
|
|
text: 'Default'
|
|
});
|
|
|
|
assert.deepEqual($select.val(), ['default']);
|
|
});
|
|
|
|
test('multiple adds to the old value', function (assert) {
|
|
var $select = $('#qunit-fixture .multiple');
|
|
|
|
var data = new ArrayData($select, arrayOptions);
|
|
|
|
var container = new MockContainer();
|
|
data.bind(container, $('<div></div>'));
|
|
|
|
$select.val(['One']);
|
|
|
|
assert.deepEqual($select.val(), ['One']);
|
|
|
|
data.select({
|
|
id: 'default',
|
|
text: 'Default'
|
|
});
|
|
|
|
assert.deepEqual($select.val(), ['One', 'default']);
|
|
});
|
|
|
|
test('option tags are automatically generated', function (assert) {
|
|
var $select = $('#qunit-fixture .single-empty');
|
|
|
|
var data = new ArrayData($select, arrayOptions);
|
|
|
|
var container = new MockContainer();
|
|
data.bind(container, $('<div></div>'));
|
|
|
|
assert.equal(
|
|
$select.find('option').length,
|
|
4,
|
|
'An <option> element should be created for each object'
|
|
);
|
|
});
|
|
|
|
test('automatically generated option tags have a result id', function (assert) {
|
|
var $select = $('#qunit-fixture .single-empty');
|
|
|
|
var data = new ArrayData($select, arrayOptions);
|
|
|
|
var container = new MockContainer();
|
|
data.bind(container, $('<div></div>'));
|
|
|
|
data.select({
|
|
id: 'default'
|
|
});
|
|
|
|
assert.ok(
|
|
Utils.GetData($select.find(':selected')[0], 'data')._resultId,
|
|
'<option> default should have a result ID assigned'
|
|
);
|
|
});
|
|
|
|
test('option tags can receive new data', function(assert) {
|
|
var $select = $('#qunit-fixture .single');
|
|
|
|
var data = new ArrayData($select, extraOptions);
|
|
|
|
var container = new MockContainer();
|
|
data.bind(container, $('<div></div>'));
|
|
|
|
assert.equal(
|
|
$select.find('option').length,
|
|
2,
|
|
'Only one more <option> element should be created'
|
|
);
|
|
|
|
data.select({
|
|
id: 'default'
|
|
});
|
|
|
|
assert.ok(
|
|
Utils.GetData($select.find(':selected')[0], 'data').extra,
|
|
'<option> default should have new data'
|
|
);
|
|
|
|
data.select({
|
|
id: 'One'
|
|
});
|
|
|
|
assert.ok(
|
|
Utils.GetData($select.find(':selected')[0], 'data').extra,
|
|
'<option> One should have new data'
|
|
);
|
|
});
|
|
|
|
test('optgroup tags can also be generated', function (assert) {
|
|
var $select = $('#qunit-fixture .single-empty');
|
|
|
|
var data = new ArrayData($select, nestedOptions);
|
|
|
|
var container = new MockContainer();
|
|
data.bind(container, $('<div></div>'));
|
|
|
|
assert.equal(
|
|
$select.find('option').length,
|
|
1,
|
|
'An <option> element should be created for the one selectable object'
|
|
);
|
|
|
|
assert.equal(
|
|
$select.find('optgroup').length,
|
|
2,
|
|
'An <optgroup> element should be created for the two with children'
|
|
);
|
|
});
|
|
|
|
test('optgroup tags have the right properties', function (assert) {
|
|
var $select = $('#qunit-fixture .single-empty');
|
|
|
|
var data = new ArrayData($select, nestedOptions);
|
|
|
|
var container = new MockContainer();
|
|
data.bind(container, $('<div></div>'));
|
|
|
|
var $group = $select.children('optgroup');
|
|
|
|
assert.equal(
|
|
$group.prop('label'),
|
|
'Default',
|
|
'An `<optgroup>` label should match the text property'
|
|
);
|
|
|
|
assert.equal(
|
|
$group.children().length,
|
|
1,
|
|
'The <optgroup> should have one child under it'
|
|
);
|
|
});
|
|
|
|
test('existing selections are respected on initialization', function (assert) {
|
|
var $select = $(
|
|
'<select>' +
|
|
'<option>First</option>' +
|
|
'<option selected>Second</option>' +
|
|
'</select>'
|
|
);
|
|
|
|
var options = new Options({
|
|
data: [
|
|
{
|
|
id: 'Second',
|
|
text: 'Second'
|
|
},
|
|
{
|
|
id: 'Third',
|
|
text: 'Third'
|
|
}
|
|
]
|
|
});
|
|
|
|
assert.equal($select.val(), 'Second');
|
|
|
|
var data = new ArrayData($select, options);
|
|
|
|
var container = new MockContainer();
|
|
data.bind(container, $('<div></div>'));
|
|
|
|
assert.equal($select.val(), 'Second');
|
|
}); |