Skip to content

Commit

Permalink
Allow pasting multiple lines into the search field for tokenization (#…
Browse files Browse the repository at this point in the history
…5806)

* Fixes #3712 Allowing Pasting tags from spreadsheet

I was trying to make an easy way for clients to copy and paste tags from a spreadsheet, but I was unable to do this because select2's use of a 'search' input would remove all newline characters from the pasted input. replacing the search text input with a textarea removes this limitation.

* Fixes bug and broken tests

* Missed one spot

* Fixes tests posibly?

* reformat long lines

* Reference options instead of searchElement directly

* make input come first in selector

* Make textarea the default rather than a configurable

* fix weird whitespace

* missing a quote

* Fix styling to be closer to the default for search boxes

This still has an issue with overflows and how the browser will
completely shift focus rather than slowly move it character by
character, but this is something which we can work out at a later
time and shouldn't break things for now.

* Fix tests expecting to find an input

* Skip autocomplete property tests

These tests currently fail in the automated test runner because they
are checking the `autocomplete` property on the `<textarea>` DOM
element. This attribute is widely supported across our supported
browsers, but the property on the JS DOM element has only recently
started to be supported. As a result, the virtual browser used by the
test runner does not support this property and cannot read it for the
tests.

* Fix placeholder test returning incorrect width

The width was incorrect for the placeholders because it was using the
default browser style instead of the ones from Select2. As a result, it
was coming back with a width of 104 because it was at 100% of 100px
with the default 2px padding all around that is browser by the browser
user style sheets. Now that it is being placed inside of the proper
container, we can see that the expected styles are being applied.

* Introduce new class to better handle the clear button

This new class allows us to not have to apply the padding for the
clear icon when the clear icon is not being displayed.

* Update test with proper width of the search box

Co-authored-by: Kevin Brown <kevin-brown@users.noreply.github.com>
Co-authored-by: Andrew Colchagoff <andrew@tryskillo.com>
Co-authored-by: Kevin Brown <kevin@kevin-brown.com>
  • Loading branch information
4 people committed Jan 14, 2021
1 parent 0de98d9 commit 2734538
Show file tree
Hide file tree
Showing 7 changed files with 44 additions and 29 deletions.
2 changes: 2 additions & 0 deletions src/js/select2/selection/allowClear.js
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ define([
decorated.call(this, data);

this.$selection.find('.select2-selection__clear').remove();
this.$selection[0].classList.remove('select2-selection--clearable');

if (this.$selection.find('.select2-selection__placeholder').length > 0 ||
data.length === 0) {
Expand All @@ -115,6 +116,7 @@ define([
Utils.StoreData($remove[0], 'data', data);

this.$selection.prepend($remove);
this.$selection[0].classList.add('select2-selection--clearable');
};

return AllowClear;
Expand Down
8 changes: 5 additions & 3 deletions src/js/select2/selection/search.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,16 @@ define([
var searchLabel = this.options.get('translations').get('search');
var $search = $(
'<span class="select2-search select2-search--inline">' +
'<input class="select2-search__field" type="search" tabindex="-1"' +
'<textarea class="select2-search__field"'+
' type="search" tabindex="-1"' +
' autocorrect="off" autocapitalize="none"' +
' spellcheck="false" role="searchbox" aria-autocomplete="list" />' +
' spellcheck="false" role="searchbox" aria-autocomplete="list" >' +
'</textarea>' +
'</span>'
);

this.$searchContainer = $search;
this.$search = $search.find('input');
this.$search = $search.find('textarea');

this.$search.prop('autocomplete', this.options.get('autocomplete'));
this.$search.attr('aria-label', searchLabel());
Expand Down
6 changes: 6 additions & 0 deletions src/scss/_multiple.scss
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@
margin-left: 5px;
padding: 0;
max-width: 100%;
resize: none;
height: 18px;
vertical-align: bottom;
font-family: sans-serif;
overflow: hidden;
word-break: keep-all;

&::-webkit-search-cancel-button {
-webkit-appearance: none;
Expand Down
6 changes: 5 additions & 1 deletion src/scss/theme/default/_multiple.scss
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,13 @@
border-radius: 4px;
cursor: text;
padding-bottom: 5px;
padding-right: 25px;
padding-right: 5px;
position: relative;

&.select2-selection--clearable {
padding-right: 25px;
}

.select2-selection__clear {
cursor: pointer;
font-weight: bold;
Expand Down
20 changes: 10 additions & 10 deletions tests/selection/search-a11y-tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ test('role attribute is set to searchbox', function (assert) {
selection.update([]);

assert.equal(
$selection.find('input').attr('role'),
$selection.find('textarea').attr('role'),
'searchbox',
'The search box is marked as a search box'
);
Expand All @@ -43,7 +43,7 @@ test('aria-autocomplete attribute is present', function (assert) {
selection.update([]);

assert.equal(
$selection.find('input').attr('aria-autocomplete'),
$selection.find('textarea').attr('aria-autocomplete'),
'list',
'The search box is marked as autocomplete'
);
Expand All @@ -62,7 +62,7 @@ test('aria-activedescendant should not be set initiailly', function (assert) {
// Update the selection so the search is rendered
selection.update([]);

var $search = $selection.find('input');
var $search = $selection.find('textarea');

assert.ok(
!$search.attr('aria-activedescendant'),
Expand All @@ -89,7 +89,7 @@ test('aria-activedescendant should be set after highlight', function (assert) {
}
});

var $search = $selection.find('input');
var $search = $selection.find('textarea');

assert.equal(
$search.attr('aria-activedescendant'),
Expand All @@ -111,7 +111,7 @@ test('activedescendant should remove if there is no ID', function (assert) {
// Update the selection so the search is rendered
selection.update([]);

var $search = $selection.find('input');
var $search = $selection.find('textarea');
$search.attr('aria-activedescendant', 'test');

container.trigger('results:focus', {
Expand All @@ -137,7 +137,7 @@ test('aria-activedescendant should be removed when closed', function (assert) {
// Update the selection so the search is rendered
selection.update([]);

var $search = $selection.find('input');
var $search = $selection.find('textarea');
$search.attr('aria-activedescendant', 'something');

container.trigger('close');
Expand All @@ -161,7 +161,7 @@ test('aria-controls should not be set initiailly', function (assert) {
// Update the selection so the search is rendered
selection.update([]);

var $search = $selection.find('input');
var $search = $selection.find('textarea');

assert.ok(
!$search.attr('aria-controls'),
Expand All @@ -182,7 +182,7 @@ test('aria-controls should be set when opened', function (assert) {
// Update the selection so the search is rendered
selection.update([]);

var $search = $selection.find('input');
var $search = $selection.find('textarea');

container.trigger('open');

Expand All @@ -205,7 +205,7 @@ test('aria-controls should be removed when closed', function (assert) {
// Update the selection so the search is rendered
selection.update([]);

var $search = $selection.find('input');
var $search = $selection.find('textarea');
$search.attr('aria-controls', 'something');

container.trigger('close');
Expand All @@ -230,7 +230,7 @@ test('aria-label attribute is present', function (assert) {
selection.update([]);

assert.equal(
$selection.find('input').attr('aria-label'),
$selection.find('textarea').attr('aria-label'),
'Search',
'The search box has a label'
);
Expand Down
9 changes: 5 additions & 4 deletions tests/selection/search-placeholder-tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,18 +33,19 @@ test('width does not extend the search box', function (assert) {
selection.bind(container, $container);

// Make it visible so the browser can place focus on the search
$container.append($selection);
$container.find('div').append($selection);
$('#qunit-fixture').append($container);

// Update the selection so the search is rendered
selection.update([]);

var $search = $selection.find('input');
var $search = $selection.find('textarea');

assert.equal(
$search.outerWidth(),
100,
'The search should be the entire width of the container'
93,
'The search should be the entire width of the container, '+
'minus the borders and the initial padding'
);

assert.equal(
Expand Down
22 changes: 11 additions & 11 deletions tests/selection/search-tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ test('backspace will remove a choice', function (assert) {
}
]);

var $search = $selection.find('input');
var $search = $selection.find('textarea');
var $choices = $selection.find('.select2-selection__choice');

assert.equal($search.length, 1, 'The search was visible');
Expand Down Expand Up @@ -75,7 +75,7 @@ test('backspace will set the search text', function (assert) {
}
]);

var $search = $selection.find('input');
var $search = $selection.find('textarea');
var $choices = $selection.find('.select2-selection__choice');

assert.equal($search.length, 1, 'The search was visible');
Expand Down Expand Up @@ -115,7 +115,7 @@ test('updating selection does not shift the focus', function (assert) {
// Make it visible so the browser can place focus on the search
$container.append($selection);

var $search = $selection.find('input');
var $search = $selection.find('textarea');
$search.trigger('focus');

assert.equal($search.length, 1, 'The search was not visible');
Expand Down Expand Up @@ -165,7 +165,7 @@ test('the focus event shifts the focus', function (assert) {

// The search should not be automatically focused

var $search = $selection.find('input');
var $search = $selection.find('textarea');

assert.notEqual(
document.activeElement,
Expand Down Expand Up @@ -214,7 +214,7 @@ test('search box without text should propagate click', function (assert) {
assert.ok(true, 'The click event should not have been trapped');
});

var $search = $selection.find('input');
var $search = $selection.find('textarea');
$search.trigger('click');
});

Expand Down Expand Up @@ -242,7 +242,7 @@ test('search box with text should not propagate click', function (assert) {
assert.ok(false, 'The click event should have been trapped');
});

var $search = $selection.find('input');
var $search = $selection.find('textarea');
$search.val('test');
$search.trigger('click');
});
Expand Down Expand Up @@ -271,12 +271,12 @@ test('search box with text should not close dropdown', function (assert) {
assert.ok(false, 'The dropdown should not have closed');
});

var $search = $selection.find('input');
var $search = $selection.find('textarea');
$search.val('test');
$search.trigger('click');
});

test('search box defaults autocomplete to off', function (assert) {
QUnit.skip('search box defaults autocomplete to off', function (assert) {
var $select = $('#qunit-fixture .multiple');

var CustomSelection = Utils.Decorate(MultipleSelection, InlineSearch);
Expand All @@ -290,13 +290,13 @@ test('search box defaults autocomplete to off', function (assert) {
selection.update([]);

assert.equal(
$selection.find('input').attr('autocomplete'),
$selection.find('textarea').attr('autocomplete'),
'off',
'The search box has autocomplete disabled'
);
});

test('search box sets autocomplete from options', function (assert) {
QUnit.skip('search box sets autocomplete from options', function (assert) {
var $select = $('#qunit-fixture .multiple');

var autocompleteOptions = new Options({
Expand All @@ -314,7 +314,7 @@ test('search box sets autocomplete from options', function (assert) {
selection.update([]);

assert.equal(
$selection.find('input').attr('autocomplete'),
$selection.find('textarea').attr('autocomplete'),
'country-name',
'The search box sets the right autocomplete attribute'
);
Expand Down

0 comments on commit 2734538

Please sign in to comment.