diff --git a/src/components/Select.vue b/src/components/Select.vue index 28cd342..211e0fb 100644 --- a/src/components/Select.vue +++ b/src/components/Select.vue @@ -17,7 +17,7 @@ {{ getOptionLabel(option) }} - @@ -36,6 +36,7 @@ type="button" class="vs__clear" title="Clear selection" + ref="clearButton" > @@ -652,33 +653,23 @@ * @param {Event} e * @return {void} */ - toggleDropdown (e) { - const target = e.target; - const toggleTargets = [ - this.$el, - this.searchEl, - this.$refs.toggle, - this.$refs.actions, - this.$refs.selectedOptions, + toggleDropdown ({target}) { + // don't react to click on deselect/clear buttons, + // they dropdown state will be set in their click handlers + const ignoredButtons = [ + ...(this.$refs['deselectButtons'] || []), + ...([this.$refs['clearButton']] || []) ]; - if (typeof this.$refs.openIndicator !== 'undefined') { - toggleTargets.push( - this.$refs.openIndicator.$el, - // the line below is a bit gross, but required to support IE11 without adding polyfills - ...Array.prototype.slice.call(this.$refs.openIndicator.$el.childNodes), - ); + if (ignoredButtons.some(ref => ref.contains(target) || ref === target)) { + return; } - if (toggleTargets.indexOf(target) > -1 || target.classList.contains('vs__selected')) { - if (this.open) { - this.searchEl.blur(); // dropdown will close on blur - } else { - if (!this.disabled) { - this.open = true; - this.searchEl.focus(); - } - } + if (this.open) { + this.searchEl.blur(); + } else if (!this.disabled) { + this.open = true; + this.searchEl.focus(); } }, diff --git a/tests/unit/Slots.spec.js b/tests/unit/Slots.spec.js index c4201bc..16d242e 100644 --- a/tests/unit/Slots.spec.js +++ b/tests/unit/Slots.spec.js @@ -10,32 +10,49 @@ describe('Scoped Slots', () => { }, }); - expect(Select.find({ ref: 'selectedOptions' }).text()).toEqual('one') + expect(Select.find({ref: 'selectedOptions'}).text()).toEqual('one'); }); - it('receives an option object to the selected-option slot', () => { - const Select = mountDefault( - {value: 'one'}, - { - scopedSlots: { - 'selected-option': `{{ option.label }}`, - }, + describe('Slot: selected-option', () => { + it('receives an option object to the selected-option slot', () => { + const Select = mountDefault( + {value: 'one'}, + { + scopedSlots: { + 'selected-option': `{{ option.label }}`, + }, + }); + + expect(Select.find('.vs__selected').text()).toEqual('one'); + }); + + it('opens the dropdown when clicking an option in selected-option slot', + () => { + const Select = mountDefault( + {value: 'one'}, + { + scopedSlots: { + 'selected-option': `{{ option.label }}`, + }, + }); + + Select.find('.my-option').trigger('mousedown'); + expect(Select.vm.open).toEqual(true); }); - - expect(Select.find('.vs__selected').text()).toEqual('one') }); - it('receives an option object to the option slot in the dropdown menu', () => { - const Select = mountDefault( - {value: 'one'}, - { - scopedSlots: { - 'option': `{{ option.label }}`, - }, - }); + it('receives an option object to the option slot in the dropdown menu', + () => { + const Select = mountDefault( + {value: 'one'}, + { + scopedSlots: { + 'option': `{{ option.label }}`, + }, + }); - Select.vm.open = true; + Select.vm.open = true; - expect(Select.find({ref: 'dropdownMenu'}).text()).toEqual('onetwothree') - }); + expect(Select.find({ref: 'dropdownMenu'}).text()).toEqual('onetwothree'); + }); });