128 lines
3.3 KiB
JavaScript
128 lines
3.3 KiB
JavaScript
import { show, customProperty, detectAnimation, ClassName } from './util'
|
|
import { buildClickStepLinearListener, buildClickStepNonLinearListener } from './listeners'
|
|
|
|
const DEFAULT_OPTIONS = {
|
|
linear: true,
|
|
animation: false,
|
|
selectors: {
|
|
steps: '.step',
|
|
trigger: '.step-trigger',
|
|
stepper: '.bs-stepper'
|
|
}
|
|
}
|
|
|
|
class Stepper {
|
|
constructor (element, _options = {}) {
|
|
this._element = element
|
|
this._currentIndex = 0
|
|
this._stepsContents = []
|
|
|
|
this.options = {
|
|
...DEFAULT_OPTIONS,
|
|
..._options
|
|
}
|
|
|
|
this.options.selectors = {
|
|
...DEFAULT_OPTIONS.selectors,
|
|
...this.options.selectors
|
|
}
|
|
|
|
if (this.options.linear) {
|
|
this._element.classList.add(ClassName.LINEAR)
|
|
}
|
|
|
|
this._steps = [].slice.call(this._element.querySelectorAll(this.options.selectors.steps))
|
|
|
|
this._steps.filter(step => step.hasAttribute('data-target'))
|
|
.forEach(step => {
|
|
this._stepsContents.push(
|
|
this._element.querySelector(step.getAttribute('data-target'))
|
|
)
|
|
})
|
|
|
|
detectAnimation(this._stepsContents, this.options)
|
|
this._setLinkListeners()
|
|
Object.defineProperty(this._element, customProperty, {
|
|
value: this,
|
|
writable: true
|
|
})
|
|
|
|
if (this._steps.length) {
|
|
show(this._element, this._currentIndex, this.options, () => {})
|
|
}
|
|
}
|
|
|
|
// Private
|
|
|
|
_setLinkListeners () {
|
|
this._steps.forEach(step => {
|
|
const trigger = step.querySelector(this.options.selectors.trigger)
|
|
|
|
if (this.options.linear) {
|
|
this._clickStepLinearListener = buildClickStepLinearListener(this.options)
|
|
trigger.addEventListener('click', this._clickStepLinearListener)
|
|
} else {
|
|
this._clickStepNonLinearListener = buildClickStepNonLinearListener(this.options)
|
|
trigger.addEventListener('click', this._clickStepNonLinearListener)
|
|
}
|
|
})
|
|
}
|
|
|
|
// Public
|
|
|
|
next () {
|
|
const nextStep = (this._currentIndex + 1) <= this._steps.length - 1 ? this._currentIndex + 1 : (this._steps.length - 1)
|
|
|
|
show(this._element, nextStep, this.options, () => {
|
|
this._currentIndex = nextStep
|
|
})
|
|
}
|
|
|
|
previous () {
|
|
const previousStep = (this._currentIndex - 1) >= 0 ? this._currentIndex - 1 : 0
|
|
|
|
show(this._element, previousStep, this.options, () => {
|
|
this._currentIndex = previousStep
|
|
})
|
|
}
|
|
|
|
to (stepNumber) {
|
|
const tempIndex = stepNumber - 1
|
|
const nextStep = tempIndex >= 0 && tempIndex < this._steps.length
|
|
? tempIndex
|
|
: 0
|
|
|
|
show(this._element, nextStep, this.options, () => {
|
|
this._currentIndex = nextStep
|
|
})
|
|
}
|
|
|
|
reset () {
|
|
show(this._element, 0, this.options, () => {
|
|
this._currentIndex = 0
|
|
})
|
|
}
|
|
|
|
destroy () {
|
|
this._steps.forEach(step => {
|
|
const trigger = step.querySelector(this.options.selectors.trigger)
|
|
|
|
if (this.options.linear) {
|
|
trigger.removeEventListener('click', this._clickStepLinearListener)
|
|
} else {
|
|
trigger.removeEventListener('click', this._clickStepNonLinearListener)
|
|
}
|
|
})
|
|
|
|
this._element[customProperty] = undefined
|
|
this._element = undefined
|
|
this._currentIndex = undefined
|
|
this._steps = undefined
|
|
this._stepsContents = undefined
|
|
this._clickStepLinearListener = undefined
|
|
this._clickStepNonLinearListener = undefined
|
|
}
|
|
}
|
|
|
|
export default Stepper
|