Skip to content

Commit 73a1c73

Browse files
authored
fix: allow Component to handle all event listeners without binding external (#60)
Wrap all events in a single handler which will delegate out the events to the provided functions. This means that if the external function changes we do not need to rebind the function, fixing issues with functional react components.
1 parent 5ccf95e commit 73a1c73

File tree

1 file changed

+46
-15
lines changed

1 file changed

+46
-15
lines changed

src/CornerstoneViewport/CornerstoneViewport.js

Lines changed: 46 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -120,9 +120,10 @@ class CornerstoneViewport extends Component {
120120
isFlippedHorizontally: undefined,
121121
};
122122

123+
this._validateExternalEventsListeners();
124+
123125
// TODO: Deep Copy? How does that work w/ handlers?
124126
// Save a copy. Props could change before `willUnmount`
125-
this.eventListeners = this.props.eventListeners;
126127
this.startLoadHandler = this.props.startLoadHandler;
127128
this.endLoadHandler = this.props.endLoadHandler;
128129
this.loadHandlerTimeout = undefined; // "Loading..." timer
@@ -286,6 +287,8 @@ class CornerstoneViewport extends Component {
286287
if (Object.keys(updatedState).length > 0) {
287288
this.setState(updatedState);
288289
}
290+
291+
this._validateExternalEventsListeners();
289292
}
290293

291294
/**
@@ -470,29 +473,40 @@ class CornerstoneViewport extends Component {
470473
}
471474

472475
/**
476+
* Listens out for all events and then defers handling to a single listener to act on them
473477
*
474478
* @param {string} target - "cornerstone" || "element"
475479
* @param {boolean} [clear=false] - True to clear event listeners
476480
* @returns {undefined}
477481
*/
478-
_bindExternalEventListeners(target, clear = false) {
479-
if (!this.eventListeners) {
480-
return;
481-
}
482+
_bindExternalEventListeners(targetType, clear=false) {
483+
const addOrRemoveEventListener = clear
484+
? 'removeEventListener'
485+
: 'addEventListener';
482486

483487
const cornerstoneEvents = Object.values(cornerstone.EVENTS);
484488
const cornerstoneToolsEvents = Object.values(cornerstoneTools.EVENTS);
485-
const addOrRemoveEventListener = clear
486-
? 'removeEventListener'
487-
: 'addEventListener';
488-
489-
for (let i = 0; i < this.eventListeners.length; i++) {
490-
const { target: targetType, eventName, handler } = this.eventListeners[i];
491-
if (targetType !== target) { continue; }
489+
const events = cornerstoneEvents.concat(cornerstoneToolsEvents);
490+
const targetElementOrCornerstone =
491+
targetType === 'element' ? this.element : cornerstone.events;
492+
const targetListener = targetElementOrCornerstone[addOrRemoveEventListener];
493+
const boundMethod = this._handleExternalEventListeners.bind(this);
494+
for (let i = 0; i < events.length; i++) {
495+
targetListener(events[i], boundMethod);
496+
}
497+
}
492498

493-
const targetElementOrCornerstone =
494-
targetType === 'element' ? this.element : cornerstone.events;
499+
/**
500+
* Called to validate that events passed into the event listeners prop are valid
501+
*
502+
* @returns {undefined}
503+
*/
504+
_validateExternalEventsListeners() {
505+
const cornerstoneEvents = Object.values(cornerstone.EVENTS);
506+
const cornerstoneToolsEvents = Object.values(cornerstoneTools.EVENTS);
495507

508+
for (let i = 0; i < this.props.eventListeners.length; i++) {
509+
const { target: targetType, eventName, handler } = this.props.eventListeners[i];
496510
if (
497511
!cornerstoneEvents.includes(eventName) &&
498512
!cornerstoneToolsEvents.includes(eventName)
@@ -502,8 +516,25 @@ class CornerstoneViewport extends Component {
502516
);
503517
continue;
504518
}
519+
}
520+
}
521+
/**
522+
* Handles delegating of events from cornerstone back to the defined
523+
* external events handlers
524+
*
525+
* @param {event}
526+
* @returns {undefined}
527+
*/
528+
_handleExternalEventListeners(event){
529+
if (!this.props.eventListeners) {
530+
return;
531+
}
532+
for (let i = 0; i < this.props.eventListeners.length; i++) {
533+
const { eventName, handler } = this.props.eventListeners[i];
505534

506-
targetElementOrCornerstone[addOrRemoveEventListener](eventName, handler);
535+
if (event.type === eventName) {
536+
handler(event);
537+
}
507538
}
508539
}
509540

0 commit comments

Comments
 (0)