From 957a4a65ac671f16a7254e2904d20e83399b3268 Mon Sep 17 00:00:00 2001
From: Christoph Reiter <reiter.christoph@gmail.com>
Date: Thu, 24 Jun 2021 14:39:01 +0200
Subject: [PATCH] Fix some event handler leaks with person/organization-select

It was using the click event but never removed the event listener
---
 .../src/organization-select.js                | 27 +++++++--------
 packages/person-select/src/person-select.js   | 33 ++++++++++---------
 2 files changed, 31 insertions(+), 29 deletions(-)

diff --git a/packages/organization-select/src/organization-select.js b/packages/organization-select/src/organization-select.js
index ee212b9d..578fb010 100644
--- a/packages/organization-select/src/organization-select.js
+++ b/packages/organization-select/src/organization-select.js
@@ -25,6 +25,8 @@ export class OrganizationSelect extends AdapterLitElement {
         this.cache = {};
         this.value = '';
         this.context = '';
+
+        this._onDocumentClicked = this._onDocumentClicked.bind(this);
     }
 
     static get properties() {
@@ -48,16 +50,13 @@ export class OrganizationSelect extends AdapterLitElement {
 
     connectedCallback() {
         super.connectedCallback();
+        document.addEventListener('click', this._onDocumentClicked);
         this.updateSelect2();
+    }
 
-        this.updateComplete.then(()=> {
-            // Close the popup when clicking outside of select2
-            document.addEventListener('click', (ev) => {
-                if (!ev.composedPath().includes(this)) {
-                    this._closeSelect2();
-                }
-            });
-        });
+    disconnectedCallback() {
+        document.removeEventListener('click', this._onDocumentClicked);
+        super.disconnectedCallback();
     }
 
     async load_organizations() {
@@ -71,11 +70,13 @@ export class OrganizationSelect extends AdapterLitElement {
         return this.cache[this.lang] === undefined;
     }
 
-    _closeSelect2() {
-        const $select = this.$('#' + this.selectId);
-        console.assert($select.length, "select2 missing");
-        if (this.select2IsInitialized($select)) {
-            $select.select2('close');
+    _onDocumentClicked(ev) {
+        // Close the popup when clicking outside of select2
+        if (!ev.composedPath().includes(this)) {
+            const $select = this.$('#' + this.selectId);
+            if ($select.length && this.select2IsInitialized($select)) {
+                $select.select2('close');
+            }
         }
     }
 
diff --git a/packages/person-select/src/person-select.js b/packages/person-select/src/person-select.js
index 02df24f8..67c74666 100644
--- a/packages/person-select/src/person-select.js
+++ b/packages/person-select/src/person-select.js
@@ -44,6 +44,8 @@ export class PersonSelect extends ScopedElementsMixin(AdapterLitElement) {
         this.showReloadButton = false;
         this.reloadButtonTitle = '';
         this.showDetails = false;
+
+        this._onDocumentClicked = this._onDocumentClicked.bind(this);
     }
 
     static get scopedElements() {
@@ -84,28 +86,27 @@ export class PersonSelect extends ScopedElementsMixin(AdapterLitElement) {
 
     connectedCallback() {
         super.connectedCallback();
-        const that = this;
+        document.addEventListener('click', this._onDocumentClicked);
 
         this.updateComplete.then(()=>{
-            that.$select = that.$('#' + that.selectId);
-
-            // Close the popup when clicking outside of select2
-            document.addEventListener('click', (ev) => {
-                if (!ev.composedPath().includes(this)) {
-                    this._closeSelect2();
-                }
-            });
-
+            this.$select = this.$('#' + this.selectId);
             // try an init when user-interface is loaded
-            that.initJSONLD();
+            this.initJSONLD();
         });
     }
 
-    _closeSelect2() {
-        const $select = this.$('#' + this.selectId);
-        console.assert($select.length, "select2 missing");
-        if (this.select2IsInitialized($select)) {
-            $select.select2('close');
+    disconnectedCallback() {
+        document.removeEventListener('click', this._onDocumentClicked);
+        super.disconnectedCallback();
+    }
+
+    _onDocumentClicked(ev) {
+        // Close the popup when clicking outside of select2
+        if (!ev.composedPath().includes(this)) {
+            const $select = this.$('#' + this.selectId);
+            if ($select.length && this.select2IsInitialized($select)) {
+                $select.select2('close');
+            }
         }
     }
 
-- 
GitLab