Textarea with Mentions
by sstur
HTML
<div class="x">
<pre></pre>
<textarea></textarea>
</div>
CSS
body {
margin: 0;
padding: 5px;
}
.x {
max-width: 200px;
position: relative;
font-family: "Helvetica", "Arial", "FreeSans", "Verdana", "Tahoma", "Lucida Sans", "Lucida Sans Unicode", "Luxi Sans", sans-serif;
font-size: 13px;
line-height: 18px;
border: 1px solid #ddd;
}
.x pre, .x textarea {
padding: 0;
margin: 0;
border: 5px solid transparent;
font-family: inherit;
font-size: inherit;
line-height: inherit;
min-height: 36px;
white-space: pre-wrap;
word-wrap: break-word;
}
.x pre {
color: #900;
}
.x pre .mention {
color: #009;
}
.x textarea {
color: #000;
-webkit-text-fill-color: transparent;
background: transparent none;
display: block;
position: absolute;
top: 0;
left: 0;
resize: none;
box-sizing: border-box;
width: 100%;
height: 100%;
}
.x textarea:focus {
outline: 0;
}
JavaScript
var x = document.querySelector('.x');
var pre = x.querySelector('pre');
var textArea = x.querySelector('textarea');
textArea.addEventListener('input', function(event) {
var text = event.target.value;
console.log('value', text);
while (pre.firstChild) pre.removeChild(pre.firstChild);
var lastIndex = 0;
var frag = document.createDocumentFragment();
text.replace(/@\w+/g, function(match, index) {
var previous = text.slice(lastIndex, index);
if (previous) {
frag.appendChild(document.createTextNode(previous));
}
var span = document.createElement('span');
span.classList.add('mention');
span.appendChild(document.createTextNode(match));
frag.appendChild(span);
lastIndex = index + match.length;
});
frag.appendChild(document.createTextNode(text.slice(lastIndex)));
pre.appendChild(frag);
});