Mostrando entradas con la etiqueta javascript. Mostrar todas las entradas
Mostrando entradas con la etiqueta javascript. Mostrar todas las entradas

martes, 27 de junio de 2023

Manipulación de JSON en JavaScript: Transposición de Datos

¡Hola a todos! Estamos de vuelta con un nuevo artículo sobre JavaScript. Esta vez, exploraremos un tema fundamental pero a menudo repetitivo: cómo trabajar con JSON. Vamos a sumergirnos directamente en el código, donde mostraremos cómo transponer valores de filas a columnas en un arreglo JSON.


¿Qué es la Transposición de Datos?

La transposición de datos implica cambiar la orientación de los datos, es decir, convertir filas en columnas y viceversa. En este artículo, te mostraré cómo hacerlo usando JavaScript.


La Función transpuesta

La función transpuesta se encarga de transponer los valores de un objeto JSON. A continuación, se explica cómo funciona esta función paso a paso:


Código de la Función

/**
 * Función transpuesta: Transpone valores de filas a columnas en un arreglo JSON.
 * @param {Object} obj - El objeto JSON que contiene los datos a transponer.
 * @returns {Array} - El nuevo arreglo con los valores transpuestos.
 */
function transpuesta(obj) {
    var rtn = [];
    var key = {};
    var x = 0;

    // Función de comparación de objetos
    var c = function(a, b) {
        return JSON.stringify(a) === JSON.stringify(b);
    };

    // Recorre el arreglo o JSON que recibe
    $.each(obj.arr, function(i, v) {
        var nObj = {};
        var keys = Object.keys(v);
        
        // Crea un objeto sin las llaves y valores a transponer
        for (var j = 0; j < keys.length; j++) {
            if (keys[j] !== obj.field.structure.value && keys[j] !== obj.value) {
                nObj[keys[j]] = v[keys[j]];
            }
        }

        var rn = -1;

        // Evalúa si la llave ya tiene un objeto asociado
        if (Object.keys(key).length == 0) {
            key['a_' + x] = { k: nObj, r: rtn.length };
            x++;
        } else {
            var existe = false;
            for (var y = 0; y < x; y++) {
                if (c(key['a_' + y].k, nObj)) {
                    existe = true;
                    rn = key['a_' + y].r;
                }
            }

            if (!existe) {
                key['a_' + x] = { k: nObj, r: rtn.length };
                x++;
            }
        }

        var tmpObj = {};
        $.extend(tmpObj, nObj);

        var k = obj.field.structure;
        var prp = k.prepend + (v[k.value] + "").replace(k.rp[0] || '', k.rp[1] || '') + k.append;

        if (rn == -1) {
            tmpObj[prp] = v[obj.value];
            rtn.push(tmpObj);
        } else {
            rtn[rn][prp] = v[obj.value];
        }
    });

    return rtn;
}

Ejemplo de Uso

Vamos a ver un ejemplo práctico de cómo usar esta función.


JSON de Entrada

var jsn = [
    {folio: 4401685, fecha: '20/07/2022', orden: 352673, identificador: 44156245, pieza: 312, equivalencia: 'XY-A1'},
    {folio: 4401685, fecha: '20/07/2022', orden: 352673, identificador: 44156245, pieza: 504, equivalencia: 'XY-A3'},
    {folio: 4401685, fecha: '20/07/2022', orden: 352673, identificador: 44156245, pieza: 312, equivalencia: 'XY-A4'},
    {folio: 4401685, fecha: '20/07/2022', orden: 352673, identificador: 44156245, pieza: 1272, equivalencia: 'XY-A6'},
    {folio: 4401685, fecha: '20/07/2022', orden: 352673, identificador: 44156245, pieza: 960, equivalencia: 'XY-A7'},
    {folio: 4401685, fecha: '20/07/2022', orden: 352673, identificador: 44156245, pieza: 624, equivalencia: 'XY-A8'}
];

Invocación de la Función

var jsonRtn = transpuesta({
    arr: jsn,
    field: {
        structure: {
            prepend: 'E_',
            value: 'equivalencia',
            rp: ['-', '_'],
            append: '_PZ'
        }
    },
    value: 'pieza'
});

Resultado

La función transpuesta transformará los datos de la siguiente manera:

console.log(jsonRtn);
/*
[
    {
        folio: 4401685,
        fecha: '20/07/2022',
        orden: 352673,
        identificador: 44156245,
        E_XY_A1_PZ: 312,
        E_XY_A3_PZ: 504,
        E_XY_A4_PZ: 312,
        E_XY_A6_PZ: 1272,
        E_XY_A7_PZ: 960,
        E_XY_A8_PZ: 624
    }
]
*/

Conclusión

En este artículo, hemos aprendido a transponer valores en un arreglo JSON usando JavaScript. Esta técnica es útil para reorganizar datos y hacerlos más manejables para diferentes propósitos.


Si este artículo te ha sido útil, por favor, deja tu comentario y comparte tu experiencia. Gracias por leernos y hasta la próxima.

miércoles, 2 de noviembre de 2022

Validacion de datos en ExcelJS

 Hoy les traigo a la mano la información para poder crear datavalidation con ExcelJS o bien un dropdownlist en los archivos exportados desde java, sin mas por el momento vamos al codigo.


Un dataValidation permite agregar dropdownlist a una hoja de excel esta puede ser asignada por medio de un array de tipo string o bien hacer referencia de la informacion en otra hoja.


En el ejemplo de hoy veremos el caso de crear la lista a partir de la referencia de otra hoja del mismo documento, para ello creamos nuestro objeto Workbook. 


  
     var workbook = new ExcelJS.Workbook();
     workbook.creator = 'DivingJS';
     workbook.lastModifiedBy = 'inovania.blogspot.com';
     workbook.created = new Date();
     
  

Ahora por el momento agregaremos el primer registro que bien puede servir como header del documento para ello.

	var workSheet=workbook.addWorksheet("sheet_1");
    workSheet.addRow(["item 1","item 2", "item 3"]);

Aquí agregamos el contenido de la segunda hoja

	var workSheet_2=workbook.addWorksheet("sheet_2");
    workSheet_2.addRow(["elemento 1"]);
    workSheet_2.addRow(["elemento 2"]);
    workSheet_2.addRow(["elemento 3"]);
    workSheet_2.addRow(["elemento 4"]);
    workSheet_2.addRow(["elemento 5"]);
    workSheet_2.addRow(["elemento 6"]);
    

Una vez teniendo esto lo que sigue es agregar la regla para poder generar el dataValidation, esto queda de la siguiente manera.

    worksheet.getCell("B2").dataValidation = {
         type: 'list',
         allowBlank: true,
         showInputMessage: true,
         showErrorMessage: true,
         formulae: ["=sheet_2!$A$1:$A$6"]

Ahora bien, recibe los parametros allowBlank , showInputMessage, showErrorMessage, type, formulae. la propiedad type corresponde al tipo de dato que estará alojado en la celda seleccionada en este caso una lista.

En el parámetro formulae recibe un arreglo o en este caso la referencia para hacer un arreglo el cual lo encontrara en la hoja 2 asociado de la celda A1 a la celda A6. 

De esta manera es como referenciamos a otra hoja para crear nuestra lista.

Por ultimo exportamos el archivo y listo.

   await workbook.xlsx.writeBuffer()
         .then(buffer => saveAs(new Blob([buffer]),obj.name))
         .catch(err => console.log(err));

No olvides seguirme para ser de los primeros a quienes les llegue la notificación de lo que se publique.

jueves, 28 de julio de 2022

Exportar Imagen en Excel JS

 Hola a todos, en este momento aremos un archivo de excel a partir de la informacion en un arreglo de propiedades, entre estas propiedades estará una constante con images en base64.
Para ello utilizaremos las librerias de exceljs.js y FileSaver.js puedes acceder a estas librerías en las siguientes direcciones.


<script src="https://cdnjs.cloudflare.com/ajax/libs/amcharts/3.21.15/plugins/export/libs/FileSaver.js/FileSaver.min.js" type="text/javascript"> </script>
 <script crossorigin="anonymous" integrity="sha512-UnrKxsCMN9hFk7M56t4I4ckB4N/2HHi0w/7+B/1JsXIX3DmyBcsGpT3/BsuZMZf+6mAr0vP81syWtfynHJ69JA==" referrerpolicy="no-referrer" src="https://cdnjs.cloudflare.com/ajax/libs/exceljs/4.3.0/exceljs.min.js"> </script>


A partir de aquí lo que sigue es preparar nuestra información.

  var arreglo = [{ name: "Jane Doe",foto:'data:image/png;base64,/9j/4QAYRXhpZgAAS...'},{ name: "John Doe",foto:'data:image/png;base64,/9j/4QAYRXhpZgAAS...'}];
 var cols= [{field:'name',title:'Nombre'},{field:'foto',title:'IMAGEN'}];
  
Una vez que tenemos el insumo creamos nuestra función.
  async function exportFile(arry,cols,fileName){
     var workbook = new ExcelJS.Workbook();
     workbook.creator = 'inovania.blogspot.com';
     workbook.lastModifiedBy = 'inovania.blogspot.com';
     workbook.created = new Date();
     var worksheet =  workbook.addWorksheet('Sheet 1');
     var grd={
          columns:cols,
          data:array
     };
     var arrRow=[];
     grd.columns.map((e,i) => {
          arrRow.push(e.title);
     });
     worksheet.addRow(arrRow);
     for(var e=0;e<grd.data.length;e++){
          var arrDt = [];
          var logo;
          for(var x=0;x<grd.columns.length;x++){
               var c = grd.columns[x].field;
               if(x==0){
                    logo = workbook.addImage({
                         base64: grd.data[e][c],
                         extension: 'jpg',
                    });
                    arrDt.push("");
               }else{
                    arrDt.push(grd.data[e][c]);
               }
          }
          worksheet.addRow(arrDt);
          worksheet.addImage(logo, ('A'+(e+2)+":"+"A"+(e+2)));
     }
     await workbook.xlsx.writeBuffer()
          .then(buffer => saveAs(new Blob([buffer]),fileName+".xlsx"))
          .catch(err => console.log(err) );
};
  
Con esto solo nos queda el llamado el cual queda de la siguiente manera

  exportFile(arreglo,cols,"archivoInnovania");
De esta manera queda nuestro objeto capas de exportar imagenes en base64 en un archivo de excel.

Cabe mencionar que la función worksheet.addImage(img,rango); ocupa dos parámetros el primero es la imagen y el segundo parámetro es un rango de celdas, en este caso lo deje en la misma celda, pasándole como rango desde la celda ( A1 hasta la celda A1) A1:A1, simulando que este será un rango de celdas.


Quedo en espera de sus comentarios, hasta la proxima.

jueves, 5 de marzo de 2020

Chat Privado con NodeJs parte 5 ( Creando estilo a ventana privada ) Final.

Continuando con el proyecto del chat privado con node js, es momento de finalizar, de antemano les agradezco el prestarme su tiempo para leerme y continuar con el proyecto, entrada tras entrada.


Comencemos, Es hora de dar fin al proyecto concluyendo con el estilo a la ventana privada de nuestro chat, para ello, nos vamos a nuestro archivo chatstyle.css agregando los siguientes estilos.

chatstyle.css

body {
    font: 13px Helvetica, Arial;
}
.contentUser {
    border: solid 1px;
    width: 300px;
    position: absolute;
    top: 10px;
    left: 10px;
    border-radius: 5px;
    height: 500px;
}
ul#usersActivos {
    list-style: none;
    padding: 0;
    height: 445px;
    overflow: hidden;
    overflow-y: scroll;
}
.title-users {
    padding: 1em;
    background-color: #2f2f5d;
    text-align: center;
    color: #f1f1f1;
    cursor: move;
}
#usersActivos li {
    border-bottom: solid 1px;
    padding: 0.75em;
    cursor: pointer;
}
#usersActivos li div {
    font-size: 1.15em;
}
.conv-privada {
    border: solid 1px #a0a0a0;
    width: 300px;
    position: absolute;
    left: 300px;
    background-color: #fafafa;
}
.cnt-title {
    padding: 0.5em;
    background-color: #2f2f5d;
    color: white;
    cursor: move;
}
.cnt-conv {
    height: 250px;
    overflow: hidden;
    background-color: #f7f4f4;
    overflow-y: scroll;
    margin-bottom: 0.25em;
}
.cntControl {
    border-top: solid 1px;
}
.conv {
    list-style: none;
    padding: 0.15em;
}
.conv li {
    margin: 0.15em;
    padding: 0.5em;
}

.msg-amigo {
    background-color: #bfbaf7;
}

.msg-propio {
    text-align: right;
    background-color: #a9c9e4;
}
.msg-amigo div, .msg-propio div {
    word-break: break-all;
}
.msg-propio span, .msg-amigo span {
    font-size: 0.75em;
}
.conv-close {
    position: absolute;
    right: 0.75em;
    font-style: initial;
    cursor: pointer;
    font-size: 1.25em;
    top: 0.25em;
}
.conv-finalizada {
    height: 26.15em;
    width: -webkit-fill-available;
    background: #3e3e3e5c;
    position: absolute;
    top: 2em;
}


Hagamos un resumen de lo expuesto.

La estructura del proyecto deberá haber quedado de la siguiente manera.


El archivo chatstyle.css quedará como lo muestro anteriormente, ahora, control.js queda de la siguiente manera:

Control.js

var socket = io();
var btnLogin = document.getElementById('btnLogin');
var lg = document.getElementById('login');
btnLogin.onclick=function(){
 var usr = document.getElementById('user');
 if((usr.value.trim()).length>0){
  socket.emit('connectUser',usr.value);
  window.datos={
   user:usr.value,
   clave: socket.id
  };
  window.document.title = usr.value;
 }
}
socket.on('isLogin',function(value){
 if(typeof window.datos != 'undefined'){
  lg.setAttribute('hidden','');
  var userActivos = document.getElementById('usersActivos');
  userActivos.parentNode.removeAttribute('hidden');
  userActivos.innerHTML = "";
  for(var i = 0; i0){
   ntf.textContent=dta.user+" is writing...";
  }else{
   ntf.textContent='';
  }
 }
});
socket.on('isDisconnected',function(dta){
 if(document.getElementById(dta.clave)!=null){
  var ntf = document.getElementById('isW_'+dta.clave);
  ntf.textContent=dta.user+" is disconnected";
  var block = create({type:'DIV',class:'conv-finalizada'});
  var cnt = document.getElementById(dta.clave);
  cnt.appendChild(block);
 }
});
function create(dta){
 var obj = Object.keys(dta);
 var elemento = document.createElement(dta.type);
 for( var i = 0; i < obj.length; i ++ ){
  if(obj[i]!='type'){
   elemento.setAttribute(obj[i],dta[obj[i]]);
  }
 }
 return elemento;
}
function draggable_2(title, content) {
    var px = 0, py = 0;
    var dragObj = null;
    var obj = content || title;
    obj.style.position = "absolute";
    title.addEventListener('mousedown', function () {
        obj.addEventListener('mousedown', onMouseDown);
        function onMouseDown(a) {
            px = a.layerX;
            py = a.layerY;
            dragObj = obj;
        }
        obj.addEventListener('mouseup', function (e) {
            obj.removeEventListener('mousedown', onMouseDown, false);
            dragObj = null;
        });
        obj.addEventListener('mousemove', function (e) {
            var x = e.pageX - px;
            var y = e.pageY - py;
            if (dragObj == null)
                return;
            dragObj.style.left = x + "px";
            dragObj.style.top = y + "px";
        });
    });
}
function armaVentanaPrivada(clave,to){
 if(document.getElementById(clave)==null){
  var cnt = create({type:'DIV','id':clave,class:'conv-privada'});
  var emClose = create({type:'EM',class:'conv-close'});
  var ttl = create({type:'DIV',class:'cnt-title'});
  var cntCnv = create({type:'DIV',class:'cnt-conv','id':'cntCnv_'+clave});
  var lista = create({type:'UL',class:'conv','id':'conv_'+clave});
  var cntCtr = create({type:'DIV',class:'cntControl'});
  var notificacion = create({type:'DIV',class:'is-writing',id:'isW_'+clave});
  var txtMsg = create({type:'TEXTAREA',name:'entrada',rows:'4','id':'inpMsg_'+clave,'style':'resize:none;width:225px;'});
  var btn = create({type:'BUTTON','id':'btn_'+clave,'style':'float: right;padding: 0.7em;margin-top: 0em;padding-top: 1.5em;padding-bottom: 2em;position: absolute;'});
  ttl.textContent=to;
  btn.textContent="Aceptar";
  emClose.textContent='X';
  cntCtr.appendChild(txtMsg);
  cntCtr.appendChild(btn);
  cntCnv.appendChild(lista);
  ttl.appendChild(emClose);
  cnt.appendChild(ttl);
  cnt.appendChild(cntCnv);
  cnt.appendChild(notificacion);
  cnt.appendChild(cntCtr);
  document.body.appendChild(cnt);
  draggable_2(ttl,cnt);
  txtMsg.onkeyup=function(){
   socket.emit('imWriting',{
    user:window.datos.user,
    clave:window.datos.clave,
    length: this.value.length,
    recibe:to
   });
  }
  emClose.onclick = function(){
   cnt.remove();
  }
  btn.onclick = function(){
   if((txtMsg.value.trim()).length>0){
    socket.emit('send_message',{
     recibe:to,
     envia:{user:window.datos.user,clave:window.datos.clave},
     message:txtMsg.value
    });
    agregaMensaje(lista,1,window.datos.user,txtMsg.value, cntCnv);
    txtMsg.value = '';
    txtMsg.focus();
   }
  }
  return {lista:lista,content:cntCnv};
 }else{
  return {lista:document.getElementById('conv_'+clave), content: document.getElementById('cntCnv_'+clave)};
 }
}
function agregaMensaje(ul,cve,de,msg,cntCnv){
 var dvm = create({type:'DIV'});
 var li = create({type:'LI',class:((cve==1)?'msg-propio':'msg-amigo')});
 var spn = create({type:'SPAN'});
 var fd = new Date();
 var time = fd.getHours()+":"+fd.getMinutes()+":"+fd.getSeconds();
 spn.textContent= ((cve==1)?time+" "+de:de+" "+time);
 dvm.textContent= msg;
 li.appendChild(spn);
 li.appendChild(dvm);
 ul.appendChild(li);
 cntCnv.scrollTo(0,cntCnv.scrollHeight);
}
draggable_2(document.getElementById('ttlUsersActivos'), document.getElementById('cntUsersActivos'));


El lado del cliente, es decir el index, debera quedar de la siguiente manera.

index.html

<!DOCTYPE html>
<html lang="en">
<head>
     <meta charset="UTF-8">
     <title>inovania</title>
          <script type="text/javascript" src="/socket.io/socket.io.js"></script>
          <link rel="stylesheet" type="text/css" href="/css/chatstyle.css">
     </head>
     <body>
          <div class="login" id="login">
               <input type="text" id="user" placeholder="UserName"><button id="btnLogin">Aceptar</button>
          </div>
          <div class="contentUser" id="cntUsersActivos" hidden>
               <div class="title-users" id="ttlUsersActivos">Usuarios Activos</div>
               <ul id="usersActivos"></ul>
          </div>
          <script type="text/javascript" src="/js/control.js"></script>
     </body>
</html>





y por ultimo el app.js queda de la siguiente manera.

app.js


var express = require("express");
var app = express();
var http = require("http").createServer(app);
var io = require("socket.io")(http);
var path = require("path");
var users = [];
app.get('/',function(req,res){
 res.sendFile(__dirname+"/pages/index.html");
});
var publicDir = path.join(__dirname,'/');
app.use(express.static(publicDir));
io.on('connection',function(socket){
 socket.on('disconnect',function(){
  var keys =  Object.keys(users);
  var existe = false;
  var disconnected = {};
  for( var i = 0;i < keys.length; i ++ ){
   if( users[keys[i]] == socket.id ){
    disconnected.user = keys[i];
    disconnected.clave = users[keys[i]];
    delete users[keys[i]];
    existe = true;
   }
  }
  if(disconnected.hasOwnProperty('user')){
   io.emit('isDisconnected',disconnected);
  }
  if(existe){
   var nKeys = Object.keys(users);
   var arrRtn = [];
   for( var i = 0;i < nKeys.length; i ++ ){
    arrRtn.push({'user':nKeys[i], 'clave': users[nKeys[i]]});
   }
   io.emit('isLogin',arrRtn);
  }
 });
 socket.on('connectUser',function(user){
  var existe = false;
  var keys =  Object.keys(users);
  var arrRtn=[];
  for( var i = 0;i < keys.length; i ++ ){
   arrRtn.push({'user':keys[i], 'clave': users[keys[i]]});
   if( users[keys[i]] == socket.id ){
    existe = true;
   }
  }
  if(!existe){
   users[user]=socket.id;
   arrRtn.push({'user':user, 'clave': socket.id});
  }
  io.emit('isLogin',arrRtn);
 });
 socket.on('send_message',function(data){
  var socketId = users[data.recibe];
  io.to(socketId).emit("newMessage",data);
 });
 socket.on('imWriting',function(dta){
  var socketId = users[dta.recibe];
  io.to(socketId).emit("isWriting",dta);
 });
});
http.listen(8420,function(){
 console.log('listening');
});



Anterior

Sin mas por el momento, me despido... Te invito a dejar tu comentario, que te parecio el tutorial, si quieres que le agregemos algo mas, o si tienes sugerencias al respecto.


Saludos, hasta la proxima.


miércoles, 26 de febrero de 2020

Chat Privado con NodeJs parte 4 ( Creación de ventana privada )

En chat privado con NodeJs.

Como les comente en la entrada anterior, vimos como generar la lista de usuarios y mandarla a las ventanas ( usuarios ) conectados.

Creando la venta privada.


Ahora veremos como hacer la ventana de conversación privada a manera que valla quedando de la siguiente manera...

Por ahora comenzaremos con los siguientes cambios.

app.js

//
 socket.on('send_message',function(data){
  var socketId = users[data.recibe];
  io.to(socketId).emit("newMessage",data);
 });

Este código trata de lo siguiente, obtenemos de dta -> el usuario quien va a recibir el mensaje, extraemos el socket.id de la lista de usuarios  y reenviamos dta directo a la función newMessage, por otro lado en control.js estaremos haciendo muchos mas cambios.

Comenzando por el echo de agregar la siguiente linea a la función isLogin.

control.js

   liUser.onclick=newConversacion;

newConversacion:


Se encarga de invocar la función armaVentanaPrivada la cual construirá lo necesario para que se tenga una conversación privada con cierto usuario.

control.js

function newConversacion(e){
 var to = e.target.innerText;
 var clave = e.target.getAttribute('clave');
 armaVentanaPrivada(clave, to);
}

function armaVentanaPrivada(clave,to){
 if(document.getElementById(clave)==null){
  var cnt = create({type:'DIV','id':clave,class:'conv-privada'});
  var emClose = create({type:'EM',class:'conv-close'});
  var ttl = create({type:'DIV',class:'cnt-title'});
  var cntCnv = create({type:'DIV',class:'cnt-conv','id':'cntCnv_'+clave});
  var lista = create({type:'UL',class:'conv','id':'conv_'+clave});
  var cntCtr = create({type:'DIV',class:'cntControl'});
  var notificacion = create({type:'DIV',class:'is-writing',id:'isW_'+clave});
  var txtMsg = create({type:'TEXTAREA',name:'entrada',rows:'4','id':'inpMsg_'+clave,'style':'resize:none;width:225px;'});
  var btn = create({type:'BUTTON','id':'btn_'+clave,'style':'float: right;padding: 0.7em;margin-top: 0em;padding-top: 1.5em;padding-bottom: 2em;position: absolute;'});
  ttl.textContent=to;
  btn.textContent="Aceptar";
  emClose.textContent='X';
  cntCtr.appendChild(txtMsg);
  cntCtr.appendChild(btn);
  cntCnv.appendChild(lista);
  ttl.appendChild(emClose);
  cnt.appendChild(ttl);
  cnt.appendChild(cntCnv);
  cnt.appendChild(notificacion);
  cnt.appendChild(cntCtr);
  document.body.appendChild(cnt);
  draggable_2(ttl,cnt);
  txtMsg.onkeyup=function(){
   socket.emit('imWriting',{
    user:window.datos.user,
    clave:window.datos.clave,
    length: this.value.length,
    recibe:to
   });
  }
  emClose.onclick = function(){
  cnt.remove();
 }
 btn.onclick = function(){
  if((txtMsg.value.trim()).length>0){
   socket.emit('send_message',{
    recibe:to,
    envia:{user:window.datos.user,clave:window.datos.clave},
    message:txtMsg.value
   });
   agregaMensaje(lista,1,window.datos.user,txtMsg.value, cntCnv);
   txtMsg.value = '';
   txtMsg.focus();
  }
 }
 return {lista:lista,content:cntCnv};
}else{
 return {lista:document.getElementById('conv_'+clave), content: document.getElementById('cntCnv_'+clave)};
}
}
                
Para esta función le pasaremos dos parámetros, clave la cual es el socket.id de quien esta enviando el mensaje o bien a quien se va a enviar el mensaje y como segundo parámetro es el nombre del usuario. La acción de esta función, es bastante básica.
  • Pregunta si ya existe una conversación para la clave que se está pasando como parámetro
    • de ser así retornará un objeto de dos propiedades, { lista: el objeto de lista de conversación, content: el objeto contenedor de la conversación } 
  • Si no existe la conversación con la clave que se esta pasando, se construirá la ventana flotante.
    • Ahora bien, al botón se agrega el evento click, el cual va a extraer el contenido del text área y se enviara a la función send_message pasando le un objeto con las propiedades, 
    • {
      • recibe: el id del socket a quien queremos enviar el mensaje,
      • envia: { 
        • user: usuario que está enviando el mensaje, 
        • clave: clave del usuario que envia el mensaje 
        • }, 
      • message: el contenido del textarea 
    • }
  • Ahora bien. A la caja de texto se agrega el evento keyup el cual siempre y cuando el value de esta caja sea mayor a 1 en ese caso se envía una petición a la función imWriting pasando como parámetro un objeto con las características.
    • {
      • user: usuario que envía,
      • clave: clave del usuario que envía,
      • length: longitud de texto escrito,
      • recibe: id de usuario que recibirá la notificación
    • }
  • De esta manera el usuario con quien se esta conversando sabrá que se esta escribiendo su respuesta a  su comentario.

Debido a que del lado del servidor tenemos un reenvio del mensaje, o bien, recibiendo el mensaje de alguien, es necesario hacer la función newMessage quedando de la siguiente manera.

control.js

//
socket.on('newMessage',function(value){
 var obj = armaVentanaPrivada(value.envia.clave,value.envia.user);
 agregaMensaje(obj.lista,2,value.envia.user,value.message,obj.content);
 var ntf = document.getElementById('isW_'+value.envia.clave);
 ntf.textContent='';
});


Como pueden ver en la función armaVentanaPrivada se invoca una función llamada create, bueno esta funcion esta construida de la manera que sirve para poder hacer los elementos del dom pasando solo las propiedades del elemento, 

control.js

//
function create(dta){
 var obj = Object.keys(dta);
 var elemento = document.createElement(dta.type);
 for( var i = 0; i < obj.length; i ++ ){
  if(obj[i]!='type'){
   elemento.setAttribute(obj[i],dta[obj[i]]);
  }
 }
 return elemento;
}

Para concluir me quedan un par de funciones que agregar, en este caso las funciones que muestran cuando el usuario con quien estamos hablando esta escribiendo o bien cuando el usuario con quien estamos hablando se desconecta.

control.js

socket.on('isWriting',function(dta){
 if(document.getElementById(dta.clave)!=null){
  var ntf = document.getElementById('isW_'+dta.clave);
  if(dta.length>0){
   ntf.textContent=dta.user+" is writing...";
  }else{
   ntf.textContent='';
  }
 }
});
socket.on('isDisconnected',function(dta){
 if(document.getElementById(dta.clave)!=null){
  var ntf = document.getElementById('isW_'+dta.clave);
  ntf.textContent=dta.user+" is disconnected";
  var block = create({type:'DIV',class:'conv-finalizada'});
  var cnt = document.getElementById(dta.clave);
  cnt.appendChild(block);
 }
});


Se me estaba olvidando una de las funciones mas importantes del tema, el agregar el mensaje a nuestra conversación, quedando de la siguiente manera.

control.js

function agregaMensaje(ul,cve,de,msg,cntCnv){
 var dvm = create({type:'DIV'});
 var li = create({type:'LI',class:((cve==1)?'msg-propio':'msg-amigo')});
 var spn = create({type:'SPAN'});
 var fd = new Date();
 var time = fd.getHours()+":"+fd.getMinutes()+":"+fd.getSeconds();
 spn.textContent= ((cve==1)?time+" "+de:de+" "+time);
 dvm.textContent= msg;
 li.appendChild(spn);
 li.appendChild(dvm);
 ul.appendChild(li);
 cntCnv.scrollTo(0,cntCnv.scrollHeight);
}

Sin mas por el momento me despido, esperando que me dejen sus comentarios, que tal les ha parecido el tutorial hasta ahora, si quienren que se agrege algo mas o si me pase de algo....


No olvides hacerte un seguidor y estar al pendiente de la proxima entrada en la cual mostraremos como hacer el estilo a la ventana privada.


hasta pronto.

Anterior                                                                                     Siguiente

lunes, 24 de febrero de 2020

Chat Privado con NodeJs parte 3 ( Estilo a lista de usuarios )

Continuando con el tema del chat es momento de embellecer nuestra lista de usuarios.

Es el momento de crear y modificar el archivo  chatStyle.css en la carpeta raíz/css/chatstyle.css, para ello, lo creamos y comenzamos a agregar los estilos a las diferentes clases.

chatstyle.css

body {
    font: 13px Helvetica, Arial;
}
.contentUser {
    border: solid 1px;
    width: 300px;
    position: absolute;
    top: 10px;
    left: 10px;
    border-radius: 5px;
    height: 500px;
}
ul#usersActivos {
    list-style: none;
    padding: 0;
    height: 445px;
    overflow: hidden;
    overflow-y: scroll;
}
.title-users {
    padding: 1em;
    background-color: #2f2f5d;
    text-align: center;
    color: #f1f1f1;
    cursor: move;
}
#usersActivos li {
    border-bottom: solid 1px;
    padding: 0.75em;
    cursor: pointer;
}
#usersActivos li div {
    font-size: 1.15em;
}


Esto dejara una lista de usuarios con el siguiente estilo

Y es así como concluimos esta entrada... 



Esperare sus comentarios, si no se han unido al blog, agrégalo como favorito. 




Chat privado con nodeJs Parte. 2 ( Conexion y registro de usuarios )

Historia:


Continuando con el proyecto de chat privado con nodeJs ahora veremos como hacer los métodos del lado del servidor.

Desde este lado nos encargaremos de hacer que los clientes se conecten entre si poniendo un intermediario a la conversación.

En este caso los archivos a modificar son, index.html, app.js y control.js, agregando las siguientes lineas.

Código:


index.html
<!-- pantalla login -->
   <div class="login" id="login">
      <input type="text" id="user" placeholder="UserName">
      <button id="btnLogin">Aceptar</button>
   </div>
<!-- plantilla de usuarios -->
   <div class="contentUser" id="cntUsersActivos" hidden>
        <div class="title-users" id="ttlUsersActivos">Usuarios Activos</div>
        <ul id="usersActivos"></ul>
   </div>

Este fragmento se va directo al body del index, dando pie a un input el cual contendra el usuario y un boton que mandara la petición al app.js para asignar un nombre al socket que se acaba de conectar. La acción la agregamos al.

control.js

var btnLogin = document.getElementById('btnLogin');
btnLogin.onclick=function(){
 var usr = document.getElementById('user');
 if((usr.value.trim()).length>0){
  socket.emit('connectUser',usr.value);
  window.datos={
   user:usr.value,
   clave: socket.id
  };
  window.document.title = usr.value;
 }
}


Obtenemos el elemento btnLogin y le asignamos la función click, mediante la cual le decimos que obtenga del input su valor y lo mande a la función ('conectUser') que se encuentra en app.js ademas de crear una variable global en window llamada [" datos "] con los parametros user y clave, por ultimo se cambia el titulo de la ventana dandole el nombre del usuario que se a conectado.

Ademas de agregar el evento click al botón, hay que agregar la función de la recepción de usuarios del lado del cliente, es decir, la parte que agrega usuarios a nuestra lista.

control.js

var lg = document.getElementById('login');
socket.on('isLogin',function(value){
 if(typeof window.datos != 'undefined'){
  lg.setAttribute('hidden','');
  var userActivos = document.getElementById('usersActivos');
  userActivos.parentNode.removeAttribute('hidden');
  userActivos.innerHTML = "";
  for(var i = 0; i<value.length; i ++ ){
   if(value[i].clave!=window.datos.clave){
    var liUser = document.createElement('LI');
    var divUser = document.createElement('DIV');
    divUser.textContent=value[i].user;
    divUser.setAttribute('clave',value[i].clave);
    liUser.setAttribute('clave',value[i].clave);
    liUser.appendChild(divUser);
    userActivos.appendChild(liUser);
   }
  }
 }
});


socket.on( 'isLogin') se encarga de escuchar del lado del cliente, las emisiones del servidor, app.js, en este caso leemos cada uno de los usuarios agregandolos o eliminandolos de nuestra lista.

Ahora bien, del lado del app es necesario explicar lo siguiente. crearemos un arreglo llamado users en el cual se agrega el usuario que se acaba de conectar, modificando la funcion de disconnect, preguntamos por el id que se esta desconectando, para asi eliminar el usuario correspondiente del lado del cliente.

app.js

var users = [];
io.on('connection',function(socket){
 socket.on('disconnect',function(){
  var keys =  Object.keys(users);
  var existe = false;
  for( var i = 0;i < keys.length; i ++ ){
   if( users[keys[i]] == socket.id ){
    delete users[keys[i]];
    existe = true;
   }
  }
  if(existe){
   var nKeys = Object.keys(users);
   var arrRtn = [];
   for( var i = 0;i < nKeys.length; i ++ ){
    arrRtn.push({'user':nKeys[i], 'clave': users[nKeys[i]]});
   }
   io.emit('isLogin',arrRtn);
  }
 });
 socket.on('connectUser',function(user){
  var existe = false;
  var keys =  Object.keys(users);
  var arrRtn=[];
  for( var i = 0;i < keys.length; i ++ ){
   arrRtn.push({'user':keys[i], 'clave': users[keys[i]]});
   if( users[keys[i]] == socket.id ){
    existe = true;
   }
  }
  if(!existe){
   users[user]=socket.id;
   arrRtn.push({'user':user, 'clave': socket.id});
  }
  io.emit('isLogin',arrRtn);
 });
});


Agregamos la función connectUser pasando como parámetro al usuario recién conectado, primero preguntamos si el usuario nuevo existe, de ser así no se hace nada, de lo contrario si no existe se agrega al arreglo y finalmente se envía al cliente en el arreglo de usuarios.




Por ahora es todo, espero sus comentarios.

Unete a mi blog, para asi poder estar al tanto de la siguiente entrada.



Anterior             Siguiente

domingo, 23 de febrero de 2020

Chat privado con NodeJS

Historia:


Anteriormente les deje una entrada con el tema Principios con NodeJs en el cual les hablo de como iniciar un proyecto de hola mundo con node js.

Bueno ahora les traigo un proyecto con la idea de hacer un chat privado, bastante básico y sencillo de hacer.

Sin mas comenzamos.

Instalacion:


Primero que nada comencemos con la instalacion de node js la cual es muy sencilla, bajamos el instalador correspondiente a nuestro sistema en mi caso es windows de 64 bits.

Link: https://nodejs.org/es/download/



La instalación es bastante sencilla como cualquier programa, Instalar-> siguiente -> siguiente 
->siguiente -> finalizar, una vez instalado lo que sigue es la construcción de nuestro proyecto, en xampp\htdocs creamos una carpeta la cual sera nuestro chat. para ello seguimos los siguientes pasos...

Configuracion:



   C:\xampp\htdocs>mkdir inovaniachat

una vez creada la carpeta inicializamos el proyecto,

     npm init


instalamos express y socket.io

        npm install express@4.15.2
        npm install socket.io


con ello tenemos todo lo necesario para continuar con nuestro proyecto, lo que sigue es hacer el index.html y nuestra app.js  quedando con el siguiente codigo.

Código:


index.html

<!DOCTYPE html>
<html lang="en">
<head>
     <meta charset="UTF-8">
     <title>inovania</title>
          <script type="text/javascript" src="/socket.io/socket.io.js"></script>
          <link rel="stylesheet" type="text/css" href="/css/chatstyle.css">
     </head>
     <body>
          <script type="text/javascript" src="/js/control.js"></script>
     </body>
</html>



control.js

var socket = io();


app.js

var express = require("express");
var app = express();
var http = require("http").createServer(app);
var io = require("socket.io")(http);
var path = require("path");

app.get('/',function(req,res){
 res.sendFile(__dirname+"/pages/index.html");
});
var publicDir = path.join(__dirname,'/');
app.use(express.static(publicDir));

io.on('connection',function(socket){
 console.log('user is connected');
 socket.on('disconnect',function(){
  console.log('user is disconnected');
 });
});
http.listen(8420,function(){
 console.log('listening');
});


Les dejo aquí un vídeo de referencia.

Sin mas por el momento los espero en la próxima entrada.



Deja tu comentario, si tienes cuenta de google, hazte un seguidor de inovania para que te lleguen las notificaciones de los siguientes post.

Siguiente

miércoles, 16 de octubre de 2019

Cargar CSV en JavaScript

Cargar y leer un archivo csv en JavaScript sin necesidad de php, java u otro más.

Así es, tal y como lo leen, hoy les traigo un código que espero les ayude tanto como a mi me a ayudado hasta este momento, con un poco de lógica, que les dejara como resultado el contenido del archivo en un array.

Y como siempre lo digo... vamos al punto.

<div id="drop_file_zone" ondragover="return false" ondrop="upload_file(event)">
 <div id="drag_upload_file">
  <div id="datos">
   <h2>
    Drag and drop file here or click for selected file
   </h2>
  </div>
  <input id="selectfile" type="file" />
 </div>
</div>
<div id="dvCSV"></div>
dando como resultado lo siguiente


A esto demos le un poco de estilo.


#drop_file_zone{
 border: solid 1px;
 cursor: pointer;
 }
#drop_file_zone #drag_upload_file{
 height: 3em;
 padding: 1em;
 }
#drop_file_zone:hover{
 border-style: dashed;
 border-radius: 5px;
 border-color: blue;
 }
#drop_file_zone input[type=file]{
 display: none;
 }

Esto quedara así


Ahora lo mas esperado. Así es, el codigo.

Comencemos con las acciones del drop y el evento click a nuestra área de archivo.

---

$( '#drag_upload_file' ).click(function(){
 document.getElementById('selectfile').click();
 document.getElementById('selectfile').onchange = function () {
  uploadCsv( document.getElementById('selectfile').files[0], function(data){
   createTable( data );
  });
 };
});
function upload_file( e ){
 e.preventDefault();
 uploadCsv( e.dataTransfer.files[0], function(data){
  createTable( data );
 } );
}
function uploadCsv( fileUpload, callback ){}
function createTable( datos ){}
---

Con esto, decimos que cuando den click o bien cuando dejen un archivo en nuestra área esta invocará la función uploadCsv, la cual recibe como primer parametro el archivo del file upload mientras que en su segundo parametro deja una funcion de retorno.

Ahora bien el codigo de la funcion uploadCsv es el siguiente.


---

function uploadCsv(fileUpload, callBack) {
 var rtn = {};
 var regex = /^([a-zA-Z0-9\s_\\.\-:])+(.csv)$/;
 if (regex.test(fileUpload.name.toLowerCase())) {
  rtn.name = fileUpload.name;
  rtn.data = [];
  rtn.size = fileUpload.size;
  rtn.encabezado = [];
  if (typeof (FileReader) != "undefined") {
   var reader = new FileReader();
   reader.onload = function (e) {
    var x = 0;
    var rows = e.target.result.split("\n");
    for (var i = 0; i < rows.length; i++) {
     var cells = rows[ i ].split( "," );
     var obj = {};
     var have = 0;
     for( var j = 0; j < cells.length; j ++ ){
      if( cells[ j ].length == 0 )break;
      have = 1;
      if( i == 0 ){
       obj[ 'field_' + j ] = ( cells[ j ].trim() ).toUpperCase();
      }else{
       var field =  rtn.encabezado[0]['field_' + j ] ;
       obj[ field ] = cells[ j ];
      }
     }
     if( i == 0 ){
      rtn.encabezado.push( obj );
     }else{
      if( have == 1 )
       rtn.data.push( obj );
     }
     x++;
    }
    rtn.total = x ;
    callBack( rtn );
   }
   reader.readAsText(fileUpload);//.files[0]);
  } else {
   callBack( "Este navegador no soporta html5" );
  }
 } else {
  callBack( "El archivo no es csv");
 }
}
---

Ahora solo falta el mostrar el contenido de nuestro archivo, y para ello nos creamos la funcion createTable con lo siguiente,


---

function createTable(datos) {
 var table = document.createElement("table");
 var rows = datos.data;
 var cells = Object.keys( datos.encabezado[ 0 ] );
 for (var i = 0; i < rows.length; i++) {
  var row = table.insertRow(-1);
  for (var j = 0; j < cells.length; j++) {
   var cell = row.insertCell(-1);
   cell.innerHTML = datos.data[i][ datos.encabezado[ 0 ][ cells[ j ] ] ];
  }
 }
 var head = table.createTHead( -1 );
 var row = head.insertRow( -1 );
 for( var j = 0; j < cells.length; j ++ ){
  var th = document.createElement( 'TH' );
  th.innerHTML = datos.encabezado[ 0 ][ cells[ j ] ];
  row.appendChild( th );
 }
 var caption = table.createCaption();
 caption.innerHTML = "
" + datos.name + "";

 var dvCSV = document.getElementById("dvCSV");
 dvCSV.append( table );
}
---

Y así de simple es como queda esto. no sin antes darle un mejor estilo a nuestra tabla creada a partir del contenido del archivo csv.


----

table{
 width: 100%;
 border: 1px;
 border-collapse: collapse;
}
table caption {
 border: solid 1px;
 font-size: larger;
 padding: 0.5em;
}
table thead tr th {
 padding: 0.75em;
 border: solid 1px;
 border-top: none;
 font-size: larger;
}
table tr td {
 border: solid 1px;
 padding: 0.5em;
 font-size: small;
}
----
dejando al final un resultado como el siguiente.


Espero les sirva de apoyo para su desarrollo, sin mas.. me despido por el momento, espero sus comentarios.

jueves, 3 de octubre de 2019

Pricipios con NodeJs

Así es, tal y como sus ojos lo leen, esta vez les traigo una entrada referente a la librería node.js.

Para comenzar instalaremos el paquete, para ello es lo siguiente.

https://nodejs.org/es/download/

Dependiendo del caso que lo requiera Windows, Linux o Mac.

Una vez instalado, comprobamos la librería abriendo la terminal o linea de comando, con la orden.

C:\>_ node --version

Para continuar es necesario seguir estos pasos.

1.- Crear un directorio
2.- En el directorio nuevo, crear el init con node.
3.- Descargar los módulos necesarios para la aplicación requerida.

Con todo esto aclarado aremos nuestro primer "Hola mundo" desde node.js, Manos a la obra.

En xampp/htdocs: creamos la carpeta holamundo, desde cmd nos posicionamos en la carpeta holamundo e indicamos.


El resultado debería ser el siguiente.


Esto nos deja un archivo package.json el cual ira cargando los módulos que se instalen.

Dentro de hola mundo, creamos un archivo js llamado index.js, el cual contendrá el siguiente código...


var http = require( "http" );
http.createServer( function( req, res ){
res.writeHead( 200, {
'Content-Type':'text/plain'
});
res.end( 'hola Mundo\n' );
}).listen( 8420 );
console.log( 'servidor en url http://localhost:8420' );


Al final, damos el comando.

nos colocamos en nuestro navegador en el puerto indicado y listo, tenemos nuestro hola mundo echo en node js



No olvides dejarme tu comentario.

Si puedo ayudarte en algo escribeme.

Asta la próxima.

jueves, 23 de mayo de 2019

ForEach en javaScript

Buen día a todos.

Así como en javaScript existe el ForEach en java su similar no se llama ForEach o Each como normalente se llamaría, en java se invoca igual que un for normal solo que la declaración de las variables cambia esto se ve reflejado de la siguiente manera,


ForEach:


String[] semana = { "lun","mar","mie","jue","vie","sab","dom" };

for( String sem: semana ){
   System.out.println( sem );
}

Suponiendo que tenemos una clase con los siguientes datos:

class Datos{
   String nombre;
   int edad;
   String ciudad;
}

Con sus respectivos set's y get's, ahora hemos creado una lista del tipo Datos la cual contiene n... cantidad de registros y lo que quieres es recorrerla, el ciclo queda de esta manera.


List listita; // ya la tienes seteada con su respectiva información.

for( Datos dato: listita ){
   System.out.println( dato.getNombre() + " " + dato.getEdad() + " " + dato.getCiudad() );
}


En cuanto al uso de un foreach recomiendo mas solo cuando se trata de recorrer un conjunto de datos ya sea un array o bien una lista, el punto aquí es que si solo se requiere recorrer.

Por otro lado tal vez te preguntas como es que le haces para salir de un ciclo como esto, bueno el código para finalizar es con un break; quedando así


for( String sem: semana ){
   if( sem.equals( "mie" ) ){
      break;
   }
}

Por hoy es todo. Espero les aya servido de algo, si es así, deja tu comentario, si algo se me paso, de igual manera deja tu comentario. si tienes alguna duda espero poder ayudarte.


saludos y hasta la proxima;