Chat (Long-Pooling Example)

by bizamajig

HTML

<div id="chat">
    <ul id="mensagens">
    </ul>
    <form action="#" method="post" accept-charset="utf-8">
        <label for="escrever">Escrever</label><input type="text" name="escrever" value="" id="escrever">
        <input id="send" type="submit" value="Continue &rarr;">
    </form>
</div>

CSS

*{
    color: #444; 
    font: 13px/1.48 "Helvetica Neue", Helvetica, Arial, FreeSans, sans-serif;
    text-rendering: optimizeLegibility; /*Safari hack for font smoothing, text-stroke causes some performance issues on scrolling*/
    -webkit-font-smoothing: antialiased; 
}

strong{
    font-weight: bold;
}
#mensagens{
    border: 1px solid #aaa;
    height: 300px;
    overflow-y: scroll;
}

form {
    background: #444;
    padding: 5px;
}

label{
    display: none;
}

input[type=text]{
    border: 1px solid #aaa;
    width: 80%;
    height: 30px;
}

input[type=submit]{
    width: 18%;
}

JavaScript

var $e = $('<b />'); /* Basic Pub/Sub object. */

/* Generate a User ID */

function S4() {
    return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
}

function guid() {
    return (S4() + S4() + "-" + S4());
}

/* Pooling Constructor */

function LongPooling() {
    var instance = this;

    this.makeRequest = function(event, msgs) {
        var delay = (msgs) ? 100 : 10000;
        $.ajax({
            url: 'http://15ml.at/LPexample/chat.php',
            type: 'GET',
            data: (msgs) ? msgs : null,
            dataType: 'jsonp',
            async: true,
            cache: false,
            timeout: 10000,
            success: function(msg) {
                $e.trigger('chat/get/success', [msg]);
               
                setTimeout(instance.makeRequest, delay); /* Pedido espaçado de novas mensagens */
            },
            error: function(msg) {
                $e.trigger('chat/get/error', [msg]);
                setTimeout(instance.makeRequest, 15000);
            }
        });
    };
}

/* Chat Constructor */

function ChatMessaging() {
    var instance = this,
        $escrever = $('#escrever');

    this.user = guid();

    this.sendMsg = function(event) {
        event.preventDefault();
        var obj = {
            user: instance.user,
            type: 'sent',
            msg: $escrever.val()
        };

        if (obj.msg.length) {
            $e.trigger('chat/post/msg', [obj]);
        }

        $escrever.val("");
    };

    this.receivedMsg = function(event, msg) {
        var $container = $('#mensagens'),
            container = $container.get(0),
            i, /* for counter*/
            tmlp = '';

        for (i in msg) { /* i freaking hate for in's */
            if (msg.hasOwnProperty(i)) {
                tmlp += '<li class="' + msg[i].type + '"><time>' + msg[i].time + '</time><strong>&lt;' + msg[i].user + '&gt;</strong><span> ' + msg[i].content + '</span></li>';
               ...