7

I am making a web based code editor and am using a textarea for text editing. I want to add tab support to the textarea so that pressing tab doesn't de-focus the element. I have the textarea defined like this:

<textarea id="codeEdit_txt" rows="50" cols="80" onkeydown="return codeEdit_keyDown(event);">

and the function codeEdit_keyDown defined as:

function codeEdit_keyDown(e) {
    if (e.keyCode == 9) {
        return false;
    }
}

This prevents the tab key press from de-focusing the textarea, though it doesn't leave the tab character behind. While I was trying to get this to work initially, I noticed that if I defined the function as below, it would put a tab character at the cursor position.

function codeEdit_keyDown(e) {
    if (e.keyCode == 9) {
        alert("");
        return false;
    }
}

My two questions are:

  1. Why does adding the alert cause a tab to be added?
  2. Is there a way to add the tab at the cursor without having to find the cursor position, split the text in the texarea and manually add a tab character (and without having to have an alert every time the user pressed tab)?

Thanks

EDIT: This only seems to work in Chrome, not in IE, Safari or Firefox

Andy Metcalfe
  • 73
  • 1
  • 4

3 Answers3

5

See this question:

https://stackoverflow.com/a/13130/420001

You're looking for .preventDefault();

EDIT: A fiddle.

EDIT 2: A better fiddle, thanks to rainecc.

Community
  • 1
  • 1
Josh
  • 12,448
  • 10
  • 74
  • 118
  • I found that question whilst I was looking for answers and preventDefault worked for not losing focus but it didn't add the tab character. Is there a way with to add the tab character as well? – Andy Metcalfe May 04 '12 at 21:27
  • 1
    I modified Josh's fiddle to add a tab character - works perfectly for me. Kudos Josh. http://jsfiddle.net/rainecc/n6aRj/1/ – rainecc May 04 '12 at 21:33
  • Sorry, I see, the code is manually added 4 spaces for the tab. I want to be able to add the tab where the cursor is, so I would want to add it in the middle of existing text in the texbox/textarea. Do I just need to find the cursor location, split it and insert the tab inbetween the two splits? – Andy Metcalfe May 04 '12 at 21:35
  • The latter fiddle is adding a literal tab character '\t'. The textbox may be rendering it with less, as it's jumping to the next tab-stop, but it's there. – Josh May 04 '12 at 21:36
  • 1
    this.value += "\t"; is the solution if you want the real tab :) – Andrius Naruševičius May 04 '12 at 21:37
2

The other answer is nice, but it ends tabs at the end. I looked up how to add the tab at the cursor location, and added that to the solution.

You can find the working code here: http://jsfiddle.net/felixc/o2ptfd5z/9/

Code inline as a safeguard:

  function insertAtCursor(myField, myValue) {
   //IE support
   if (document.selection) {
    myField.focus();
    sel = document.selection.createRange();
    sel.text = myValue;
   }
   //MOZILLA and others
   else if (myField.selectionStart || myField.selectionStart == '0') {
    var startPos = myField.selectionStart;
    var endPos = myField.selectionEnd;
    myField.value = myField.value.substring(0, startPos)
     + myValue
     + myField.value.substring(endPos, myField.value.length);
    myField.selectionStart = startPos + myValue.length;
    myField.selectionEnd = startPos + myValue.length;
   } else {
    myField.value += myValue;
   }
  } 

  function addTabSupport(elementID, tabString) {
   // Get textarea element
   var myInput = document.getElementById(elementID);

   // At keydown: Add tab character at cursor location
   function keyHandler(e) {
    var TABKEY = 9;
    if(e.keyCode == TABKEY) {
     insertAtCursor(myInput, tabString);
     if(e.preventDefault) {
      e.preventDefault();
     }
     return false;
    }
   }   

   // Add keydown listener
   if(myInput.addEventListener ) {
    myInput.addEventListener('keydown',keyHandler,false);
   } else if(myInput.attachEvent ) {
    myInput.attachEvent('onkeydown',this.keyHandler); /* damn IE hack */
   }
  }
    
    // easily add tab support to any textarea you like
    addTabSupport("input", "\t");
<h1>Click in the text and hit tab</h1>

<textarea id="input" rows=10 cols=50>function custom(data){
 return data;
}</textarea>
felixc
  • 31
  • 2
0

Here's what I used for my own editor (using some other answers) :

function insertAtCursor (el, text) {
  text = text || '';
  if (document.selection) {
    // IE
    el.focus();
    var sel = document.selection.createRange();
    sel.text = text;
  } else if (el.selectionStart || el.selectionStart === 0) {
    // Others
    var startPos = el.selectionStart;
    var endPos = el.selectionEnd;
    el.value = el.value.substring(0, startPos) +
      text +
      el.value.substring(endPos, el.value.length);
    el.selectionStart = startPos + text.length;
    el.selectionEnd = startPos + text.length;
  } else {
    el.value += text;
  }
};
document.querySelector("#editor").addEventListener("keydown", function(e) {
    var TABKEY = 9;
    if(e.keyCode == TABKEY) {
        insertAtCursor(this, "\t");
    if(e.preventDefault) {
        e.preventDefault();
    }
    return false;
    }
}, false);
Wise Man
  • 169
  • 2
  • 12