@govbr-ds/core
Version:
Padrão Digital de Governo
305 lines (270 loc) • 8.27 kB
JavaScript
import flatpickr from 'flatpickr'
const Brazilian = require('flatpickr/dist/l10n/pt').default.pt
/** Classe para instanciar um objeto BRDateTimePicker*/
class BRDateTimePicker {
/**
* Instancia do objeto
* @param {string} name - Nome do componente em minúsculo
* @param {object} component - Objeto referenciando a raiz do componente DOM
* @param {string} config - atributo de configuração do componente
* @param {object} language arquivo de linguagem do flatpick por padrão nesse componente vem portugues
*/
constructor(name, component, config, language = Brazilian) {
this.name = name
this.component = component
this.language = language
this.component.querySelectorAll('.br-button').forEach((elem) => {
elem.setAttribute('aria-hidden', 'true')
elem.setAttribute('tab-index', '-1')
})
this.component.addEventListener('blur', () => {
if (!isNaN(new Date(this.component.value))) {
fp.setDate(this.component.value)
}
})
this.component.addEventListener('keyup', () => {
if (!isNaN(new Date(this.component.value))) {
// if the cursor is at the end of the edit and we have a full sized date, allow the date to immediately change, otherwise just move to the correct month without actually changing it
if (this.component.selectionStart >= 10) fp.setDate(this.component.value)
else fp.jumpToDate(this.component.value)
}
})
// localization global
flatpickr.localize(language)
this.configAttribute = this.component.getAttribute('datetimepicker-config')
if (this.configAttribute) {
// Transforma o atributo em um objeto
const properties = this.configAttribute.split(',')
this.obj = []
properties.forEach((element) => {
const tup = element.split(':')
this.obj[tup[0]] = tup[1].replaceAll("'", '').trim() // eslint-disable-line
this.saida = this.obj
}, this)
this.config = this.obj
} else {
this.config = config
}
this._buildDateTimePicker()
}
/**
* Adiciona máscara de data no input
* @param {*} elm
*/
_dateInputMask(elm) {
elm.setAttribute('maxlength', 10)
elm.addEventListener('keypress', (e) => {
if (e.keyCode < 47 || e.keyCode > 57) {
e.preventDefault()
}
const len = elm.value.length
if (len !== 1 || len !== 3) {
if (e.keyCode === 47) {
e.preventDefault()
}
}
if (len === 2) {
elm.value += '/'
}
if (len === 5) {
elm.value += '/'
}
})
}
/**
* Adiciona máscara de hora no input
* @param {*} elm * Dom do elemento input
*/
_dateTimeInputMask(elm) {
elm.setAttribute('maxlength', 16)
elm.addEventListener('keypress', (e) => {
if (e.keyCode < 47 || e.keyCode > 57) {
e.preventDefault()
}
const len = elm.value.length
if (len !== 1 || len !== 3) {
if (e.keyCode === 47) {
e.preventDefault()
}
}
switch (len) {
case 2:
elm.value += '/'
break
case 5:
elm.value += '/'
break
case 10:
elm.value += ' '
break
case 13:
elm.value += ':'
break
default:
break
}
})
}
/**
* Coloca máscara com range de data no input
* @param {*} elm * Dom do elemento input
*/
_dateRangeInputMask(elm) {
elm.setAttribute('maxlength', 25)
elm.addEventListener('keypress', (e) => {
if (e.keyCode < 47 || e.keyCode > 57) {
e.preventDefault()
}
const len = elm.value.length
if (len !== 1 || len !== 3) {
if (e.keyCode === 47) {
e.preventDefault()
}
}
this._positionRangeMask(elm, len)
})
}
/**
* Insere a máscara na Dom
* @param {*} elm Dom do elemento input
* @param {*} len Tamanho do elemento inserido
*/
_positionRangeMask(elm, len) {
const tamSeparator = this.language.rangeSeparator.length
const daySeparator = 10 + tamSeparator + 2
const monthSeparator = 10 + tamSeparator + 5
elm.setAttribute('maxlength', 20 + tamSeparator)
switch (len) {
case 2:
elm.value += '/'
break
case 5:
elm.value += '/'
break
case 10:
elm.value += this.language.rangeSeparator
break
case daySeparator:
elm.value += '/'
break
case monthSeparator:
elm.value += '/'
break
default:
break
}
}
/**
* Insere máscara de hora
*
* @param {*} elm dom do elemento input
*/
_timeInputMask(elm) {
elm.setAttribute('maxlength', 5)
elm.addEventListener('keypress', (e) => {
if (e.keyCode < 47 || e.keyCode > 57) {
e.preventDefault()
}
const len = elm.value.length
if (len !== 1 || len !== 3) {
if (e.keyCode === 47) {
e.preventDefault()
}
}
if (len === 2) {
elm.value += ':'
}
})
}
/**
* Formata o componente e monta instância flatpickr
* @private
*/
_buildDateTimePicker() {
let format = 'd/m/Y'
let time = false
let noCalendar = false
switch (this.component.getAttribute('data-type')) {
case 'date':
format = 'd/m/Y'
time = false
noCalendar = false
this._dateInputMask(this.component.querySelectorAll('input')[0])
break
case 'time':
format = 'H:i'
time = true
noCalendar = true
this._timeInputMask(this.component.querySelectorAll('input')[0])
break
case 'datetime-local':
format = 'd/m/Y H:i'
time = true
noCalendar = false
this._dateTimeInputMask(this.component.querySelectorAll('input')[0])
break
case 'datetime-range':
format = 'd/m/Y'
time = false
noCalendar = false
this._dateRangeInputMask(this.component.querySelectorAll('input')[0])
break
default:
format = 'd/m/Y'
time = false
noCalendar = false
if (this.component.getAttribute('data-mode') === 'range') {
this._dateRangeInputMask(this.component.querySelectorAll('input')[0])
} else {
this._dateInputMask(this.component.querySelectorAll('input')[0])
}
break
}
this.config_native = {
allowInput: true,
dateFormat: format,
enableTime: time,
minuteIncrement: 1,
wrap: true,
}
/**
* Sobreescreve com os atributos visuais necessarios
*/
this.config_min_flat = {
clickOpens: false,
disableMobile: 'true',
mode: this.component.getAttribute('data-mode'),
nextArrow: '<button class="br-button circle small" type="button"><i class="fas fa-chevron-right"></i></button>',
noCalendar: noCalendar,
prevArrow:
'<button class="br-button circle small" type="button"><i class="fas fas fa-chevron-left"></i></button>',
wrap: true,
}
this.config_flatpick = Object.assign(this.config_native, this.config)
this.config_flatpick = Object.assign(this.config_flatpick, this.config_min_flat)
this.calendar = flatpickr(this.component, Object.assign(this.config_native, this.config))
this.calendar.config.onOpen.push(() => {
if (this.config_flatpick.allowInput) {
this.component.querySelectorAll('.br-button').forEach((elem) => {
elem.setAttribute('aria-hidden', 'true')
elem.setAttribute('tab-index', '-1')
})
} else {
this.component.querySelectorAll('.flatpickr-calendar').forEach((elem) => {
console.log(elem)
elem.setAttribute('tab-index', '-1')
})
}
document.querySelectorAll('.flatpickr-day').forEach((element) => {
element.setAttribute('tabindex', '1')
})
document.querySelectorAll('.arrowUp').forEach((element) => {
element.classList.add('fas', 'fa-chevron-up')
})
document.querySelectorAll('.arrowDown').forEach((element) => {
element.classList.add('fas', 'fa-chevron-down')
})
})
}
}
export default BRDateTimePicker