I seem to be encountering a race condition with a function of mine even though I am not using async functions in it
window.focusElem = (elem, overrideGroupNextFocus) => {
if (!elem) return
console.log(`FOCUS: ${elem.id}`)
if (store.getState().app.isExitVisible &&
elem.id !== 'exitExitButton' &&
elem.id !== 'exitBackButton'
) {
return
}
// Remove focus class from existing focused elements
Array.from(document.querySelectorAll('.focus')).forEach(e => {
console.log(`FOCUS: ${elem.id} removing focus from ${e.id}`)
e.classList.remove('focus')
})
const parentFocusGroup = findParentFocusGroup(elem)
let elemToFocus = elem
const focusGroupNextFocusId = parentFocusGroup ? parentFocusGroup.getAttribute('data-focusgroup-next-focus') : ''
if (!overrideGroupNextFocus &&
focusGroupNextFocusId &&
document.activeElement.id !== focusGroupNextFocusId) {
elemToFocus = parentFocusGroup.querySelector(`#${focusGroupNextFocusId}`) || elem
}
store.dispatch(setFocusElem(elemToFocus.id))
if (elemToFocus.id.startsWith('appNav')) {
Array.from(document.querySelectorAll('.active')).forEach(e => e.classList.remove('active'))
elemToFocus.classList.add('active')
document.querySelector('.app-wrapper').setAttribute('data-sidebar', 'open')
} else if (!elemToFocus.hasAttribute('data-focus-inmodal')) {
document.querySelector('.app-wrapper').setAttribute('data-sidebar', 'closed')
}
lastFocused = elemToFocus
console.log(`FOCUS: ${elem.id} add focus to ${elemToFocus.id}`)
elemToFocus.classList.add('focus')
document.dispatchEvent(new CustomEvent('app:focusChanged', { detail: elemToFocus }))
}
function findParentFocusGroup(elem) {
if (elem.hasAttribute('data-focusgroup')) {
return elem
}
const parent = elem.parentNode
if (parent && parent.nodeType !== 9) return findParentFocusGroup(parent)
}
I notice if this function is called in fast succession, I can get the following output in console:
FOCUS: history0
FOCUS: history0 removing focus from vodBannerProgram
FOCUS: vodBannerProgram
FOCUS: vodBannerProgram add focus to vodBannerProgram
FOCUS: history0 add focus to history0
Notice, it seems like this function is called for history0 first then vodBannerProgram. But it seems like it executed halfway for history0 then proceeded to vodBannerProgram then back again? forEach are synchronous correct?