158

I'm wondering how I can insert text into a text area using jquery, upon the click of an anchor tag.

I don't want to replace text already in textarea, I want to append new text to textarea.

gdoron
  • 147,333
  • 58
  • 291
  • 367
  • 1
    If this is the solution - Would prefer to build it in myself, however. Its for a personal blog I'm doing fora friend, so anything that will fit this. –  Jun 03 '09 at 19:05
  • so you want to select a text, and whichever one selected, use jquery to populate a textarea, if so where is this text coming from, inputted manually or from an special tag? – TStamper Jun 03 '09 at 19:08
  • TStamper, I want to be able to click a button, and depending on what is clicked insert text into a textarea. –  Jun 03 '09 at 19:09
  • so if you click on a button labeled "bold" you want bold in the textarea? – TStamper Jun 03 '09 at 19:12
  • Not bold text, but bold tags (probably custom as opposed to html) –  Jun 03 '09 at 19:14
  • ? Im not understanding, so if you click on a bold button, you would want the bold tag in your textarea?"" – TStamper Jun 03 '09 at 19:16
  • Yes, or a variation of that. If you do not understand, don't worry, others are here to help me too. –  Jun 03 '09 at 19:20
  • @Oliver- my reasoning for questioning was to make sure I understand as well as others, nothing to take offense to – TStamper Jun 03 '09 at 19:26
  • Sorry, didn't mean to come over as aggresive, your input is helpful anyhow. –  Jun 03 '09 at 19:30

17 Answers17

187

I like the jQuery function extension. However, the this refers to the jQuery object not the DOM object. So I've modified it a little to make it even better (can update in multiple textboxes / textareas at once).

jQuery.fn.extend({
insertAtCaret: function(myValue){
  return this.each(function(i) {
    if (document.selection) {
      //For browsers like Internet Explorer
      this.focus();
      var sel = document.selection.createRange();
      sel.text = myValue;
      this.focus();
    }
    else if (this.selectionStart || this.selectionStart == '0') {
      //For browsers like Firefox and Webkit based
      var startPos = this.selectionStart;
      var endPos = this.selectionEnd;
      var scrollTop = this.scrollTop;
      this.value = this.value.substring(0, startPos)+myValue+this.value.substring(endPos,this.value.length);
      this.focus();
      this.selectionStart = startPos + myValue.length;
      this.selectionEnd = startPos + myValue.length;
      this.scrollTop = scrollTop;
    } else {
      this.value += myValue;
      this.focus();
    }
  });
}
});

This works really well. You can insert into multiple places at once, like:

$('#element1, #element2, #element3, .class-of-elements').insertAtCaret('text');
John Fouhy
  • 41,203
  • 19
  • 62
  • 77
Aniebiet Udoh
  • 1,871
  • 2
  • 11
  • 2
  • 3
    There is a trailing }) in the anwer so at first I tought that solution wasn't working, but after fixing it, it works great in IE7 and FF3.5. You can insert a piece of text at caret for a TEXTAREA element. Thank you! – Philippe Jun 08 '10 at 13:17
  • 1
    this also works in Chrome. thanks for saving me some time :) and thank you to @Thinker for the original code. – Veli Gebrev Jun 09 '10 at 10:38
  • Came here from a google search.. .I know your answer is a year old, but thanks so much for this. Works like a charm – Mike Turley Jul 05 '11 at 13:34
  • 6
    Is `sel` meant to be global? – qwertymk Apr 18 '12 at 00:33
  • Perfect, this works. I would have submitted my own version of the code modification from @Thinker, when I stumbled into this. Same concept: The 'this' of jQuery is a jQuery object. The intended 'this' of the DOM code is a DOM element. The 'each' did the trick. – Ardee Aram Jan 31 '13 at 09:45
  • This seems to just always post my text at the end of the selection. Its probably because selectionStart is never written before this method is called. – Trip Jul 15 '13 at 19:26
  • 1
    For anyone that wants the coffeescript version: https://gist.github.com/zachaysan/7100458 – zachaysan Oct 22 '13 at 13:09
  • This won't trigger onchange or oninput events, which it should here. Try add `$(this).trigger("input");` – kbridge4096 May 16 '17 at 16:45
  • @ArdeeAram a little editing of [Thinker's answer](https://stackoverflow.com/a/946556/6225838) was enough to make it working, avoiding this duplicate. Aniebiet reputation at the moment consists solely of the upvotes in this answer... – CPHPython Jul 11 '18 at 09:14
131

From what you have in Jason's comments try:

$('a').click(function() //this will apply to all anchor tags
{ 
   $('#area').val('foobar'); //this puts the textarea for the id labeled 'area'
})

Edit- To append to text look at below

$('a').click(function() //this will apply to all anchor tags
{ 
   $('#area').val($('#area').val()+'foobar'); 
})
TStamper
  • 30,098
  • 10
  • 66
  • 73
51

I use this function in my code:

$.fn.extend({
  insertAtCaret: function(myValue) {
    this.each(function() {
      if (document.selection) {
        this.focus();
        var sel = document.selection.createRange();
        sel.text = myValue;
        this.focus();
      } else if (this.selectionStart || this.selectionStart == '0') {
        var startPos = this.selectionStart;
        var endPos = this.selectionEnd;
        var scrollTop = this.scrollTop;
        this.value = this.value.substring(0, startPos) +
          myValue + this.value.substring(endPos,this.value.length);
        this.focus();
        this.selectionStart = startPos + myValue.length;
        this.selectionEnd = startPos + myValue.length;
        this.scrollTop = scrollTop;
      } else {
        this.value += myValue;
        this.focus();
      }
    });
    return this;
  }
});
input{width:100px}
label{display:block;margin:10px 0}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<label>Copy text from: <input id="in2copy" type="text" value="x"></label>
<label>Insert text in: <input id="in2ins" type="text" value="1,2,3" autofocus></label>
<button onclick="$('#in2ins').insertAtCaret($('#in2copy').val())">Insert</button>

It's not 100% mine, I googled it somewhere and then tuned for mine app.

Usage: $('#element').insertAtCaret('text');

CPHPython
  • 12,379
  • 5
  • 59
  • 71
Thinker
  • 14,234
  • 9
  • 40
  • 55
  • Does this highlight inserted text also? –  Jun 03 '09 at 19:11
  • 2
    But that solution won't work, when user move his cursor somewhere back :) Anyway, nevermind. – Thinker Jun 03 '09 at 22:14
  • 3
    you use 'this' as both a wrapped set and an element. hmmm .. just tried and it doesn't work w/o edits – Scott Evernden Oct 09 '09 at 22:09
  • hi, I tried this code and it simply doesn't work ... @Scott: how did you get tinker with this to get it working? Thanks :) – sillyMunky Dec 02 '09 at 09:56
  • 5
    I couldn't get this code to work either. I'm using jQuery. I tried both a textarea and a text field. I believe this.value for instance should be this.val(), etc.. – Nick B Feb 25 '10 at 19:45
  • 1
    Yeah on IE it kept inserting at the top of the DOM and on Fox it did nothing. Using latest JQuery... – Caveatrob Jul 16 '10 at 20:17
  • Hello, tried this, and doesn't work at all. Using Google Chrome. – Ardee Aram Jan 31 '13 at 09:18
  • @Nick there was a `.each` loop missing, I edited the answer to contain a running snippet that accesses the jQuery elements properly. – CPHPython Jul 11 '18 at 08:38
20

I know this is an old question but for people searching for this solution it's worth noting that you should not use append() to add content to a textarea. the append() method targets innerHTML not the value of the textarea. The content may appear in the textarea but it will not be added to the element's form value.

As noted above using:

$('#textarea').val($('#textarea').val()+'new content'); 

will work fine.

Marcus
  • 357
  • 1
  • 4
  • 14
13

this one allow you "inject" a piece of text to textbox, inject means: appends the text where cursor is.

function inyectarTexto(elemento,valor){
 var elemento_dom=document.getElementsByName(elemento)[0];
 if(document.selection){
  elemento_dom.focus();
  sel=document.selection.createRange();
  sel.text=valor;
  return;
 }if(elemento_dom.selectionStart||elemento_dom.selectionStart=="0"){
  var t_start=elemento_dom.selectionStart;
  var t_end=elemento_dom.selectionEnd;
  var val_start=elemento_dom.value.substring(0,t_start);
  var val_end=elemento_dom.value.substring(t_end,elemento_dom.value.length);
  elemento_dom.value=val_start+valor+val_end;
 }else{
  elemento_dom.value+=valor;
 }
}

And you can use it like this:

<a href="javascript:void(0);" onclick="inyectarTexto('nametField','hello world');" >Say hello world to text</a>

Funny and have more sence when we have "Insert Tag into Text" functionality.

works in all browsers.

panchicore
  • 11,451
  • 12
  • 74
  • 100
  • 6
    @temoto: Down-vote for non-english variable names? It's still completely readable as-is. The down-vote button is supposed to be used if an answer is not helpful which isn't the case here. BTW it also costs you a few reputation when you down-vote. – Josh M. May 05 '11 at 22:21
  • Took a while to understand spanish code. and there is a bug in this code. It was inserting always towards the start of the text box rather than towards the end. For ex: If the text is: Dear user and onclicking it was inserting before dear rather than after the text user. – Dev Sep 15 '16 at 14:56
  • @JoshM. the thing is, this is a duplicate of the [older and more complete answer written by Thinker](https://stackoverflow.com/a/946556/6225838) in here... He took out some of the `.focus()` invocations and the updates to the `selectionStart` and `selectionEnd` after the modification. Spanish variables may have been used to justify another answer... – CPHPython Jul 11 '18 at 08:57
12

Hej this is a modified version which works OK in FF @least for me and inserts at the carets position

  $.fn.extend({
  insertAtCaret: function(myValue){
  var obj;
  if( typeof this[0].name !='undefined' ) obj = this[0];
  else obj = this;

  if ($.browser.msie) {
    obj.focus();
    sel = document.selection.createRange();
    sel.text = myValue;
    obj.focus();
    }
  else if ($.browser.mozilla || $.browser.webkit) {
    var startPos = obj.selectionStart;
    var endPos = obj.selectionEnd;
    var scrollTop = obj.scrollTop;
    obj.value = obj.value.substring(0, startPos)+myValue+obj.value.substring(endPos,obj.value.length);
    obj.focus();
    obj.selectionStart = startPos + myValue.length;
    obj.selectionEnd = startPos + myValue.length;
    obj.scrollTop = scrollTop;
  } else {
    obj.value += myValue;
    obj.focus();
   }
 }
})
John Farrell
  • 24,673
  • 10
  • 77
  • 110
Babak Bandpay
  • 177
  • 6
  • 15
10

have you tried:

$("#yourAnchor").click(function () {
    $("#yourTextarea").val("your text");
});

not sure about autohighlighting, though.

EDIT:

To append:

$("#yourAnchor").click(function () {
    $("#yourTextarea").append("your text to append");
});
Jason
  • 51,583
  • 38
  • 133
  • 185
  • Thanks, i'll give it a go, I am new to jQuery so am not aware of all of the easy to use functions. –  Jun 03 '09 at 19:10
  • i'm relatively new too. it's fun and super easy once you get the hang of it. Check this out for more reference: http://docs.jquery.com/Main_Page – Jason Jun 03 '09 at 19:12
  • 6
    As noted by Marcus below, `append()` doesn't work on the value of a `textarea`. The `append()` method targets the innerHTML, not the value of the textarea. – Turadg Jun 23 '11 at 18:29
6

What you ask for should be reasonably straightforward in jQuery-

$(function() {
    $('#myAnchorId').click(function() { 
        var areaValue = $('#area').val();
        $('#area').val(areaValue + 'Whatever you want to enter');
    });
});

The best way that I can think of highlighting inserted text is by wrapping it in a span with a CSS class with background-color set to the color of your choice. On the next insert, you could remove the class from any existing spans (or strip the spans out).

However, There are plenty of free WYSIWYG HTML/Rich Text editors available on the market, I'm sure one will fit your needs

Russ Cam
  • 124,184
  • 33
  • 204
  • 266
5

Here is a quick solution that works in jQuery 1.9+:

a) Get caret position:

function getCaret(el) {
        if (el.prop("selectionStart")) {
            return el.prop("selectionStart");
        } else if (document.selection) {
            el.focus();

            var r = document.selection.createRange();
            if (r == null) {
                return 0;
            }

            var re = el.createTextRange(),
                    rc = re.duplicate();
            re.moveToBookmark(r.getBookmark());
            rc.setEndPoint('EndToStart', re);

            return rc.text.length;
        }
        return 0;
    };

b) Append text at caret position:

function appendAtCaret($target, caret, $value) {
        var value = $target.val();
        if (caret != value.length) {
            var startPos = $target.prop("selectionStart");
            var scrollTop = $target.scrollTop;
            $target.val(value.substring(0, caret) + ' ' + $value + ' ' + value.substring(caret, value.length));
            $target.prop("selectionStart", startPos + $value.length);
            $target.prop("selectionEnd", startPos + $value.length);
            $target.scrollTop = scrollTop;
        } else if (caret == 0)
        {
            $target.val($value + ' ' + value);
        } else {
            $target.val(value + ' ' + $value);
        }
    };

c) Example

$('textarea').each(function() {
  var $this = $(this);
  $this.click(function() {
    //get caret position
    var caret = getCaret($this);

    //append some text
    appendAtCaret($this, caret, 'Some text');
  });
});
Avram Cosmin
  • 383
  • 7
  • 8
3

It works good for me in Chrome 20.0.11

var startPos = this[0].selectionStart;
var endPos = this[0].selectionEnd;
var scrollTop = this.scrollTop;
this[0].value = this[0].value.substring(0, startPos) + myVal + this[0].value.substring(endPos, this[0].value.length);
this.focus();
this.selectionStart = startPos + myVal.length;
this.selectionEnd = startPos + myVal.length;
this.scrollTop = scrollTop;
Long
  • 31
  • 2
1

If you want to append content to the textarea without replacing them, You can try the below

$('textarea').append('Whatever need to be added');

According to your scenario it would be

$('a').click(function() 
{ 
  $('textarea').append($('#area').val()); 
})
Techie
  • 44,706
  • 42
  • 157
  • 243
0

Another solution is described also here in case some of the other scripts does not work in your case.

Community
  • 1
  • 1
d.popov
  • 4,175
  • 1
  • 36
  • 47
0

Simple solution would be : (Assumption: You want whatever you type inside the textbox to get appended to what is already there in the textarea)

In the onClick event of the < a > tag,write a user-defined function, which does this:

function textType(){

  var **str1**=$("#textId1").val();

  var **str2**=$("#textId2").val();

  $("#textId1").val(str1+str2);

}

(where the ids,textId1- for o/p textArea textId2-for i/p textbox')

Aurasphere
  • 3,841
  • 12
  • 44
  • 71
SidTechs1
  • 67
  • 4
  • 12
0

This is similar to the answer given by @panchicore with a minor bug fixed.

function insertText(element, value) 
{
   var element_dom = document.getElementsByName(element)[0];
   if (document.selection) 
   {
      element_dom.focus();
      sel = document.selection.createRange();
      sel.text = value;
      return;
    } 
   if (element_dom.selectionStart || element_dom.selectionStart == "0") 
   {
     var t_start = element_dom.selectionStart;
     var t_end = element_dom.selectionEnd;
     var val_start = element_dom.value.substring(value, t_start);
     var val_end = element_dom.value.substring(t_end, element_dom.value.length);
     element_dom.value = val_start + value + val_end;
   } 
   else
   {
      element_dom.value += value;
   }
}
Dev
  • 1,451
  • 20
  • 30
0
$.fn.extend({
    insertAtCaret: function(myValue) {
        var elemSelected = window.getSelection();
        if(elemSelected) {
            var startPos = elemSelected.getRangeAt(0).startOffset;
            var endPos = elemSelected.getRangeAt(0).endOffset;
            this.val(this.val().substring(0, startPos)+myValue+this.val().substring(endPos,this.val().length));
        } else {
            this.val(this.val()+ myValue) ;
        }
    }
});
George SEDRA
  • 796
  • 8
  • 11
0

I think this would be better

$(function() {
$('#myAnchorId').click(function() { 
    var areaValue = $('#area').val();
    $('#area').val(areaValue + 'Whatever you want to enter');
});
});
-2

I used that and it work fine :)

$("#textarea").html("Put here your content");

Remi

Remi
  • 13
  • 1
  • 2
    No it doesn't. If you change the html of the textarea, you see the content there, but when you save the FORM it doesn't work, because the form needs the textarea value, not the inner HTML. – tothemario Apr 17 '12 at 19:17