I’m trying to make a character selector, which select each character separately every time button pressing. But its not working at all
<!DOCTYPE html>
<html lang="en">
<head>
<title>HELLO WORLD</title>
</head>
<body>
<center>
<br />
<p id="temp">ABCDEFGHIJKLMNOPQRSTUVWXYZ</p>
<br />
<input type="button" onclick="selector()" value="SELECT" />
<script>
var x = document.getElementById("temp").innerHTML;
var i = 0;
function selector() {
x.charAt(i).style.backgroundColor = "red";
i++;
}
</script>
</center>
</body>
</html>
The primary issue is that you can only apply styling to HTML elements, not individual characters that make up the text content of an element.
This is why you are getting the "undefined" error that you are... backgroundColor
can't be set on undefined
, which refers to the return value of the style
property, which doesn't exist on individual characters.
So first, you must wrap the character(s) to be highlighted in another element (a <span>
is the best choice here) and then you can have the contents of the <span>
be highlighted.
You weren't exactly clear on whether each click of the button should highlight only the next character or if the highlighting should be extended to include the next character, so I have solutions for both of those below. See comments inline for detailed explanations:
Solution #1 (highlight single character at a time)
// Get DOM reference to paragraph (not contents of paragraph)
var x = document.getElementById("temp");
// Get DOM reference to button so we can wire it up to
// an event handler in JS (not via inline event handling attributes).
var btn = document.getElementById("btn");
// Set up event handler:
btn.addEventListener("click", selector);
var i = 0;
function selector() {
// Get the character to be highlighted
var char = x.textContent.charAt(i);
// Set the contents of the paragraph to a new string that has the particular character
// wrapped with a <span> that is set to use a predetermined class that does the actual
// highlighting.
x.innerHTML = x.textContent.replace(char, "<span class='highlight'>" + char + "</span>");
// Increment i until we've hit the 26th value, then reset to 0
i < 25 ? i++ : i = 0;
}
.highlight { background-color:red; }
<p id="temp">ABCDEFGHIJKLMNOPQRSTUVWXYZ</p>
<br>
<!-- There is no closing tag for input elements! -->
<input type="button" id="btn" value="SELECT">
Solution #2 (extend highlighting to include next character)
// Get DOM reference to paragraph (not contents of paragraph)
var x = document.getElementById("temp");
// Get DOM reference to button so we can wire it up to an event handler in JS (not via inline event
// handling attributes).
var btn = document.getElementById("btn");
// Set up event handler:
btn.addEventListener("click", selector);
var i = 0;
function selector() {
// Get the character to be highlighted
var char = x.textContent.charAt(i);
// Set the contents of the paragraph to a new string that encloses all the characters
// up to and including the current one in a <span> that is set to use a predetermined
// class that does the actual highlighting.
x.innerHTML = "<span class='highlight'>" + x.textContent.replace(char, char + "</span>");
// Increment i until we've hit the 26th value, then reset to 0
i < 25 ? i++ : i = 0;
}
.highlight { background-color:red; }
<p id="temp">ABCDEFGHIJKLMNOPQRSTUVWXYZ</p>
<br>
<!-- There is no closing tag for input elements! -->
<input type="button" id="btn" value="SELECT">
Here's one possible implementation
string#split
.map
function. We want to check if these are alphabetical characters so we use the test
function.keydown
, which listens for keypresses.document.querySelectorAll
, and pass in [index]
var chars = document.getElementById("par").innerHTML.split('');
var wrapped = chars.map( c => /[a-z]/i.test(c) ? "<span class='char'>" + c + "</span>" : "").join('');
var numLetters = wrapped.replace(/<span class='char'>/g, '').replace(/<\/span>/g, '').length;
document.getElementById("par").innerHTML = wrapped;
var index = 0;
document.addEventListener("keydown", function() {
document.querySelectorAll(".char")[index].style.color = "red";
if (index == 0) {
document.querySelectorAll(".char")[numLetters - 1].style.color = "black";
}
if (index > 0) {
document.querySelectorAll(".char")[index - 1].style.color = "black";
}
index = index == numLetters - 1 ? 0 : index + 1
});
<p id="par">This is a paragraph</p>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With