mtt-simple
Version:
Biblioteca de componentes y helpers para desarrollo de formularios en SIMPLE digital
132 lines (118 loc) • 4.25 kB
JavaScript
'use strict'
const $ = require('jquery')
/**
* @typedef {Object} DropdownSimpleOpsTypedef
* @property {string} propEtiqueta - nombre de la propiedad en el objeto usado como etiqueta del campo
* @property {string} propValor - nombre de la propiedad en el objeto usada como valor del campo
* @property {string} valorComo - forma en que se guarda el valor en el campo destino object|value
* @property {string} textoSeleccionar - texto que aparecerá como primer valor en caso de que el Select no tenga valor
* @property {number} habilitaBusqueda - cantidad de elementos máxima presentada sin habilitar la búsqueda
*/
/**
* @type {DropdownSimpleOpsTypedef}
*/
const DEFAULTS_DROPDOWN_SIMPLE = {
propEtiqueta: 'etiqueta',
propValor: 'valor',
valorComo: 'object', // 'object', 'value',
textoSeleccionar: 'Seleccione',
habilitaBusqueda: 5 // -1 search disabled
}
class DropdownSimpleUI {
/**
*
* @param {string} nombreCampo
* @param {any[]} listaDatos
* @param {any} valorInicial
* @param {DropdownSimpleOpsTypedef} opciones
*/
constructor(nombreCampo, listaDatos, valorInicial, opciones) {
const elm = $(`[name='${nombreCampo}']`)
if (elm.length) {
this.$elmRef = elm[0]
this.listadoDatos = listaDatos
this.valorInicial = valorInicial
/** @type {DropdownSimpleOpsTypedef} */
this.opts = Object.assign({}, DEFAULTS_DROPDOWN_SIMPLE, opciones || {})
this._dibujar()
} else {
throw new Error(`elemento de formulario no encontrado '${nombreCampo}'`)
}
}
/**
* Obtener el valor del elemento dependiendo del tipo y la configuracion
* relativa al estilo seleccion 'valorComo'
*/
_getValorElemento(elm) {
if (typeof elm === 'object') {
return elm[this.opts.propValor] + ''
} else {
return elm + ''
}
}
/**
* Obtener el valor usado para mostrar como etiqueta del elemento indicado dependiendo tipo
* y configuracion relativa al estilo selección 'valorComo'
*/
_getTextoEtiqueta(elm) {
if (typeof elm === 'object') {
if (typeof this.opts.propEtiqueta === 'function') {
return this.opts.propEtiqueta(elm)
}
else {
return elm[this.opts.propEtiqueta]
}
} else {
return elm
}
}
/**
* comparación de dos elementos a y b en torno a su valor
* usando configuración relativa a 'valorComo'
* @param {any} a
* @param {any} b
*/
_valoresIguales(a, b) {
return this._getValorElemento(a) === this._getValorElemento(b)
}
/**
* despliega el elemento en pantalla según el tipo de elemento referenciado
*/
_dibujar() {
if (this.$elmRef.nodeName === 'SELECT') {
this.$formElement = this._transformarElemento(this.$elmRef)
} else {
this.$formElement = this._crearElemento()
}
}
_agregarOptions(select, items, selected, placeholderText) {
const $select = $(select)
$select.append(`<option value=''>${placeholderText}</option>`)
items.forEach(item => {
const valueEquals = this._valoresIguales(item, selected)
const opt = $(`<option value='${this._getValorElemento(item)}' ${valueEquals ? 'selected' : ''}>${this._getTextoEtiqueta(item)}</option>`)
$select.append(opt)
});
}
_transformarElemento(elm) {
const $elm = $(elm)
const selectedValue = $elm.val() || this.valorInicial
$elm.empty()
this._agregarOptions(elm, this.listadoDatos, selectedValue, this.opts.textoSeleccionar)
// forzar redibujo para tomar nuevas opciones
$elm.chosen('destroy').chosen({
disable_search_threshold: this.opts.habilitaBusqueda > 0 ? this.opts.habilitaBusqueda : 999999
})
return $elm
}
_crearElemento() {
const $select = $(`<select id='${DropdownSimpleUI._name}_${this.$elmRef.attr('name')}' class="form-control form-control-chosen" data-placeholder="${this.opts.textoSeleccionar}"></select>`)
this._agregarOptions($select, this.listadoDatos)
$select.chosen()
return $select
}
}
DropdownSimpleUI._name = 'DropdownSimpleUI'
module.exports = {
DropdownSimpleUI
}