mirror of https://github.com/vector-im/riot-web
hack around React having its own bubbling phase
parent
5c1c1f64b6
commit
10a74696b3
|
@ -106,7 +106,7 @@ const LoggedInView = React.createClass({
|
|||
|
||||
CallMediaHandler.loadDevices();
|
||||
|
||||
document.addEventListener('keydown', this._onKeyDown);
|
||||
document.addEventListener('keydown', this._onNativeKeyDown, false);
|
||||
|
||||
this._sessionStore = sessionStore;
|
||||
this._sessionStoreToken = this._sessionStore.addListener(
|
||||
|
@ -136,7 +136,7 @@ const LoggedInView = React.createClass({
|
|||
},
|
||||
|
||||
componentWillUnmount: function() {
|
||||
document.removeEventListener('keydown', this._onKeyDown);
|
||||
document.removeEventListener('keydown', this._onNativeKeyDown, false);
|
||||
this._matrixClient.removeListener("accountData", this.onAccountData);
|
||||
this._matrixClient.removeListener("sync", this.onSync);
|
||||
this._matrixClient.removeListener("RoomState.events", this.onRoomStateEvents);
|
||||
|
@ -272,6 +272,42 @@ const LoggedInView = React.createClass({
|
|||
});
|
||||
},
|
||||
|
||||
/*
|
||||
SOME HACKERY BELOW:
|
||||
React optimizes event handlers, by always attaching only 1 handler to the document for a given type.
|
||||
It then internally determines the order in which React event handlers should be called,
|
||||
emulating the capture and bubbling phases the DOM also has.
|
||||
|
||||
But, as the native handler for React is always attached on the document,
|
||||
it will always run last for bubbling (first for capturing) handlers,
|
||||
and thus React basically has its own event phases, and will always run
|
||||
after (before for capturing) any native other event handlers (as they tend to be attached last).
|
||||
|
||||
So ideally one wouldn't mix React and native event handlers to have bubbling working as expected,
|
||||
but we do need a native event handler here on the document,
|
||||
to get keydown events when there is no focused element (target=body).
|
||||
|
||||
We also do need bubbling here to give child components a chance to call `stopPropagation()`,
|
||||
for keydown events it can handle itself, and shouldn't be redirected to the composer.
|
||||
|
||||
So we listen with React on this component to get any events on focused elements, and get bubbling working as expected.
|
||||
We also listen with a native listener on the document to get keydown events when no element is focused.
|
||||
Bubbling is irrelevant here as the target is the body element.
|
||||
*/
|
||||
_onReactKeyDown: function(ev) {
|
||||
// events caught while bubbling up on the root element
|
||||
// of this component, so something must be focused.
|
||||
this._onKeyDown(ev);
|
||||
},
|
||||
|
||||
_onNativeKeyDown: function(ev) {
|
||||
// only pass this if there is no focused element.
|
||||
// if there is, _onKeyDown will be called by the
|
||||
// react keydown handler that respects the react bubbling order.
|
||||
if (ev.target === document.body) {
|
||||
this._onKeyDown(ev);
|
||||
}
|
||||
},
|
||||
|
||||
_onKeyDown: function(ev) {
|
||||
/*
|
||||
|
@ -560,7 +596,7 @@ const LoggedInView = React.createClass({
|
|||
}
|
||||
|
||||
return (
|
||||
<div className='mx_MatrixChat_wrapper' aria-hidden={this.props.hideToSRUsers} onMouseDown={this._onMouseDown} onMouseUp={this._onMouseUp}>
|
||||
<div onKeyDown={this._onReactKeyDown} className='mx_MatrixChat_wrapper' aria-hidden={this.props.hideToSRUsers} onMouseDown={this._onMouseDown} onMouseUp={this._onMouseUp}>
|
||||
{ topBar }
|
||||
<DragDropContext onDragEnd={this._onDragEnd}>
|
||||
<div ref={this._setResizeContainerRef} className={bodyClasses}>
|
||||
|
|
Loading…
Reference in New Issue