Henry Boldizsar
Henry Boldizsar

Reputation: 489

How to move cursor to next/previous word in textarea?

How would you move the cursor to the next or previous word in a textarea using Javascript? I'm trying to replicate the Emacs commands "forward one word" and "back one word" in an HTML textarea.

I can get the current caret/cursor position using rangyinputs, but I'm not yet sure how to efficiently move to the next word without using various splits that could be slow on very long pieces of text.

Upvotes: 3

Views: 2148

Answers (2)

Henry Boldizsar
Henry Boldizsar

Reputation: 489

I used setCaretToTextEnd() from here and .selectRange() from here. The following functions use Emacs style caret positions, and is more efficient than looping through words.

function nextWord(input) {
  let currentCaretPosition = input.selectionStart;

  // -1 Because Emacs goes to end of next word.
  let nextWordPosition = input.value.indexOf(' ', currentCaretPosition) - 1;
  if (nextWordPosition < 0) {
    input.setCaretToTextEnd();
  } else {
    input.selectRange(nextWordPosition);
  }
}

function previousWord(input) {
  let currentCaretPosition = input.selectionStart;

  // +1 Because Emacs goes to start of previous word.
  let previousWordPosition = input.value.lastIndexOf(' ', currentCaretPosition) + 1;
  if (previousWordPosition < 0) {
    input.selectRange(0);
  } else {
    input.selectRange(previousWordPosition);
  }
}

Upvotes: 2

Michał Perłakowski
Michał Perłakowski

Reputation: 92531

See this fiddle. I used functions from jQuery Set Cursor Position in Text Area to change position of cursor.

function nextWord(input) {
    var words = input.value.split(" "),
        index = 0;
    for (var i in words) {
        var word = words[i];
        if (index+word.length >= input.selectionStart) {
            setCaretToPos(input, index+word.length+1);
            break;
        }
        index += word.length+1;
    }
}
function previousWord(input) {
    var words = input.value.split(" ").reverse(),
        index = input.value.length;
    for (var i in words) {
        var word = words[i];
        if (index+1 <= input.selectionStart) {
        setCaretToPos(input, index-word.length);
            break;
        }
        index -= word.length+1;
    }
}

Upvotes: 0

Related Questions