Skip to content

Commit

Permalink
Register only one DOMContentLoaded event listener in `onDOMContentL…
Browse files Browse the repository at this point in the history
…oaded` (twbs#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 <xhmikosr@gmail.com>
  • Loading branch information
2 people authored and marvin-hinkley-vortx committed Aug 18, 2021
1 parent 1d121af commit a4f0d7e
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 3 deletions.
11 changes: 10 additions & 1 deletion js/src/util/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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()
}
Expand Down
13 changes: 11 additions & 2 deletions js/tests/unit/util/index.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -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"', () => {
Expand Down

0 comments on commit a4f0d7e

Please sign in to comment.