Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

making a JavaScript character selector

Tags:

javascript

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>
like image 802
Psycho Nerd Avatar asked Dec 24 '22 21:12

Psycho Nerd


2 Answers

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">
like image 99
Scott Marcus Avatar answered Jan 07 '23 08:01

Scott Marcus


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>
like image 44
Richard Hamilton Avatar answered Jan 07 '23 10:01

Richard Hamilton