diff --git a/src/js/control-bar/track-button.js b/src/js/control-bar/track-button.js index 52125f7171..579fefd376 100644 --- a/src/js/control-bar/track-button.js +++ b/src/js/control-bar/track-button.js @@ -36,20 +36,55 @@ class TrackButton extends MenuButton { return; } - const updateHandler = Fn.bind_(this, this.update); - - tracks.addEventListener('removetrack', updateHandler); - tracks.addEventListener('addtrack', updateHandler); - tracks.addEventListener('labelchange', updateHandler); - this.player_.on('ready', updateHandler); - - this.player_.on('dispose', function() { - tracks.removeEventListener('removetrack', updateHandler); - tracks.removeEventListener('addtrack', updateHandler); - tracks.removeEventListener('labelchange', updateHandler); - }); + this.updateHandler_ = Fn.bind_(this, this.update); + this.cleanupHandler_ = Fn.bind_(this, this.cleanupTrackListeners_); + + tracks.addEventListener('removetrack', this.updateHandler_); + tracks.addEventListener('addtrack', this.updateHandler_); + tracks.addEventListener('labelchange', this.updateHandler_); + + this.player_.on('ready', this.updateHandler_); + this.player_.on('dispose', this.cleanupHandler_); + } + + /** + * Remove all track list event listeners without triggering a full dispose. + * Used as the player 'dispose' handler and called by dispose() before super. + * + * @private + */ + cleanupTrackListeners_() { + if (!this.updateHandler_) { + return; + } + + const tracks = this.options_.tracks; + + if (tracks) { + tracks.removeEventListener('removetrack', this.updateHandler_); + tracks.removeEventListener('addtrack', this.updateHandler_); + tracks.removeEventListener('labelchange', this.updateHandler_); + } + + if (this.player_) { + this.player_.off('ready', this.updateHandler_); + this.player_.off('dispose', this.cleanupHandler_); + } + + this.updateHandler_ = null; + this.cleanupHandler_ = null; } + /** + * Dispose of the Component and remove all event listeners. + * + * @override + */ + dispose() { + this.cleanupTrackListeners_(); + + super.dispose(); + } } Component.registerComponent('TrackButton', TrackButton);