Skip to content

Commit

Permalink
[FEATURE] Disable search in multiple selects
Browse files Browse the repository at this point in the history
Now the search on multiple selects can be disabled. The trigger component only handles events
on it's content.
  • Loading branch information
cibernox committed Feb 11, 2016
1 parent 14d342b commit 4448213
Show file tree
Hide file tree
Showing 11 changed files with 113 additions and 35 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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
Expand Down
23 changes: 22 additions & 1 deletion addon/components/power-select-multiple.js
Original file line number Diff line number Diff line change
@@ -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;

Expand Down Expand Up @@ -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(); }
}
});
13 changes: 2 additions & 11 deletions addon/components/power-select-multiple/trigger.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -74,8 +67,6 @@ export default Ember.Component.extend({
select.actions.search(get(lastSelection, searchField));
}
}
} else {
select.actions.handleKeydown(e);
}
}
},
Expand Down
3 changes: 2 additions & 1 deletion addon/components/power-select.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
4 changes: 2 additions & 2 deletions addon/templates/components/power-select-multiple.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
options=options
selected=selected
onchange=onchange
onkeydown=onkeydown
onkeydown=(action "handleKeydown")
onfocus=(action "handleFocus")
onopen=(action "handleOpen")
onclose=onclose
Expand Down Expand Up @@ -44,7 +44,7 @@
options=options
selected=selected
onchange=onchange
onkeydown=onkeydown
onkeydown=(action "handleKeydown")
onfocus=(action "handleFocus")
onopen=(action "handleOpen")
onclose=onclose
Expand Down
18 changes: 10 additions & 8 deletions addon/templates/components/power-select-multiple/trigger.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@
</li>
{{/each}}
</ul>
<input type="search" class="ember-power-select-trigger-multiple-input {{elementId}}-input"
tabindex="0" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"
aria-controls={{listboxId}}
style={{triggerMultipleInputStyle}}
placeholder={{maybePlaceholder}}
disabled={{disabled}}
oninput={{action "search" value="target.value"}}
onkeydown={{action "handleKeydown"}}>
{{#if searchEnabled}}
<input type="search" class="ember-power-select-trigger-multiple-input {{elementId}}-input"
tabindex="0" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"
aria-controls={{listboxId}}
style={{triggerMultipleInputStyle}}
placeholder={{maybePlaceholder}}
disabled={{disabled}}
oninput={{action "search" value="target.value"}}
onkeydown={{action "handleKeydown"}}>
{{/if}}
<span class="ember-power-select-status-icon"></span>
8 changes: 6 additions & 2 deletions addon/templates/components/power-select.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -81,7 +85,6 @@
{{#component triggerComponent
options=(readonly results)
selected=(readonly selected)
highlighted=(readonly highlighted)
searchText=(readonly searchText)
lastSearchedText=(readonly lastSearchedText)
placeholder=(readonly placeholder)
Expand All @@ -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}}
Expand Down
14 changes: 7 additions & 7 deletions tests/dummy/app/templates/legacy-demo.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,6 @@
<input type="text" value="sample input">
<h2 id="title">Welcome to the demo of ember-power-select (provisional name)</h2>

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

<p><strong>Trying to reproduce bug with store.findAll('user')</strong></p>

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

<h4>Select multiple [WORK IN PROGRESS]</h4>
<h4>Select multiple with async search</h4>
{{#power-select-multiple options=(readonly simpleOptions) selected=emptyMultipleSelection onchange=(action (mut multipleSelection)) search=(action 'asyncSearch') as |option|}}
{{option}}
{{/power-select-multiple}}

<h4>Select multiple [WORK IN PROGRESS]</h4>
<h4>Select multiple</h4>
{{#power-select-multiple options=(readonly simpleOptions) selected=multipleSelection onchange=(action (mut multipleSelection)) as |option|}}
{{option}}
{{/power-select-multiple}}
Expand Down Expand Up @@ -154,6 +150,11 @@
{{option}}
{{/power-select}}

<h4>The search box can be disabled passing `searchEnabled=false` on multiple selects too</h4>
{{#power-select-multiple searchEnabled=false options=complexOptions selected=choosenCountry onchange=(action (mut choosenCountry)) searchField='name' as |country|}}
{{country.name}}
{{/power-select-multiple}}

<h4>Right to left styles</h4>
{{#power-select options=(readonly complexOptions) dir="rtl" selected=(readonly complexSelected) allowClear=true onchange=(action (mut complexSelected)) as |option|}}
{{option.code}}: {{option.name}}
Expand All @@ -177,7 +178,6 @@
{{opt}}
{{/power-select}}
</div>

<br>
<br>
<br>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
61 changes: 60 additions & 1 deletion tests/integration/components/power-select/multiple-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand All @@ -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);

Expand Down Expand Up @@ -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');
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -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');
Expand Down

0 comments on commit 4448213

Please sign in to comment.