JSFiddle - React, Tailwind, and code Playground
HTML
<textarea id="text" cols="50" rows="3"></textarea>
CSS
http://jsfiddle.net/HXdnd/4/#run
JavaScript
// Caret positioning code
function getCaretPosition(el) {
if (el.selectionStart) {
return el.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;
}
function setCaretPosition(el, caretPos) {
if (el.createTextRange) {
var range = el.createTextRange();
range.move('character', caretPos);
range.select();
} else if (el.selectionStart) {
el.focus();
el.setSelectionRange(caretPos, caretPos);
} else {
el.focus();
}
}
// Formatting code
var area = document.getElementById('text');
area.addEventListener('keyup', function(e) {
formatTextarea(area, 3, 55);
}, false);
function formatTextarea(textarea, maxLines, maxChars) {
var caret = getCaretPosition(textarea);
var value = textarea.value;
var lines = value.split('\n');
lines.forEach(function(line, li) {
var words = line.split(/\s+/);
line = words[0] || '';
for (var i = 1, length = words.length; i < length; i++) {
if ((line.length + 2 + words[i].length) <= maxChars) {
if (words[i] !== ' ')
line += ' ' + words[i];
} else {
if (lines.length <= li + 1) {
lines.push(words[i]);
} else {
lines[li + 1] = words[i] + ' ' + lines[li + 1];
}
}
}
lines[li] = line;
});
textarea.value = lines.join('\n');
setCaretPosition(textarea, caret);
// evt: textarea.value = lines.slice(0, maxLines).join('\n');
}