views:

83

answers:

2

Hi guys, I'm building a simple templating system here. Basically I've set up buttons that add preset variables into a textarea.

The thing is that I want to be able to add text in my textarea at the position where my cursor is. Just like when you click on the URL link in the editor window for posts here at stackoverflow the link is added at the position where your cursor is.

How can I do that? And can it be done using prototype JS?

+1  A: 

TinyMCE

or

http://stackoverflow.com/questions/946534/insert-text-into-textarea-with-jquery

http://www.dedestruct.com/2008/03/22/howto-cross-browser-cursor-position-in-textareas/ (gives 404 currently, but the code is here: http://www.dedestruct.com/cursorPosition.html )

Prototype: http://lifescaler.com/2008/12/getting-the-cursor-position-inside-a-text-field-and-smart-ways-to-build-form-validators/

mplungjan
The link to dedestruct.com gives a 404, but according to the root page (http://www.dedestruct.com) there's something wrong there at the moment.
Marcel Korpel
Thanks that should teach me to re-check my links
mplungjan
+1  A: 

It's a bit tricky in IE, which does an exceptionally bad job of this kind of thing. The following will insert text at the end of the current selection in a textarea or text input (or at the caret if the no text is selected) and then position the cursor after the text:

function getSelectionBoundary(el, start) {
    var property = start ? "selectionStart" : "selectionEnd";
    var originalValue, textInputRange, precedingRange, pos, bookmark;

    if (typeof el[property] == "number") {
        return el[property];
    } else if (document.selection && document.selection.createRange) {
        el.focus();

        var range = document.selection.createRange();
        if (range) {
            // Collapse the selected range if the selection is not a caret
            if (document.selection.type == "Text") {
                range.collapse(!!start);
            }

            originalValue = el.value;
            textInputRange = el.createTextRange();
            precedingRange = el.createTextRange();
            pos = 0;

            bookmark = range.getBookmark();
            textInputRange.moveToBookmark(bookmark);

            if (originalValue.indexOf("\r\n") > -1) {
                // Trickier case where input value contains line breaks

                // Insert a character in the text input range and use that
                //as a marker
                textInputRange.text = " ";
                precedingRange.setEndPoint("EndToStart", textInputRange);
                pos = precedingRange.text.length - 1;

                // Executing an undo command deletes the character inserted
                // and prevents adding to the undo stack.
                document.execCommand("undo");
            } else {
                // Easier case where input value contains no line breaks
                precedingRange.setEndPoint("EndToStart", textInputRange);
                pos = precedingRange.text.length;
            }
            return pos;
        }
    }
    return 0;
}

function offsetToRangeCharacterMove(el, offset) {
    return offset - (el.value.slice(0, offset).split("\r\n").length - 1);
}

function setSelection(el, startOffset, endOffset) {
    var range = el.createTextRange();
    var startCharMove = offsetToRangeCharacterMove(el, startOffset);
    range.collapse(true);
    if (startOffset == endOffset) {
        range.move("character", startCharMove);
    } else {
        range.moveEnd("character", offsetToRangeCharacterMove(el, endOffset));
        range.moveStart("character", startCharMove);
    }
    range.select();
}

function insertTextAtCaret(el, text) {
    var pos = getSelectionBoundary(el, false);
    var newPos = pos + text.length;
    var val = el.value;
    el.value = val.slice(0, pos) + text + val.slice(pos);
    setSelection(el, newPos, newPos);
}

var textarea = document.getElementById("your_textarea");
insertTextAtCaret(textarea, "[INSERTED]");
Tim Down