From ff09b4921e73f03d9399d66015425eec812e9e72 Mon Sep 17 00:00:00 2001 From: guerin olivier Date: Wed, 14 Sep 2016 06:31:23 +0200 Subject: [PATCH] [fixed] Close modal when mouseDown and MouseUp happen only on the overlay (#217) --- lib/components/ModalPortal.js | 30 +++++++++++++++------- specs/Modal.spec.js | 47 ++++++++++++++++++++++++++++++++--- 2 files changed, 65 insertions(+), 12 deletions(-) diff --git a/lib/components/ModalPortal.js b/lib/components/ModalPortal.js index 5e887b4f..30075d6a 100644 --- a/lib/components/ModalPortal.js +++ b/lib/components/ModalPortal.js @@ -21,6 +21,7 @@ var CLASS_NAMES = { var ModalPortal = module.exports = React.createClass({ displayName: 'ModalPortal', + shouldClose: null, getDefaultProps: function() { return { @@ -128,20 +129,28 @@ var ModalPortal = module.exports = React.createClass({ } }, - handleOverlayClick: function(event) { - var node = event.target - - while (node) { - if (node === this.refs.content) return - node = node.parentNode + handleOverlayMouseDown: function(event) { + if (this.shouldClose === null) { + this.shouldClose = true; } + }, - if (this.props.shouldCloseOnOverlayClick) { + handleOverlayMouseUp: function(event) { + if (this.shouldClose && this.props.shouldCloseOnOverlayClick) { if (this.ownerHandlesClose()) this.requestClose(event); else this.focusContent(); } + this.shouldClose = null; + }, + + handleContentMouseDown: function(event) { + this.shouldClose = false; + }, + + handleContentMouseUp: function(event) { + this.shouldClose = false; }, requestClose: function(event) { @@ -175,14 +184,17 @@ var ModalPortal = module.exports = React.createClass({ ref: "overlay", className: this.buildClassName('overlay', this.props.overlayClassName), style: Assign({}, overlayStyles, this.props.style.overlay || {}), - onClick: this.handleOverlayClick + onMouseDown: this.handleOverlayMouseDown, + onMouseUp: this.handleOverlayMouseUp }, div({ ref: "content", style: Assign({}, contentStyles, this.props.style.content || {}), className: this.buildClassName('content', this.props.className), tabIndex: "-1", - onKeyDown: this.handleKeyDown + onKeyDown: this.handleKeyDown, + onMouseDown: this.handleContentMouseDown, + onMouseUp: this.handleContentMouseUp }, this.props.children ) diff --git a/specs/Modal.spec.js b/specs/Modal.spec.js index 1c748a01..6cee0450 100644 --- a/specs/Modal.spec.js +++ b/specs/Modal.spec.js @@ -247,7 +247,8 @@ describe('Modal', function () { equal(modal.props.isOpen, true); var overlay = TestUtils.scryRenderedDOMComponentsWithClass(modal.portal, 'ReactModal__Overlay'); equal(overlay.length, 1); - Simulate.click(overlay[0]); // click the overlay + Simulate.mouseDown(overlay[0]); // click the overlay + Simulate.mouseUp(overlay[0]); ok(!requestCloseCallback.called) }); @@ -263,10 +264,49 @@ describe('Modal', function () { equal(modal.props.isOpen, true); var overlay = TestUtils.scryRenderedDOMComponentsWithClass(modal.portal, 'ReactModal__Overlay'); equal(overlay.length, 1); - Simulate.click(overlay[0]); // click the overlay + Simulate.mouseDown(overlay[0]); // click the overlay + Simulate.mouseUp(overlay[0]); ok(requestCloseCallback.called) }); + it('verify overlay mouse down and content mouse up when shouldCloseOnOverlayClick sets to true', function() { + var requestCloseCallback = sinon.spy(); + var modal = renderModal({ + isOpen: true, + shouldCloseOnOverlayClick: true, + onRequestClose: function() { + requestCloseCallback(); + } + }); + equal(modal.props.isOpen, true); + var overlay = TestUtils.scryRenderedDOMComponentsWithClass(modal.portal, 'ReactModal__Overlay'); + var content = TestUtils.scryRenderedDOMComponentsWithClass(modal.portal, 'ReactModal__Content'); + equal(overlay.length, 1); + equal(content.length, 1); + Simulate.mouseDown(overlay[0]); // click the overlay + Simulate.mouseUp(content[0]); + ok(!requestCloseCallback.called) + }); + + it('verify content mouse down and overlay mouse up when shouldCloseOnOverlayClick sets to true', function() { + var requestCloseCallback = sinon.spy(); + var modal = renderModal({ + isOpen: true, + shouldCloseOnOverlayClick: true, + onRequestClose: function() { + requestCloseCallback(); + } + }); + equal(modal.props.isOpen, true); + var overlay = TestUtils.scryRenderedDOMComponentsWithClass(modal.portal, 'ReactModal__Overlay'); + var content = TestUtils.scryRenderedDOMComponentsWithClass(modal.portal, 'ReactModal__Content'); + equal(content.length, 1); + equal(overlay.length, 1); + Simulate.mouseDown(content[0]); // click the overlay + Simulate.mouseUp(overlay[0]); + ok(!requestCloseCallback.called) + }); + it('should not stop event propagation', function() { var hasPropagated = false var modal = renderModal({ @@ -290,7 +330,8 @@ describe('Modal', function () { equal(modal.props.isOpen, true); var overlay = TestUtils.scryRenderedDOMComponentsWithClass(modal.portal, 'ReactModal__Overlay'); equal(overlay.length, 1); - Simulate.click(overlay[0]); // click the overlay + Simulate.mouseDown(overlay[0]); // click the overlay + Simulate.mouseUp(overlay[0]); ok(requestCloseCallback.called) // Check if event is passed to onRequestClose callback. var event = requestCloseCallback.getCall(0).args[0];