Reputation: 179
I'm trying to build a simple color highlighter using a textarea calling a function on keyup, and a div to output the result (highlighted/colored text).
The words to be highlighted and their associated color are stored in this object :
var obj = {
"to": "green",
"code": "red",
"applet": "blue"
}
The input string is then split into word units to check if they match the obj
keys.
var splitRequest = input.value.toLowerCase().split(' ');
If they do, then they should be highlighted. I wrote a simple code that does the trick (see fiddle at the end), except for this line :
output.innerHTML += '<span style="color:' + obj[splitRequest[i]] + '">' + splitRequest[i] + " </span>";
It prints the whole text on each keypress instead of replacing the current content with the new one because of the +=
sign. Problem is that I can't simply use the =
sign because it will only print the first element of the splitRequest
array instead of the whole array. I tried to use the join()
method but it obviously didn't work as I expected (test).
Maybe the code itself isn't so good and I should use another approach to get it working. This would be a great way to learn javascript better, but I actually have no idea how to do this.
How can I output the text user types in while highlighting the matching words without having this problem ?
Here is the working demo where I'm stuck : https://jsfiddle.net/Lau1989/9oL7umtt/1/
Thanks for your help
PS : I know there are third-parties availables for syntax highlighting, but for the sake of educating myself I'm trying to code it from scratch using pure javascript (no jQuery).
Upvotes: 2
Views: 141
Reputation: 89547
Here is an example of ES2015/ES6 style, using map/reduce and string templating.
'use strict'
const obj = {
"to": "green",
"code": "red",
"applet": "blue"
}
const output = document.getElementById('output')
document.getElementById('input')
.addEventListener('keyup', highlight)
/**
* Process text and provides provides that text in output control
*/
function highlight() {
output.innerHTML = processText(input.value.toLowerCase())
}
/**
* Process text and returns formatted HTML text to be displayed
*
* @param {string} text - text to be processed
* @return {string} - formatted HTML text
*/
function processText(text) {
return text.split(' ')
.map(x => obj[x] ? `<span style="color: ${obj[x]}">${x}</span>` : x)
.reduce((prev, cur) => `${prev} ${cur}`)
}
/**
* Trigger first time hightlight function
* so it will highlight text if there is any text in input contol
*/
highlight()
textarea {
padding: 10px;
}
div {
width: 235px;
height: 80px;
border: 1px solid black;
padding: 10px;
overflow: auto;
color: black;
}
<textarea cols="30" rows="5" id="input" autofocus>To code or not to code this Applet</textarea>
<div id="output"></div>
Upvotes: 1
Reputation: 381
you can use this. var obj = { "to": "green", "code": "red", "applet": "blue" }
props = [];
for (var p in obj) {
props.push(p);
}
var pat = new RegExp("\\s+(" + props.join("|") + ")(?=\\s+)", "gi");
alert(pat);
function highlight() {
var input = document.getElementById('input');
var output = document.getElementById('output');
output.innerHTML = input.value.replace(pat, function (x) { return "<span style=\"color:" + obj[x.toLowerCase().trim()] + "\"> " + x + "</span>" });
}
Upvotes: 1
Reputation: 381
here is a working solution
var obj = {
"to": "green",
"code": "red",
"applet": "blue"
}
function highlight() {
var input = document.getElementById('input');
var output = document.getElementById('output'),
pattern = /\s+(to|code|applet)(?=\s+)/gi;
output.innerHTML = input.value.replace(pattern, function (x) {
return "<span style=\"color:" + obj[x.toLowerCase().trim()] +
"\"> " + x + "</span>" });
}
Upvotes: 1
Reputation: 2168
add
output.innerHTML = "";
after
var output = document.getElementById('output');
on LINE 9
https://jsfiddle.net/Lauy79kv/
Upvotes: 1