最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

making a JavaScript character selector - Stack Overflow

programmeradmin4浏览0评论

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 increment i. – Scott Marcus Commented Jan 30, 2017 at 16:19
  • Thanks so much... – Psycho Nerd Commented Jan 30, 2017 at 18:15
Add a ment  | 

3 Answers 3

Reset to default 5

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 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 the test 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>

发布评论

评论列表(0)

  1. 暂无评论