Andy Metcalfe
Andy Metcalfe

Reputation: 73

HTML text area tab support

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

Upvotes: 7

Views: 10260

Answers (3)

Wise Man
Wise Man

Reputation: 189

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);

Upvotes: 1

felixc
felixc

Reputation: 31

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>

Upvotes: 2

Josh
Josh

Reputation: 12566

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.

Upvotes: 5

Related Questions