JavaScript get word before cursor
Asked Answered
P

3

19

Okay, I've been looking all over the web to find a solution but I couldn't find one, is there a way to get the word before the caret position in an editable div so a bit like:

This is some| demo texts

This should return the word "some"... I don't know if this is possible, I would be glad for any help, thanks :).

Prefix answered 31/3, 2012 at 21:7 Comment(2)
Do you have any browser requirements? People will also want to know if jquery is ok.Caracal
yes use all the web languages you want, preferablly all browsers but mainly firefox :)Prefix
C
24

With using Caret Position finder method provided here this will do what you want.

function ReturnWord(text, caretPos) {
    var index = text.indexOf(caretPos);
    var preText = text.substring(0, caretPos);
    if (preText.indexOf(" ") > 0) {
        var words = preText.split(" ");
        return words[words.length - 1]; //return last word
    }
    else {
        return preText;
    }
}

function AlertPrevWord() {
    var text = document.getElementById("textArea");
    var caretPos = GetCaretPosition(text)
    var word = ReturnWord(text.value, caretPos);
    if (word != null) {
        alert(word);
    }

}

function GetCaretPosition(ctrl) {
    var CaretPos = 0;   // IE Support
    if (document.selection) {
        ctrl.focus();
        var Sel = document.selection.createRange();
        Sel.moveStart('character', -ctrl.value.length);
        CaretPos = Sel.text.length;
    }
    // Firefox support
    else if (ctrl.selectionStart || ctrl.selectionStart == '0')
        CaretPos = ctrl.selectionStart;
    return (CaretPos);
}
<input id="textArea" type="text" />
<br />
<input id="Submit" type="submit" value="Test" onclick="AlertPrevWord()" />

Here is also a jsfiddle.

Compose answered 31/3, 2012 at 21:37 Comment(9)
Could please make a jsfiddle? Cause I don't know how to implement this into a textarea...Prefix
By | the OP meant caret position, not the actual vertical line character present in source string.Carminacarminative
@Dmitry Pashkevich Updated my answerChoriamb
This is pretty much what I want, but I can't get this to work in a contenteditable div and I'm not sure why??? I changed the .value to .innerHTMLPrefix
@Lenny if you replace ctrl.value and text.value with ctrl.innerText & text.innerText than it works in IE. Don't know the solution for Firefox. div.selectionStart returns undefined.Choriamb
yeh I've realised that the above code for finding the cursor position isn't working in firefox but I can't find a way to get it to work... I think I'm gonna have to find a work around for what I'm trying to do :) but cheers for the hard work ;)Prefix
great great great. you made my day. wish i could upvote this hundred times :DGosney
This doesn't seems to be working well with spaces. However, gives a clear idea about the solution.Brassbound
index is not used in ReturnWord and also when looking for preText.indexOf(" ") we don't into account new line characterSizzler
C
10

Here is a rough method using the Selection and Range objects.

function getWord() {
    var range = window.getSelection().getRangeAt(0);
    if (range.collapsed) {
        text = range.startContainer.textContent.substring(0, range.startOffset+1);
        return text.split(/\b/g).pop();
    }
    return '';
}

You can see it in action here: http://jsfiddle.net/ggfFw/1/. This will not work in IE. If you need IE support look at the Rangy library.

Caracal answered 31/3, 2012 at 22:30 Comment(0)
C
4

I had something like that https://mcmap.net/q/634925/-javascript-get-word-before-cursor yet at some point it wasn't getting a selection in my Chrome browser. Based on my other answer here: https://mcmap.net/q/673132/-how-to-get-range-of-characters-between-and-caret-in-contenteditable - I changed it accordingly to be:

function getLastWordBeforeCaret() {
    const containerEl = document.getElementById('element-id');
    let preceding = '';
    let sel;
    let range;
    if (window.getSelection) {
        sel = window.getSelection();
        if (sel && sel.rangeCount > 0) {
            range = sel.getRangeAt(0).cloneRange();
            range.collapse(true);
            range.setStart(containerEl, 0);
            preceding = range.toString();
        }
    }
    let queryMatch = preceding.match(/([^\s]+)$/i);
    if (queryMatch) {
        return queryMatch[1];
    } else {
        return '';
    }
}
Cannonade answered 22/12, 2017 at 15:14 Comment(1)
Great solution but this will leave out the character just before the cursor. will fix and post edit.Tonl

© 2022 - 2024 — McMap. All rights reserved.