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
263 lines (221 loc) • 9.18 kB
JavaScript
import BaseComponent from './base-component.js'
import EventHandler from './dom/event-handler'
import SelectorEngine from './dom/selector-engine'
const NAME = 'transfer'
const DATA_KEY = 'bs.transfer'
const EVENT_KEY = `.${DATA_KEY}`
const DATA_API_KEY = '.data-api'
const EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`
const EVENT_KEYUP_DATA_API = `keyup${EVENT_KEY}${DATA_API_KEY}`
const EVENT_CLICK = `click${EVENT_KEY}`
const CLASS_NAME_ACTIVE = 'active'
const CLASS_NAME_SOURCE = 'source'
const CLASS_NAME_SEMICHECKED = 'semi-checked'
const SELECTOR_BLOCK = '[data-bs-transfer]' //'.it-transfer-block'
const SELECTOR_BTN_TRANS = 'a.transfer'
const SELECTOR_BTN_TRANS_BACK = 'a.backtransfer'
const SELECTOR_BTN_RESET = 'a.reset'
const SELECTOR_HEAD = '.transfer-header'
const SELECTOR_HEAD_INPUT = '.transfer-header input'
const SELECTOR_HEAD_LABEL = '.transfer-header span.num'
const SELECTOR_LIST_INPUT = '.transfer-group input'
const SELECTOR_TRANS_WRAPPER = '.it-transfer-wrapper'
const SELECTOR_TRANS_GROUP = '.transfer-group'
const SELECTOR_SOURCE = `${SELECTOR_TRANS_WRAPPER}.source`
const SELECTOR_TARGET = `${SELECTOR_TRANS_WRAPPER}.target`
const SELECTOR_FORM_CHECK = '.form-check'
class Transfer extends BaseComponent {
constructor(element) {
super(element)
this._addBtnElement = SelectorEngine.findOne(SELECTOR_BTN_TRANS, this._element)
this._invBtnElement = SelectorEngine.findOne(SELECTOR_BTN_TRANS_BACK, this._element)
this._resetBtnElement = SelectorEngine.findOne(SELECTOR_BTN_RESET, this._element)
this._listDefault = {
source: SelectorEngine.find(SELECTOR_SOURCE + ' ' + SELECTOR_TRANS_GROUP + ' ' + SELECTOR_FORM_CHECK, this._element),
target: SelectorEngine.find(SELECTOR_TARGET + ' ' + SELECTOR_TRANS_GROUP + ' ' + SELECTOR_FORM_CHECK, this._element),
}
this._bindEvents()
}
// Getters
static get NAME() {
return NAME
}
// Public
// Private
_bindEvents() {
SelectorEngine.find(SELECTOR_HEAD_INPUT, this._element).forEach((input) => {
EventHandler.on(input, EVENT_CLICK, () => {
this._checkListHeader(input.closest(SELECTOR_TRANS_WRAPPER))
})
})
SelectorEngine.find(SELECTOR_LIST_INPUT, this._element).forEach((input) => {
EventHandler.on(input, EVENT_CLICK, () => {
this._checkList(input.closest(SELECTOR_TRANS_WRAPPER))
})
})
EventHandler.on(this._addBtnElement, EVENT_CLICK, (evt) => {
evt.preventDefault()
// disattivo il pulsante corrente
this._disableElement(this._addBtnElement)
this._addItems()
})
EventHandler.on(this._invBtnElement, EVENT_CLICK, (evt) => {
evt.preventDefault()
// disattivo il pulsante corrente
this._disableElement(this._invBtnElement)
this._addItems(true)
})
EventHandler.on(this._resetBtnElement, EVENT_CLICK, (evt) => {
evt.preventDefault()
this._disableElement(this._addBtnElement)
this._disableElement(this._invBtnElement)
this._disableElement(this._resetBtnElement)
this._resetAll()
})
}
_disableElement(element) {
element.classList.remove(CLASS_NAME_ACTIVE)
element.setAttribute('disabled', 'disabled')
element.setAttribute('aria-disabled', 'true')
}
_enableElement(element) {
element.classList.add(CLASS_NAME_ACTIVE)
element.removeAttribute('disabled')
element.removeAttribute('aria-disabled')
}
_getScopeData(scope) {
return {
scope,
list: SelectorEngine.find(SELECTOR_LIST_INPUT, scope),
listChecked: SelectorEngine.find(SELECTOR_LIST_INPUT + ':checked', scope),
head: SelectorEngine.findOne(SELECTOR_HEAD, scope),
inputHead: SelectorEngine.findOne(SELECTOR_HEAD_INPUT, scope),
labelNumHead: SelectorEngine.findOne(SELECTOR_HEAD_LABEL, scope),
group: SelectorEngine.findOne(SELECTOR_TRANS_GROUP, scope),
}
}
_checkList(scopeElControl) {
const scopeData = this._getScopeData(scopeElControl)
if (scopeData.listChecked.length == 0) {
scopeData.inputHead.classList.remove(CLASS_NAME_SEMICHECKED)
scopeData.inputHead.checked = true
// controllo quale pulsante centrale disattivare
if (scopeElControl.classList.contains(CLASS_NAME_SOURCE)) {
this._disableElement(this._addBtnElement)
} else {
this._disableElement(this._invBtnElement)
}
} else {
if (scopeData.listChecked.length == scopeData.list.length) {
scopeData.inputHead.classList.remove(CLASS_NAME_SEMICHECKED)
scopeData.inputHead.checked = true
} else {
scopeData.inputHead.classList.add(CLASS_NAME_SEMICHECKED)
scopeData.inputHead.checked = false
}
// controllo quale pulsante centrale disattivare
if (scopeElControl.classList.contains(CLASS_NAME_SOURCE)) {
this._enableElement(this._addBtnElement)
} else {
this._enableElement(this._invBtnElement)
}
}
}
_checkListHeader(scopeElControl) {
const scopeData = this._getScopeData(scopeElControl)
if (scopeData.listChecked.length > 0) {
scopeData.list.forEach((item) => {
item.checked = false
})
scopeData.inputHead.classList.remove(CLASS_NAME_SEMICHECKED)
scopeData.inputHead.checked = false
// controllo quale pulsante centrale disattivare
if (scopeElControl.classList.contains(CLASS_NAME_SOURCE)) {
this._disableElement(this._addBtnElement)
} else {
this._disableElement(this._invBtnElement)
}
} else {
scopeData.list.forEach((item) => {
item.checked = true
})
// controllo quale pulsante centrale attivare
if (scopeElControl.classList.contains(CLASS_NAME_SOURCE)) {
this._enableElement(this._addBtnElement)
} else {
this._enableElement(this._invBtnElement)
}
}
}
_addItems(inverse) {
const sourceData = this._getScopeData(SelectorEngine.findOne(inverse ? SELECTOR_TARGET : SELECTOR_SOURCE, this._element))
const targetData = this._getScopeData(SelectorEngine.findOne(inverse ? SELECTOR_SOURCE : SELECTOR_TARGET, this._element))
const sourceItems = sourceData.listChecked //sourceControl.find('.transfer-group input:checked')
//const sourceItemsBlock = SelectorEngine.findOne('.form-check', sourceData.head) //sourceData.head('.form-check')
const sourceHeadInput = sourceData.inputHead //sourceControl.find('.transfer-header input')
const sourceHeadLabel = sourceData.labelNumHead //sourceControl.find('.transfer-header span.num')
const sourceItemsQty = sourceItems.length
const sourceTotalQty = sourceData.list.length
const targetDiv = targetData.group
const targetQty = targetData.list.length + sourceItemsQty
const targetHeadLabel = targetData.labelNumHead
const targetHeadInput = targetData.inputHead
// ciclo di aggiunta
sourceItems.forEach((item) => {
const wrapper = item.closest(SELECTOR_FORM_CHECK)
wrapper.remove()
targetDiv.appendChild(wrapper)
item.checked = false
})
// update label
const totalSource = sourceTotalQty - sourceItemsQty
const totalTarget = targetQty
sourceHeadLabel.innerText = totalSource
targetHeadLabel.innerText = totalTarget
// disattivazione header input se non ci sono più elementi
if (totalSource == 0) {
sourceHeadInput.setAttribute('disabled', true)
}
if (totalTarget > 0) {
targetHeadInput.removeAttribute('disabled')
}
// ripristino stato iniziale input header
sourceHeadInput.classList.remove(CLASS_NAME_SEMICHECKED)
sourceHeadInput.checked = false
// attivo il pulsante di reset
this._enableElement(this._resetBtnElement)
}
_resetAll() {
const blocks = {
source: this._getScopeData(SelectorEngine.findOne(SELECTOR_SOURCE, this._element)),
target: this._getScopeData(SelectorEngine.findOne(SELECTOR_TARGET, this._element)),
}
Object.keys(blocks).forEach((key) => {
blocks[key].list.forEach((item) => item.closest(SELECTOR_FORM_CHECK).remove())
})
Object.keys(blocks).forEach((key) => {
this._listDefault[key].forEach((item) => {
item.checked = false
blocks[key].group.appendChild(item)
})
blocks[key].labelNumHead.innerText = this._listDefault[key].length
blocks[key].inputHead.removeAttribute('disabled')
blocks[key].inputHead.classList.remove(CLASS_NAME_SEMICHECKED)
blocks[key].inputHead.checked = false
})
}
}
/**
* ------------------------------------------------------------------------
* Data Api implementation
* ------------------------------------------------------------------------
*/
if (typeof window !== 'undefined' && typeof document !== 'undefined') {
EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_BLOCK + ' .form-check label', function () {
Transfer.getOrCreateInstance(this.closest(SELECTOR_BLOCK))
})
EventHandler.on(document, EVENT_KEYUP_DATA_API, SELECTOR_BLOCK + ' .form-check label', function () {
Transfer.getOrCreateInstance(this.closest(SELECTOR_BLOCK))
})
}
export default Transfer