1

I would like to have a function that underline particular characters in a word (that is in a html tag). Here's the thing I have for the moment:

<html>
    <header>
        <style>
            .underlined {
                color: #aaa;
                text-decoration: underline;
            }
        </style>
        <script type="text/javascript" language="javascript">
            var rUnderlinedLettersLocation = [1, 3, 5]
            function test(){
                var sWord = document.getElementsByClassName("word")[0].innerHTML;
                for(i = rUnderlinedLettersLocation.length;i > 0; i--){
                    console.log("full word = " + sWord);
                    console.log("letter that needs to be underlined : " + sWord[rUnderlinedLettersLocation[i-1]]);
                    sWord[rUnderlinedLettersLocation[i-1]] = "<span class='underlined'>" + sWord[rUnderlinedLettersLocation[i-1]] + "</span>";
                }
                console.log("modified word is = " + sWord);
                document.getElementsByClassName("word")[0].innerHTML = sWord;
            }
        </script>
    </header>
    <body>
        <input type="button" value="click" onclick="test()"/>
        <p class="word">Helowdi</p>
    </body>
</html>

The output I have is:

full word = Helowdi
letter that needs to be underlined : d
full word = Helowdi
letter that needs to be underlined : o
full word = Helowdi
letter that needs to be underlined : e
modified word is = Helowdi

Where I should be expecting something like:

full word = Helowdi
letter that needs to be underlined : d
full word = Helow<span class="underlined">d</span>i
letter that needs to be underlined : o
full word = Hel<span class="underlined">o</span>w<span class="underlined">d</span>i
letter that needs to be underlined : e
modified word is = H<span class="underlined">e</span>l<span class="underlined">o</span>w<span class="underlined">d</span>i

It seems like i'm not adding the "span" thing correctly. Thanks for your help.

smirnoff103
  • 196
  • 1
  • 13
  • 1
    Strings are immutable in JS, so `sWord[index] = whatever` won't work. See this: https://stackoverflow.com/a/1431113/3776299 – helb Oct 31 '17 at 13:25

3 Answers3

1

A string is immutable in js, meaning you can't change it the way you are trying. What you can do is to create a new string from your string, with the updated contents. I would do so by splitting the input string to an array, reverse that, and then do everything from 0 to end:

let s = 'Helowdi'.split('').reverse();
let underlinedLettersLocation = [1, 3, 5];

for (let index of underlinedLettersLocation) {
  s[index] = '<span class="underlined">' + s[index] + '</span>';
}

let newString = s.reverse().join('');

console.log(newString);
baao
  • 71,625
  • 17
  • 143
  • 203
0

You could split the characters into an array and join them together at the end:

var rUnderlinedLettersLocation = [1, 3, 5]

function test() {
  const wordElement = document.getElementsByClassName("word")[0];
  const word = wordElement.innerText;
  const replaced = word.split( '' ).map( ( char, index ) => {
    if ( rUnderlinedLettersLocation.indexOf( index ) > -1 ) {
      return '<span class="underlined">' + char + '</span>';
    }
    return char;
  } );
  wordElement.innerHTML = replaced.join( '' );
}
.underlined {
  color: #aaa;
  text-decoration: underline;
}
<input type="button" value="click" onclick="test()" />
<p class="word">Helowdi</p>
lumio
  • 7,428
  • 4
  • 40
  • 56
0

You've got a few things wrong. First, you declare "sWord" as a string

var sWord = document.getElementsByClassName("word")[0].innerHTML; // sWord: Helowdi

Then you start treating it like an array

sWord[rUnderlinedLettersLocation[i-1]] = "<span class='underlined'>" + sWord[rUnderlinedLettersLocation[i-1]] + "</span>";

Then you try to put it back into the DOM as a string again

document.getElementsByClassName("word")[0].innerHTML = sWord;

There are a number of different ways to go about this. I'm not 100% sure what you're trying to accomplish, but if I were trying to do exactly what you're trying to do, I would use an array of characters.

function underlineWord(text,key) {
  let charArr = text.split(""); // Converts string to character array ["f","o","o","b","a","r"]
  for (let i = 0; i < key.length; i++) {
    let replaceAt = key[i]; // replaceAt is 1, 3, and 5 for each loop
    charArr[replaceAt] = "<span class='underlined'>" + charArr[replaceAt] + "</span>";
  }
  return charArr.join(""); // Converts char array back to string;
}

let changedWord = underlineWord("foobar",[1,3,5]));
$(".word").HTML(changedWord);

You could also use string functions, like substring. Or you would have an empty string variable and keep adding to it (something like this)

let changedWord = "";
let underlineKey = [1,3,5];
for (var i = 0; i < str.length; i++) {
  // arr.includes(1) returns true if the value "1" is somewhere in the array
  if (underlineKey.includes(i)) {
    changedWord += "<span class='underlined'>" + str[i] + "</span>";
  }  else  {
    changedWord += str[i];
  }
}

Coding's fun, but can be confusing at first. I would suggest you spend a week or so going through tutorials before you try making your own solutions. There are a lot of tools at your disposal, like CodeCademy.

JasonHorsleyTech
  • 392
  • 1
  • 5
  • 11
  • Thanks :) I'm used to code in C++ (something like 10 years ago) and there a string was an array of char, that's why I thought JS was approximately the same. Thanks for the help – smirnoff103 Oct 31 '17 at 14:06
  • Javascript is very very strange, especially coming from C. If you want something a little similar, you should try "use string", which complains a lot more (like C). You could also look into typescript, which enforces datatypes. (sorry if I sounded patronizing) – JasonHorsleyTech Oct 31 '17 at 14:10