Files
TechOdyssey_Designs_Dashboard/assets/plugins/bs-stepper/js/util.js
2025-01-03 23:10:59 +00:00

169 lines
4.7 KiB
JavaScript

import { WinEvent, createCustomEvent } from './polyfill'
const MILLISECONDS_MULTIPLIER = 1000
const ClassName = {
ACTIVE: 'active',
LINEAR: 'linear',
BLOCK: 'dstepper-block',
NONE: 'dstepper-none',
FADE: 'fade',
VERTICAL: 'vertical'
}
const transitionEndEvent = 'transitionend'
const customProperty = 'bsStepper'
const show = (stepperNode, indexStep, options, done) => {
const stepper = stepperNode[customProperty]
if (stepper._steps[indexStep].classList.contains(ClassName.ACTIVE) || stepper._stepsContents[indexStep].classList.contains(ClassName.ACTIVE)) {
return
}
const showEvent = createCustomEvent('show.bs-stepper', {
cancelable: true,
detail: {
from: stepper._currentIndex,
to: indexStep,
indexStep
}
})
stepperNode.dispatchEvent(showEvent)
const activeStep = stepper._steps.filter(step => step.classList.contains(ClassName.ACTIVE))
const activeContent = stepper._stepsContents.filter(content => content.classList.contains(ClassName.ACTIVE))
if (showEvent.defaultPrevented) {
return
}
if (activeStep.length) {
activeStep[0].classList.remove(ClassName.ACTIVE)
}
if (activeContent.length) {
activeContent[0].classList.remove(ClassName.ACTIVE)
if (!stepperNode.classList.contains(ClassName.VERTICAL) && !stepper.options.animation) {
activeContent[0].classList.remove(ClassName.BLOCK)
}
}
showStep(stepperNode, stepper._steps[indexStep], stepper._steps, options)
showContent(stepperNode, stepper._stepsContents[indexStep], stepper._stepsContents, activeContent, done)
}
const showStep = (stepperNode, step, stepList, options) => {
stepList.forEach(step => {
const trigger = step.querySelector(options.selectors.trigger)
trigger.setAttribute('aria-selected', 'false')
// if stepper is in linear mode, set disabled attribute on the trigger
if (stepperNode.classList.contains(ClassName.LINEAR)) {
trigger.setAttribute('disabled', 'disabled')
}
})
step.classList.add(ClassName.ACTIVE)
const currentTrigger = step.querySelector(options.selectors.trigger)
currentTrigger.setAttribute('aria-selected', 'true')
// if stepper is in linear mode, remove disabled attribute on current
if (stepperNode.classList.contains(ClassName.LINEAR)) {
currentTrigger.removeAttribute('disabled')
}
}
const showContent = (stepperNode, content, contentList, activeContent, done) => {
const stepper = stepperNode[customProperty]
const toIndex = contentList.indexOf(content)
const shownEvent = createCustomEvent('shown.bs-stepper', {
cancelable: true,
detail: {
from: stepper._currentIndex,
to: toIndex,
indexStep: toIndex
}
})
function complete () {
content.classList.add(ClassName.BLOCK)
content.removeEventListener(transitionEndEvent, complete)
stepperNode.dispatchEvent(shownEvent)
done()
}
if (content.classList.contains(ClassName.FADE)) {
content.classList.remove(ClassName.NONE)
const duration = getTransitionDurationFromElement(content)
content.addEventListener(transitionEndEvent, complete)
if (activeContent.length) {
activeContent[0].classList.add(ClassName.NONE)
}
content.classList.add(ClassName.ACTIVE)
emulateTransitionEnd(content, duration)
} else {
content.classList.add(ClassName.ACTIVE)
content.classList.add(ClassName.BLOCK)
stepperNode.dispatchEvent(shownEvent)
done()
}
}
const getTransitionDurationFromElement = element => {
if (!element) {
return 0
}
// Get transition-duration of the element
let transitionDuration = window.getComputedStyle(element).transitionDuration
const floatTransitionDuration = parseFloat(transitionDuration)
// Return 0 if element or transition duration is not found
if (!floatTransitionDuration) {
return 0
}
// If multiple durations are defined, take the first
transitionDuration = transitionDuration.split(',')[0]
return parseFloat(transitionDuration) * MILLISECONDS_MULTIPLIER
}
const emulateTransitionEnd = (element, duration) => {
let called = false
const durationPadding = 5
const emulatedDuration = duration + durationPadding
function listener () {
called = true
element.removeEventListener(transitionEndEvent, listener)
}
element.addEventListener(transitionEndEvent, listener)
window.setTimeout(() => {
if (!called) {
element.dispatchEvent(WinEvent(transitionEndEvent))
}
element.removeEventListener(transitionEndEvent, listener)
}, emulatedDuration)
}
const detectAnimation = (contentList, options) => {
if (options.animation) {
contentList.forEach(content => {
content.classList.add(ClassName.FADE)
content.classList.add(ClassName.NONE)
})
}
}
export {
show,
ClassName,
customProperty,
detectAnimation
}