0

I’m trying to show a toolbar under some selected text once the user has selected some text. I browsed through many stackoverflow answers and the best I could come up with is the code below.

I want the toolbar to trigger when a user selects some text not only on mouse click but also on keyboard selection (alt+shift+arrow keys). Pretty much like in this text editor.

The getSelected() function returns selected text just fine on either mouse or keyboard selection. But when I go to insert a dummy element at that range, it always inserts (I added some text, "bar", to see where the dummy is inserted) the dummy at the top of the textarea.

I’m guessing it’s got something to do with .getRangeAt(0). I want to get the position of the selected text (with the insertion of the dummy <span>).

function getSelected(){
  var t = '';
  if(window.getSelection){
    t = window.getSelection();
  }else if(document.getSelection){
    t = document.getSelection();
  }else if(document.selection){
    t = document.selection.createRange().text;
  }
  return t;//.toString()
}

$('#post_content').on('select',function(){
    var range = getSelected().getRangeAt(0);
    range.collapse(false);
    var dummy = document.createElement("span");
    // dummy.innerHTML = "bar";
    range.insertNode(dummy);
    var rect = dummy.getBoundingClientRect();
    var x = rect.left, y = rect.top;
    dummy.parentNode.removeChild(dummy);
    alert(x + "/" + y);
});

Check out the JSFiddle: http://jsfiddle.net/aTq5q/

Any ideas? Thanks!

Alex
  • 1,576
  • 3
  • 17
  • 35
  • Just so you know, in jQuery 1.9 the .live() method has been removed. You should use the .on() method instead to future-proof this: http://jquery.com/upgrade-guide/1.9/#live-removed – Matt Jan 25 '13 at 15:17
  • Thanks, @matt. Changed my code. – Alex Jan 25 '13 at 15:45
  • Is the element with ID "post_content" a ` – Tim Down Jan 25 '13 at 16:58
  • @TimDown Yeah, I tried both ` – Alex Jan 25 '13 at 17:03
  • That's one reason why I asked :) Another is that in some browsers (Firefox, for example), `window.getSelection()` does not apply to textareas. Another problem is that you won't be able use the insert-a-dummy-node trick within the content of a textarea, since a textarea may only contain text. – Tim Down Jan 25 '13 at 17:08
  • 2
    There are similar questions on SO with answers of varying quality. A quick search got me http://stackoverflow.com/questions/9012835/find-caret-position-in-textarea-in-pixels and http://stackoverflow.com/questions/128342/display-div-at-cursor-position-in-textarea and http://stackoverflow.com/questions/3510009/textarea-caret-coordinates-jquery – Tim Down Jan 25 '13 at 17:12
  • @TimDown Thanks. Yeah, I thought that might be the case. I mean it works fine for the `div` and if I change the script to `$('#post_content').click(function(){` but I also want to trigger it with the keyboard selection. I tried a go at the http://hallojs.org source code, but it’s too complex for my level, to get anything out of it :) Will take a look at those links you gave me. – Alex Jan 25 '13 at 17:21
  • 1
    If you use contenteditable instead then you can use the (non-standard) `selectionchange` event on the document. Only works in WebKit and IE, sadly. – Tim Down Jan 25 '13 at 17:32

1 Answers1

1

Looks like you have two problems:

  1. Determining the X/Y coordinates of the caret in a text area
  2. Catching the selection change event.

For the first problem, check out the Component.io textarea-caret-position plugin. Small, simple, cross-browser, and doesn't have any dependencies - demo.

Community
  • 1
  • 1
Dan Dascalescu
  • 143,271
  • 52
  • 317
  • 404