I have a textarea
and when I type something, for some words the color should change.
For example, if the typed text is next one: He went to the market to buy an apple
- The "market" word should become green
- The "apple" word should become red
This is my current code:
var str = 'market';
var value = str.includes('market');
if (value == str) {
document.getElementById("text").style.color = "green";
} else {
document.getElementById("text").style.color = "red";
}
<textarea rows="9" cols="100" id="text" onClick="changeText();"></textarea>
Unfortunately, you can't add markup inside a textarea
, but here is an idea you could take as a starting approach, it comes from this link. The approach will be based on this:
The basic idea is to carefully position a <div>
behind the <textarea>
. Then JavaScript
will be used to copy any text entered into the <textarea>
to the <div>
. A bit more JavaScript
will make that both elements scroll as one. With everything perfectly aligned, we can add markup inside the <div>
to give colors to some particular words, and we going to set text color to transparent on the <textarea>
, completing the illusion.
Base Implementation:
// Initialization.
const colorMap = {"apple": "red", "market": "green", "banana": "orange"};
let textArea = document.getElementById("myTextArea");
let customArea = document.querySelector(".custom-area");
let backdrop = document.querySelector(".backdrop");
// Event listeners.
textArea.addEventListener("input", function()
{
customArea.innerHTML = applyColors(textArea.value);
});
textArea.addEventListener("scroll", function()
{
backdrop.scrollTop = textArea.scrollTop;
});
function applyColors(text)
{
let re = new RegExp(Object.keys(colorMap).join("|"), "gi");
return text.replace(re, function(m)
{
let c = colorMap[m.toLowerCase()];
return `<spam style="color:${c}">${m}</spam>`;
});
}
.backdrop, #myTextArea {
font: 12px 'Open Sans', sans-serif;
letter-spacing: 1px;
width: 300px;
height: 100px;
}
#myTextArea {
margin: 0;
position: absolute;
border-radius: 0;
background-color: transparent;
color: transparent;
caret-color: #555555;
z-index: 2;
resize: none;
}
.backdrop {
position: absolute;
z-index: 1;
border: 2px solid transparent;
overflow: auto;
pointer-events: none;
}
.custom-area {
white-space: pre-wrap;
word-wrap: break-word;
}
<div class="container">
<div class="backdrop">
<div class="custom-area">
<!-- Cloned text with colors will go here -->
</div>
</div>
<textarea id="myTextArea"></textarea>
</div>
Note this is just a base approach to understand the underlying idea. But with some work on it, maybe you can get a generalized version. For example, by now, the textarea
can't be resizable. But maybe you can detect that event and rezise the backdrop
dinamically.
You can style the text in the textarea as a whole, but since a textarea does not have sub-elements such as or you cannot give separate text within that textarea separate styles.
on the other hand if you had a separate div displaying a copy of the text you could in the innerHTML of the div assign
apple
to replace the word apple in the .. but the text in the textarea would remain unchanged.. possibly overlay div on top of the textarea but hidden until text is entered in the textarea. Not certain of the precise code to do that piece or if it would work. but at least it is a viable logic chain that I hope may help you find a solution.
To color a specific word from that text you must wrap that word with a html tag. But textarea doesn't support html tag.
You can do it outside of the textarea field.