From 4927388197a3a2b1b041dce1be513c4cc5c39d22 Mon Sep 17 00:00:00 2001 From: alpadev <2838324+alpadev@users.noreply.github.com> Date: Tue, 22 Jun 2021 19:19:55 +0200 Subject: [PATCH] Register only one `DOMContentLoaded` event listener in `onDOMContentLoaded` (#34158) * refactor: reuse one DOMContentLoaded event listener in onDOMContentLoaded function Instead of adding an event listener everytime the utility function is called, cache the callbacks and execute them all at once. * refactor: drop iife for onDOMContentLoaded Co-authored-by: XhmikosR --- js/src/util/index.js | 11 ++++++++++- js/tests/unit/util/index.spec.js | 13 +++++++++++-- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/js/src/util/index.js b/js/src/util/index.js index 6edfaa580d..064b4e9431 100644 --- a/js/src/util/index.js +++ b/js/src/util/index.js @@ -201,9 +201,18 @@ const getjQuery = () => { return null } +const DOMContentLoadedCallbacks = [] + const onDOMContentLoaded = callback => { if (document.readyState === 'loading') { - document.addEventListener('DOMContentLoaded', callback) + // add listener on the first call when the document is in loading state + if (!DOMContentLoadedCallbacks.length) { + document.addEventListener('DOMContentLoaded', () => { + DOMContentLoadedCallbacks.forEach(callback => callback()) + }) + } + + DOMContentLoadedCallbacks.push(callback) } else { callback() } diff --git a/js/tests/unit/util/index.spec.js b/js/tests/unit/util/index.spec.js index 04ad6bf432..9b5d7b70e2 100644 --- a/js/tests/unit/util/index.spec.js +++ b/js/tests/unit/util/index.spec.js @@ -582,15 +582,24 @@ describe('Util', () => { }) describe('onDOMContentLoaded', () => { - it('should execute callback when DOMContentLoaded is fired', () => { + it('should execute callbacks when DOMContentLoaded is fired and should not add more than one listener', () => { const spy = jasmine.createSpy() + const spy2 = jasmine.createSpy() + + spyOn(document, 'addEventListener').and.callThrough() spyOnProperty(document, 'readyState').and.returnValue('loading') + Util.onDOMContentLoaded(spy) - window.document.dispatchEvent(new Event('DOMContentLoaded', { + Util.onDOMContentLoaded(spy2) + + document.dispatchEvent(new Event('DOMContentLoaded', { bubbles: true, cancelable: true })) + expect(spy).toHaveBeenCalled() + expect(spy2).toHaveBeenCalled() + expect(document.addEventListener).toHaveBeenCalledTimes(1) }) it('should execute callback if readyState is not "loading"', () => {