/**
* Aquí están contenidas todas las funciones que se encargan de darle interacción a la grid de Fw7, todas las funciones
* que usen la grid, requieren que ya esté inicializada
* @module HtmlGrid
* @author Cristian Camilo Cantillo
* @tutorial gridConf
* @tutorial gridEvent
*/
var _$ = jQuery.noConflict();
var dProgress = null;
var STATUS_LOCK = "1", STATUS_UNLOCK = "0";
var maxRowsValidate = 50;
/**
*Se encarga de inicializar el objeto que manejara las funciones de la grid
*@param {string} id id de la tabla HTML
*@param {object} conf Objeto de configuración de la grid, {@tutorial gridConf}
*@returns {object} Objeto configurado con las opciones y listo para usarse
*@example initFromTable("gPruebas", gPruebasConf);
*/
function initFromTable(id, conf) {
var grid = null;
var tabla = _$(id);
if (tabla != null && tabla.length > 0) {
var contTabla = tabla.parents('.data-table-init')[0];
var header = tabla.find('thead')[0];
var body = tabla.find('tbody')[0];
var tablaLimpia = null;
var inWorker = false;
if (_$(id + 'L_').length > 0)
tablaLimpia = _$(id + 'L_')[0];
grid = {
'tabla': tabla[0], 'header': header, 'body': body, 'contenedor': contTabla
, 'colsHidden': {}, 'colsFormat': {}, 'pintarFilaOculta': true, 'editOnClick': false
, 'valPopup': false, 'addEventOpt': false, rowsBuffer: '', rowsBufferNum: 0, 'tablaL': tablaLimpia
, 'iconosOpt': '', 'colOpt': -1, liteValidate:false, pagination: false
};
if (grid.tablaL != null) {
if (_$(grid.tablaL).find('tbody')[0].rows.length > maxRowsValidate) {
inWorker = true;
initWorker();
convertirHTML(grid, conf);
} else {
grid.body.innerHTML = _$(grid.tablaL).find('tbody').html();
}
}
if (getRowsNum(grid) > 0) {
if (!inWorker) {
_addRowIdAndValueFromTable(grid, conf);
_validateAttrGrid(grid);
}
if (getRowsNum(grid) < maxRowsValidate)
_addAllDataCollapsableTitle(grid);
if (!inWorker)
_addSelectRow(grid);
}
if (conf != null) {
hideColumnsConf(grid, conf);
addMaxLength(conf);
}
}
return grid;
}
function _selectRow(row) {
if (!_$(row).hasClass('table-active')) {
_$(row).addClass('table-active');
var grid = getGridFromRow(row);
var rId = getRowId(row);
_onRowSelected(grid, rId);
}
}
/**
*Selecciona la fila indicada en el parámetro row
*@param {HTMLTableRowElement} row debe ser el tr de la fila a seleccionar
*@example var rId = getSelectedRowId(gPruebas);
var row = getRow(gPruebas, rId);
*selectRow(row);
*/
function selectRow(row) {
_selectRow(row);
verModalOnClick(row);
}
/**
*Quita la selección de la fila indicada en el parámetro row
*@param {HTMLTableRowElement} row debe ser el tr de la fila a seleccionar
*@example
var rId = getSelectedRowId(gPruebas);
var row = getRow(gPruebas, rId);
*unSelectRow(row);
*/
function unSelectRow(row) {
if (_$(row).hasClass('table-active'))
_$(row).removeClass('table-active');
}
/**
*Devuelve el rowId de la fila que esté seleccionada
*@param {object} grid Objeto de la grid ya inicializada
*@returns {string} rowId único que identifica a cada fila
*@example var rId = getSelectedRowId(gPruebas);
*/
function getSelectedRowId(grid) {
var row = _$(grid.body).find("tr[class='table-active']");
if (row.length > 0)
return getRowId(row[0]);
return '';
}
/**
*Devuelve el índice de la fila que esté seleccionada
*@param {object} grid Objeto de la grid ya inicializada
*@returns {string} rowId único que identifica a cada fila
*@example var rIdx = getSelectedRowIndex(gPruebas);
*/
function getSelectedRowIndex(grid) {
var row = _$(grid.body).find("tr[class='table-active']");
if (row.length > 0)
return getRowIndex(row);
return -1;
}
/**
*Devuelve el objeto de la grid a partir de una fila (row)
*@param {HTMLTableRowElement} row algún tr de la tabla
*@returns {object} Objeto de la grid ya inicializada
*/
function getGridFromRow(row) {
return getGridFrom(row);
}
/**
*Devuelve el objeto de la grid a partir de una celda (cell)
*@param {HTMLTableCellElement} cell algún td de la tabla
*@returns {object} Objeto de la grid ya inicializada
*/
function getGridFromCell(cell) {
return getGridFrom(cell);
}
function getGridFrom(obj) {
var tb = _$(obj).parents('table')[0];
return objGrids[tb.id].grid;
}
/**
*Devuelve un nuevo y único rowId
*@returns {string} El nuevo rowId generado
*@see <a href="https://www.w3resource.com/javascript-exercises/javascript-math-exercise-23.php" target="_blank">Código de Referencia</a>
*/
function getNewRowId() {
var dt = new Date().getTime();
var rId = 'xxxxx4xxyxxxxxxxx'.replace(/[xy]/g, function (c) {
var r = (dt + Math.random() * 16) % 16 | 0;
dt = Math.floor(dt / 16);
return (c == 'x' ? r : (r & 0x3 | 0x8)).toString(16);
});
return rId;
}
/**
*Se encarga de recorrer todas las filas de la grid
*@param {object} grid Objeto de la grid ya inicializada
*@param {function} fn Función que se encargará de procesar el ciclo por cada fila,
* la función que se envía como parámetro recibe el rowId de cada fila
*@example foreachRow(gPruebas, function(rId){
var row = getRow(gPruebas, rId);
unSelectRow(row);
});
*/
function foreachRow(grid, fn) {
var nRows = getRowsNum(grid);
var rows = grid.body.rows;
for (var i = 0; i < nRows; i++) {
if (rows[i] != null)
fn.apply(this, [getRowId(rows[i])]);
}
}
/**
*Se encarga recorrer todas las celdas de una fila
*@param {object} grid Objeto de la grid ya inicializada
*@param {string} rId rowId de la fila que se desea recorrer
*@param {function} fn Función que se encargará de procesar el ciclo por cada celda,
* la función que se envía como parámetro recibe el objeto cell (td) y el ínidice de cada celda
*@example var rId = getSelectedRowId(gPruebas);
foreachCell(gPruebas,rId, function(cell, cInd){
var val = getCellValue(gPruebas, rId, cInd);
console.log(val);
});
*/
function foreachCell(grid, rId, fn) {
var row = getRow(grid, rId);
var nCells = row.cells.length;
for (var i = 0; i < nCells; i++) {
fn.apply(this, [row.cells[i], i]);
}
}
/**
*Devuelve el número de filas de una grid
*@param {object} Objeto de la grid ya inicializada
*@returns {integer} Número equivalente a la cantidad de filas
*/
function getRowsNum(grid) {
return grid.body.rows.length;
}
/**
*Devuelve el número de columnas que tiene una grid
*@param {object} Objeto de la grid ya inicializada
*@returns {integer} Número equivalente a la cantidad de columnas
*/
function getCellsNum(grid) {
return grid.header.rows[0].cells.length;
}
/**
*Devuelve el objeto row (tr) de la grid según el rowId
*@param {object} grid Objeto de la grid ya inicializada
*@param {string} rId rowId único que identifica a cada fila
*@returns {HTMLTableRowElement} row de la fila indicada
*/
function getRow(grid, rId) {
var filtro = "tr[data-rid='{0}']".format(rId);
var row = _$(grid.body).find(filtro);
if (row.length > 0)
return row[0];
return null;
}
/**
*Devuelve el objeto row (tr) de la grid según el índice de la fila
*@param {object} grid Objeto de la grid ya inicializada
*@param {integer} index índice que identifica a cada fila (0,1,2)
*@returns {HTMLTableRowElement} row de la fila indicada
*/
function getRowFromIndex(grid, index) {
var row = _$(grid.body.rows).eq(index);
if (row.length > 0)
return row[0];
return null;
}
function getHeaderCell(grid, cInd) {
var row = _$(grid.header.rows[0]).children().eq(cInd);
if (row.length > 0)
return row[0];
return null;
}
/**
*Obtiene el Label de una columna especificada
*@param {object} grid Objeto de la grid ya inicializada
*@param {integer} cInd Índice o posición del header
*@returns {string} El label del header
*/
function getHeaderLabel(grid, cInd) {
var row = getHeaderCell(grid, cInd);
if (row != null)
return row.innerHTML;
return '';
}
/**
*Cambiar el rowId de una fila
*@param {HTMLTableRowElement} row algún tr de la tabla
*@param {string} rId rowId único que identifica a cada fila
*/
function setRowId(row, rId) {
row.dataset.rid = rId;
}
/**
*Obtener el rowId de una fila
*@param {HTMLTableRowElement} row algún tr de la tabla
*@returns {string} rowId único que identifica a cada fila
*/
function getRowId(row) {
return row.dataset.rid;
}
/**
*Obtener el Indice de una fila
*@param {HTMLTableRowElement} row algún tr de la tabla
*@returns {integer} ïndice o posición de esa fila en la tabla
*/
function getRowIndex(row) {
return _$(row).index();
}
/**
*Obtener el Indice de una fila por el rowId
*@param {object} grid Objeto de la grid ya inicializada
*@param {string} rId rowId único que identifica a cada fila
*@returns {integer} ïndice o posición de esa fila en la tabla
*/
function getRowIndexFromId(grid, rId) {
var row = getRow(grid, rId);
return _$(row).index();
}
/**
*Obtener el rowId de una fila por el índice
*@param {object} grid Objeto de la grid ya inicializada
*@param {integer} index ïndice o posición de esa fila en la tabla
*@returns {string} rowId único que identifica a cada fila
*/
function getRowIdFromIndex(grid, index) {
var row = getRowFromIndex(grid, index);
return row.dataset.rid;
}
/**
*Obtener el rowId de una fila por una celda especificada
*@param {HTMLTableCellElement} cell algún td de la fila
*@returns {string} rowId único que identifica a cada fila
*/
function getRowIdFromCell(cell) {
var row = _$(cell).parent('tr')[0];
return getRowId(row);
}
/**
*Obtiene el valor de una celda específica
*@param {object} grid Objeto de la grid ya inicializada
*@param {string} rId rowId único que identifica a cada fila
*@param {integer} cInd Índice de la columna específica
*@example var rId = getSelectedRowId(gPruebas);
var val = getCellValue(gPruebas, rId, gPruebasConf.Nombre.idx);
console.log(val);
*/
function getCellValue(grid, rId, cInd) {
var row = getRow(grid, rId);
return getRowCellValue(row, cInd);
}
/**
*Obtiene el valor de una celda específica
*@param {object} grid Objeto de la grid ya inicializada
*@param {integer} rIdx índice de la fila
*@param {integer} cInd Índice de la columna específica
*@example var val = getCellValue(gPruebas, 1, gPruebasConf.Nombre.idx);
console.log(val);
*/
function getCell2Value(grid, rIdx, cInd) {
var row = getRowFromIndex(grid, rIdx);
return getRowCellValue(row, cInd);
}
function getRowCellValue(row, cInd) {
var cell = getCell(row, cInd);
if (cell == null)
return '';
return cell.dataset.value;
}
/**
*Cambia el valor de una celda específica
*@param {object} grid Objeto de la grid ya inicializada
*@param {string} rId rowId único que identifica a cada fila
*@param {integer} cInd Índice de la columna específica
*@param {string} value Valor que se desea asignar a la celda
*@example var rId = getSelectedRowId(gPruebas);
setCellValue(gPruebas, rId, gPruebasConf.Nombre.idx, 'Ricardo Jorge');
*/
function setCellValue(grid, rId, cInd, value) {
var row = getRow(grid, rId);
var cell = getCell(row, cInd);
setCell2Value(cell, value, grid, cInd);
}
function setCell2Value(cell, value, gridN, cIndN) {
var cInd = (cIndN != null)? cIndN : getCellIndex(cell);
var grid = (gridN != null) ? gridN : getGridFromCell(cell);
if (grid != null && grid.colsFormat[cInd] != null) {
cell.innerHTML = _aplNF(grid, value, cInd);
cell.dataset.value = _aplNFb(grid, cell.innerHTML, cInd);
} else {
cell.dataset.value = value;
cell.innerHTML = value;
}
}
function setCell2ValueStr(cell, value, grid, cInd) {
var lblCol = getHeaderLabel(grid, cInd);
var hide = (isColumHidden(grid, cInd)) ? 'style="display: none;"' : '';
if (grid != null && grid.colsFormat[cInd] != null) {
var valHTML = _aplNF(grid, value, cInd);
cell = cell.format(value, lblCol, valHTML, hide);
} else {
cell = cell.format(value, lblCol, value, hide);
}
return cell;
}
/**
*Obtener el objeto td especificado
*@param {HTMLTableRowElement} row tr de la tabla
*@param {integer} cInd Índice de la columna específica
*@returns {HTMLTableCellElement} cell (td) de la fila y columna indicada
*/
function getCell(row, cInd) {
var cell = _$(row).children().eq(cInd);
if (cell.length > 0)
return cell[0];
return null;
}
/**
*Obtener el índice de una celda especificada
*@param {HTMLTableCellElement} cell (td) de una fila
*@returns {integer} Índice de la celda
*/
function getCellIndex(cell) {
return _$(cell).index();
}
/**
*Oculta una columna especificada
*@param {object} grid Objeto de la grid ya inicializada
*@param {integer} cInd Índice de la columna
*@example hideColumn(gPruebas, gPruebasConf.Nombre.idx);
*/
function hideColumn(grid, cInd) {
hideShowColumn(grid, cInd, false);
}
/**
*Oculta varias columna especificadas
*@param {object} grid Objeto de la grid ya inicializada
*@param {Array} arrCInd Arreglo con los Índices de las columnas
*@example hideColumns(gPruebas, [gPruebasConf.Nombre.idx, gPruebasConf.Edad.idx]);
*/
function hideColumns(grid, arrCInd) {
for (var i = 0; i < arrCInd.length; i++) {
hideShowColumn(grid, arrCInd[i], false);
}
}
/**
*Oculta las columna según la propiedad ver de la configuración {@tutorial gridConf}
*@param {object} grid Objeto de la grid ya inicializada
*@param {object} conf Objeto de configuración de la grid
*@example hideColumnsConf(gPruebas, gPruebasConf);
*/
function hideColumnsConf(grid, conf) {
for (var c in conf) {
if (conf[c].ver != null && !conf[c].ver)
hideColumn(grid, conf[c].idx);
}
}
/**
*Muestra una columna especificada
*@param {object} grid Objeto de la grid ya inicializada
*@param {integer} cInd Índice de la columna
*@example showColumn(gPruebas, gPruebasConf.Nombre.idx);
*/
function showColumn(grid, cInd) {
hideShowColumn(grid, cInd, true);
}
/**
*Muestra varias columna especificadas
*@param {object} grid Objeto de la grid ya inicializada
*@param {Array} arrCInd Arreglo con los Índices de las columnas
*@example showColumns(gPruebas, [gPruebasConf.Nombre.idx, gPruebasConf.Edad.idx]);
*/
function showColumns(grid, arrCInd) {
for (var i = 0; i < arrCInd.length; i++) {
hideShowColumn(grid, arrCInd[i], true);
}
}
function hideShowColumn(grid, cInd, view) {
foreachRow(grid, function (rId) {
var row = getRow(grid, rId);
var cell = getCell(row, cInd);
if (view)
_$(cell).css('display', '');
else
_$(cell).css('display', 'none');
});
var hCell = getHeaderCell(grid, cInd);
if (view) {
_$(hCell).css('display', '');
delete grid.colsHidden[_$(hCell).index()];
} else {
grid.colsHidden[_$(hCell).index()] = _$(hCell).index();
_$(hCell).css('display', 'none');
}
}
/**
*Marca si al encontrar un error en una celda oculta, se pinte toda la fila de rojo
*@param {object} grid Objeto de la grid ya inicializada
*@param {boolean} validar true si desea que se marque toda la fila, false lo contrario
*@example pintarFilasOcultas(gPruebas, false);
*/
function pintarFilasOcultas(grid, validar) {
grid.pintarFilaOculta = validar;
}
/**
*Marca si se desea que al hacer click en una celda se abra el modal automáticamente para editar
*@param {object} grid Objeto de la grid ya inicializada
*@param {boolean} edit true si desea que se abra el modal, false lo contrario
*@example editOnClick(gPruebas, true);
*/
function editOnClick(grid, edit) {
grid.editOnClick = edit;
}
/**
*Habilitar lo lógica de editar y eliminar automáticamente
*@param {object} grid Objeto de la grid ya inicializada
*@param {boolean} enabled true si desea que habilitar, false lo contrario
*@param {string} iconosOpt Íconos de agregado y eliminado
*@param {integer} colOpt Índice de la columna donde van a estar los íconos
*@example var optAdd = "<i class='material-icons pointer iPopup' data-tipo='add'>add_circle_outline</i>";
var optDel = "<i class='material-icons pointer iPopup' data-tipo='delete'>remove_circle_outline</i>";
var iOpts = optAdd + optDel;
addEventOpt(gPruebas, true, iOpts, gPruebasConf.Opc.idx);
*/
function addEventOpt(grid, enabled, iconosOpt, colOpt) {
grid.addEventOpt = enabled;
if (iconosOpt != null)
grid.iconosOpt = iconosOpt;
if (colOpt != null)
grid.colOpt = colOpt;
}
/**
*Marca si se desea marcar con error los campos en el modal cuando se tenga error en la grid
*@param {object} grid Objeto de la grid ya inicializada
*@param {boolean} validar true si desea que se marquen los campos, false lo contrario
*@example validarCamposPopup(gPruebas, true);
*/
function validarCamposPopup(grid, validar) {
grid.valPopup = validar;
}
/**
*Agrega una fila a la grid
*@param {object} grid Objeto de la grid ya inicializada
*@param {string} rId (opcional) rowId único que identifica a cada fila, si no se envía se asigna uno automáticamente
*@param {Array} values Contiene los valores a agregar en la fila, si el arreglo es vacio, crea la fila sin datos
*@param {boolean} noCallEvt (opcional) Se envia true si al agregar la fila no se quiere disparar el evento onRowAdded
*@example addRow(gPruebas, '', []);
*/
function addRow(grid, rId, values, noCallEvt) {
//Se esta creando por HTML y no por DOM
return addRowStr(grid, rId, values, noCallEvt);
}
function addRowStr(grid, rId, values, noCallEvt) {
if (rId == null || rId == '')
rId = getNewRowId();
var newRow = _getNewRowStr(grid, values, rId);
_$(grid.body).append(newRow);
if (noCallEvt == null || !noCallEvt)
_onRowAdded(grid, rId);
newRow = getRow(grid, rId);
addEventsOpt(grid, newRow);
_addEventRow(newRow, 'click', function (e) {
_removeSelectedAll(grid);
selectRow(this);
});
return rId;
}
function addEventsOpt(grid, row) {
//Eventos para opciones de agregar y eliminar
if (grid.addEventOpt) {
if (grid.colOpt != null && grid.iconosOpt != null) {
var rId = getRowId(row);
var valOpt = getCellValue(grid, rId, grid.colOpt);
if (valOpt == '')
setCellValue(grid, rId, grid.colOpt, grid.iconosOpt);
}
var opts = _$(row).find(".iPopup");
if (opts.length > 0) {
opts.unbind();
opts.on('click', function (e) {
e.stopPropagation();
var row = _$(this).parents('tr')[0];
_removeSelectedAll(grid);
_selectRow(row);
verModalF7(e);
});
}
}
}
/**
*Cambia los valores de una fila completa
*@param {object} grid Objeto de la grid ya inicializada
*@param {string} rId rowId único que identifica a cada fila
*@param {Array} values tiene los valores de cada columna
*@example var rId = getSelectedRowId(gPruebas);
setDataRow(gPruebas, rId, ['Juan Carlos', 'Gonzales', '28']);
*/
function setDataRow(grid, rId, values) {
if (rId != '') {
foreachCell(grid, rId, function (cell, cInd) {
if (values[cInd] != null)
setCell2Value(cell, values[cInd], grid, cInd);
else
setCell2Value(cell, '', grid, cInd);
});
var row = getRow(grid, rId);
addEventsOpt(grid, row);
_onRowEdit(grid, rId);
}
}
/**
*Limpia una fila
*@param {object} grid Objeto de la grid ya inicializada
*@param {string} rId rowId único que identifica a cada fila
*@example var rId = getSelectedRowId(gPruebas);
clearRow(gPruebas, rId);
*/
function clearRow(grid, rId) {
if (rId != '') {
var row = getRow(grid, rId);
foreachCell(grid, rId, function (cell, cInd) {
setCell2Value(cell, '', grid, cInd);
});
}
}
/**
*Indica si una fila tiene datos, ignorando las opciones de agregar y eliminar
*@param {object} grid Objeto de la grid ya inicializada
*@param {string} rId rowId único que identifica a cada fila
*@returns {boolean} true si tiene, false si no tiene
*@example var rId = getSelectedRowId(gPruebas);
if(dataInRow(gPruebas, rId)){
console.log('Tiene datos');
}
*/
function dataInRow(grid, rId) {
if (rId != '') {
var row = getRow(grid, rId);
var iData = false;
foreachCell(grid, rId, function (cell, cInd) {
var val = getCellValue(grid, rId, cInd);
if (!iData && val != '' && _$(cell).find('i').length == 0)
iData = true;
});
}
return iData;
}
/**
*Elimina una fila especificada
*@param {object} grid Objeto de la grid ya inicializada
*@param {string} rId rowId único que identifica a cada fila
*@example var rId = getRowIdFromIndex(gPruebas, 3);
removeRow(gPruebas, rId);
*/
function removeRow(grid, rId) {
_onBeforeRowDelete(grid, rId);
__removeRow(grid, rId);
_onRowDelete(grid);
}
function __removeRow(grid, rId) {
var row = getRow(grid, rId);
_$(grid.body)[0].removeChild(row);
}
/**
*Obtiene el XML de una grid
*@param {object} grid Objeto de la grid ya inicializada
*@param {Array} cIndExcluir Índices de las columnas que no se desean grabar
*@param {function} fnVal (opcional) Función para validar si una fila se graba o no,
* la función que se envía como parámetro recibe el rowId y debe retornar un booleano
*@example var xmlGrid = getXml(gPruebas, [gPruebasConf.Opc.idx], function(rId){
var nombre = getCellValue(gPruebas, rId, gPruebasConf.Nombre.idx);
if(nombre == 'Andrés')
return false;
return true;
});
*/
function getXml(grid, cIndExcluir, fnVal) {
var fRow = '<r id="{0}">{1}</r>';
var fCell = '<c>{0}</c>';
var arrRows = [];
var idx = 0;
foreachRow(grid, function (rId) {
var arrCells = [];
if (fnVal != null) {
var rowValid = fnVal.apply(grid, [rId]);
if (!rowValid)
return;
}
foreachCell(grid, rId, function (cell, cInd) {
if (cIndExcluir.indexOf(cInd) == -1) {
var val = cell.dataset.value;
arrCells.push(fCell.format(val));
}
});
arrRows.push(fRow.format(idx, arrCells.join('')));
idx++;
});
return arrRows.join('');
}
/**
*Obtiene el XML de una grid en otro hilo
*@param {object} grid Objeto de la grid ya inicializada
*@param {Array} cIndExcluir Índices de las columnas que no se desean grabar
*@param {function} fnCb (opcional) Función de callback cuando el proceso ha finalzado, se entrega el XML
*@example getXmlWorker(gPruebas, [gPruebasConf.Opc.idx], function(xmlGrid){
console.log(xmlGrid);
});
*/
function getXmlWorker(grid, cIndExcluir, fnCb) {
worker = new Worker('../javascript/htmlGridWorker.js?v=5');
worker.addEventListener('message', function (e) {
var obj = e.data;
if (obj.nFilas != null && obj.xml != null) {
worker.terminate();
fnCb.apply(this, [obj.xml]);
}
});
var html = grid.body.innerHTML;
worker.postMessage({ 'html': html, 'tipo': 'xml', 'colsEx': cIndExcluir });
}
/**
*Carga filas en la grid mediante una cadena XML
*@param {object} grid Objeto de la grid ya inicializada
*@param {string} xml datos a parsear
*@example var xmlSample = "<rows><row id="0"><cell>Pepito</cell><cell>26</cell></row><row id="1"><cell>Jon Doe</cell><cell>43</cell></row></rows>";
parseXml(gPruebas, xmlSample);
*/
function parseXml(grid, xml) {
if (xml != '') {
try {
var iXml = StringtoXML(xml);
var rows = iXml.childNodes[0];
var nRows = rows.childNodes.length;
var nCells = rows.childNodes[0].childNodes.length;
for (var i = 0; i < nRows; i++) {
var valuesGrid = [];
var row = rows.childNodes[i];
for (var j = 0; j < nCells; j++) {
var cell = row.childNodes[j];
var val = cell.innerHTML;
valuesGrid.push(val);
}
addRow(grid, '', valuesGrid);
}
_onParseXml(grid, nRows);
} catch (E) {
console.error("Error al parsear XML", E);
}
}
}
/**
*Limpia la grid, dejándola sin filas
*@param {object} grid Objeto de la grid ya inicializada
*@example clearAll(gPruebas);
*/
function clearAll(grid) {
grid.body.innerHTML = '';
grid.rowsBuffer = '';
}
/**
*Indica si una columna está o no oculta
*@param {object} grid Objeto de la grid ya inicializada
*@param {integer} cInd Índice de la columna
*@returns {boolean} true si está oculta, false si no lo está
*/
function isColumHidden(grid, cInd) {
if (grid.colsHidden[cInd] != null)
return true;
return false;
}
function validateGridWorker(grid, conf, fnCb, fnValRow, fnBeforeValRow) {
worker = new Worker('../javascript/htmlGridWorker.js?v=1');
worker.addEventListener('message', function (e) {
var obj = e.data;
if (obj.arrDatos != null) {
worker.terminate();
var colsV = getColsValidate(conf);
var colsE = getColsEnlazadas(conf);
var errors = { totalError: 0, numFilasV: 0 };
var promesas = [];
for (var x = 0; x < obj.arrDatos.length; x++) {
promesas.push(validateRowPromesa(
grid, conf, obj.arrDatos[x].rId, fnBeforeValRow, colsV, colsE, errors)
.then(function (rId) {
if (fnValRow != null)
fnValRow.apply(grid, [rId, errors]);
if (!grid.pintarFilaOculta) {
for (var c in colsE) {
var row = getRow(grid, rId);
var cell = getCell(row, c);
var cellE = getCell(row, colsE[c]);
if (_$(cellE).hasClass('row-error'))
_$(cell).addClass('row-error');
}
}
}, function (err) {
console.log(err);
})
);
}
Promise.all(promesas)
.then((r) => {
if (fnCb != null)
fnCb.apply(grid, [errors]);
});
}
});
var confC = getConfToWorker(conf);
var idG = grid.tabla.id;
var html = _$(grid.tabla).find('tbody').html();
worker.postMessage({ 'html': html, 'id': idG, 'conf': confC, 'tipo': 'arrDatos' });
}
/**
*Valida la grid, según la configuración indicada.
*Se valida requerido, mínimo, máximo, expresión regular y valor de columna enlazada {@tutorial gridConf}
*@param {object} grid Objeto de la grid ya inicializada
*@param {object} conf Objeto de configuración de la grid
*@param {function} fnCb Función que se encargará de Obtener el resultado de la validación
* ésta función recibe un objeto que indica la cantidad de errores totales y los errores por columnas
*@param {function} fnValRow Función que se invoca después de pasar la validación por cada fila
* ésta función recibe el rowId
*@param {function} fnBeforeValRow Función que se invoca antes de pasar la validación por cada fila
* ésta función recibe el rowId
*@returns {object} Si no se envía función de callback, retorna el objeto con los errores
*@example validateGrid(gPruebas, gPruebasConf, function(errors){
if(errors.totalError > 0){
console.log('Grid con errores');
return;
}
}, null, function(rId){
var nombre = getCellValue(gPruebas, rId, gPruebasConf.Nombre.idx);
if(nombre == 'Harri')
gPruebasConf.Edad.req = false;
else
gPruebasConf.Edad.req = true;
});
*/
function validateGrid(grid, conf, fnCb, fnValRow, fnBeforeValRow) {
var colsV = getColsValidate(conf);
var colsE = getColsEnlazadas(conf);
var errors = { totalError: 0, gridId: grid.tabla.id};
//Validación rápida grids pesadas
if (grid.liteValidate) {
errors = liteValidateGrid(grid, colsV, errors);
if (fnCb != null) {
fnCb.apply(grid, [errors]);
return;
}else {
return errors;
}
}
foreachRow(grid, function (rId) {
validateRow(grid, conf, rId, fnBeforeValRow, colsV, colsE, errors);
if (fnValRow != null)
fnValRow.apply(grid, [rId, errors]);
//No pintar la fila completa, pintar la celda enlazada
if (!grid.pintarFilaOculta) {
for (var c in colsE) {
var row = getRow(grid, rId);
var cell = getCell(row, c);
var cellE = getCell(row, colsE[c]);
if (_$(cellE).hasClass('row-error'))
_$(cell).addClass('row-error');
}
}
});
if (fnCb != null)
fnCb.apply(grid, [errors]);
else
return errors;
}
function validateRow(grid, conf, rId, fnBeforeValRow, colsV, colsE, errors) {
var row = getRow(grid, rId);
_$(row).removeClass('row-error');
var errorRow = false;
if (fnBeforeValRow != null) {
fnBeforeValRow.apply(grid, [rId, errors]);
colsV = getColsValidate(conf);
}
foreachCell(grid, rId, function (cell, cInd) {
_$(cell).removeClass('row-error');
if (colsV[cInd] != null) {
var objCol = colsV[cInd];
var val = cell.dataset.value;
var labelCol = getHeaderLabel(grid, cInd);
var errorCelda = false;
if (objCol.req && val == '')
errorCelda = true;
if (objCol.min != null && val.length < objCol.min)
errorCelda = true;
if (objCol.max != null && val.length > objCol.max)
errorCelda = true;
if (objCol.regExp != null && val != '' && !objCol.regExp.test(val))
errorCelda = true;
if (objCol.colEnlazada != null && objCol.noValM == null && val != '') {
var valE = getCellValue(grid, rId, objCol.colEnlazada);
if (valE == '')
errorCelda = true;
}
if (errorCelda) {
if (grid.pintarFilaOculta && grid.colsHidden[_$(cell).index()] != null) {
_$(row).addClass('row-error');
removeAllCellError(grid, rId);
errorRow = true;
} else if (!errorRow) {
_$(cell).addClass('row-error');
}
if (errors[labelCol] == null)
errors[labelCol] = 0;
errors[labelCol]++;
errors.totalError++;
} else {
_$(cell).removeClass('row-error');
}
}
});
}
/**
*Marca una celda con error
*@param {object} grid Objeto de la grid ya inicializada
*@param {string} rId rowId único que identifica a cada fila
*@param {integer} cInd Índice de la columna
*/
function addCellError(grid, rId, cInd) {
addRemoveCellError(grid, rId, cInd, true);
}
/**
*Quita el error a una celda
*@param {object} grid Objeto de la grid ya inicializada
*@param {string} rId rowId único que identifica a cada fila
*@param {integer} cInd Índice de la columna
*/
function removeCellError(grid, rId, cInd) {
addRemoveCellError(grid, rId, cInd, false);
}
function addRemoveCellError(grid, rId, cInd, add) {
var row = getRow(grid, rId);
var cell = getCell(row, cInd);
if(add)
_$(cell).addClass('row-error');
else
_$(cell).removeClass('row-error');
}
/**
*Quita el error a todas las celda
*@param {object} grid Objeto de la grid ya inicializada
*@param {string} rId rowId único que identifica a cada fila
*/
function removeAllCellError(grid, rId) {
foreachCell(grid, rId, function (cell, cInd) {
_$(cell).removeClass('row-error');
});
//v2
//_$('tr[data-rid="{0}"] td'.format(rId)).removeClass('row-error');
}
function getColsValidate(conf) {
var colsV = {};
for (var k in conf) {
if (conf[k].req || conf[k].min || conf[k].max || conf[k].regExp || conf[k].colEnlazada)
colsV[conf[k].idx] = conf[k];
}
return colsV;
}
function getColsEnlazadas(conf) {
var colsE = {};
for (var k in conf) {
if (conf[k].colEnlazada)
colsE[conf[k].idx] = conf[k].colEnlazada;
}
return colsE;
}
function getObjColIdx(idx, gConf) {
for (var c in gConf) {
if (gConf[c].idx == idx) {
return gConf[c];
}
}
return null;
}
/**
*Busca dentro de la grid un valor especificado
*@param {object} grid Objeto de la grid ya inicializada
*@param {integer} cInd Índice de la columna
*@param {string} val valor a buscar
*@param {boolean} first true si desea devolver solo la primera fila que encuentra
*@returns {Array} contiene objetos con el rowId y los índices de las celdas que coinciden
*@example var arrRIds = find(gPruebas, gPruebasConf.Apellido.idx, 'Perez', true);
if(arrRIds.length > 0){
var nombre = getCellValue(gPruebas, arrRIds[0].rId, gPruebasConf.Nombre.idx);
console.log(nombre);
}
*/
function find(grid, cInd, val, first) {
var rFiles = [];
if (grid.body != null) {
var cell = _$(grid.body).find("td[data-value='{0}']".format(val));
if (cell.length > 0) {
for (var i = 0; i < cell.length; i++) {
if (cInd == null || cInd == getCellIndex(cell[i])) {
var row = _$(cell[i]).parent('tr')[0];
rFiles.push({ 'rId': getRowId(row), 'cInd': getCellIndex(cell[i]) });
if (first)
return rFiles;
}
}
}
}
return rFiles;
}
/**
*Busca dentro de la grid combinaciones de valores
*@param {object} grid Objeto de la grid ya inicializada
*@param {Array} arrCInd Índices de las columnas donde se va a buscar
*@param {Array} arrVal valores a buscar, deben corresponder a las columnas y estar en el mismo orden
*@param {boolean} first true si desea devolver solo la primera fila que encuentra
*@returns {Array} contiene objetos con el rowId y los índices de las celdas que coinciden
*@example var arrRIds = findMulti(gPruebas, [gPruebasConf.Nombre.idx, gPruebasConf.Apellido.idx], ['Juan', 'Perez'], true);
if(arrRIds.length > 0){
var edad = getCellValue(gPruebas, arrRIds[0].rId, gPruebasConf.Edad.idx);
console.log(edad);
}
*/
function findMulti(grid, arrCInd, arrVal, first) {
var rFiles = [];
if (grid.body != null) {
var cell = _$(grid.body).find("td[data-value='{0}']".format(arrVal[0]));
if (cell.length > 0) {
//Buscar sobre las filas encontradas con el primer valor los demás valores
for (var i = 0; i < cell.length; i++) {
if (arrCInd[0] == getCellIndex(cell[i])) {
var arrValFind = [];
arrValFind.push(cell[i].dataset.value);
var row = _$(cell[i]).parent('tr')[0];
for (var c = 1; c < arrVal.length; c++) {
var cellA = _$(row).find("td[data-value='{0}']".format(arrVal[c]));
if (cellA.length > 0) {
for (var x = 0; x < cellA.length; x++) {
if(arrCInd[c] == getCellIndex(cellA[x]))
arrValFind.push(cellA[0].dataset.value);
}
}
}
if (arrValFind.join('') == arrVal.join(''))
rFiles.push({ 'rId': getRowId(row), 'cInd': getCellIndex(cell[i]) });
if (first && rFiles.length > 0)
return rFiles;
}
}
}
}
return rFiles;
}
/**
*Agrea formato numérico a columnas en la grid
*@param {object} grid Objeto de la grid ya inicializada
*@param {string} mask Máscara usada para el formateo
*@param {integer} cInd Índice de la columna
*@param {string} p_sep Separador de miles
*@param {string} d_sep Separador de decimales
*@example setNumberFormat(gPruebas, '$ 000,000', gPruebasConf.Salario.idx, '.', ',');
*/
function setNumberFormat(grid, mask, cInd, p_sep, d_sep) {
var nmask = mask.replace(/[^0\,\.]*/g, "");
var pfix = nmask.indexOf(".");
if (pfix > -1)
pfix = nmask.length - pfix - 1;
var dfix = nmask.indexOf(",");
if (dfix > -1)
dfix = nmask.length - pfix - 2 - dfix;
if (typeof p_sep != "string")
p_sep = '.';
if (typeof d_sep != "string")
d_sep = ',';
var pref = mask.split(nmask)[0];
var postf = mask.split(nmask)[1];
grid.colsFormat[cInd] = [
pfix,
dfix,
pref,
postf,
p_sep,
d_sep
];
}
//Funciones Internas
function _aplNFb(grid, data, ind) {
var a = grid.colsFormat[ind];
if (!a)
return data;
var ndata = parseFloat(data.toString().replace(/[^0-9]*/g, ""));
if (data.toString().substr(0, 1) == "-")
ndata = ndata * -1;
if (a[0] > 0)
ndata = ndata / Math.pow(10, a[0]);
return ndata;
}
function _aplNF(grid, data, ind) {
if (isNaN(parseFloat(data)))
data = 0;
var a = grid.colsFormat[ind];
if (!a)
return data;
var c = (parseFloat(data) < 0 ? "-" : "")+a[2];
data=Math.abs(Math.round(parseFloat(data)*Math.pow(10, a[0] > 0 ? a[0] : 0))).toString();
data=(data.length
< a[0]
? Math.pow(10, a[0]+1-data.length).toString().substr(1, a[0]+1)+data.toString()
: data).split("").reverse();
data[a[0]]=(data[a[0]]||"0")+a[4];
if (a[1] > 0)
for (var j = (a[0] > 0 ? 0 : 1)+a[0]+a[1]; j < data.length; j+=a[1])data[j]+=a[5];
return c+data.reverse().join("")+a[3];
}
function _hideColumnsRow(grid, rId) {
foreachCell(grid, rId, function (cell, cInd) {
if (isColumHidden(grid, cInd))
hideColumn(grid, cInd);
});
}
function _addRowIdAndValueFromTable(grid, conf) {
var nRows = getRowsNum(grid);
var rows = grid.body.rows;
var nCells = rows[0].cells.length;
for (var i = 0; i < nRows; i++) {
setRowId(rows[i], getNewRowId());
if (nRows <= maxRowsValidate && conf != null)
_normalizeGrid(grid, conf, nCells, i);
for (var j = 0; j < nCells; j++) {
var cell = getCell(rows[i], j);
var valHtml = cell.innerHTML;
if (valHtml.indexOf(' ') != -1) {
valHtml = valHtml.replace(/ /g, '');
cell.innerHTML = valHtml;
}
cell.dataset.value = valHtml;
}
}
}
function _normalizeGrid(grid, conf, nCells, idxRow, rId) {
var colsHeader = grid.header.rows[0].cells.length;
if (nCells < colsHeader) {
var numColsF = colsHeader - nCells;
for (var i = 0; i < numColsF; i++) {
var colIdx = nCells;
var objCol = getObjColIdx(colIdx, conf);
var label = getHeaderLabel(grid, colIdx);
var vDef = (objCol != null && objCol.vDef != null) ? objCol.vDef : '';
var td = '<td data-value="{0}" data-collapsible-title="{1}">{0}</td>'.format(vDef, label);
_$(grid.body.rows[idxRow]).append(td);
if (objCol != null && objCol.eventOpc != null) {
grid.addEventOpt = true;
addEventsOpt(grid, grid.body.rows[idxRow]);
grid.addEventOpt = false;
}
}
}
}
function _addRowIdFromTable(grid) {
var nRows = getRowsNum(grid);
var rows = grid.body.rows;
for (var i = 0; i < nRows; i++) {
setRowId(rows[i], (getNewRowId() + i));
}
}
function _addAllDataCollapsableTitle(grid) {
foreachRow(grid, function (rId) {
foreachCell(grid, rId, function (cell) {
_addDataCollapsableTitle(grid, cell);
});
});
}
function _addRowCellDataCollapsableTitle(grid, rId) {
foreachCell(grid, rId, function (cell) {
_addDataCollapsableTitle(grid, cell);
});
}
function _addDataCollapsableTitle(grid, cell) {
var cInd = getCellIndex(cell);
var hCell = getHeaderCell(grid, cInd);
if (hCell != null)
cell.dataset.collapsibleTitle = hCell.innerHTML;
}
function _addValueFromTable(grid) {
foreachRow(grid, function (rId) {
foreachCell(grid, rId, function (cell) {
var valHtml = cell.innerHTML;
if (valHtml.indexOf(' ') != -1) {
valHtml = valHtml.replace(/ /g, '');
cell.innerHTML = valHtml;
}
var val = cell.dataset.value;
cell.dataset.value = valHtml;
});
});
}
function _addEventRows(grid, evento, fn) {
var nRows = getRowsNum(grid);
var rows = grid.body.rows;
for (var i = 0; i < nRows; i++) {
_addEventRow(rows[i], evento, fn);
}
}
function _addEventRow(row, evento, fn) {
_$(row).on(evento, fn);
}
function _removeSelectedAll(grid) {
_$(grid.body).find('.table-active').removeClass('table-active')
}
function _getNewRow(grid, values) {
var row = document.createElement('tr');
var nCells = getCellsNum(grid);
for (var i = 0; i < nCells; i++) {
var cell = document.createElement('td');
var val = (values[i] != null) ? values[i] : '';
setCell2Value(cell, val, grid, i);
_$(row).append(cell);
}
return row;
}
function _getNewRowStr(grid, values, rId) {
var row = '<tr data-rid="{0}">{1}</tr>';
var arrCell = [];
var nCells = getCellsNum(grid);
for (var i = 0; i < nCells; i++) {
var cell = '<td data-value="{0}" data-collapsible-title="{1}" {3}>{2}</td>';
var val = (values[i] != null) ? values[i] : '';
try {
if (val != null || typeof val == 'string')
val = val.replace(/"/g, "'");
} catch (E) {}
cell = setCell2ValueStr(cell, val, grid, i);
arrCell.push(cell);
}
return row.format(rId, arrCell.join(''));
}
//Eventos
/**
*Agrega un evento específico a la grid
*@param {string} event Nombre del evento que se desea agrear a la grid {@tutorial gridEvent}
*@param {object} grid Objeto de la grid ya inicializada
*@param {function} fnCb Función que manejará el evento,
* todos los eventos retornan el rowId, excepto onRowDelete
*@example addEventGrid('onRowAdded', gPruebas, function(rId){
setCellValue(gPruebas, rId, gPruebasConf.Estatus.idx, 'Nuevo');
});
*/
function addEventGrid(event, grid, fnCb) {
if (grid[event] == null)
grid[event] = [];
grid[event].push(fnCb);
}
function _onRowAdded(grid, rId) {
_callEvent(grid, rId, 'onRowAdded');
}
function _onRowEdit(grid, rId) {
_callEvent(grid, rId, 'onRowEdit');
}
function _onRowDelete(grid) {
_callEvent(grid, null, 'onRowDelete');
}
function _onBeforeRowDelete(grid, rId) {
_callEvent(grid, rId, 'onBeforeRowDelete');
}
function _onBeforeOpenPopup(grid, rId) {
_callEvent(grid, rId, 'onBeforeOpenPopup');
}
function _onOpenPopup(grid, rId) {
_callEvent(grid, rId, 'onOpenPopup');
}
function _onRowSelected(grid, rId) {
_callEvent(grid, rId, 'onRowSelected');
}
function _onParseXml(grid, nRows) {
if (grid['onParseXml'] != null)
grid['onParseXml'].apply(grid, [nRows]);
}
function _callEvent(grid, rId, event) {
if (grid[event] != null && grid[event].length > 0) {
try {
for (var i = 0; i < grid[event].length; i++) {
if (rId != null)
grid[event][i].apply(grid, [rId]);
else
grid[event][i].apply(grid);
}
} catch (E) {
console.error('Error en el evento ' + event, grid.tabla.id, E);
}
}
}
function _addSelectRow(grid) {
_$(grid.body.rows).on('click', function (e) {
_removeSelectedAll(grid);
selectRow(this);
});
}
function StringtoXML(text) {
if (window.ActiveXObject) {
var doc = new ActiveXObject('Microsoft.XMLDOM');
doc.async = 'false';
doc.loadXML(text);
} else {
var parser = new DOMParser();
var doc = parser.parseFromString(text, 'text/xml');
}
return doc;
}
//Popups
/**
*Guarda los datos del Popup en la grid a partir del event
*@param {event} e Evento que disparan las opciones de agregar, editar y eliminar
*/
function guardarDatosPopup(e) {
var dvPadre = _$(e.target).parents('.popup');
if (_$(dvPadre).hasClass('noGrid'))
return;
guardarPopup(dvPadre);
}
/**
*Guarda los datos del Popup en la grid a partir del div popup
*@param {object} dvPadre Objeto jQuery con el div popup
*@example guardarPopup(_$('#_gPruebas'));
*/
function guardarPopup(dvPadre) {
if (dvPadre.length > 0) {
var idGrid = dvPadre[0].id.replace('_', '');
var rId = dvPadre[0].dataset.rid;
var grid = objGrids[idGrid].grid;
var confGrid = objGrids[idGrid].conf;
var datos = getDatosPopup(confGrid);
if ((rId == null || rId == '') && (getRowsNum(grid) == 1)) {
rId = getRowIdFromIndex(grid, 0);
if (dataInRow(grid, rId))
rId = null;
}
if (rId != null && rId != '') {
setDataRow(grid, rId, datos);
} else if (agregoDatosPopup(confGrid)) {
addRow(grid, '', datos);
}
if (!_$(dvPadre).hasClass('noClosePopup')) {
app.popup.close('#_' + idGrid);
dvPadre[0].dataset.rid = '';
}
}
}
/**
*Obtiene el arreglo con los datos ingresados en el popup
*@param {object} conf Objeto de configuración de la grid, {@tutorial gridConf}
*@param {boolean} forceValidate Indica si se desea forzar la validación de los campos en el modal
*@example var data = getDatosPopup(gDatosConf, false);
*/
function getDatosPopup(conf, forceValidate) {
var datos = [];
for (var e in conf) {
var idE = conf[e].id;
if (idE == null) {
continue;
console.log('idConf Null ' + JSON.stringify(conf[e]));
}
if (idE != '') {
if (isFieldType(idE.toUpperCase(), ['R', '_R', 'C', '_C'])) {
datos[conf[e].idx] = _$('input[name="' + idE + '"]:checked').val();
} else {
if (_$('#' + idE).prop('multiple') != null && _$('#' + idE).prop('multiple'))
datos[conf[e].idx] = _$('#' + idE).val().join(',');
else
datos[conf[e].idx] = _$('#' + idE).val();
}
} else if (conf[e].vDef) {
datos[conf[e].idx] = conf[e].vDef;
}
if (forceValidate != null && forceValidate) {
if (_$('#' + idE).val() == '')
app.input.validate('#' + idE);
}
}
return datos;
}
/**
*Indica si en el popup ingresaron datos
*@param {object} conf Objeto de configuración de la grid, {@tutorial gridConf}
*@returns {boolean} true si se agregó algún valor, false si no
*@example if(!agregoDatosPopup(gPruebasConf)){
console.log('No agregó ningún valor en el popup');
}
*/
function agregoDatosPopup(conf) {
var datos = [];
for (var e in conf) {
var idE = conf[e].id;
if (idE != '')
datos[conf[e].idx] = _$('#' + idE).val();
}
if (datos.join('') == '')
return false;
return true;
}
/**
*Obtiene los datos de una fila específica
*@param {object} grid Objeto de la grid ya inicializada
*@param {string} rId rowId único que identifica a cada fila
*@param {object} conf Objeto de configuración de la grid, {@tutorial gridConf}
*@returns {Array} Datos de la fila
*@example var rId = getSelectedRowId(gPruebas);
var data = getDatosCellGrid(gPruebas, rId, gPruebasConf);
console.log(data);
*/
function getDatosCellGrid(grid, rId, conf) {
var datos = [];
for (var e in conf) {
var val = getCellValue(grid, rId, conf[e].idx);
var idE = conf[e].id;
if (idE != '')
datos[conf[e].idx] = val;
}
return datos;
}
function reverseValueXML(val) {
return val.replace(/&/g, '&');
}
/**
*Carga los datos de una fila de la grid en el popup
*@param {object} grid Objeto de la grid ya inicializada
*@param {string} rId rowId único que identifica a cada fila
*@param {object} conf Objeto de configuración de la grid, {@tutorial gridConf}
*@example var rId = getSelectedRowId(gPruebas);
cargarDatosPopup(gPruebas, rId, gPruebasConf);
*/
function cargarDatosPopup(grid, rId, conf) {
for (var e in conf) {
var valCell = getCellValue(grid, rId, conf[e].idx);
valCell = reverseValueXML(valCell);
var idE = conf[e].id;
if (conf[e].vDef != null && valCell == '')
valCell = conf[e].vDef;
if (idE != null && idE != '') {
if (isFieldType(idE.toUpperCase(), ['R', '_R', 'C', '_C'])) {
_$('input[name="' + idE + '"]').prop('checked', false);
_$('input[name="' + idE + '"][value="' + valCell + '"]').prop('checked', true);
} else if (isFieldType(idE.toUpperCase(), ['S', '_S'])) {
if (_$('#' + idE).prop('multiple') != null && _$('#' + idE).prop('multiple')) {
if (valCell != '')
_$('#' + idE).val(valCell.split(','));
else
_$('#' + idE).val([]);
} else {
_$('#' + idE).val(valCell);
}
var s = app.smartSelect.get('.' + idE);
if (s != null) {
var txt = _$('#' + idE).find("option:selected").text();
s.setValue(txt);
}
} else {
_$('#' + idE).val(valCell);
}
}
}
}
/**
*Limpia el popup
*@param {object} conf Objeto de configuración de la grid, {@tutorial gridConf}
*@example limpiarPopup(gPruebasConf);
*/
function limpiarPopup(conf) {
for (var e in conf) {
var idE = conf[e].id;
if (idE == '')
continue;
if (isFieldType(idE.toUpperCase(), ['R', '_R', 'C', '_C'])) {
_$('input[name="' + idE + '"]').prop('checked', false);
} else if (isFieldType(idE.toUpperCase(), ['S', '_S'])) {
var s = app.smartSelect.get('.' + idE);
if (s != null)
s.setValue('');
_$('#' + idE).val('');
_$('#' + idE).find('option').prop('selected', false);
}
else {
_$('#' + idE).val('');
}
}
}
/**
*Traslada los errores de una fila al popup
*@param {object} grid Objeto de la grid ya inicializada
*@param {string} rId rowId único que identifica a cada fila
*@param {object} conf Objeto de configuración de la grid, {@tutorial gridConf}
*@example var rId = getSelectedRowId(gPruebas);
addErrorPopup(gPruebas, rId, gPruebasConf);
*/
function addErrorPopup(grid, rId, conf) {
cleanErrorPopup(conf);
if (grid.valPopup != null && grid.valPopup) {
var row = getRow(grid, rId);
var cellError = _$(row).find('.row-error');
for (var r = 0; r < cellError.length; r++) {
var cInd = getCellIndex(cellError[r]);
var obj = getObjColIdx(cInd, conf);
if (obj != null) {
var dvPadre = getDvPadrePopup(obj.id);
if(dvPadre != null)
_$(dvPadre).addClass('has-error');
}
}
}
}
/**
*Limpia los errores marcados en el popup
*@param {object} conf Objeto de configuración de la grid, {@tutorial gridConf}
*@example cleanErrorPopup(gPruebasConf);
*/
function cleanErrorPopup(conf) {
for (var e in conf) {
var idE = conf[e].id;
if (idE == null) {
continue;
console.log('idConf Null ' + JSON.stringify(conf[e]));
}
if (idE != '') {
var dvPadre = getDvPadrePopup(idE);
if (dvPadre != null)
_$(dvPadre).removeClass('has-error');
}
}
}
/**
*Obtiene el Div padre de un campo en el modal
*@param {string} id id de la grid
*@returns {object} Div jQuery que contiene el campo
*@example var dvPadre = getDvPadrePopup("t2");
*/
function getDvPadrePopup(id) {
if (id == '')
return null;
var dvPadre = _$('#' + id).parents('.col-100')[0];
if (isFieldType(id.toUpperCase(), ['R', '_R', 'C', '_C'])) {
dvPadre = _$('input[name="' + id + '"]').parents('.col-100')[0];
if (dvPadre == null)
dvPadre = _$('input[name="' + id + '"]').parents('.list')[0];
return dvPadre;
}
if (dvPadre == null)
dvPadre = _$('#' + id).parents('.list')[0];
return dvPadre;
}
/**
*Abre el popup de la grid y cargar los valores, se puede hacer solo con el event, o enviando el row y la acción
*@param {event} e (opcional) evento que generan las opciones de agregar, editar y eliminar
*@param {HTMLTableRowElement} row (opcional) tr de la tabla
*@param {string} tipo (opcional) puede ser add, edit, delete
*@example var rId = getSelectedRowId(gPruebas);
var row = getRow(gPruebas, rId);
verModalF7(null, row, 'edit');
*/
function verModalF7(e, row, tipo) {
var tipo = (tipo == null) ? _$(e.target)[0].dataset.tipo : tipo;
var tb = (row == null) ? _$(e.target).parents('table')[0] : _$(row).parents('table')[0];
var rId = (row == null) ? getRowIdFromCell(_$(e.target).parents('td')[0]) : getRowId(row);
var grid = objGrids[tb.id].grid;
var conf = objGrids[tb.id].conf;
if (_isRowLocked(row))
return;
if (tipo == 'add') {
limpiarPopup(conf);
verOcultarCamposPopup(grid, conf);
_onBeforeOpenPopup(grid, '');
app.popup.open('#_' + tb.id);
_onOpenPopup(grid, '');
} else if (tipo == 'edit') {
_$('#_' + tb.id)[0].dataset.rid = rId;
verOcultarCamposPopup(grid, conf);
addErrorPopup(grid, rId, conf);
_onBeforeOpenPopup(grid, rId);
app.popup.open('#_' + tb.id);
if (getRowsNum(grid) > maxRowsValidate) {
setTimeout(function () {
cargarDatosPopup(grid, rId, conf);
_onOpenPopup(grid, rId);
}, 200);
} else {
cargarDatosPopup(grid, rId, conf);
_onOpenPopup(grid, rId);
}
} else if (tipo == 'delete') {
if (dataInRow(grid, rId)) {
app.dialog.confirm('Está seguro de eliminar la fila?', function () {
_removeRow(grid, rId);
});
} else {
if (getRowsNum(grid) > 1)
_removeRow(grid, rId);
}
}
}
function verModal2F7(rId, tipo, idPopup, grid, conf) {
if (tipo == 'add') {
limpiarPopup(conf);
verOcultarCamposPopup(conf);
app.popup.open('#' + idPopup);
_onOpenPopup(grid, '');
} else if (tipo == 'edit') {
_$('#' + idPopup)[0].dataset.rid = rId;
verOcultarCamposPopup(conf);
addErrorPopup(grid, rId, conf);
cargarDatosPopup(grid, rId, conf);
app.popup.open('#' + idPopup);
_onOpenPopup(grid, rId);
} else if (tipo == 'delete') {
if (dataInRow(grid, rId)) {
app.dialog.confirm('Está seguro de eliminar la fila?', function () {
grid.deleteRow(rId);
});
} else {
if (grid.getRowsNum() > 1)
grid.deleteRow(rId);
}
}
}
function verModalOnClick(row) {
try {
var grid = getGridFromRow(row);
if (grid != null && grid.editOnClick)
verModalF7(null, row, 'edit');
} catch (E) {
console.error(E);
}
}
/**
*Muestra u oculta campos en el popup basado en la configuración
*@param {object} grid Objeto de la grid ya inicializada
*@param {object} conf Objeto de configuración de la grid, {@tutorial gridConf}
*@example verOcultarCamposPopup(gPruebas, gPruebasConf);
*/
function verOcultarCamposPopup(grid, conf) {
for (var c in conf) {
if (conf[c].verModal != null) {
var dvPadre = getDvPadrePopup(conf[c].id);
if (dvPadre != null) {
if (conf[c].verModal)
_$(dvPadre).removeClass('nb-hidden');
else if(!conf[c].verModal)
_$(dvPadre).addClass('nb-hidden');
}
}
}
}
/**
*Muestra todos los campos del popup
*@param {object} conf Objeto de configuración de la grid, {@tutorial gridConf}
*@example verTodosCamposPopup(gPruebasConf);
*/
function verTodosCamposPopup(conf) {
verOcultarTodosCamposPopup(conf, true);
}
/**
*Oculta todos los campos del popup
*@param {object} conf Objeto de configuración de la grid, {@tutorial gridConf}
*@example ocultarTodosCamposPopup(gPruebasConf);
*/
function ocultarTodosCamposPopup(conf) {
verOcultarTodosCamposPopup(conf, false);
}
function verOcultarTodosCamposPopup(conf, ver) {
for (var c in conf) {
if (conf[c].verModal != null) {
if (conf[c].id == null) {
continue;
console.log('idConf Null ' + JSON.stringify(conf[e]));
}
var dvPadre = getDvPadrePopup(conf[c].id);
if (dvPadre != null) {
if (ver)
_$(dvPadre).removeClass('nb-hidden');
else
_$(dvPadre).addClass('nb-hidden');
}
}
}
}
/**
*Muestra u oculta en el popup los campos indicados
*@param {Array} arrIds Id de los campos que se desean mostrar u ocultar
*@param {boolean} ver true para mostrar, false para ocultar
*@example verOcultarPorCamposPopup([gPruebasConf.Apellido.id, gPruebasConf.Estado.id], false);
*/
function verOcultarPorCamposPopup(arrIds, ver) {
for (var i = 0; i < arrIds.length; i++) {
var dvPadre = getDvPadrePopup(arrIds[i]);
if (dvPadre != null) {
if (ver)
_$(dvPadre).removeClass('nb-hidden');
else
_$(dvPadre).addClass('nb-hidden');
}
}
}
function _removeRow(grid, rId) {
removeRow(grid, rId);
if (getRowsNum(grid) < 1)
addRow(grid, '', []);
}
function addMaxLength(conf) {
for (var c in conf) {
if (conf[c].max != null) {
var idE = conf[c].id;
if (idE != null && idE != '')
_$('#' + idE).prop('maxlength', conf[c].max);
}
}
}
function addRowsBuffer(grid, rId, values) {
if (rId == null || rId == '')
rId = getNewRowId();
var newRow = _getNewRowStr(grid, values, rId);
if (grid.rowsBufferNum >= maxRowsValidate) {
var idxTr = newRow.indexOf('>');
newRow = newRow.substring(0, idxTr) + ' style="display:none"; ' + newRow.substring(idxTr);
}
grid.rowsBufferNum += 1;
grid.rowsBuffer += newRow;
}
function parseRowsBuffer(grid) {
if (grid.rowsBuffer != null && grid.rowsBuffer != '') {
_$(grid.body).append(grid.rowsBuffer);
_addSelectRow(grid);
if (grid.rowsBufferNum > maxRowsValidate)
_enabledPagination(grid, grid.rowsBufferNum);
grid.rowsBuffer = '';
grid.rowsBufferNum = 0;
}
}
var worker = null;
function initWorker(grid) {
worker = new Worker('../javascript/htmlGridWorker.js?v=2');
worker.addEventListener('message', function (e) {
var obj = e.data;
if (obj.nFilas != null && obj.nFilas > 0 && obj.html != '') {
if (dProgress.setText != null)
dProgress.setText('Cargando los datos');
setTimeout(function () {
var idGrid = obj.id;
var grid = objGrids[idGrid].grid;
grid.body.innerHTML = obj.html;
_addSelectRow(grid);
worker.terminate();
app.dialog.close();
}, 100);
}
if (obj.avance != null) {
var prog = obj.avance / obj.filas * 100;
if (dProgress.setProgress != null) {
dProgress.setProgress(prog);
dProgress.setText('Procesando Filas {0}'.format(obj.avance));
}
}
}, false);
}
function convertirHTML(grid, conf) {
if (grid.tablaL != null) {
var idG = grid.tabla.id;
var html = _$(grid.tablaL).find('tbody').html();
var nFilas = _$(grid.tablaL).find('tbody')[0].rows.length;
_enabledPagination(grid, nFilas);
dProgress = app.dialog.progress('Cargando {0} Filas'.format(nFilas), 0);
var confC = getConfToWorker(conf);
worker.postMessage({ 'html': html, 'id': idG, 'conf': confC, 'maxRows': maxRowsValidate });
clearAll(grid);
}
}
function getConfToWorker(confC) {
var confC = confC;
for (var c in confC) {
if (confC[c].onkeyp != null)
confC[c].onkeyp = null;
}
return confC;
}
function _validateAttrGrid(grid) {
var rows = getRowsNum(grid);
var cells = grid.body.rows[0].cells.length;
var numCells = rows * cells;
var arrCellsAttr = _$(grid.body).find('td[data-value]');
if (numCells > arrCellsAttr.length) {
console.log('Faltan atributos {0} {1}'.format(numCells, arrCellsAttr.length));
_addRowIdAndValueFromTable(grid);
}
}
/**
*Devuelve el objeto de la grid ya inicializada
*@param {string} idGrid id de la tabla HTML
*@returns {object} Objeto de la grid ya inicializada
*@example var gPruebas = getGridForId("gPruebas");
*/
function getGridForId(idGrid) {
var grid = objGrids[idGrid].grid;
return grid;
}
/**
*Devuelve el objeto de configuración de la grid
*@param {string} idGrid id de la tabla HTML
*@returns {object} Objeto de la configuración
*@example var gPruebasConf = getConfForId("gPruebas");
*/
function getConfForId(idGrid) {
var confGrid = objGrids[idGrid].conf;
return confGrid;
}
String.prototype.format = function () {
var txt = this;
for (var i = 0; i < arguments.length; i++) {
var exp = new RegExp('\\{' + (i) + '\\}', 'gm');
txt = txt.replace(exp, arguments[i]);
}
return txt;
}
function validateRowPromesa(grid, conf, rId, fnBeforeValRow, colsV, colsE, errors) {
return new Promise(function (ok, err) {
try {
validateRow(grid, conf, rId, fnBeforeValRow, colsV, colsE, errors);
ok(rId);
} catch (E) {
err(E);
}
});
}
function getGridArrDatosWorker(grid, conf, fnCb) {
var workerG = new Worker('../javascript/htmlGridWorker.js?v=1');
workerG.addEventListener('message', function (e) {
var obj = e.data;
if (obj.arrDatos != null) {
workerG.terminate();
fnCb.apply(grid, [obj, grid, conf]);
}
});
var confC = getConfToWorker(conf);
var idG = grid.tabla.id;
var html = _$(grid.tabla).find('tbody').html();
workerG.postMessage({ 'html': html, 'id': idG, 'conf': confC, 'tipo': 'arrDatos' });
}
function copiarContenidoModal() {
if (_$('.modal-in').length > 0) {
var idGrid = _$('.modal-in')[0].id.replace('_', '');
var conf = getConfForId(idGrid);
var grid = getGridForId(idGrid);
copiarContenido(grid, conf);
}
}
function copiarContenido(grid, conf) {
if (conf != null && grid != null) {
var datos = getDatosPopup(conf);
foreachRow(grid, function (rId) {
foreachCell(grid, rId, function (cell, cInd) {
var obj = getObjColIdx(cInd, conf);
var val = getCellValue(grid, rId, cInd);
if (obj != null && obj.copiar != null && obj.copiar) {
setCellValue(grid, rId, cInd, datos[cInd]);
}
});
});
}
}
function cargarCamposCopiar() {
if (_$('.modal-in').length > 0) {
_$('#_sCopy').find('option').prop('selected', false);
if (_$('#_sCopy')[0].options.length == 1) {
var idGrid = _$('.modal-in')[0].id.replace('_', '');
var conf = getConfForId(idGrid);
var grid = getGridForId(idGrid);
cargarComboCamposCopiar(grid, conf);
}
var sCopy = app.smartSelect.get('._sCopy');
var evtClose = false;
if (sCopy.eventsListeners.close != null && sCopy.eventsListeners.close.length > 0) {
for (var e = 0; e < sCopy.eventsListeners.close.length; e++) {
if (sCopy.eventsListeners.close[e].toString().indexOf('jsonConf') != -1) {
evtClose = true;
break;
}
}
}
if (!evtClose) {
sCopy.on('close', function () {
var jsonConf = _$('#_sCopy')[0].dataset.conf;
var confN = JSON.parse(jsonConf);
var arrVal = _$('#_sCopy').val();
for (var c in confN) {
if (confN[c].copiar != null)
confN[c].copiar = null;
}
for (var i = 0; i < arrVal.length; i++) {
if (arrVal[i] != '') {
var obj = getObjColIdx(arrVal[i] * 1, confN);
if (obj != null) {
obj.copiar = true;
if (obj.colEnlazada != null) {
var objE = getObjColIdx(obj.colEnlazada, confN);
objE.copiar = true;
}
}
}
}
copiarContenido(grid, confN);
});
}
sCopy.open();
}
}
function cargarComboCamposCopiar(grid, conf) {
_$('#_sCopy')[0].options.length = 1;
var colE = -1;
for (var c in conf) {
if (conf[c].copiar != null) {
if (conf[c].colEnlazada != null)
colE = conf[c].colEnlazada;
var lblCampo = getHeaderLabel(grid, conf[c].idx);
var option = new Option(lblCampo, conf[c].idx);
if (colE != -1 && conf[c].idx == colE)
continue;
_$('#_sCopy').append(option);
}
}
_$('#_sCopy')[0].dataset.conf = JSON.stringify(conf);
}
function getJsonCells(grid, conf) {
var objCells = [];
foreachRow(grid, function (rId) {
objCells.push(getJsonCell(grid, conf, rId));
});
return objCells;
}
/**
*Obtiene un JSON con los headers de las columnas y sus valores de una fila especificada
*@param {object} grid Objeto de la grid ya inicializada
*@param {object} conf Objeto de configuración de la grid, {@tutorial gridConf}
*@param {string} rId rowId único que identifica a cada fila
*@returns {object} Objeto con los datos de la grid
*@example var rId = getSelectedRowId(gPruebas);
var dataRow = getJsonCell(gPruebas, gPruebasConf, rId);
console.log(dataRow);
//{'Nombre': 'Pepito', 'Apellido': 'Perez', 'Edad': '25'}
*/
function getJsonCell(grid, conf, rId) {
var objColumns = {};
foreachCell(grid, rId, function (cell, cInd) {
var objConfCell = getObjColIdx(cInd, conf);
if (objConfCell != undefined) {
if (objConfCell.colMap != undefined) {
var val = cell.dataset.value;
var header = objConfCell.colMap;
objColumns[header] = val;
}
}
});
return objColumns;
}
/**
*Bloquea o desbloquea una fila
*@param {HTMLTableRowElement} row tr de la tabla
*@param {boolean} bloq true para bloquear, false para desbloquear
*@example var rId = getSelectedRowId(gPruebas);
var row = getRow(gPruebas, rId);
lockRow(row, true);
*/
function lockRow(row, bloq) {
if (bloq)
row.dataset.lock = STATUS_LOCK;
else
row.dataset.lock = STATUS_UNLOCK;
}
function _isRowLocked(row) {
if (row == undefined)
return false;
var status = row.dataset.lock;
if (status == STATUS_LOCK)
return true;
else
return false;
}
/**
*Habilita o deshabilita la validación rápida, solo valida requeridos
*@param {object} grid Objeto de la grid ya inicializada
*@param {boolean} enabled true para habilitar, false para deshabilitar
*@example enabledLiteValidation(gPruebas, true);
*/
function enabledLiteValidation(grid, enabled) {
grid.liteValidate = enabled;
}
function liteValidateGrid(grid, colsV, errors) {
_$(grid.body).find('.row-error').removeClass('row-error')
_$(grid.body).find('td[data-value=""]').each(function () {
var idxTd = _$(this).index();
if (colsV[idxTd] != null && colsV[idxTd].req) {
var labelCol = getHeaderLabel(grid, idxTd);
if (errors[labelCol] == null)
errors[labelCol] = 0;
errors[labelCol]++;
errors.totalError++;
_$(this).addClass('row-error');
}
});
return errors;
}
function _enabledPagination(grid, numRows) {
grid.pagination = true;
var numPagin = [10, 20, 30, 40, 50];
var numPaginR = numPagin.reverse();
var numPaginDef = 10;
for (var i = 0; i < numPaginR.length; i++) {
if (numRows / numPaginR[i] >= 3) {
numPaginDef = numPaginR[i];
break;
}
}
//HTML para controles
var cardTable = _$(grid.tabla).parents('.card');
if (cardTable.find('.data-table-footer').length == 0)
cardTable.append(getHTMLPagination());
cardTable.find('.rows-page').val(numPaginDef);
cardTable.find('.rows-page').on('change', function () {
refreshNumPage(grid);
cardTable.find('input[type="number"]').trigger('change');
});
cardTable.find('input[type="number"]').val(1);
cardTable.find('input[type="number"]').on('change', function () {
var page = parseInt(this.value);
var numPages = calcNumPages(grid);
if (page <= numPages)
showGridPage(grid, page);
else
this.value = numPages;
});
refreshNumPage(grid);
showGridPage(grid, 1);
}
function calcNumPages(grid) {
var rowsPage = _$(grid.tabla).parents('.card').find('.rows-page').val();
var numRows = getRowsNum(grid);
return Math.ceil(numRows / rowsPage);
}
function refreshNumPage(grid) {
var rowsPages = calcNumPages(grid);
_$(grid.tabla).parents('.card').find('.curr-page span').html(rowsPages);
_$(grid.tabla).parents('.card').find('input[type="number"]').attr('max', rowsPages);
}
function showGridPage(grid, page) {
var cardTable = _$(grid.tabla).parents('.card');
var rowsPage = cardTable.find('.rows-page').val() * 1;
var rows = _$(grid.body).find('tr');
rows.hide();
var start = (page - 1) * rowsPage;
var end = start + rowsPage;
rows.slice(start, end).show();
}
function getHTMLPagination() {
var htmlPag = '<div class="card-footer data-table-footer"><div class="data-table-rows-select">Filas por página:<div class="input input-dropdown input-with-value"><select class="input-with-value rows-page"><option value="10">10</option><option value="20">20</option><option value="30">30</option><option value="40">40</option><option value="50">50</option></select></div><div class="curr-page"><div>Página <input type="number" min="1" style="display:inline;width:50px" /> de <span></span></div></div></div></div>';
return htmlPag;
}
function isFieldType(id, arrType) {
for (var i = 0; i < arrType.length; i++) {
if (id.startsWith(arrType[i])) {
return true;
}
}
return false;
}