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>
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>
Share
Improve this question
edited Jan 30, 2017 at 16:18
Mosh Feu
29.4k18 gold badges93 silver badges141 bronze badges
asked Jan 30, 2017 at 16:02
Psycho NerdPsycho Nerd
534 bronze badges
4
-
You can't style a single character. I would suggest wrapping all individual characters each in a
span
, and styling that. – evolutionxbox Commented Jan 30, 2017 at 16:06 - Challenge bees, @evolutionxbox, to make sure you're not wrapping each character of any nested tags. Given the innerHTML shown, that's not an issue. But if this same code gets reused with descendant tags, you would be thoroughly breaking them by this approach. – Snowmonkey Commented Jan 30, 2017 at 16:11
-
@Armin The
selector()
function does incrementi
. – Scott Marcus Commented Jan 30, 2017 at 16:19 - Thanks so much... – Psycho Nerd Commented Jan 30, 2017 at 18:15
3 Answers
Reset to default 5The 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 ments 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
- Create a list of characters in the HTML element by using
string#split
. - Wrap each of these characters inside a span tag. This is easy to do using the
map
function. We want to check if these are alphabetical characters so we use thetest
function. - We then need to find the number of characters in the original string. We can do that by stripping the new string of all of it's span tags. Set the initial index to the first character, which in JavaScript is zero.
- Call an event listener. This could be for example
keydown
, which listens for keypresses. - All of our characters have now been wrapped with a char class. To find a particular one, use
document.querySelectorAll
, and pass in[index]
- In the event that we cycle through the string, we will remove the styling for the last character in the list. Otherwise, naturally, the previous character will be converted back to normal.
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>
You need to put all character into a span tag, and change the span background color.
var i = 0;
function selector() {
if (document.getElementById("temp_" + i))
document.getElementById("temp_" + i).style.backgroundColor = "red";
i++;
}
<p id="temp">
<span id='temp_0'>A</span>
<span id='temp_1'>B</span>
<span id='temp_2'>C</span>
<span id='temp_3'>D</span>
</p>
<button onclick='selector();'>Test</button>