package.src.directives.x-show.js Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of alpinejs Show documentation
Show all versions of alpinejs Show documentation
The rugged, minimal JavaScript framework
import { evaluateLater } from '../evaluator'
import { directive } from '../directives'
import { mutateDom } from '../mutation'
import { once } from '../utils/once'
directive('show', (el, { modifiers, expression }, { effect }) => {
let evaluate = evaluateLater(el, expression)
// We're going to set this function on the element directly so that
// other plugins like "Collapse" can overwrite them with their own logic.
if (! el._x_doHide) el._x_doHide = () => {
mutateDom(() => {
el.style.setProperty('display', 'none', modifiers.includes('important') ? 'important' : undefined)
})
}
if (! el._x_doShow) el._x_doShow = () => {
mutateDom(() => {
if (el.style.length === 1 && el.style.display === 'none') {
el.removeAttribute('style')
} else {
el.style.removeProperty('display')
}
})
}
let hide = () => {
el._x_doHide()
el._x_isShown = false
}
let show = () => {
el._x_doShow()
el._x_isShown = true
}
// We are wrapping this function in a setTimeout here to prevent
// a race condition from happening where elements that have a
// @click.away always view themselves as shown on the page.
let clickAwayCompatibleShow = () => setTimeout(show)
let toggle = once(
value => value ? show() : hide(),
value => {
if (typeof el._x_toggleAndCascadeWithTransitions === 'function') {
el._x_toggleAndCascadeWithTransitions(el, value, show, hide)
} else {
value ? clickAwayCompatibleShow() : hide()
}
}
)
let oldValue
let firstTime = true
effect(() => evaluate(value => {
// Let's make sure we only call this effect if the value changed.
// This prevents "blip" transitions. (1 tick out, then in)
if (! firstTime && value === oldValue) return
if (modifiers.includes('immediate')) value ? clickAwayCompatibleShow() : hide()
toggle(value)
oldValue = value
firstTime = false
}))
})