/**
* Módulo general para manerjar el control de adjuntar en los formularios normales y en las grids Fw7.
* jQuery es una dependencia para este script
* @module genAdjunto
*/
var _$ = jQuery.noConflict();
/**
* Objeto global que almacena la definición de cada control adjuntar
*/
var _filesForm = [];
var loadIframeUploda = false;
var modalUpload = null;
var _gridFiles = {};
var _isResponse = false;
/*
* gridFiles
* -> gridId
* -> idx Columna
* -> idx Row
* -> Arreglo Adjuntos
*/
/**
*Inicializa todos los controles de adjuntar en el formulario.
*Todos los controles se buscan con la clase .btnAdjuntar
*/
function initFiles() {
_initUpload();
_$('.btnAdjuntar').each(function () {
var idFile = this.dataset.idf;
var f = getFileFormConf(idFile);
if (f == null) {
var obj = JSON.parse(JSON.stringify(this.dataset));
if (obj.fnRemove)
obj.fnRemove = eval(obj.fnRemove);
if (obj.grid)
_gridFiles[obj.grid] = {};
if (_gridFiles[obj.grid] && obj.gridCol) {
_gridFiles[obj.grid][obj.gridCol] = {};
_addFileEvtGrid(obj.grid);
}
_filesForm.push(obj);
cleanFileBtnAttr(this);
} else {
f = JSON.parse(JSON.stringify(this.dataset));
console.error('Ya existe un file con el id {0} configurado en el formulario'.format(idFile));
}
});
_$('.btnAdjuntar').on('click', function () {
var idFile = this.dataset.idf;
var f = getFileFormConf(idFile);
if (f != null)
adjuntarFile(idFile);
});
}
/**
*Limpia los data atributos para adjuntar de un botón disparador del control adjuntar.
*@param {HTMLButtonElement} btn botón que dispara el modal para adjuntar
*@example cleanFileBtnAttr(_$('#btnf1')[0]);
*/
function cleanFileBtnAttr(btn) {
var attrs = ['data-tipo-f', 'data-num-files', 'data-kb'];
for (var i = 0; i < attrs.length; i++) {
btn.removeAttribute(attrs[i]);
}
}
/**
*Obtiene la configuración de un file desde el objeto global mediante el id.
*@param {string} idFile id que se asigna en el control HTML ol
*@returns {object} objeto con la configuración del file
*@example getFileFormConf('f1');
*/
function getFileFormConf(idFile) {
var f = _filesForm.find(x => x.idf == idFile);
return f;
}
/**
*Carga la configuración y abre el modal para adjuntar, esta función se invoca automáticamente
*@param {string} idFile id que se asigna en el control HTML ol
*@param {string} type extensión con los archivos permitidos
*@param {string} kb tamaño máximo admitido en Kilobytes
*@param {string} numFiles Número máximo de archivos que se pueden adjuntar
*/
function adjuntarFile(idFile, type, kb, numFiles) {
var uploadArgs = { 'type': '', 'kb': '4096', 'numFiles': '2', 'idFile': idFile };
var f = _filesForm.find(x => x.idf == idFile);
if (f != null) {
uploadArgs.type = f.tipoF;
uploadArgs.kb = f.kb;
uploadArgs.numFiles = f.numFiles;
}
if (type != null && type != '')
uploadArgs.type = type;
if (kb != null && kb != '')
uploadArgs.kb = kb;
if (numFiles != null && numFiles != '')
uploadArgs.numFiles = numFiles;
uploadArgs.numFiles -= _$('#' + idFile).find('li').length;
setUploadIframe(uploadArgs);
modalUpload.idFile = idFile;
viewUpload(true);
}
function _initUpload() {
initModalUpload();
addBloqOverlay();
}
/**
*Inicializa el contenido HTML para el modal
*/
function initModalUpload() {
modalUpload = document.createElement("div");
_$(modalUpload).addClass('uploadModal nb-hidden');
modalUpload.close = function (rFiles) {
try {
addFileInForm(rFiles, this.idFile);
} catch (E) {
console.error(E);
}
viewUpload(false);
}
_$(document.body).append(modalUpload);
}
/**
*Carga en el control adjuntar los archivos subidos, se invoca luego de cerrar el modal
*Si el archivo ya existe, lo valida, dispara eventos cuando existe y cuando agrega los archivos
*@param {string} dataFile Objeto de la grid ya inicializada
*@param {string} idFile id que se asigna en el control HTML ol
*/
function addFileInForm(dataFile, idFile) {
if (dataFile) {
var files = dataFile.split('¬');
for (var i = 0; i < files.length; i++) {
var arrDataFiles = files[i].split("&");
var fileName = arrDataFiles[0];
var fileMD5 = arrDataFiles[1];
if (!existFile(fileMD5)) {
addNewLiFile(idFile, fileMD5, fileName, true);
} else {
var confFile = getFileFormConf(idFile);
if (confFile != null && confFile.removeMsg != null) {
if (confFile.removeMsg == 'fw7' && app != null)
app.dialog.alert('El archivo {0} ya ha sido adjuntado'.format(fileName), '!Opps');
} else {
var evtExistFile = new CustomEvent('existFile', { 'detail': arrDataFiles });
_$('#' + idFile)[0].dispatchEvent(evtExistFile);
}
console.error('El archivo {0} ruta {1} ya fue adjuntado'.format(fileName, fileMD5));
}
}
setValidate(idFile);
showHideBtnFile(idFile);
var f = getFileFormConf(idFile);
var evtAddFile = new CustomEvent('addFile', { 'detail': f });
_$('#' + idFile)[0].dispatchEvent(evtAddFile);
addEvtPreview(idFile);
addFileGrid(idFile);
}
addEvtRemove();
}
/**
*Valida que un mismo archivo no se adjunte 2 veces
*/
function existFile(ruta) {
var eFile = _$('ol').find('li[id="{0}"]'.format(ruta));
return eFile.length > 0;
}
/**
*Asigna el evento de previsualización a los files
*/
function addEvtPreview(idFile) {
_$('#' + idFile).find('li').unbind();
_$('#' + idFile).find('li').on('click', function () {
_previewAdjunto(this);
});
}
/**
*Asigna el evento para remover los archivos
*/
function addEvtRemove() {
_$('.remove-file').unbind();
_$('.remove-file').on('click', function () {
var idFile = _$(this).parents('ol').prop('id');
var f = getFileFormConf(idFile);
if (f.fnRemove)
f.fnRemove.apply(_$(this).parent()[0], [f]);
else
removeFile(_$(this).parent()[0], f);
});
}
/**
*Devuelve el contenido HTML necesario para crear un nodo li para el control adjuntar
*@param {string} url ruta del archivo adjunto
*@param {string} name nombre del archivo
*@param {boolean} remove true para que aparezca el botón para eliminar, false para que no aparezca
*@returns {string} contenido HTML con el li listo
*/
function getNewLiFile(url, name, remove) {
var li = '<li id="{0}" title="{1}"><label>{1}</label><span class="remove-file {2}">x</span></li>'.format(url, name, (!remove) ? 'nb-hidden':'');
return li;
}
/**
*Agrega un nuevo nodo li sobre el control adjuntar <ol>
*@param {string} idFile id que se asigna en el control HTML ol
*@param {string} url ruta del archivo adjunto
*@param {string} name nombre del archivo
*@param {boolean} remove true para que aparezca el botón para eliminar, false para que no aparezca
*/
function addNewLiFile(idFile, url, name, remove) {
var li = getNewLiFile(url, name, remove);
_$('#' + idFile).append(li);
}
/**
*Elimina un nodo li del control adjuntar
*@param {HTMLLIElement} li control li que se desea eliminar
*@param {object} f objeto de configuración del file
*/
function removeFile(li, f) {
var idFile = _$(li).parents('ol').prop('id');
var fileData = { 'file': li.id, 'name': li.title, 'idFile': idFile };
_$(li).remove();
showHideBtnFile(idFile);
if (f != null && f.grid != null) {
var conf = getGridDataConf(f);
var idxFile = _gridFiles[conf.idGrid][conf.gridCol][conf.idxRow].findIndex(x => x.ruta == fileData.file);
if (idxFile != -1)
_gridFiles[conf.idGrid][conf.gridCol][conf.idxRow].splice(idxFile);
}
var evtRemoveFile = new CustomEvent('removeFile', { 'detail': fileData });
_$('#' + idFile)[0].dispatchEvent(evtRemoveFile);
setValidate(idFile);
}
/**
*Muestra y oculta el botón que dispara la acción de adjuntar para adjuntar de cada control
*@param {string} idFile id que se asigna en el control HTML ol
*/
function showHideBtnFile(idFile) {
var f = getFileFormConf(idFile);
if (_$('#' + idFile).find('li').length >= (f.numFiles * 1))
_$('#btn' + idFile).addClass('nb-hidden');
else
_$('#btn' + idFile).removeClass('nb-hidden');
}
/**
*Muestra y oculta el modal de adjuntar
*@param {boolean} view true para ver, false para ocultar
*/
function viewUpload(view) {
if (view) {
_$(modalUpload).removeClass('nb-hidden');
viewBloqOverlay(view);
} else {
_$(modalUpload).addClass('nb-hidden');
viewBloqOverlay(view);
}
}
function addBloqOverlay() {
if (_$('.bloqOverlay').length == 0) {
var bloqDiv = document.createElement("div");
var loadDiv = document.createElement("div");
loadDiv.id = '_lUpload';
_$(bloqDiv).addClass('bloqOverlay nb-hidden');
_$(loadDiv).addClass('loaderCont nb-hidden').html('<div class="loader"></div>');
_$(document.body).append([bloqDiv, loadDiv]);
}
}
function viewBloqOverlay(view) {
if (view)
_$('.bloqOverlay').removeClass('nb-hidden');
else
_$('.bloqOverlay').addClass('nb-hidden');
}
function setUploadIframe(uploadArgs) {
var srcIframe = "{0}/solicitudes/plantillas/upload.aspx?t={1}&m={2}&c={3}&f={4}"
.format(location.origin, uploadArgs.type, uploadArgs.kb, uploadArgs.numFiles, uploadArgs.idFile);
_$('#_lUpload').removeClass('nb-hidden');
if (_$('#_upload_').length == 0) {
var upload = document.createElement("iframe");
_$(upload).prop('id', '_upload_');
_$(upload).prop('src', srcIframe);
_$(upload).addClass('iframeUpload nb-hidden');
_$(modalUpload).append(upload);
_$(upload).on('load', function () {
_$(this).removeClass('nb-hidden');
_$('#_lUpload').addClass('nb-hidden');
});
} else {
_$('#_upload_').addClass('nb-hidden');
_$('#_upload_').prop('src', srcIframe);
}
}
/**
*Previsualiza el adjunto en un modal
*@param {HTMLLIElement} li control li que se desea previsualizar
*/
function _previewAdjunto(li) {
var id = li.id.toUpperCase();
_$('#_nPrev').html(li.title);
if (li.id.indexOf('archivos') == -1)
_$('#_file_').prop('href', '../archivos/temp/' + li.id);
else
_$('#_file_').prop('href', li.id);
_$('#_file_').prop('download', li.title);
_$('.prevFile, #_prevAll').addClass('nb-hidden');
_$('#_fPrev, #imgPrev').addClass('nb-hidden');
_$('#_adjPrev').removeClass('nb-hidden');
if (id.indexOf('.JPG') != -1 || id.indexOf('.PNG') != -1 || id.indexOf('.JPEG') != -1
|| id.indexOf('.GIF') != -1) {
if (li.id.indexOf('archivos') == -1)
_$('#imgPrev').prop('src', '../archivos/temp/' + li.id);
else
_$('#imgPrev').prop('src', li.id);
_$('#imgPrev').removeClass('nb-hidden');
} else if (id.indexOf('.PDF') != -1 || id.indexOf('.TXT') != -1) {
if (li.id.indexOf('archivos') == -1)
_$('#fPrev').prop('src', '../archivos/temp/' + li.id);
else
_$('#fPrev').prop('src', li.id);
_$('#_fPrev').removeClass('nb-hidden');
} else {
_$('#msgNoPrev').removeClass('nb-hidden');
}
var ol = _$(li).parents('ol')[0];
var confFile = getFileFormConf(ol.id);
if (confFile != null && confFile.preview != null) {
if (confFile.preview == 'fw7' && app != null)
app.popup.open('#_prevAdjunto');
} else {
var evtPrevFile = new CustomEvent('previewFile', { 'detail': { 'idModal': '_prevAdjunto' } });
ol.dispatchEvent(evtPrevFile);
}
}
function setValidate(idFile) {
if (_$('#_t' + idFile).length > 0) {
var arrFiles = [];
_$('#' + idFile).find('li').each(function () {
arrFiles.push(this.title);
});
_$('#_t' + idFile).val((arrFiles.length == 0) ? '' : arrFiles.join(','));
}
}
/**
*Convierte todos los files en el formulario de respuesta a la misma visualización que el formulario de edición
*@param {boolean} response true si se va a usar para formularios de respuesta, false si no
*/
function convertResponseAllFiles(response) {
_$('.fileResp').each(function () {
convertResponseFile(this, response);
});
}
/**
*Carga todos los enlaces de los archivos adjuntos al nuevo esquema de control adjuntar
*@param {HTMLDivElement} dvFiles <div> contenedor que debe tener las clases fw7Link y fileResp
*@param {boolean} response true si se va a usar para formularios de respuesta, false si no
*/
function convertResponseFile(dvFiles, response) {
var idFile = dvFiles.dataset.idf;
var ol = '<ol id="{0}" class="view-file ufiles"></ol>'.format(idFile);
_$(dvFiles).append(ol);
_$(dvFiles).find('a').each(function () {
_$(this).addClass('nb-hidden');
var url = this.href;
var name = this.innerHTML;
if (response != null)
addNewLiFile(idFile, url, name, true);
else
addNewLiFile(idFile, url, name, false);
});
addEvtPreview(idFile);
if (response != null) {
addEvtRemove();
_$('#btn' + idFile).addClass('nb-hidden');
}
}
/**
*Cargar los archivos ya guardados si el formulario se devuelve
*/
function loadFileInEdition() {
convertResponseAllFiles(true);
}
/**
*Esta función se debe llamar antes de guardar los datos, si el formulario se devuelve
*/
function cleanFileInEdition() {
_$('.ufiles').each(function () {
_$(this).find('li').each(function () {
var idFileS = this.id.toLowerCase();
if (idFileS.startsWith('http')) {
var idxF = idFileS.indexOf('archivos');
var urlF = idFileS.substring(idxF+8);
this.id = '';
this.name = urlF;
this.title = urlF;
}
});
});
}
/**
*Función para agregar un adjunto en la grid
*@param {string} idFile id que se asigna en el control HTML ol
*/
function addFileGrid(idFile) {
var f = getFileFormConf(idFile);
if (f != null && f.grid != null) {
var idGrid = f.grid;
var gridCol = f.gridCol * 1;
var grid = getGridForId(idGrid);
var conf = getGridDataConf(f);
if (_gridFiles[conf.idGrid][conf.gridCol][conf.idxRow] == null)
_gridFiles[idGrid][gridCol][conf.idxRow] = [];
_$('#{0} li'.format(idFile)).each(function () {
var objAdj = getObjAdjunto(this.id, this.title);
var arrFilesG = _gridFiles[conf.idGrid][conf.gridCol][conf.idxRow];
var fAdd = arrFilesG.find(x => x.ruta == objAdj.ruta);
if (fAdd == null) {
arrFilesG.push(objAdj);
}
});
}
}
/**
*Obtiene los datos de una grid basado en el objeto de configuración del adjunto
*@param {object} f Objeto de configuración que se obtiene con la función getFileFormConf
*@returns {object} objeto con la configuración de la grid
*/
function getGridDataConf(f) {
var idGrid = f.grid;
var gridCol = f.gridCol * 1;
var grid = getGridForId(idGrid);
var rId = _$('#_' + idGrid)[0].dataset.rid;
var idxRow = (rId == "") ? getRowsNum(grid) : getRowIndexFromId(grid, rId);
var data = { 'idGrid': idGrid, 'gridCol': gridCol, 'idxRow': idxRow };
return data;
}
function getObjAdjunto(ruta, nombre) {
var objAdj = { 'ruta': ruta, 'nombre': nombre };
return objAdj;
}
/**
*Tiene la lógica para cargar los adjuntos en cada fila de la grid al abrir el modal
*@param {string} idGrid id de la grid
*/
function _addFileEvtGrid(idGrid) {
var grid = getGridForId(idGrid);
addEventGrid('onOpenPopup', grid, function (rId) {
var idxRow = getRowIndexFromId(grid, rId);
_loadGridFiles(idGrid, idxRow);
});
}
/**
*Cargar los adjuntos de la grid cuando se abre el modal de una fila con adjuntos
*@param {string} idGrid id de la grid
*@param {integer} idxRow indice de la fila de la grid
*/
function _loadGridFiles(idGrid, idxRow) {
for (var idxCol in _gridFiles[idGrid]) {
var fConf = _filesForm.find(x => x.grid == idGrid && x.gridCol === idxCol);
var arrFiles = _gridFiles[idGrid][idxCol][idxRow];
if (arrFiles && arrFiles.length > 0) {
_$('#' + fConf.idf).html('');
for (var i = 0; i < arrFiles.length; i++) {
var ff = arrFiles[i];
addNewLiFile(fConf.idf, ff.ruta, ff.nombre, !isResponse());
}
addEvtPreview(fConf.idf);
showHideBtnFile(fConf.idf);
} else {
_$('#' + fConf.idf).html('');
showHideBtnFile(fConf.idf);
}
}
addEvtRemove();
}
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;
}