3

I am trying to make a facebook style user typing system. But i have one question about keypress.

So my code is working fine but i want to change something else like keypress, keyup, paste ect.

I am using following javascript and ajax codes. In the following my ajax code is working like if ($.trim(updateval).length == 0) { send width notyping.php notyping.php posting 0 and the 0 is don't show typing message.

If if ($.trim(updateval).length > 13) { send with usertyping.php usertyping.php posting 1 and the 1 is show typing message.

The problem is here if user is stoped to wrire some message then it is everytime saying typing. What should I do to fix for it anyone can help me in this regard ?

All ajax and javascript code is here:

;
(function($) {
  $.fn.extend({
    donetyping: function(callback, timeout) {
      timeout = timeout || 1000; // 1 second default timeout
      var timeoutReference,
        doneTyping = function(el) {
          if (!timeoutReference) return;
          timeoutReference = null;
          callback.call(el);
        };
      return this.each(function(i, el) {
        var $el = $(el);
        // Chrome Fix (Use keyup over keypress to detect backspace)
        // thank you @palerdot
        $el.is(':input') && $el.is(':input') && $el.on('keyup keypress paste', function(e) {
          // This catches the backspace button in chrome, but also prevents
          // the event from triggering too premptively. Without this line,
          // using tab/shift+tab will make the focused element fire the callback.
          if (e.type == 'keypress' && e.keyCode != 8) return;

          // Check if timeout has been set. If it has, "reset" the clock and
          // start over again.
          if (timeoutReference) clearTimeout(timeoutReference);
          timeoutReference = setTimeout(function() {
            // if we made it here, our timeout has elapsed. Fire the
            // callback
            doneTyping(el);
          }, timeout);
        }).on('blur', function() {
          // If we can, fire the event since we're leaving the field
          doneTyping(el);
        });
      });
    }
  });
})(jQuery);

Checking text value if is 0 then send data is 0 for user no typing

$('#chattextarea').donetyping(function() {
  var typingval = $("#chattextarea").val();
  var tpy = $('#tpy').val();
  if ($.trim(typingval).length == 0) {
    $.ajax({
      type: "POST",
      url: "/notyping.php",
      data: {
        tpy: tpy
      },
      success: function(data) {

      }
    });
  } 

Checking text value is >13 then send data is 1 for user typing.(Maybe need to change this if statement)

if ($.trim(typingval).length > 13) {
    $.ajax({
      type: "POST",
      url: "/usertyping.php",
      data: {
        tpy: tpy
      },
      success: function(data) {

      }
    });
  }

});

Check and show user typing:

function getTyping(){
     setInterval(function(){
         var tpy = $('#tpy').val();
           $.ajax({
            type: "POST",
            url: "/getTyping.php",
            data: { tpy: tpy },
            success: function(data) {
               $('#s').html(data);
              }
             });
         },1000);
    }   
getTyping();

HTML

<textarea id="chattextarea"></textarea>
<div id="s"></div>
  • 6
    I would strongly suggest you using websockets for a chat system. It's much more suited to the task over making a multitude of AJAX requests. – Rory McCrossan Nov 28 '15 at 17:49
  • It so happens sometimes that when check for keypress, your javascript is given more priority than entering text. So when user clears text, your js is called before clearing. As a result the length is not zero. – Manikiran Nov 28 '15 at 17:57
  • Why do you have `$el.is(':input') && $el.is(':input')`? Anyway, have you tried to bind to `input` event instead of `keyup keypress paste`? – Arg0n Nov 29 '15 at 08:30

3 Answers3

7

I have some remarks about your code and app :

  • At the first, and as mentioned by @rory-mccrossan, unless you have the infrastructure of facebook, google or microsoft, ..., I think it's really a bad idea to use Ajax instead of Websockets for a real time application like a chat.

  • Now about your code, I don't know what your PHP scripts are doing behind the scene, but I think that you don't need to send two requests to indicate that the user is typing or not, you can limit that to one request to be sent when the user is typing otherwise, he is surely not typing. Of course you can use some sort of a timeout in your getTyping.php script to limit the life time of a "typing" status (for example 5 seconds), so if a request is sent after that timeout, you can know that your user is not typing.

  • And about your current problem, I think that's because the "not typing" status is just fired when the textarea is empty, so of course, after stopping writing and the length of the current text is more that 13, so the "not typing" status will never be fired (sent), that's why you need a timeout as I told you in the 2nd point ...

  • Also, don't forget the cache problem when getting the status using the getTyping.php script which should be not cacheable (or at least for a very limited period) ...

  • Then, I don't see in your posted code any information(s) to identify the current user and the one which is converting with him ... maybe you haven't included that in the question, I don't know !

...

Hope that can help.

akmozo
  • 9,829
  • 3
  • 28
  • 44
  • Thanks for your answer. If you have a time can you check it for me ? Maybe you don't remember me. –  Dec 03 '15 at 18:42
  • @innovation I already see your code, it's globally fine except what I told you in my answer. And you, did you checked my answer (2nd, 3rd and 4th points) ? – akmozo Dec 03 '15 at 18:55
  • I have tested your answer but doesn't worked correctly. –  Dec 06 '15 at 13:16
  • @innovation My answer was just some recommendations, but how did you included them ? – akmozo Dec 06 '15 at 13:19
  • I have tested this answer that answer like your answer [ANSWER](http://stackoverflow.com/questions/4220126/run-javascript-function-when-user-finishes-typing-instead-of-on-key-up) –  Dec 06 '15 at 13:21
  • @innovation And how did you implement that in your case ? And don't forget that you are using a server side script in your case (`getTyping.php`) ... – akmozo Dec 06 '15 at 13:29
  • i have removed `if ($.trim(typingval).length == 0) {` for notyping.php . And moved outside `$('#chattextarea').donetyping(function() {` then i used it like that answer –  Dec 06 '15 at 13:33
  • @innovation As I'v already mentioned in my answer, you can use just one ajax request to send (set) the "typing" status in your server side where you can use a sort of a "timeout" as a lifetime of that status, and when you send a request to `getTyping.php` script, it can verify if the last "typing" status is still alive so the user is "typing" otherwise (you've exceeded the "timeout") he is not typing ... – akmozo Dec 06 '15 at 13:39
0

My suggestion here to have external setInterval which will each 3 seconds save current text in oldValue variable and compare currentText with oldValue if they are equal then user stopped writing then send ajax to notyping.php

Armen
  • 4,064
  • 2
  • 23
  • 40
0

your updated code is given below i have created a getTyping function which will be call at every time 1 sec interval if user get start typing.

in get getTyping setinterval function i called a function check_which_function.

in function check_which_funciton i used your code by applying conditions on textarea value length which is in nested if else statement , so now

if user start typing but if content length is =0 than

$.trim(typingval).length == 0 will execute till length is not equal to 12

if length of content is greather equal to 13 than

$.trim(typingval).length > 13 will execute

by default getTyping2() function is executing in this function getTyping.php ajax call is going

<script>
    (function ($) {
        $.fn.extend({
            donetyping: function (callback, timeout) {
                timeout = timeout || 1000; // 1 second default timeout
                var timeoutReference,
                        doneTyping = function (el) {
                            if (!timeoutReference)
                                return;
                            timeoutReference = null;
                            callback.call(el);
                        };
                return this.each(function (i, el) {
                    var $el = $(el);
                    // Chrome Fix (Use keyup over keypress to detect backspace)
                    // thank you @palerdot
                    $el.is(':input') && $el.is(':input') && $el.on('keyup keypress paste', function (e) {
                        // This catches the backspace button in chrome, but also prevents
                        // the event from triggering too premptively. Without this line,
                        // using tab/shift+tab will make the focused element fire the callback.
                        if (e.type == 'keypress' && e.keyCode != 8)
                            return;

                        // Check if timeout has been set. If it has, "reset" the clock and
                        // start over again.
                        if (timeoutReference)
                            clearTimeout(timeoutReference);
                        timeoutReference = setTimeout(function () {
                            // if we made it here, our timeout has elapsed. Fire the
                            // callback
                            doneTyping(el);
                        }, timeout);
                    }).on('blur', function () {
                        // If we can, fire the event since we're leaving the field
                        doneTyping(el);
                    });
                });
            }
        });
    })(jQuery);


    function getTyping2() {
        var tpy = $('#tpy').val();
        $.ajax({
            type: "POST",
            url: "/getTyping.php",
            data: {tpy: tpy},
            success: function (data) {
                $('#s').html(data);
            }
        });
    }
    function check_which_action() {
        $('#chattextarea').donetyping(function () {
        var typingval = $("#chattextarea").val();
        var tpy = $('#tpy').val();
        if ($.trim(typingval).length == 0) {
            $.ajax({
                type: "POST",
                url: "/notyping.php",
                data: {
                    tpy: tpy
                },
                success: function (data) {

                }
            });
        }

        else if ($.trim(typingval).length > 13) {
            $.ajax({
                type: "POST",
                url: "/usertyping.php",
                data: {
                    tpy: tpy
                },
                success: function (data) {

                }
            });
        }
        else {
            getTyping2() ;
        }

    });
    }
    function getTyping() {
        setInterval(check_which_action, 1000);
    }
    getTyping();

</script>

<textarea id="chattextarea"></textarea>
<div id="s"></div>
Rajveer gangwar
  • 715
  • 4
  • 14