diff --git a/CHANGELOG.md b/CHANGELOG.md index a94c4ce14..6880322d5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ # Master +- [FEATURE] Search can be disabled in multiple selects, instead of only in single selects. - [BUGFIX] Pressing enter in a select without searchbox correctly selects the highlighted element # 0.9.0-beta.1 diff --git a/addon/components/power-select-multiple.js b/addon/components/power-select-multiple.js index 3fed22227..694c92094 100644 --- a/addon/components/power-select-multiple.js +++ b/addon/components/power-select-multiple.js @@ -1,6 +1,7 @@ import Ember from 'ember'; import layout from '../templates/components/power-select-multiple'; import fallbackIfUndefined from '../utils/computed-fallback-if-undefined'; +import { emberPowerSelectBuildSelection as buildNewSelection } from '../helpers/ember-power-select-build-selection'; const { computed } = Ember; @@ -32,11 +33,31 @@ export default Ember.Component.extend({ let action = this.get('onfocus'); if (action) { action(select, e); } this.focusInput(); + }, + + handleKeydown(select, e) { + let action = this.get('onkeydown'); + if (action) { action(select, e); } + if (e.defaultPrevented) { return; } + let selected = Ember.A((this.get('selected') || [])); + if (e.keyCode === 13 && select.isOpen) { + e.stopPropagation(); + if (select.highlighted !== undefined) { + if (selected.indexOf(select.highlighted) === -1) { + select.actions.choose(buildNewSelection([select.highlighted, selected], { multiple: true }), e); + } else { + select.actions.close(e); + } + } else { + select.actions.close(e); + } + } } }, // Methods focusInput() { - this.element.querySelector('.ember-power-select-trigger-multiple-input').focus(); + let input = this.element.querySelector('.ember-power-select-trigger-multiple-input'); + if (input) { input.focus(); } } }); diff --git a/addon/components/power-select-multiple/trigger.js b/addon/components/power-select-multiple/trigger.js index 51c427863..a348fbf79 100644 --- a/addon/components/power-select-multiple/trigger.js +++ b/addon/components/power-select-multiple/trigger.js @@ -50,19 +50,12 @@ export default Ember.Component.extend({ }, handleKeydown(e) { - let { highlighted, onkeydown, select } = this.getProperties('highlighted', 'onkeydown', 'select'); + let { onkeydown, select } = this.getProperties('onkeydown', 'select'); if (onkeydown) { onkeydown(select, e); } if (e.defaultPrevented) { return; } let selected = Ember.A((this.get('selected') || [])); - if (e.keyCode === 13 && select.isOpen && highlighted !== undefined) { - e.stopPropagation(); - if (selected.indexOf(highlighted) === -1) { - select.actions.choose(buildNewSelection([highlighted, selected], { multiple: true }), e); - } else { - select.actions.close(e); - } - } else if (e.keyCode === 8 && isBlank(e.target.value)) { + if (e.keyCode === 8 && isBlank(e.target.value)) { let lastSelection = get(selected, 'lastObject'); if (lastSelection) { select.actions.select(buildNewSelection([lastSelection, selected], { multiple: true }), e); @@ -74,8 +67,6 @@ export default Ember.Component.extend({ select.actions.search(get(lastSelection, searchField)); } } - } else { - select.actions.handleKeydown(e); } } }, diff --git a/addon/components/power-select.js b/addon/components/power-select.js index 9967a38c8..64a17916e 100644 --- a/addon/components/power-select.js +++ b/addon/components/power-select.js @@ -268,7 +268,8 @@ export default Ember.Component.extend({ const ownActions = { search: this._doSearch.bind(this, dropdown), highlight: this._doHighlight.bind(this, dropdown), - select: this._doSelect.bind(this, dropdown) + select: this._doSelect.bind(this, dropdown), + choose: (selected, e) => this.send('choose', dropdown, selected, e) }; return { isOpen: dropdown.isOpen, diff --git a/addon/templates/components/power-select-multiple.hbs b/addon/templates/components/power-select-multiple.hbs index 51addfe7c..f6c76b689 100644 --- a/addon/templates/components/power-select-multiple.hbs +++ b/addon/templates/components/power-select-multiple.hbs @@ -3,7 +3,7 @@ options=options selected=selected onchange=onchange - onkeydown=onkeydown + onkeydown=(action "handleKeydown") onfocus=(action "handleFocus") onopen=(action "handleOpen") onclose=onclose @@ -44,7 +44,7 @@ options=options selected=selected onchange=onchange - onkeydown=onkeydown + onkeydown=(action "handleKeydown") onfocus=(action "handleFocus") onopen=(action "handleOpen") onclose=onclose diff --git a/addon/templates/components/power-select-multiple/trigger.hbs b/addon/templates/components/power-select-multiple/trigger.hbs index 336fe08cc..f23b7ae7f 100644 --- a/addon/templates/components/power-select-multiple/trigger.hbs +++ b/addon/templates/components/power-select-multiple/trigger.hbs @@ -12,12 +12,14 @@ {{/each}} - +{{#if searchEnabled}} + +{{/if}} \ No newline at end of file diff --git a/addon/templates/components/power-select.hbs b/addon/templates/components/power-select.hbs index 74bc55f24..addb2bd43 100644 --- a/addon/templates/components/power-select.hbs +++ b/addon/templates/components/power-select.hbs @@ -63,11 +63,15 @@ {{yield option term}} {{/component}} {{/if}} - {{component afterOptionsComponent select=(readonly select) searchPlaceholder=(readonly searchPlaceholder) searchEnabled=(readonly searchEnabled)}} + {{component afterOptionsComponent + select=(readonly select) + searchPlaceholder=(readonly searchPlaceholder) + searchEnabled=(readonly searchEnabled)}} {{/with}} {{else}} {{#with (hash isOpen=registeredDropdown.isOpen + highlighted=(readonly highlighted) actions=(hash open=registeredDropdown.actions.open close=registeredDropdown.actions.close @@ -81,7 +85,6 @@ {{#component triggerComponent options=(readonly results) selected=(readonly selected) - highlighted=(readonly highlighted) searchText=(readonly searchText) lastSearchedText=(readonly lastSearchedText) placeholder=(readonly placeholder) @@ -92,6 +95,7 @@ onkeydown=(readonly onkeydown) listboxId=(readonly optionsId) selectedItemComponent=(readonly selectedItemComponent) + searchEnabled=(readonly searchEnabled) searchField=(readonly searchField) as |opt term|}} {{yield opt term}} {{/component}} diff --git a/tests/dummy/app/templates/legacy-demo.hbs b/tests/dummy/app/templates/legacy-demo.hbs index b439c896a..2a080b766 100644 --- a/tests/dummy/app/templates/legacy-demo.hbs +++ b/tests/dummy/app/templates/legacy-demo.hbs @@ -2,10 +2,6 @@

Welcome to the demo of ember-power-select (provisional name)

- {{#power-select-multiple options=complexOptions selected=choosenCountry onchange=(action (mut choosenCountry)) searchField='name' as |country|}} - {{country.name}} - {{/power-select-multiple}} -

Trying to reproduce bug with store.findAll('user')

{{#power-select options=model selected=selectedUser onchange=(action (mut selectedUser)) as |user|}} @@ -56,12 +52,12 @@ {{option.code}}: {{option.name}} {{/power-select}} -

Select multiple [WORK IN PROGRESS]

+

Select multiple with async search

{{#power-select-multiple options=(readonly simpleOptions) selected=emptyMultipleSelection onchange=(action (mut multipleSelection)) search=(action 'asyncSearch') as |option|}} {{option}} {{/power-select-multiple}} -

Select multiple [WORK IN PROGRESS]

+

Select multiple

{{#power-select-multiple options=(readonly simpleOptions) selected=multipleSelection onchange=(action (mut multipleSelection)) as |option|}} {{option}} {{/power-select-multiple}} @@ -154,6 +150,11 @@ {{option}} {{/power-select}} +

The search box can be disabled passing `searchEnabled=false` on multiple selects too

+ {{#power-select-multiple searchEnabled=false options=complexOptions selected=choosenCountry onchange=(action (mut choosenCountry)) searchField='name' as |country|}} + {{country.name}} + {{/power-select-multiple}} +

Right to left styles

{{#power-select options=(readonly complexOptions) dir="rtl" selected=(readonly complexSelected) allowClear=true onchange=(action (mut complexSelected)) as |option|}} {{option.code}}: {{option.name}} @@ -177,7 +178,6 @@ {{opt}} {{/power-select}} -


diff --git a/tests/integration/components/power-select/general-behaviour-test.js b/tests/integration/components/power-select/general-behaviour-test.js index 56c84cb92..a6cd81b7c 100644 --- a/tests/integration/components/power-select/general-behaviour-test.js +++ b/tests/integration/components/power-select/general-behaviour-test.js @@ -262,7 +262,6 @@ test('If the user passes `closeOnSelect=false` the dropdown remains visible afte assert.equal($('.ember-power-select-dropdown').length, 1, 'Dropdown is rendered'); }); - test('If the content of the options is refreshed (starting with empty array proxy) the available options should also refresh', function(assert) { let done = assert.async(); assert.expect(2); diff --git a/tests/integration/components/power-select/multiple-test.js b/tests/integration/components/power-select/multiple-test.js index 0e6e2fb49..a42389198 100644 --- a/tests/integration/components/power-select/multiple-test.js +++ b/tests/integration/components/power-select/multiple-test.js @@ -270,6 +270,23 @@ test('Pressing ENTER when the select is closed opens and nothing is written on t assert.equal($('.ember-power-select-dropdown').length, 1, 'Dropdown is rendered'); }); +test('Pressing ENTER on a multiple select with `searchEnabled=false` when it is closed opens it', function(assert) { + assert.expect(2); + + this.numbers = numbers; + this.render(hbs` + {{#power-select-multiple searchEnabled=false options=numbers selected=foo onchange=(action (mut foo)) as |option|}} + {{option}} + {{/power-select-multiple}} + `); + + let trigger = this.$('.ember-power-select-trigger')[0]; + trigger.focus(); + assert.equal($('.ember-power-select-dropdown').length, 0, 'Dropdown is not rendered'); + triggerKeydown(trigger, 13); + assert.equal($('.ember-power-select-dropdown').length, 1, 'Dropdown is rendered'); +}); + test('Pressing ENTER over a highlighted element selects it', function(assert) { assert.expect(2); @@ -290,6 +307,48 @@ test('Pressing ENTER over a highlighted element selects it', function(assert) { assert.ok(/two/.test($('.ember-power-select-trigger').text().trim()), 'The element was selected'); }); +test('Pressing ENTER over a highlighted element on a multiple select with `searchEnabled=false` selects it', function(assert) { + assert.expect(2); + + this.numbers = numbers; + this.render(hbs` + {{#power-select-multiple searchEnabled=false options=numbers selected=foo onchange=(action (mut foo)) as |option|}} + {{option}} + {{/power-select-multiple}} + `); + + clickTrigger(); + assert.equal($('.ember-power-select-dropdown').length, 1, 'Dropdown is rendered'); + let trigger = this.$('.ember-power-select-trigger')[0]; + triggerKeydown(trigger, 40); + triggerKeydown(trigger, 13); + assert.ok(/two/.test($('.ember-power-select-trigger').text().trim()), 'The element was selected'); +}); + + +test('Pressing ENTER over a highlighted element on a select with `searchEnabled=false` selects it', function(assert) { + assert.expect(4); + + this.numbers = numbers; + this.change = (selected) => { + assert.deepEqual(selected, ['two']); + this.set('foo', selected); + }; + this.render(hbs` + {{#power-select-multiple searchEnabled=false options=numbers selected=foo onchange=change as |option|}} + {{option}} + {{/power-select-multiple}} + `); + + clickTrigger(); + assert.equal(this.$('.ember-power-select-multiple-option').length, 0, 'There is no elements selected'); + let trigger = this.$('.ember-power-select-trigger')[0]; + triggerKeydown(trigger, 40); + triggerKeydown(trigger, 13); + assert.equal(this.$('.ember-power-select-multiple-option').length, 1, 'There is one element selected'); + assert.ok(/two/.test($('.ember-power-select-trigger').text().trim()), 'The element is "two"'); +}); + test('Pressing ENTER over a highlighted element what is already selected closes the select without doing anything and focuses the trigger', function(assert) { assert.expect(3); @@ -601,4 +660,4 @@ test('The trigger of multiple selects have a special class to distinguish them f assert.ok(this.$('.ember-power-select-trigger').hasClass('ember-power-select-multiple-trigger'), 'The trigger has the default class'); assert.ok(this.$('.ember-power-select-trigger').hasClass('foobar-trigger'), 'The trigger has the given class'); -}); \ No newline at end of file +}); diff --git a/tests/integration/components/power-select/public-actions-test.js b/tests/integration/components/power-select/public-actions-test.js index d64fc8b9b..ae6c28d4d 100644 --- a/tests/integration/components/power-select/public-actions-test.js +++ b/tests/integration/components/power-select/public-actions-test.js @@ -115,7 +115,7 @@ test('The onkeydown of multiple selects action receives the public API and the k this.numbers = numbers; this.onKeyDown = (select, e) => { assert.equal(typeof select.isOpen, 'boolean', 'select.isOpen is a boolean'); - assert.equal(typeof select.highlighted, 'undefined', 'select.highlighted is still undefined'); + assert.equal(typeof select.highlighted, 'string', 'select.highlighted is a string'); assert.equal(typeof select.actions.open, 'function', 'select.actions.open is a function'); assert.equal(typeof select.actions.close, 'function', 'select.actions.close is a function'); assert.equal(typeof select.actions.search, 'function', 'select.actions.search is a function');