From 4241f6c04031a5e432f974e75d7331cc6d3b3a37 Mon Sep 17 00:00:00 2001 From: Martin Jujou Date: Sat, 3 Sep 2016 17:23:36 +1000 Subject: [PATCH 1/3] Handle touch outside to dismiss --- src/Select.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/Select.js b/src/Select.js index 19717a1a6a..d28ee72e83 100644 --- a/src/Select.js +++ b/src/Select.js @@ -171,6 +171,8 @@ const Select = React.createClass({ if (this.props.autofocus) { this.focus(); } + + document.addEventListener('touchstart', this.handleTouchOutside); }, componentWillReceiveProps(nextProps) { @@ -223,6 +225,13 @@ const Select = React.createClass({ } }, + 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(); From 5001083b93f922b8b6e5e42011a79138617b4c1b Mon Sep 17 00:00:00 2001 From: Martin Jujou Date: Sat, 3 Sep 2016 18:15:09 +1000 Subject: [PATCH 2/3] Made it only trigger one event for multiple selects on the screen --- src/Select.js | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/Select.js b/src/Select.js index d28ee72e83..01eeaa4c06 100644 --- a/src/Select.js +++ b/src/Select.js @@ -171,8 +171,6 @@ const Select = React.createClass({ if (this.props.autofocus) { this.focus(); } - - document.addEventListener('touchstart', this.handleTouchOutside); }, componentWillReceiveProps(nextProps) { @@ -187,6 +185,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(); } @@ -225,6 +224,18 @@ 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)) { From 9267932671daac2c29358d4c40176efdffd5cc56 Mon Sep 17 00:00:00 2001 From: Martin Jujou Date: Sun, 4 Sep 2016 21:48:09 +1000 Subject: [PATCH 3/3] Added test --- test/Select-test.js | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) 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', () => {