Dectecting when a client is typing.

Need help with SmartFoxServer? You didn't find an answer in our documentation? Please, post your questions here!

Moderators: Lapo, Bax

User avatar
mnkyhead
Posts: 13
Joined: 10 May 2006, 14:59
Location: Maine, USA
Contact:

Dectecting when a client is typing.

Postby mnkyhead » 12 Oct 2006, 21:15

Is there a way to detect, and display a message when, someone is typing a message?
You know have it say "is typing" next to the users name.
User avatar
Lapo
Site Admin
Posts: 23026
Joined: 21 Mar 2005, 09:50
Location: Italy

Postby Lapo » 13 Oct 2006, 06:49

Yes, you should check keypresses on the client side and send a message (for example using sendObject()) to the other client(s)

Just use the Flash Key object to detect the keyboard
Lapo
--
gotoAndPlay()
...addicted to flash games
User avatar
mnkyhead
Posts: 13
Joined: 10 May 2006, 14:59
Location: Maine, USA
Contact:

Postby mnkyhead » 13 Oct 2006, 16:02

Thats what I was thinking, but do you think this could slow down the app? If it sends a message with each key press, that could create a lot of traffic.
User avatar
Virusescu
Posts: 260
Joined: 07 Sep 2005, 09:36
Location: [RO]Bucharest
Contact:

Postby Virusescu » 13 Oct 2006, 19:55

Nobody sugested that you send a message each time a key is pressed.
No way !!!
You need to check when the user starts typing and when it stops, with a precission of like 500 milliseconds.
If no keypress occures between 2 intervals, then the user stoped typing. If at least one keypress occurs, then the user is typing.
Each 500 milliseconds, you need to decide that, and send the object with the userIsTyping = true or false information attached.
Also, you need to make sure that you send this object only if a change occurs. If 5 seconds ago the user wasn't typing anything, and now he also isn't typing, then there's no need to send an object telling others that he is still doesn't typing :P

I hope you got the ideea.
function onJoin(usr) {if (usr.getName() == "Lapo") trace ("All Hail Lapo");}
User avatar
mnkyhead
Posts: 13
Joined: 10 May 2006, 14:59
Location: Maine, USA
Contact:

Postby mnkyhead » 17 Oct 2006, 22:29

hmm, didn't think of that. I just have it send an object on every key press, that is probably why I am getting this warning
[ WARNING ] [id: 12] (SystemHandler.processEvent): SysHandler -> Bad room id. Action: asObj >> java.lang.NumberFormatException: For input string: "null"

So tell my if this sounds right,
have a boolean isTyping
In the Key listener function check against that boolean, if false, set the boolean to true and send the object to sfs, start the interval to watch the key presses.
If the interval function doesn't see a key press in 500ms set the boolean to false and send the object, and kill the interval.
User avatar
mnkyhead
Posts: 13
Joined: 10 May 2006, 14:59
Location: Maine, USA
Contact:

Postby mnkyhead » 18 Oct 2006, 00:29

I'm a little stumped on how to go about watching for no typing.
I have a Key listener, so I know when a key is pressed, but I am unclear as to what to put in my Interval function to check for no key presses....
I was thinking a boolean in a onKeyDown set to true, and onKeyUp set to false, but that seems pretty hap-hazard, and real easy to break.

But I can't think of any other way to go about it other then using the Key listeners.
wallis2xk
Posts: 43
Joined: 01 Sep 2006, 10:00
Location: United Kingdom

Postby wallis2xk » 18 Oct 2006, 07:44

Perhaps this?

Code: Select all

input_box.onChanged = function() {
   if(this.text == "") {
      isTyping = false;
      //send out server message
   }else{
      if(!isTyping) {
         isTyping = true;
         //send out server message
      }
   }
}
User avatar
Virusescu
Posts: 260
Joined: 07 Sep 2005, 09:36
Location: [RO]Bucharest
Contact:

Postby Virusescu » 18 Oct 2006, 13:31

Hey, mnkyhead, you got it almost right.
Your problem is simple. You don't check in the keylistener wheter the user is typing or not, because you already KNOW he's typing. You are doing this in the key listener when a key is pressed so, dooh, he's typing, you can bet on it :) - (maybe check if the current focus is on the chat_txt - depending of your application).
Try this way
Have a boolean isTyping, and one like lastTypingStatus=false;
In the Key listener function set isTyping = true;
In the interval function that keeps repeating, check isTyping and lastTypingStatus like this

Code: Select all

if (isTyping) {
// user is typing
// but was he typing the previous interval?
    if(lastTypingStatus) {
      // do nothing because he was typing the previous interval
      // and you already sent the message
      // you can eliminate this if and switch the else with an if(!lastTypingStatus) ...
    }else {
      // he wasn't typing you need to notify the players
      sendTypingNotice(true);
      lastTypingStatus = true; // you could set this value inside the sendTypingNotice, whatever suits you best
    }
}else {
   // means that it remained false
   // means that user stopped typing
   if (lastTypingStatus) {
      //if he was typing last interval, the we need to inform the other users that I stoped typing
      sendTypingNotice(false);
      lastTypingStatus = false;
   }else {
     // this is not necessary, because you don't need to notify the others
     // you already notffied them in the previous interval
   }
}
// after all this you need to reset the isTyping value
isTyping = false;


I hope it's all more clear now.

@wallis2xk the onChanged is called on each keypress. It's the same thing as asigning a key listener. But we don't want to send messages each time a user presses a key. Think about it ;). It would be an unnecessary overload for the server. You need to notify users only when something changes. In our "example", the behaviour of the user. He starts/stops typing. So, you need to define what "the user stop typing" means. If I stop for 100 miliseconds between keypresses does this really means I've stoped typing?

Hope the steps above will help you understand what I'm talking about.

A nice day to you all.
function onJoin(usr) {if (usr.getName() == "Lapo") trace ("All Hail Lapo");}
User avatar
mnkyhead
Posts: 13
Joined: 10 May 2006, 14:59
Location: Maine, USA
Contact:

Postby mnkyhead » 18 Oct 2006, 14:54

Virusescu thanks for the help.
Here is what I came up with

Code: Select all

//this is the main boolean checked in the key listener
var isTyping:Boolean = false;
//Interval
var typeChecking:Number;
//boolean set in key functions, onKeyDown set to true, onKeyUp set to false
var keyHit:Boolean = false;
//
smartfox.onObjectReceived = function(obj:Object, sender:User){
   if(obj.is == true){
      trace("typing");
   }else{
      trace("not typing");
   }
   
}
//function called by Interval
function keyPressed(){
        //if keyHit is false, typing has stopped
   if(!keyHit){
      clearInterval(typingCheck);
      isTyping = false;
      sendTypingMsg();
   }
}
//send the object
function sendTypingMsg(){
   var Typing:Object = new Object();
   Typing.is = isTyping;
   smartfox.sendObject(Typing);
}
//Key listeners
var keyListener:Object = new Object();
keyListener.onKeyDown = function() {
   keyHit = true;
   if(Key.getCode() == Key.ENTER){
      sendChatMsg();
      clearInterval(typingCheck);
      isTyping = false;
      sendTypingMsg();
   }else{
      if(!isTyping){
         isTyping = true;
         sendTypingMsg();
         typingCheck = setInterval(keyPressed,2000);
      }
   }
   
};
keyListener.onKeyUp = function() {
   keyHit = false;
}
Key.addListener(keyListener);


It seems to work ok. I set the interval to 2000 to compensate for slower typers.
Let me know what you think.
User avatar
Virusescu
Posts: 260
Joined: 07 Sep 2005, 09:36
Location: [RO]Bucharest
Contact:

Postby Virusescu » 18 Oct 2006, 19:38

Why kill the interval?
This is what I was thinking about

Code: Select all

//this is the main boolean checked in the key listener
var isTyping:Boolean = false;
var lastWasTyping = false;
smartfox.onObjectReceived = function(obj:Object, sender:User){
  // you'll need to separate the objects it you want to use this mechanism for other commands - but now it's ok
 if(obj.is == true){
      trace("The user STARTED typing");
   }else{
      trace("The user STOPED typing");
}
// notice the emphasis on the state change and not on the action itself
//function called by Interval
function keyPressed(){
        //if keyHit is false, typing has stopped
   if(isTyping){
      if (!lastWasTyping) {
        // the user started typing
        sendTypingMsg(true);
      }else {
        // the user was already typing, don't notify further
       }
       lastWasTyping = true;
   }else {
       // the user hasn't typed since last interval
       if (lastWasTyping) {
          // the user was typing last time we checked
          // means he stopped, so we need to notiffy users
         sendTypingMsg(false);
       } else {
          //nothing changed, do nothing :)
       }
       lastWasTyping = false;
   }
   // we reset the isTyping wich will be set back to true when a key is pressed
   isTyping = false;
}
//send the object
function sendTypingMsg(bool){
   var Typing:Object = new Object();
   Typing.is = bool;
   smartfox.sendObject(Typing);
}
//Key listeners
var keyListener:Object = new Object();
keyListener.onKeyDown = function() {
   isTyping = true;
};
keyListener.onKeyUp = function() {
   if(Key.getCode() == Key.ENTER){
      // i'd suggest putting this in the onKeyUp to prevent repetition if user has his finger stucked on the enter key ;)
      sendChatMsg();
    }
   isTyping = true;
}
Key.addListener(keyListener);
typingCheck = setInterval(keyPressed,2000);


I hope there aren't too many mistakes here, because I written it here.
Tell me if it works and if you understand, finaly, what I was trying to say. Try to read again the previous post, maybe the explanations will help more with this piece of code.
You need to send data ONLY when it changes ;). This is optimising bandwith usage.
function onJoin(usr) {if (usr.getName() == "Lapo") trace ("All Hail Lapo");}
User avatar
Virusescu
Posts: 260
Joined: 07 Sep 2005, 09:36
Location: [RO]Bucharest
Contact:

Postby Virusescu » 18 Oct 2006, 19:40

What I am trying to say is that you still send irrelevant messages, even if now it's better because you send a message every 2 seconds.
But all can be done better :). And you can rise the interval to 1 second, because messages won't be sent each second... except it there's a change in the user's behaviour :).
Do you understand :)?
function onJoin(usr) {if (usr.getName() == "Lapo") trace ("All Hail Lapo");}
wallis2xk
Posts: 43
Joined: 01 Sep 2006, 10:00
Location: United Kingdom

Postby wallis2xk » 19 Oct 2006, 08:33

@wallis2xk the onChanged is called on each keypress. It's the same thing as asigning a key listener. But we don't want to send messages each time a user presses a key. Think about it Wink. It would be an unnecessary overload for the server. You need to notify users only when something changes. In our "example", the behaviour of the user. He starts/stops typing. So, you need to define what "the user stop typing" means. If I stop for 100 miliseconds between keypresses does this really means I've stoped typing?


I would imagine the functionality you are looking is for, (which is what is employed in all the IMs I use), is that if I have something in my input box, then I am considered to be typing a message. If it's empty I'm not. If I pause for a few seconds to think about what I'm going to say, it shouldn't mean I've stopped typing a message.

So you just need to check whether you input box has changed from empty to something or something to empty, and only send a message if either of those occurs. Much simpler and less bandwidth.
User avatar
Virusescu
Posts: 260
Joined: 07 Sep 2005, 09:36
Location: [RO]Bucharest
Contact:

Postby Virusescu » 19 Oct 2006, 09:46

Yeppp.. you are right wallis2xk. I've missed the first check if(this.text == "")

Your code would turn out much easyer :oops:

I sometimes tend to get overlycomplicated with such easy things.
function onJoin(usr) {if (usr.getName() == "Lapo") trace ("All Hail Lapo");}
wallis2xk
Posts: 43
Joined: 01 Sep 2006, 10:00
Location: United Kingdom

Postby wallis2xk » 19 Oct 2006, 10:31

Virusescu wrote:I sometimes tend to get overlycomplicated with such easy things.


Join the club :)

Return to “SmartFoxServer 1.x Discussions and Help”

Who is online

Users browsing this forum: No registered users and 63 guests