Search code examples
javascriptjquerydelay

Keyout and keyup


I've found a need JS function that perfectly suits all my needs and wants. However, there is one minor downside to it.

The function waits for x milliseconds (iKeyDelay) before executes a function, all this is bind to a key event (keyup or keydown). This all works.

However, when the user exits the input so the input loses the focus, the function is executed again. This extra execution should be prevented to occur, because it is unnecessary.

My JS skills are not that good, but maybe one of you can help me?

$.fn.DelayedKey = function(fn, iKeyDelay, sKeyEvent) {
   var iTimeoutId, 
   oEventData;

   if (!$.isFunction(fn)) {
      oEventData = arguments[0];
      fn = arguments[1];
      iKeyDelay = arguments[2];
      sKeyEvent = arguments[3];
   }

   if (!iKeyDelay || 0 > iKeyDelay) {
      iKeyDelay = 500;
   }

   if (!sKeyEvent || !this[sKeyEvent]) {
      sKeyEvent = 'keydown';
   }

   function fnExecCallback() {
      clearTimeout(iTimeoutId);
      fn.apply(this, arguments);
   }

   function fnDelayCallback() {
      var that = this,
      args = arguments;
      clearTimeout(iTimeoutId);
      iTimeoutId = setTimeout(function() {
         fnExecCallback.apply(that, args);
      }, iKeyDelay);
   }

   if (oEventData) {
      this.change(oEventData, fnExecCallback);
      this[sKeyEvent](oEventData, fnDelayCallback);
   }
   else {
      this.change(fnExecCallback);
      this[sKeyEvent](fnDelayCallback);
   }

  return this;
};

Solution

  • All fixed! I changed the following function, and it seemed to correct your issue.

    function fnExecCallback(e) {
        if ( e.type != sKeyEvent )
            return;
        clearTimeout(iTimeoutId);
        fn.apply(this, arguments);
    }
    

    Here is the updated jsfiddle.