Reputation: 672
I have two textareas written in HTML like this:
<textarea id="checked-words"></textarea>
<br />
<textarea id="words" onkeyup="displayColoredText()"></textarea>
<div id="text-to-insert"></div>
(into the div
element, I will insert text, using JavaScript
)
My task is to write into the div
section the text from the second textarea
and make red the occurrences of strings from the first textarea
.
Example
If the first textarea
contains the following words: aaa
, aab
and the second contains aaab
, all of the characters have to be red. If the second one contains abaa, none of the characters will be red in the div
section.
Here is my JavaScript
function which displays and colorize the text:
function displayColoredText() {
//Displays the colored text below the second textarea
//Find the two textareas
var firstTextArea = document.getElementById('checked-words');
var secondTextArea = document.getElementById('words');
//Split by spaces
var checkedWords = firstTextArea.value.split(" ");
var text = secondTextArea.value.split(" ");
var textToInsert = secondTextArea.value;
for(i in checkedWords) {
console.log(checkedWords.length);
textToInsert = textToInsert.replace(new RegExp(checkedWords[i], 'g'), '<span class="insertRed">' + checkedWords[i] + '</span>');
}
document.getElementById('text-to-insert').innerHTML = textToInsert;
}
My problem is, that an already replaced text won't be considered, for example, if the first textarea
contains aaa
and aab
and if the second one contains aaab
, only the first three characters will be red, instead of the whole string. How can I resolve this?
EDIT: Screenshot of the problem
Upvotes: 1
Views: 160
Reputation: 181
Your problem is how your strings get replaced. Your first string is 'aaa aab'. After replacing for 'aaa' in 'aaab', you get '<span class="insertRed">aaa</span>b'. Trying to find 'aab' in this string will come up with no results. You have to replace from your original string and somehow combine the two. I'm not sure how to do this, but I hope this sets you on the right track.
EDIT: I think this will work: Instead of replacing the text in the string, place the beginning coordinate in an array and the end coordinate in a second array. Keep doing this for every word found. Then at all of the beginning coordinates, insert the string '<span class="insertRed">'. At all of the end coordinates, insert the string '<span>'. Here is the JS:
function displayColoredText() {
//Displays the colored text below the second textarea
//arrays with coordinates
var beginnings = [];
var ends = [];
//Find the two textareas
var firstTextArea = document.getElementById('checked-words');
var secondTextArea = document.getElementById('words');
//Split by spaces
var checkedWords = firstTextArea.value.split(" ");
var text = secondTextArea.value.split(" ");
var textToInsert = firstTextArea.value;
for(i in checkedWords) {
console.log(checkedWords.length);
if (firstTextArea.value.indexOf(checkedWords[i]) != -1) {
beginnings.push(firstTextArea.value.indexOf(checkedWords[i]));
ends.push(firstTextArea.value.indexOf(checkedWords[i]) + checkedWords[i].length);
}
}
beginnings.sort(function(a, b){return b-a});
ends.sort(function(a, b){return b-a});
for (b in beginnings) {
textToInsert = textToInsert.slice(0, ends[b]) + "</span>" + textToInsert.slice(ends[b]);
textToInsert = textToInsert.slice(0, beginnings[b]) + '<span class="insertRed">' + textToInsert.slice(beginnings[b]);
}
document.getElementById('text-to-insert').innerHTML = textToInsert;
}
This code is untested, so tell me if something doesn't work and I will change it. Basically, what I am doing is instead of replacing occurrences, I find them first, place them in arrays, and insert the correct text at those coordinates. I hope this helps!
Upvotes: 0
Reputation: 96241
Your original input from the second text area is pure text, not HTML, so this is the "state" of the data you want to do this in.
This would be my way of implementing it as mentioned in comments, recording which positions have a match first, and then simply looping over all characters in the end to wrap them in a span each:
function displayColoredText() {
//Displays the colored text below the second textarea
//Find the two textareas
var firstTextArea = document.getElementById('checked-words');
var secondTextArea = document.getElementById('words');
//Split by spaces
var checkedWords = firstTextArea.value.split(" ");
var text = secondTextArea.value;
// empty array with keys 0 to length-1 set to undefined
var markedMatches = new Array(secondTextArea.value.length);
for (var i = 0, l = checkedWords.length; i < l; ++i) {
var checkedWord = checkedWords[i],
start = 0,
matchPos;
// check for match from current starting position
while ((matchPos = text.indexOf(checkedWord, start)) !== -1) {
// mark positions from current match start to that plus length of match
for (var k = matchPos, m = matchPos + checkedWord.length; k < m; ++k) {
markedMatches[k] = true;
}
// advance starting position to continue searching
start = matchPos + 1;
}
}
var textToInsert = '';
for (var i = 0, l = text.length; i < l; ++i) {
// wrap in span if markedMatches contains true at this position
textToInsert += (markedMatches[i] ? '<span class="match">' + text[i] + '</span>' : text[i]);
}
document.getElementById('text-to-insert').innerHTML = textToInsert;
}
https://jsfiddle.net/t9xjzkaw/
As I said, you could get more sophisticated in collecting the matches as intervals, or putting multiple adjoining matching characters into a single span element, instead of wrapping each one on its own ... but this does the basic job.
Upvotes: 2