0

I need to change all the <li> items that starts with two specific letters ("F" or "C"). It needs to be done with .startsWith.

The thing is, I cannot modify, add or modify my HTML or CSS (Constraint given by my teacher). I can only add to my JS function with basic code, not Regex or Jquery buildins methods.

This is what I've written so far. My loop If is not working. I am trying to get only "Cat" and "Chien" (since they both start with the letter C) to be added .bordure_verte.

function exercice() {

            var x = document.querySelectorAll("li");

            for (let i = 0; i < x.length; i++) {

                var liStartsWithC = x[i].startsWith("C");
                var liStartsWithF = x[i].startsWith("F");

                if (liStartsWithC && liStartsWithF ) {
                    x[i].classList.add("bordure_verte");
                }

                else {
                    break;
                }
            }

        }
<body>
    <h2>Animaux</h2>
    <ul id="liste_animaux">
        <li>Chien</li>
        <li>Polar bear</li>
        <li>Penguin</li>
        <li>Cat</li>
    </ul>

    <h2>Sports</h2>
    <ul>
        <li>Hockey</li>
        <li>Swimming</li>
        <li>Soccer</li>
    </ul>
    <button onclick="exercice()">Test</button>
</body>
        .bordure_verte {
            border-color: LimeGreen;
            border-width: 2px;
            border-style: solid;
            width: 200px;
        }
freedomn-m
  • 27,664
  • 8
  • 35
  • 57
dev4chae
  • 19
  • 3
  • 5
    `liStartsWithC && liStartsWithF` will always be false. You want `||`. – mbojko Feb 20 '23 at 13:18
  • 2
    Ironically, `startsWith` is a *relatively* new addition to js. (with reference to "with basic code"). – freedomn-m Feb 20 '23 at 13:21
  • 1
    Tip: read your code out loud. `if both li starts with C *and* li starts with F` - it'll never start with both, so you want `if either li starts with C *or* li starts with F` - so use `||` (as commented above, just adding the "read out loud" part) – freedomn-m Feb 20 '23 at 13:24
  • 1
    `else break;` - this says "if it doesn't match then stop looking for matches" - remove the `break`. – freedomn-m Feb 20 '23 at 13:26
  • 1
    Currently when you're using the `startsWith` method you're using it on a NodeList element and not a text element, so you want to use `x[i].outerText.startsWith("C");` on both lines instead. – Alexander Vestergaard Eriksen Feb 20 '23 at 13:26

4 Answers4

1

You can iterate with forEach and check if start with "C" or "F".

function exercice() {

    var x = document.querySelectorAll("li");

    x.forEach(item=>{
    
        var liStartsWithC = item.textContent.startsWith("C");
        var liStartsWithF = item.textContent.startsWith("F");
        
        if (liStartsWithC || liStartsWithF ) {
            item.classList.add("bordure_verte");
        }
    })
 
}

exercice()
.bordure_verte {
      border-color: LimeGreen;
      border-width: 2px;
      border-style: solid;
      width: 200px;
  }
<body>
    <h2>Animaux</h2>
    <ul id="liste_animaux">
        <li>Chien</li>
        <li>Polar bear</li>
        <li>Penguin</li>
        <li>Cat</li>
    </ul>

    <h2>Sports</h2>
    <ul>
        <li>Hockey</li>
        <li>Swimming</li>
        <li>Soccer</li>
    </ul>
    <button onclick="exercice()">Test</button>
</body>
BTSM
  • 1,585
  • 8
  • 12
  • 26
  • 1
    Don't use `.innerHTML` when working with non-HTML strings. It's less efficient and can open up security holes. Also, in this case, it would check any embedded HTML within the `li`, rather than the text content of the HTML elements. Instead, use `.textConent`. – Scott Marcus Feb 20 '23 at 13:25
1

There are 3 issues with your code:

  • .startsWith() needs a string/text, not a DOM node
  • break will exist the loop
  • && requires both to match

Fixes are:

  • x[i].textContent.startsWith(...
  • remove the break
  • || to match either

Without completely rewriting your code, here are the applied changes:

function exercice() {

  var lis = document.querySelectorAll("li");

  for (let i = 0; i < lis.length; i++) {

    var liStartsWithC = lis[i].textContent.startsWith("C");
    var liStartsWithF = lis[i].textContent.startsWith("F");

    if (liStartsWithC || liStartsWithF) {
      lis[i].classList.add("bordure_verte");
    }
  }
}
 .bordure_verte {
   border-color: LimeGreen;
   border-width: 2px;
   border-style: solid;
   width: 200px;
 }
<body>
  <h2>Animaux</h2>
  <ul id="liste_animaux">
    <li>Chien</li>
    <li>Polar bear</li>
    <li>Penguin</li>
    <li>Feline</li>
    <li>Cat</li>
  </ul>

  <h2>Sports</h2>
  <ul>
    <li>Hockey</li>
    <li>Swimming</li>
    <li>Soccer</li>
  </ul>
  <button onclick="exercice()">Test</button>
</body>
freedomn-m
  • 27,664
  • 8
  • 35
  • 57
  • Thank you for help! Is there a way around without textContent? is it not allowed since I don't have been taught about it. thanks again – dev4chae Feb 20 '23 at 13:35
  • @dev4chae If you haven't been taught how to correctly access the text within an element, what have you been taught? You'll have to use that then. However, your teacher sounds more and more like they really don't know HTML/JavaScript very well and is just following what the "crowd" does incorrectly. Based on this and the other issues I pointed out in my answer, I would be very concerned that you are being taught incorrectly. – Scott Marcus Feb 20 '23 at 13:47
  • Learning programming should never be about limiting to what you've been taught; unless you've been given specific instructions such as *"use .startsWith"* and "*don't use regex*". – freedomn-m Feb 20 '23 at 14:04
0

First, does your teacher know that the first heading in the body of an HTML page, should not be an h2? It should be an h1. And does your teacher know that using inline HTML event attributes like onclick is a legacy approach to setting up events that should not be used today?

Next, if you get into the habit of naming your variables something that represents what the variable holds, life will become much easier when you try to read your code.

See comments inline below for details:

function exercice() {
  // Name your variable something that represents what it holds:
  var items = document.querySelectorAll("li");

  for (let index = 0; index < items.length; index++) {
    // You need to test the text within the element, not the element
    // itself, so do that with .textContent.
    var liStartsWithC = items[index].textContent.startsWith("C");
    var liStartsWithF = items[index].textContent.startsWith("F");

    // Your trying to check for values that start with C OR F, so use the 
    // logical OR operator (||) instead of the logical AND operator (&&).
    if (liStartsWithC || liStartsWithF ) {
      items[index].classList.add("bordure_verte");
    }
  }
}
.bordure_verte {
   border-color: LimeGreen;
   border-width: 2px;
   border-style: solid;
   width: 200px;
}
<body>
    <!-- Headings are not for styling, they are for document structure.
         The first heading should always be h1. Then, to sub-divide the
         document lower level headings are used. -->
    <h2>Animaux</h2>
    <ul id="liste_animaux">
        <li>Chien</li>
        <li>Polar bear</li>
        <li>Penguin</li>
        <li>Cat</li>
    </ul>

    <h2>Sports</h2>
    <ul>
        <li>Hockey</li>
        <li>Swimming</li>
        <li>Soccer</li>
    </ul>
    <!--[sigh] This tells me that your teacher doesn't really know/understand
        HTML and JavaScript. Inline event attributes are the legacy approach
        to setting up events from before we had a standard.
        There are a litany of reasons not to do this. Instead, you should be
        separating your HTML from your JavaScript and setting up the event
        handler in JavaScript with .addEventListener().
     -->
    <button onclick="exercice()">Test</button>
</body>

NOTES:

Scott Marcus
  • 64,069
  • 6
  • 49
  • 71
-1

you need to read textContent instead of element itself. also && operator needs to be changed to ||

Besides, please have a look at the link below to see the issue & solution visually: TestWise Replay | Change all li items that starts with specific letters

Adnan
  • 179
  • 7
  • Thank you for your help ! I will read it. I haven't been taught about textContent therefore I can't use it. – dev4chae Feb 20 '23 at 13:34