function handleTyping(elm, ev, reply) {
  elm = $(elm);
  if (ev.keyCode == Event.KEY_RETURN) {
    elm.value = $F(elm).substr(0,$F(elm).length);
    return;
  }
  if ($F(elm).length > 140) {
    elm.value = $F(elm).substr(0,140);
    return;
  }
  var chars_left = elm.previous();
  chars_left.innerHTML = 140 - $F(elm).length;

  if (reply) {
    var reply_div = elm.up().select('div.in_reply_to_select')[0];

    if (!/@(\w+)[^\w]/.exec($F(elm))) {
      reply_div.hide();
      elm.up().select('input.in_reply_to_login')[0].value = '';
    }

    var match = /@(\w+)[^\w]+$/.exec($F(elm));
    if (match) {
      if (elm.up().select('input.in_reply_to_login')[0].value == '') {
        reply_div.hide();
        elm.up().select('input.in_reply_to_login')[0].value = match[1];
        new Ajax.Request('/messages/get_targets', {
            postBody: Form.serialize(elm.up().up()),
            onSuccess: function(t) { showTargets(elm, t); }});
      }
    }
  }
}

function showTargets(elm, t) {
  elm = $(elm);
  var reply_div = elm.up().select('div.in_reply_to_select')[0];
  reply_div.innerHTML = "Replying to:<br/>" + t.responseText;
  new Effect.SlideDown(reply_div, {queue: 'end'});
}
