4

I have a monospaced textarea (not unlike the stackexchange editor). When my user clicks, I need a character to automagically appear on the previous line using jQuery. I know I need to use .click() to bind a function to that event, but the logic of the function eludes me.

Desired Behavior...user will click at position of the asterisk *

Here is some text in my editor.
When I double click at a position*
I want to insert a new line above, with a new character at the same position

The above text should become the following after the function gets run

Here is some text in my editor.
                                 *
When I double click at a position*
I want to insert a new blank line above, at the same position

What I have tried:

I have found the caret jQuery plugin, which has a function called caret() that I can get to find the position of the the asterisk when I click (the position is 74).

<script src='jquery.caret.js'></script>

    $('textarea').click(function(e) {
      if (e.altKey){
        alert($("textarea").caret());
      }
    });

But I really need to know the position of the character within the line, not the entire textarea. So far this eludes me.

Andrew Barr
  • 3,589
  • 4
  • 18
  • 28
  • You can I think easily split the whole field value in various lines with the `split()` function, then based of the global position you got and the length of each line, you can identify which line you're up to and add whatever you wish before... – Laurent S. Jul 08 '15 at 16:03
  • question: If the asterik was in the middle of the sentence, would you want an asterisk at the middle of the line above? – MiiinimalLogic Jul 08 '15 at 16:04
  • yes. these are sort of annotations, so it could be anywere – Andrew Barr Jul 08 '15 at 16:05
  • 1
    Try searching backwards from the position of your character until you find a newline, and add another newline adjacent to its position. Something like `str.substring(0, knownIndex).lastIndexOf("\r");` might yield the index that you need to insert the newline at? With that, it should be easy to add the asterisk at the right place. – Ezra Jul 08 '15 at 16:08
  • Thanks that got me going. I am successfully inserting the new line. I still haven't figured out how to get my index position within the line (because asterisk may not fall at end of the line). I am working on suggestion of @Bartdude – Andrew Barr Jul 08 '15 at 16:27

2 Answers2

3

Here's something without using caret.js

$('textarea').dblclick(function(e){
    var text = this.value;
    var newLinePos = text.lastIndexOf('\n', this.selectionStart);
    var lineLength = this.selectionStart - newLinePos;
    var newString = '\n';
    for(var i=1; i < lineLength; ++i){
        newString += ' ';
    }
    newString += text.substr(this.selectionStart,this.selectionEnd-this.selectionStart);
    this.value = [text.slice(0, newLinePos), newString, text.slice(newLinePos)].join('');
});

Here's a fiddle. Credit to this post for 'inserting string into a string at specified position'.

Just realised that doing that on the top line is a bit broken, I'll have a look when I get home!

Update

Fixed the top-line problem.

if(newLinePos == -1){
    this.value = newString + '\n' + this.value;
} else {
    this.value = [text.slice(0, newLinePos), '\n'+newString, text.slice(newLinePos)].join('');
}

http://jsfiddle.net/daveSalomon/3dr8k539/4/

Community
  • 1
  • 1
Dave Salomon
  • 3,287
  • 1
  • 17
  • 29
0

Assuming you know the position of the caret in the whole text area here's something you might do with it.

function getCaretPosition(text, totalOffset) {
  var line = 0, pos = 0;
  for (var i = 0; i < Math.min(totalOffset, text.length); i++) {
    if (text[i] === '\n') {
      line++;
      pos = 0;
    } else {
      pos++;
    }
  }

  return { row: line, col: pos };
}

var caretPosition = getCaretPosititon($("textarea").val(), $("textarea").caret());
Skydda
  • 166
  • 3