mirror of https://github.com/docusealco/docuseal
parent
0d8e2c5ff0
commit
d078727070
@ -0,0 +1,151 @@
|
||||
export default class extends HTMLElement {
|
||||
connectedCallback () {
|
||||
this.targetId = this.dataset.targetId
|
||||
this.fieldId = this.dataset.fieldId
|
||||
this.action = (this.dataset.action || '').trim()
|
||||
this.expectedValue = this.dataset.value
|
||||
|
||||
this.targetEl = document.getElementById(this.targetId)
|
||||
this.sourceEl = document.getElementById(this.fieldId)
|
||||
|
||||
this.bindListeners()
|
||||
|
||||
this.evaluateAndApply()
|
||||
}
|
||||
|
||||
disconnectedCallback () {
|
||||
this.unbindListeners()
|
||||
}
|
||||
|
||||
bindListeners () {
|
||||
this.eventsFor(this.sourceEl).forEach((ev) => {
|
||||
this.sourceEl.addEventListener(ev, this.evaluateAndApply)
|
||||
})
|
||||
}
|
||||
|
||||
unbindListeners () {
|
||||
this.eventsFor(this.sourceEl).forEach((ev) => {
|
||||
this.sourceEl.removeEventListener(ev, this.evaluateAndApply)
|
||||
})
|
||||
}
|
||||
|
||||
eventsFor (el) {
|
||||
if (!el) return []
|
||||
|
||||
const tag = el.tagName.toLowerCase()
|
||||
|
||||
if (tag === 'textarea') return ['input']
|
||||
if (tag === 'input') return ['input', 'change']
|
||||
|
||||
return ['change']
|
||||
}
|
||||
|
||||
evaluateAndApply = () => {
|
||||
const fieldConditions = document.querySelectorAll(`field-condition[data-target-id="${this.targetId}"]`)
|
||||
|
||||
const result = [...fieldConditions].reduce((acc, cond) => {
|
||||
if (cond.dataset.operation === 'or') {
|
||||
acc.push(acc.pop() || cond.checkCondition())
|
||||
} else {
|
||||
acc.push(cond.checkCondition())
|
||||
}
|
||||
|
||||
return acc
|
||||
}, [])
|
||||
|
||||
this.apply(!result.includes(false))
|
||||
}
|
||||
|
||||
checkCondition () {
|
||||
const action = this.action
|
||||
const actual = this.getSourceValue()
|
||||
const expected = this.expectedValue
|
||||
|
||||
if (action === 'empty' || action === 'unchecked') return this.isEmpty(actual)
|
||||
if (action === 'not_empty' || action === 'checked') return !this.isEmpty(actual)
|
||||
|
||||
if (action === 'equal') {
|
||||
const list = Array.isArray(actual) ? actual : [actual]
|
||||
return list.filter((v) => v !== null && v !== undefined).map(String).includes(String(expected))
|
||||
}
|
||||
|
||||
if (action === 'contains') return this.contains(actual, expected)
|
||||
|
||||
if (action === 'not_equal') {
|
||||
const list = Array.isArray(actual) ? actual : [actual]
|
||||
return !list.filter((v) => v !== null && v !== undefined).map(String).includes(String(expected))
|
||||
}
|
||||
|
||||
if (action === 'does_not_contain') return !this.contains(actual, expected)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
getSourceValue () {
|
||||
const el = this.sourceEl
|
||||
|
||||
if (!el) return
|
||||
|
||||
const tag = el.tagName.toLowerCase()
|
||||
const type = (el.getAttribute('type') || '').toLowerCase()
|
||||
|
||||
if (tag === 'select') return el.value
|
||||
if (tag === 'textarea') return el.value
|
||||
if (tag === 'input' && type === 'checkbox') return el.checked ? (el.value || '1') : null
|
||||
if (tag === 'input') return el.value
|
||||
|
||||
return el.value ?? null
|
||||
}
|
||||
|
||||
isEmpty (obj) {
|
||||
if (obj == null) return true
|
||||
|
||||
if (Array.isArray(obj)) {
|
||||
return obj.length === 0
|
||||
}
|
||||
|
||||
if (typeof obj === 'string') {
|
||||
return obj.trim().length === 0
|
||||
}
|
||||
|
||||
if (typeof obj === 'object') {
|
||||
return Object.keys(obj).length === 0
|
||||
}
|
||||
|
||||
if (obj === false) {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
contains (actual, expected) {
|
||||
if (expected === null || expected === undefined) return false
|
||||
|
||||
const exp = String(expected)
|
||||
|
||||
if (Array.isArray(actual)) return actual.filter((v) => v !== null && v !== undefined).map(String).includes(exp)
|
||||
|
||||
if (typeof actual === 'string') return actual.includes(exp)
|
||||
|
||||
return actual !== null && actual !== undefined && String(actual) === exp
|
||||
}
|
||||
|
||||
apply (passed) {
|
||||
const controls = this.targetEl.matches('input, select, textarea, button')
|
||||
? [this.targetEl]
|
||||
: Array.from(this.targetEl.querySelectorAll('input, select, textarea, button'))
|
||||
|
||||
if (passed) {
|
||||
this.targetEl.style.display = ''
|
||||
this.targetEl.labels.forEach((label) => { label.style.display = '' })
|
||||
|
||||
controls.forEach((c) => (c.disabled = false))
|
||||
} else {
|
||||
this.targetEl.style.display = 'none'
|
||||
this.targetEl.labels.forEach((label) => { label.style.display = 'none' })
|
||||
|
||||
controls.forEach((c) => (c.disabled = true))
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in new issue