diff --git a/src/Select.js b/src/Select.js index 29c7ab1241..811a81d500 100644 --- a/src/Select.js +++ b/src/Select.js @@ -186,6 +186,7 @@ const Select = React.createClass({ componentWillUpdate (nextProps, nextState) { if (nextState.isOpen !== this.state.isOpen) { + this.toggleTouchOutsideEvent(nextState.isOpen); const handler = nextState.isOpen ? nextProps.onOpen : nextProps.onClose; handler && handler(); } @@ -224,6 +225,25 @@ const Select = React.createClass({ } }, + componentWillUnmount() { + document.removeEventListener('touchstart', this.handleTouchOutside); + }, + + toggleTouchOutsideEvent(enabled) { + if (enabled) { + document.addEventListener('touchstart', this.handleTouchOutside); + } else { + document.removeEventListener('touchstart', this.handleTouchOutside); + } + }, + + handleTouchOutside(event) { + // handle touch outside on ios to dismiss menu + if (this.wrapper && !this.wrapper.contains(event.target)) { + this.closeMenu(); + } + }, + focus () { if (!this.input) return; this.input.focus(); diff --git a/test/Select-test.js b/test/Select-test.js index 6601b65912..57338ad7ab 100644 --- a/test/Select-test.js +++ b/test/Select-test.js @@ -3324,24 +3324,29 @@ describe('Select', () => { }); }); - describe('clicking outside', () => { + describe('outside event', () => { beforeEach(() => { - instance = createControl({ options: defaultOptions }); - }); - - it('closes the menu', () => { - TestUtils.Simulate.mouseDown(getSelectControl(instance), { button: 0 }); expect(ReactDOM.findDOMNode(instance), 'queried for', '.Select-option', 'to have length', 4); + }); + it('click closes the menu', () => { TestUtils.Simulate.blur(searchInputNode); expect(ReactDOM.findDOMNode(instance), 'to contain no elements matching', '.Select-option'); }); + + it('touch closes the menu', () => { + const evt = document.createEvent('Event'); + evt.initEvent('touchstart', true, true); + document.querySelector('body').dispatchEvent(evt); + expect(ReactDOM.findDOMNode(instance), 'to contain no elements matching', '.Select-option'); + }); + }); describe('with autosize=false', () => {