Selecting and inserting text at cursor location in textfield with JS/jQuery

Posted by IceCreamYou on Stack Overflow See other posts from Stack Overflow or by IceCreamYou
Published on 2010-03-22T22:55:13Z Indexed on 2010/03/22 23:01 UTC
Read the original article Hit count: 323

Filed under:
|
|
|

Hello.

I have developed a system in PHP which processes #hashtags like on Twitter. Now I'm trying to build a system that will suggest tags as I type. When a user starts writing a tag, a drop-down list should appear beneath the textarea with other tags that begin with the same string.

Right now, I have it working where if a user types the hash key (#) the list will show up with the most popular #hashtags. When a tag is clicked, it is inserted at the end of the text in the textarea. I need the tag to be inserted at the cursor location instead. Here's my code; it operates on a textarea with class "facebook_status_text" and a div with class "fbssts_floating_suggestions" that contains an unordered list of links. (Also note that the syntax [#my tag] is used to handle tags with spaces.)

maxlength = 140;
var dest = $('.facebook_status_text:first');
var fbssts_box = $('.fbssts_floating_suggestions');
var fbssts_box_orig = fbssts_box.html();
dest.keyup(function(fbss_key) {
  if (fbss_key.which == 51) {
    fbssts_box.html(fbssts_box_orig);
    $('.fbssts_floating_suggestions .fbssts_suggestions a').click(function() {
      var tag = $(this).html();
      //This part is not well-optimized.
      if (tag.match(/W/)) {
        tag = '[#'+ tag +']';
      }
      else {
        tag = '#'+ tag;
      }
      var orig = dest.val();
      orig = orig.substring(0, orig.length - 1);
      var last = orig.substring(orig.length - 1);
      if (last == '[') {
        orig = orig.substring(0, orig.length - 1);
      }
      //End of particularly poorly optimized code.
      dest.val(orig + tag);
      fbssts_box.hide();
      dest.focus();
      return false;
    });
    fbssts_box.show();
    fbssts_box.css('left', dest.offset().left);
    fbssts_box.css('top', dest.offset().top + dest.outerHeight() + 1);
  }
  else if (fbss_key.which != 16) {
    fbssts_box.hide();
  }
});
dest.blur(function() {
  var t = setTimeout(function() { fbssts_box.hide(); }, 250);
});

When the user types, I also need get the 100 characters in the textarea before the cursor, and pass it (presumably via POST) to /fbssts/load/tags. The PHP back-end will process this, figure out what tags to suggest, and print the relevant HTML. Then I need to load that HTML into the .fbssts_floating_suggestions div at the cursor location.

Ideally, I'd like to be able to do this:

var newSuggestions = load('/fbssts/load/tags', {text: dest.getTextBeforeCursor()});
fbssts_box.html(fbssts_box_orig);
$('.fbssts_floating_suggestions .fbssts_suggestions a').click(function() {
  var tag = $(this).html();
  if (tag.match(/W/)) {
    tag = tag +']';
  }
  dest.insertAtCursor(tag);
  fbssts_box.hide();
  dest.focus();
  return false;
});

And here's the regex I'm using to identify tags (and @mentions) in the PHP back-end, FWIW.

%(\A(#|@)(\w|(\p{L}\p{M}?))+\b)|((?<=\s)(#|@)(\w|(\p{L}\p{M}?))+\b)|(\[(#|@).+?\])%u

Right now, my main hold-up is dealing with the cursor location. I've researched for the last two hours, and just ended up more confused. I would prefer a jQuery solution, but beggars can't be choosers.

Thanks!

© Stack Overflow or respective owner

Related posts about JavaScript

Related posts about jQuery