From 5f933b12bbe99c47b6c893431f36475d8597f5df Mon Sep 17 00:00:00 2001 From: Johannes Mueller Date: Fri, 5 Jun 2020 12:27:00 +0200 Subject: [PATCH] Clear listeners and nodes to avoid memory leaks --- src/button.js | 14 ++++++++++++++ src/buttongroup.js | 10 ++++++++++ src/navigator.js | 4 ++++ src/viewer.js | 20 +++++++++++++++++++- 4 files changed, 47 insertions(+), 1 deletion(-) diff --git a/src/button.js b/src/button.js index 0ddb919a..ac909933 100644 --- a/src/button.js +++ b/src/button.js @@ -396,6 +396,20 @@ $.extend( $.Button.prototype, $.EventSource.prototype, /** @lends OpenSeadragon. this.element.disabled = false; $.setElementOpacity( this.element, 1.0, true ); this.notifyGroupEnter(); + }, + + destroy: function() { + this.element.removeChild(this.imgRest); + this.imgRest = null; + this.element.removeChild(this.imgGroup); + this.imgGroup = null; + this.element.removeChild(this.imgHover); + this.imgHover = null; + this.element.removeChild(this.imgDown); + this.imgDown = null; + this.removeAllHandlers(); + this.tracker.destroy(); + this.element = null; } }); diff --git a/src/buttongroup.js b/src/buttongroup.js index 2522d2f0..995f90d3 100644 --- a/src/buttongroup.js +++ b/src/buttongroup.js @@ -129,6 +129,16 @@ $.ButtonGroup.prototype = { */ emulateExit: function() { this.tracker.exitHandler( { eventSource: this.tracker } ); + }, + + destroy: function() { + while (this.buttons.length) { + var button = this.buttons.pop(); + this.element.removeChild(button.element); + button.destroy(); + } + this.tracker.destroy(); + this.element = null; } }; diff --git a/src/navigator.js b/src/navigator.js index afa3a7f5..6ff112e0 100644 --- a/src/navigator.js +++ b/src/navigator.js @@ -406,6 +406,10 @@ $.extend( $.Navigator.prototype, $.EventSource.prototype, $.Viewer.prototype, /* return $.Viewer.prototype.addTiledImage.apply(this, [optionsClone]); }, + destroy: function() { + return $.Viewer.prototype.destroy.apply(this); + }, + // private _getMatchingItem: function(theirItem) { var count = this.world.getItemCount(); diff --git a/src/viewer.js b/src/viewer.js index 20e06186..73b2aca4 100644 --- a/src/viewer.js +++ b/src/viewer.js @@ -765,8 +765,23 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype, this.drawer.destroy(); } + if ( this.navigator ) { + this.navigator.destroy(); + THIS[ this.navigator.hash ] = null; + delete THIS[ this.navigator.hash ]; + this.navigator = null; + } + this.removeAllHandlers(); + if (this.buttons) { + this.buttons.destroy(); + } + + if (this.paging) { + this.paging.destroy(); + } + // Go through top element (passed to us) and remove all children // Use removeChild to make sure it handles SVG or any non-html // also it performs better - http://jsperf.com/innerhtml-vs-removechild/15 @@ -776,6 +791,9 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype, } } + this.container.onsubmit = null; + this.clearControls(); + // destroy the mouse trackers if (this.innerTracker){ this.innerTracker.destroy(); @@ -3261,7 +3279,7 @@ function updateOnce( viewer ) { //viewer.profiler.beginUpdate(); - if (viewer._opening) { + if (viewer._opening || !THIS[viewer.hash]) { return; }