views:

1403

answers:

4

How does one go about attaching a bunch of code to an onkeydown event, but keep entering text into a textarea fast and crisp? Anything more than a couple of IF statements seems to slow it down quite considerably.

EDIT: I should add (can't believe I forgot!) that this doesn't affect desktop browsers. It's mainly an issue with iPhone Safari. Other mobile browsers might be affected as well, but we're focusing on iPhone Safari since it executes JS the best (AFAIK)

A: 

Well, one way to go would be not using onkeydown, but using a timer instead. You can set an interval running a function checking the contents of the TextArea and run your logic there. It seems it would by pass most of the overhead. Anyway, give it a shot, I think it might help.

Here's how you would use it:

// First param is the function to call, second is 
// time interval in miliseconds
var timer = setTimeout(checkTextArea(), 5000);

function checkTextArea() {
    var text = document.getElementById("textarea").value;
    // logic...
    timer = setTimeout(checkTextArea(), 5000); // we loop it back to 
                                               //the function with the timer
}
Dave
+2  A: 

Considering your edit regarding this being focused on iPhone access...

The iPhone really just doesn't have that much power to it. You'll be better off just using onchange or onblur instead of onkeydown.



An alternative to Dave's answer is waiting for the user to pause (e.g. for 5 seconds):

var textarea = document.getElementById('textarea');

function checkTextArea() {
   if (textarea.value /* ... */) {
     /* ... */
   }
}

textarea.keyDownTimeout = null;
textarea.onkeydown = function () {
  if (textarea.keyDownTimeout) clearTimeout(textarea.keyDownTimeout);
  textarea.keyDownTimeout = setTimeout(checkTextArea, 5000);
};

This should set the timer with the first keydown, stopping and recreating the timer for each successive keydown. Finally calling 5 seconds after the user stops typing.

Also, note the lack of parenthesis after checkTextArea. This will give setTimeout the function's reference vs. its return.


You can also set this up in a function to make it easier to use for multiple elements:

function setPauseTimer(element, timeout, callback) {
  var timer = null;
  element.onkeydown = function () {
    if (timer) clearTimeout(timer);
    timer = setTimeout(function(){ callback(element); }, timeout);
  };
}

function checkTextArea(textarea) { /* moved from global to argument */
   if (textarea.value /* ... */) {
     /* ... */
   }
}

setPauseTimer(document.getElementById('textarea'), 5000, checkTextArea);
Jonathan Lonowski
+1  A: 

Maybe you could post "a bunch of code" and we could discuss whether there's some refactoring there (before complexifying it with a timer). It seems like you might be jumping to secondary optimizations first.

le dorfier
Unfortunately I can't, since it's part of company policy. That complicates matters, yes, but I was hoping someone might have found a general solution.
aditya
Given that cell phone app quality is so critically dependent on micrograined keystroke management, I would try to avoid timers etc. - the user's eye is often firmly glued to the interaction between display and keyboard. Can you generalize something and post it?
le dorfier
A: 

I had thought of the timer methods. I believe setTnterval would be better than a setTimeout, but that hardly seems an optimum solution, doesn't it?

aditya