I need to change the color of words starting with a special character, @word
inside an input tag.
Example: Hello @John how are you?
If I type that in an input tag, the part @John
should change color in the input form already.
Example:
Hello @John how are you?
It works after it's posted, but that's obviously another code. I want it to highlight words by changing color already in the input tag.
CodePudding user response:
One 5y old idea would be to:
- Make INPUT with CSS
color: transparent
text, but with visible caret:caret-color: black
- Overlay the INPUT over an underlying PRE element
- On "input" event do some
String.prototype.replace()
with a regular expression that matches @mentions on the input value and replace@John
with i.e:<span >@John</span>
- Write the result as HTML to the underlying PRE element.
const colorInput = (elInput) => {
const elPre = elInput.previousElementSibling;
elPre.innerHTML = elInput.value.replace(/(?<=^| )@\p{L} /gu, "<span class='mention'>$&</span>");
};
document.querySelectorAll(".colorInput").forEach(el => {
const elInput = el.querySelector("input");
elInput.addEventListener("input", () => colorInput(elInput));
colorInput(elInput);
});
* {
margin: 0;
box-sizing: border-box;
}
.colorInput {
font: 16px/1 sans-serif;
display: inline-block;
border: 1px solid #888;
position: relative;
}
/* The overlay input with transparent text but visible caret */
.colorInput>input {
border: 0;
width: 20rem;
font: inherit;
padding: 0.5rem;
position: relative;
background: transparent;
/* Make text invisible */
color: transparent;
/* But keep caret visible */
caret-color: black;
}
/* The underlaying DIV with colors */
.colorInput>pre {
font: inherit;
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
user-select: none;
padding: 0.5rem;
}
.mention {
color: fuchsia;
}
<div >
<pre></pre>
<input type="text" value="Hi @Daniel, how are you?">
</div>
Regarding the regex for matching mentions:
/(?<=^| )@\p{L} /gu
here's a Regex101.com example with description, and a related answer.