generated from boboko/starter
49 lines
1.5 KiB
JavaScript
49 lines
1.5 KiB
JavaScript
import { Controller } from '@hotwired/stimulus'
|
|
|
|
export default class extends Controller {
|
|
static targets = ['star', 'input', 'error']
|
|
static values = { rating: { type: Number, default: 0 } }
|
|
|
|
connect() {
|
|
this.#fill(this.ratingValue)
|
|
}
|
|
|
|
// Bound to the form's submit event (this controller sits on the <form>
|
|
// itself, not just the star widget) — a plain `required` on the hidden
|
|
// rating input would never surface: browsers exclude type="hidden" from
|
|
// constraint validation entirely, so there'd be nothing to see or hear.
|
|
validate(event) {
|
|
if (this.ratingValue < 1) {
|
|
event.preventDefault()
|
|
this.errorTarget.hidden = false
|
|
this.starTargets[0]?.focus()
|
|
}
|
|
}
|
|
|
|
hover(event) {
|
|
this.#fill(parseInt(event.currentTarget.dataset.value))
|
|
}
|
|
|
|
leave() {
|
|
this.#fill(this.ratingValue)
|
|
}
|
|
|
|
select(event) {
|
|
const val = parseInt(event.currentTarget.dataset.value)
|
|
this.ratingValue = val
|
|
this.inputTarget.value = val
|
|
this.errorTarget.hidden = true
|
|
|
|
this.starTargets.forEach(star => {
|
|
star.setAttribute('aria-pressed', String(parseInt(star.dataset.value) === val))
|
|
})
|
|
}
|
|
|
|
#fill(upTo) {
|
|
this.starTargets.forEach(star => {
|
|
const filled = parseInt(star.dataset.value) <= upTo
|
|
star.querySelector('svg').setAttribute('fill', filled ? 'currentColor' : 'none')
|
|
})
|
|
}
|
|
}
|