Search code examples
phpjavascriptajaxfacebookfacebook-chat

the facebooks 'xyz is typing' feature?


Doesd anyone has any idea of how to make the feature like Facebook uses in chat, where when you start typing it shows up on the users screen?

I have a complete working chat based on user id,s but unble to make this. The chat is working using JSON,php and ajax.


Solution

  • This is actually a pretty easy feature to add to a chat. You are first going to need a place to store the typing information. I usually just store it in a database. 1 for is typing, and 0 for not. You are going to want to use a smart setup so that when typing only 1 request is sent to show you are typing and not everytime you hit the key. I have mine set up with a timer so when the user stops typing for 2000 milliseconds, the typing setting for that conversation is set to 0

    My Script looks like:

    var typing = false,
        shift = false,
        timer;
    $(".chatText").unbind('keyup keypress blur').keypress(function (e) {
        if (e.keyCode == 13) {
            if (e.shiftKey !== true) {
                shift = true;
                return false;
            }
        }
    }).bind('keyup', function () {
        if (shift) {
            Connect.messages.send(id, to);
            Connect.type(id, 0);
            shift = false;
        } else {
            clearTimeout(timer);
            if ($(this).val().length > 0) {
                if (!typing) {
                    Connect.type(id, 1);
                }
                timer = setTimeout(function () {
                    Connect.type(id, 0);
                }, 2000);
            }
            if ($(this).val().length == 0) {
                Connect.type(id, 0);
            }
         }
    }).blur(function () {
        Connect.type(id, 0);
    });
    

    Connect.type function:

    type: function (id, t) {
        if ((t == 0 && typing) || (t == 1 && !typing)) {
            $$.connect.staticRec(btoa($$.TRANS.d("L2FqYXgvdHlwZS5waHA/aWQ9") + id + $$.TRANS.d("JlNFVD0=") + t)); //ajax/type.php?id={id}&SET={t}
        }
        if (t) {
            typing = true
        }
        else typing = false;
    }
    

    ajax/type.php:

    <?php
        require "connect.php";
        require "user.php";
    
        $number = $data['number'];
        $id = escape($_GET['id']);
    
        if (strlen($id) < 4 OR strlen($id) > 6 OR (int)$_GET['SET'] > 1) exit();
    
        $FOTQ = $mysqli->query("SELECT `from` FROM `typing` WHERE `id`='$id'")->fetch_assoc(); //from or to query
        $FOT = ($FOTQ['from'] == $number ? 'from' : 'to') . 'typing';
    
        $type = escape($_GET['SET']);
    
        $mysqli->query("UPDATE `typing` SET `$FOT`='$type' WHERE `id`='$id'");
    ?>
    

    Informing the user using Server Sent Events (note: my own SSE function):

    var $id = $(this).data("id");
    var item = $(".messageBox[data-id='" + $id + "']");
    item.data("orgName", item.children("name").text());
    $$.connect.live.create({
        url: $$.TRANS.e("/ajax/typing/" + $id),
        message: function (e) {
            item = $(".messageBox[data-id='" + item.data("id") + "']");
            if (e.data == "1") {
                var name = item.children("name").text();
                var firstName = name.split(" ")[0];
                var hasName = name.match(/[0-9]/) ? "User" : firstName;
                item.children("name").html(hasName + "..is typing");
             }
             if (e.data == "0") {
                 item.children("name").text(item.data("orgName"));
             }
         },
         duration: 2500
    }, "typing", false);
    

    My typing.php for the Server-Sent Event:

    <?php
        require "connect.php";
        require "user.php";
    
        header("Content-Type: text/event-stream\n\n");
        header('Cache-Control: no-cache');
    
        set_time_limit(1200);
    
        $id = escape($_GET['id']);
        $number = $data['number'];
        $ms = 100;
        $tS = 0; //type stat
    
        while (1) {
            $FOTQ = $mysqli->query("SELECT * FROM `typing` WHERE `id`='$id'")->fetch_assoc(); //from or to query
            $cts = $FOTQ[($FOTQ['from'] == $number ? 'to' : 'from') . 'typing']; //current type stat
    
            if ($tS != $cts) {
                echo "data:" . $cts;
                echo "\n\n";
                $tS = 1;
            }
    
            echo "\n\n";
    
            ob_flush();
            flush();
            usleep($ms * 1000);
        }
    ?>
    

    I'm using Server-Sent Events. That allows me to keep an open connection with the server.

    NOTE: My PHP skills are Meh.

    But, hope this gives you an idea.