3

I have a small shoutbox chat written with PHP and Ratchet.

In JS, I have the following event, which fires a regular js function which happens on pressing enter at the moment:

socket.onmessage = function(evt) {
    var data = JSON.parse(evt.data);
    addMessage(data.msg);
};

That works, but I want to write a message "user is typing" while the user is typing and before the message is actually sent, so I am guessing I need to call the onmessage event manually, is that possible?

relevant js:

var chat = $('#chatwindow');
var msg = $('#messagebox');

function addMessage(msg) {
    chat.append("<p>" + msg + "</p>");
}

msg.keypress(function( event ) {
    if ( event.which != 13 ) {
        return;
    }

    event.preventDefault();

    if (msg.val() == "" || !open) {
        return;
    }

    socket.send(JSON.stringify({
        msg: msg.val()
    }));

    addMessage(msg.val());
    msg.val("");

});

socket.onmessage = function(evt) {
    var data = JSON.parse(evt.data);
    addMessage(data.msg);
};
user6562256
  • 127
  • 1
  • 2
  • 10

1 Answers1

0

You have evt.data which is being passed from the server. Add another type of event, which will trigger when a user is typing.

Something like:

socket.onmessage = function(evt) {
    var data = JSON.parse(evt.data);
    if ( data.type == 'message' ) {
        addMessage(data.msg);
    } else if ( data.type == 'typing' ) {
        showUserIsTyping();
    } else if ( data.type == 'typingStopped' ) {
        hideUserIsTyping();
    }
};

All you'd need to do is send a message to the server when the user is typing, and maybe add a timeout, and send an event of typingStopped if the user hasn't typed anything in like 10 seconds or so.

Here is an example using the code you provided:

var msg = $('#messagebox');

function addMessage(msg) {
    chat.append("<p>" + msg + "</p>");
}

msg.keypress(function( event ) {
    event.preventDefault();

    if (msg.val() == "" || !open) {
        return;
    }

    //User pressed enter
    if ( event.which == 13 ) {
        socket.send(JSON.stringify({
            type: 'message'
            msg: msg.val()
        }));
        addMessage(msg.val());
        msg.val("");
    } else {
        //Keypress, but not enter
        socket.send(JSON.stringify({
            type: 'typing'
        }));
    }
});

socket.onmessage = function(evt) {
    var data = JSON.parse(evt.data);

    switch ( data.type )
    {
        case 'message':
            addMessage(data.msg);
            break;
        case 'typing':
            notifyUserTyping(); //Create this function, and have it show/hide a "Typing..." textbox or similar.
            break;
    }
};
Community
  • 1
  • 1
Blue
  • 22,608
  • 7
  • 62
  • 92
  • But how would I add my own event? The onmessage happens when a message is already sent. – user6562256 Jul 26 '16 at 16:46
  • The `onmessage` event happens because you're calling it somewhere in your code (You mentioned when a user presses enter), which is passing it the server. That doesn't mean you can't send it in other places (Like when someone is typing). Because you can modify the data however you want, simply pass the event as a key (ie. `socket.sendMessage({event: 'message', msg: 'testing'});`), so that you can parse it out on the other client. – Blue Jul 26 '16 at 16:50
  • To summarize: Send multiple messages to the server: `{type: 'message', msg: 'testing'}`, when the user hits enter. Send `{type: 'typing'}` when the user is starting to type. Send `{type: 'typingStopped'}` after a timeout period to notify the other user that they're no longer stopped. Parse out `type` on the other client to figure out what type of event happened (message, typing, or typingStopped), and fire your handlers appropriately. – Blue Jul 26 '16 at 16:52
  • I understand you in theory but not in practice, as a matter of fact I am not sure when `socket.onmessage` happens, I've pasted the relevant JS, mind having a look? – user6562256 Jul 26 '16 at 17:01
  • Thanks a lot, that solved my issue. One more q though, the `notifyUserTyping` function which is called in `socket.onmessage` happens on the other side (the receiving side), is there a way to choose sides? Because like this I do not see how to check if the sender stopped typing, I am checking if the message box is empty after a few seconds but that checks the receiver's message box. I can make a new question for this if u want. – user6562256 Jul 26 '16 at 17:27
  • There is no 'choosing sides'. You have 2 clients. You want something to end up on the other side, you have to use a websocket message, and parse it from the `onmessage` event. – Blue Jul 26 '16 at 17:34
  • Meant it figuratively :) Yes yes I am getting it now, thank you so much! – user6562256 Jul 26 '16 at 18:14