Autotel

Unchat

realtime chat

A  mini-project to learn Node JS.Is a chat in which the typed text from any user in the room, would be visible in real-time with no need to submit it. I called it unchat, because it deprecate two very important utilities of the chat: being able to talk asynchronously as the message will stay for the user to read when he can; and giving the possibility to read a text before is sent. It still lacks a node server to have it finished and running.

The code in parts:

Node server

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

User session var and function
var users=\[\];
app.get('/', function(req, res){
  res.sendFile(\_\_dirname + '/index.html');
});

function randomString(length) {
    chars="qweiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890";
    var result = '';
    for (var i = length; i > 0; --i) result += chars\[Math.round(Math.random() \* (chars.length - 1))\];
    return result;
}

Here I declare the users var, which will store all the connected users and an identificator; that will be used to relate the source user of a connection event to a message send event. This identificator is created randomly by the randomSrting function, which I grabbed and modified from Nimphious@Stack overflow. This could be understood as an automated replacement of writing one own's user name. I could have also used the IP or distinguish events by passing the socket object with each event, but I felt more comfortable with this logic for the extent of a learning experiment.

User socket events

io.on('connection', function(socket){ //user connection protocol console.log('a user connected'); var id=randomString(Math.random()*80); var pos=users.push(id)-1; console.log('given the '+id+' id at'+pos); io.emit('new user',id); socket.emit('hello',id,users); socket.on('disconnect', function(){ console.log('user disconnected'); users.splice(pos,1); io.emit('disconnect',id); }); socket.on('update', function(who,msg){ //console.log('update: '+ who +" sent "+ msg); socket.broadcast.emit('update',who, msg); }); });

So every user event is declared within the io's connection event, because there they can be associated with one single connection event; say that when a user sends a message, will be understood as the same user that connected. This because each io.emit is listening the events within the same socket object. The console.log function in the socket side, will display messages in the console that is running the socket server younodeunchatconsolesocket This code, on the event of a new user connection, will print "a user connected" in the console, then get a random string and store in the users array; and print that given id in the console. Then it will emit "new user" with this id to every client that is connected to this socket, so they browsers get aware of this event, and also emit a "hello" to the recently connected user, so that browser runs a small function to initialize given the id. Then it declares two listeners; one for disconnect, and one for update; one for when this client disconnects from the socket and the other for when the user types. Each will emit the event to the other users, and for the case of disconnect, it will erase this user id from the users array.

http.listen(3000, function(){
  console.log('listening on \*:3000');
});

At last, the http listen function. This starts the socket.

Client side

I will not speak much about the HTML and styles because they are out of this learning scope; but the whole code is available at the Git repository, linked at the bottom.

Document.ready

$(document).ready(function(){});

The whole code that I will describe occurs on the document.ready event, as the best practices recommend; basically because we want every element to be loaded and ready at the moment of applying events to them.

newuser function
function newuser(who){
    if($("#"+who).length==0){
      console.log("mr "+who+" entered");
      $('#actors').append($('<div id="'+who+'" class="actor" style="max-width: 0px; opacity: 0;">')); 
     $("#"+who).append($('<div class="text">')); $("#"+who).append('<img class="mono" src="https://upload.wikimedia.org/wikipedia/commons/4/4e/Aiga\_toiletsq\_men.svg" alt="" />');     
     $("#"+who).animate({"max-width":400,opacity:1}); } }

Initialize user
  var me="none";
  var socket = io();
  //create new user between all the peers, recieve a new user
  socket.emit('new user');
  socket.on('hello', function (who,others){
    console.log("hello,mr"+who);
    console.log(others);
    for(a=0;a<others.length;a++){ newuser(others\[a\]); } me=who; $("#"+who+">.text").append('You:<br><textarea id="voice" autocomplete="off" />');
    appendVoice();
  });
  socket.on('new user', function(who){
    newuser(who);
  });

First it declares the me variable which will store this random string that will be sent by the socket later; so currently is "none". Then it creates the socket object that will be used to emit and receive communication from the server. It also sends the new user message to the serves. As explained, this will put the server to generate a random key and send it back to the client. That response is the hello event, whose handler is declared next: it will store this random user name in the "me" variable; and also it will receive an array with all the other users, so it can know how many different id's to expect. It will create a graphic for each user received in "others" by using the "newuser()" function. It passes the random name into it; to name the element. It will also create a representation for himself. At the end, this code selects this representation and puts the text input into it and "appends the voice". It also declares a handler for a new user, which just does the newuser function again, for this new user.

appendVoice
 function appendVoice(){
    $('#voice').on('input change',function(){
      socket.emit('update',me,$('#voice').val());
    });
  }

This create a Jquery listener for "input change"; this means that whenever the user writes or makes a change in an input named voice, it will do the declared function. In this case, the voice input, is the textarea that was created before, and the resulting function consists on emiting this written text to the server.

Socket events
 socket.on('update', function(who,msg){
    console.log("mr "+who+" wrote "+msg);
    $('#'+who+">.text").html(msg);
  });
  socket.on('disconnect', function(who){
    console.log("mr "+who+" disconnected");
    $('#'+who+">img").animate({"bottom":200});
    $('#'+who+"").fadeOut();
  });

This are the client side response to the server sent events update, and disconnect. The update event is the one that contains the other user written text; therefore it is written tho the corresponding figure in the navigator; it knows which figure to put text at by using the "who", which contains this randomly generated text. Then, the disconnect event will make a little disappear animation to the representation of that user: move upward and fade out.

Go to git: github.com/autotel/unchat