bootstrap-italia
Version:
Bootstrap Italia è un tema Bootstrap 5 per la creazione di applicazioni web nel pieno rispetto delle linee guida di design per i siti internet e i servizi digitali della PA
156 lines (128 loc) • 4.32 kB
JavaScript
/**
* --------------------------------------------------------------------------
* Bootstrap Italia (https://italia.github.io/bootstrap-italia/)
* Authors: https://github.com/italia/bootstrap-italia/blob/main/AUTHORS
* Licensed under BSD-3-Clause license (https://github.com/italia/bootstrap-italia/blob/main/LICENSE)
* --------------------------------------------------------------------------
*/
import BaseComponent from './base-component'
import EventHandler from './dom/event-handler'
import SelectorEngine from './dom/selector-engine'
import InputLabel from './input-label'
const NAME = 'inputnumber'
const DATA_KEY = 'bs.inputnumber'
const EVENT_KEY = `.${DATA_KEY}`
const DATA_API_KEY = '.data-api'
const EVENT_CLICK = `click${EVENT_KEY}`
const EVENT_CHANGE = `change${EVENT_KEY}`
const EVENT_INPUT = `input`
const EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`
const CLASS_NAME_ADAPTIVE = 'input-number-adaptive'
const CLASS_NAME_DECREMENT = 'input-number-sub'
const SELECTOR_WRAPPER = '.input-number'
const SELECTOR_INPUT = 'input[data-bs-input][type="number"]'
const SELECTOR_BTN = 'button[class^="input-number-"]'
class InputNumber extends BaseComponent {
constructor(element) {
super(element)
this._wrapperElement = this._element.closest(SELECTOR_WRAPPER)
this._label = new InputLabel(element)
this._init()
this._bindEvents()
}
// Getters
static get NAME() {
return NAME
}
// Private
_init() {
if (this._wrapperElement) {
this._inputResize()
}
}
_bindEvents() {
if (this._wrapperElement) {
SelectorEngine.find(SELECTOR_BTN, this._wrapperElement).forEach((btn) => {
EventHandler.on(btn, EVENT_CLICK, (evt) => {
evt.preventDefault()
this._incrDecr(btn.classList.contains(CLASS_NAME_DECREMENT))
this._label._labelOut()
})
})
EventHandler.on(this._element, EVENT_CHANGE, () => this._checkLimit())
}
}
_inputResize() {
if (this._wrapperElement.classList.contains(CLASS_NAME_ADAPTIVE)) {
let newWidth = null
newWidth = 'calc(70px + ' + this._element.value.length + 'ch)'
if (newWidth) {
this._element.style.width = newWidth
}
}
}
_incrDecr(isDecr) {
let inputVal = 0
if (this._element.disabled || this._element.readonly) {
return
}
if (this._element.value !== '') inputVal = parseFloat(this._element.value)
if (!isNaN(inputVal)) {
//get step
let step = parseFloat(this._element.getAttribute('step'))
if (!step) {
step = 1
}
this._element.value = inputVal + step * (isDecr ? -1 : 1)
EventHandler.trigger(this._element, EVENT_CHANGE)
EventHandler.trigger(this._element, EVENT_INPUT)
}
}
_checkLimit() {
const inputVal = parseFloat(this._element.value)
if (!isNaN(inputVal)) {
let val = inputVal
const max = parseFloat(this._element.getAttribute('max'))
const min = parseFloat(this._element.getAttribute('min'))
if (min && inputVal < min) {
val = min
}
//limit max
if (max && inputVal > max) {
val = max
}
this._element.value = val
}
this._inputResize()
}
}
/**
* ------------------------------------------------------------------------
* Data Api implementation
* ------------------------------------------------------------------------
*/
const createInput = (element) => {
if (element && element.matches(SELECTOR_INPUT) && element.parentNode.querySelector(SELECTOR_BTN)) {
return InputNumber.getOrCreateInstance(element)
}
return null
}
if (typeof window !== 'undefined' && typeof document !== 'undefined') {
document.addEventListener('DOMContentLoaded', function () {
let frmel = document.querySelectorAll(SELECTOR_INPUT + ', label')
frmel.forEach(function (item) {
const target = InputLabel.getInputFromLabel(item) || item
createInput(target)
})
})
EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_BTN, function () {
const wrapper = this.closest(SELECTOR_WRAPPER)
if (wrapper) {
const input = SelectorEngine.findOne(SELECTOR_INPUT, wrapper)
if (input) {
InputNumber.getOrCreateInstance(input)
}
}
})
}
export default InputNumber