Skip to content

Bind event listeners to the shadow root if a component is being rendered into one #859

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 34 additions & 1 deletion src/core/ReactDOMComponent.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
var CSSPropertyOperations = require('CSSPropertyOperations');
var DOMProperty = require('DOMProperty');
var DOMPropertyOperations = require('DOMPropertyOperations');
var ExecutionEnvironment = require('ExecutionEnvironment');
var ReactComponent = require('ReactComponent');
var ReactEventEmitter = require('ReactEventEmitter');
var ReactMount = require('ReactMount');
Expand Down Expand Up @@ -64,11 +65,43 @@ function assertValidProps(props) {
);
}


/*
* The owning document is the Node to which we should attach event handlers.
* Under normal circumstances, this would be the document contained
* in the window.
*
* However, when rendering into a shadow root, we need to bind the handlers
* to the shadow root. That is because events are stopped at shadow boundaries.
*
* This means we have to manually walk up the parents until we find a suitable
* node.
*
* Futher complicated by the fact that this module is tested to run in web
* workers, where 'window' is not defined. So the whole function is only
* defined if it can actually run.
*/
var owningDocument = (function() {
if (ExecutionEnvironment.canUseDOM) {
var ShadowRoot = window.ShadowRoot;
return function(node) {
if (node.parentNode == null) {
return node;
} else if (ShadowRoot && node instanceof ShadowRoot) {
return node;
} else {
return owningDocument(node.parentNode);
}
}
}
})();


function putListener(id, registrationName, listener) {
var container = ReactMount.findReactContainerForID(id);
if (container) {
var doc = container.nodeType === ELEMENT_NODE_TYPE ?
container.ownerDocument :
owningDocument(container) :
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's Element.shadowRoot per spec http://www.w3.org/TR/shadow-dom/#api-partial-element-shadow-root, can it be used instead?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately no. The shadowRoot property is the ShadowRoot that is being rendered inside of the element, not the one the element is inside of.

I'm not aware of any more efficient way to determine in which ShadowRoot (if any) a given element is. But I also haven't investigated deeply.

container;
listenTo(registrationName, doc);
}
Expand Down