From 584de6ec76c5e21ca7c6736af9659a22450d0dad Mon Sep 17 00:00:00 2001 From: Joshua Thornton Date: Thu, 2 Jun 2016 13:57:57 +0800 Subject: [PATCH 1/5] The ability to specify the parent via a selector --- lib/components/Modal.js | 37 +++++++++++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/lib/components/Modal.js b/lib/components/Modal.js index 0fb48f26..55af5f1c 100644 --- a/lib/components/Modal.js +++ b/lib/components/Modal.js @@ -10,6 +10,18 @@ var Assign = require('lodash.assign'); var SafeHTMLElement = ExecutionEnvironment.canUseDOM ? window.HTMLElement : {}; var AppElement = ExecutionEnvironment.canUseDOM ? document.body : {appendChild: function() {}}; +function getParentElement(parentSelector) { + if(typeof parentSelector === 'string') { + return document.querySelector(parentSelector); + } + + if(typeof parentSelector === 'function') { + return parentSelector(); + } + + return parentSelector; +} + var Modal = React.createClass({ displayName: 'Modal', @@ -35,7 +47,12 @@ var Modal = React.createClass({ onRequestClose: React.PropTypes.func, closeTimeoutMS: React.PropTypes.number, ariaHideApp: React.PropTypes.bool, - shouldCloseOnOverlayClick: React.PropTypes.bool + shouldCloseOnOverlayClick: React.PropTypes.bool, + parentSelector: React.PropTypes.oneOfType([ + React.PropTypes.string, + React.PropTypes.func, + React.PropTypes.node + ]) }, getDefaultProps: function () { @@ -43,24 +60,36 @@ var Modal = React.createClass({ isOpen: false, ariaHideApp: true, closeTimeoutMS: 0, - shouldCloseOnOverlayClick: true + shouldCloseOnOverlayClick: true, + parentSelector: document.body }; }, componentDidMount: function() { this.node = document.createElement('div'); this.node.className = 'ReactModalPortal'; - document.body.appendChild(this.node); + + var parent = getParentElement(this.props.parentSelector); + parent.appendChild(this.node); this.renderPortal(this.props); }, componentWillReceiveProps: function(newProps) { + var currentParent = getParentElement(this.props.parentSelector); + var newParent = getParentElement(newProps.parentSelector); + + if(newParent !== currentParent) { + currentParent.removeChild(this.node); + newParent.appendChild(this.node); + } + this.renderPortal(newProps); }, componentWillUnmount: function() { ReactDOM.unmountComponentAtNode(this.node); - document.body.removeChild(this.node); + var parent = getParentElement(this.props.parentSelector); + parent.removeChild(this.node); elementClass(document.body).remove('ReactModal__Body--open'); }, From 9ada8594090e8fbbcc0ec75255ba993e60647122 Mon Sep 17 00:00:00 2001 From: Joshua Thornton Date: Thu, 2 Jun 2016 14:13:46 +0800 Subject: [PATCH 2/5] Using object to denote dom element --- lib/components/Modal.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/components/Modal.js b/lib/components/Modal.js index 55af5f1c..b5045007 100644 --- a/lib/components/Modal.js +++ b/lib/components/Modal.js @@ -51,7 +51,7 @@ var Modal = React.createClass({ parentSelector: React.PropTypes.oneOfType([ React.PropTypes.string, React.PropTypes.func, - React.PropTypes.node + React.PropTypes.object ]) }, From 0e426dd71704339ac2f2240dc70feab19c8be7d0 Mon Sep 17 00:00:00 2001 From: Thien Date: Thu, 29 Sep 2016 02:44:00 +0700 Subject: [PATCH 3/5] allow only function as parentSelector --- lib/components/Modal.js | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/lib/components/Modal.js b/lib/components/Modal.js index fe0a000f..c1f20c8e 100644 --- a/lib/components/Modal.js +++ b/lib/components/Modal.js @@ -11,15 +11,7 @@ var SafeHTMLElement = ExecutionEnvironment.canUseDOM ? window.HTMLElement : {}; var AppElement = ExecutionEnvironment.canUseDOM ? document.body : {appendChild: function() {}}; function getParentElement(parentSelector) { - if(typeof parentSelector === 'string') { - return document.querySelector(parentSelector); - } - - if(typeof parentSelector === 'function') { - return parentSelector(); - } - - return parentSelector; + return parentSelector(); } var Modal = React.createClass({ From b8717b231766c116fd8cb18503f689830351435d Mon Sep 17 00:00:00 2001 From: Thien Date: Fri, 30 Sep 2016 23:05:05 +0700 Subject: [PATCH 4/5] update README --- README.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/README.md b/README.md index 372498ab..fd424bd6 100644 --- a/README.md +++ b/README.md @@ -72,6 +72,26 @@ This doesn't affect styling as no styles are applied to this element by default. The default styles above are available on `Modal.defaultStyles`. Changes to this object will apply to all instances of the modal. +### Appended to custom node +You can choose an element for the modal to be appended to, rather than using +body tag. To do this, provide a function to `parentSelector` prop that return +the element to be used. + +```jsx + +function getParent() { + return document.querySelector('#root'); +} + + +

Modal Content.

+
+``` + ## Examples Inside an app: From f1934bcf20da26f5b98cad6b3f72296a477f6922 Mon Sep 17 00:00:00 2001 From: Thien Date: Tue, 8 Nov 2016 01:23:33 +0700 Subject: [PATCH 5/5] Fix parent selector type and default value --- lib/components/Modal.js | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/lib/components/Modal.js b/lib/components/Modal.js index f7a8caf6..d1771185 100644 --- a/lib/components/Modal.js +++ b/lib/components/Modal.js @@ -41,11 +41,7 @@ var Modal = React.createClass({ closeTimeoutMS: React.PropTypes.number, ariaHideApp: React.PropTypes.bool, shouldCloseOnOverlayClick: React.PropTypes.bool, - parentSelector: React.PropTypes.oneOfType([ - React.PropTypes.string, - React.PropTypes.func, - React.PropTypes.object - ]), + parentSelector: React.PropTypes.func, role: React.PropTypes.string, contentLabel: React.PropTypes.string.isRequired }, @@ -57,7 +53,7 @@ var Modal = React.createClass({ ariaHideApp: true, closeTimeoutMS: 0, shouldCloseOnOverlayClick: true, - parentSelector: document.body + parentSelector: () => document.body }; },