3

Hi!

Can someone take a look at my code and tell me what's wrong? (No I do not have access to edit the HTML.)

Im trying to put id="goToThis" on the first parent that matches v(weekNumber) which is v2 in this case.

Problem: It sets it on every parent and not only those which match "goToweek".

I want it to only add "goToThis" on the first matching one.

Javascript(RESULT = "2019, 2"):

function setAttributes()
{ 

    var goToweek = "<td>v" + result[1] + "</td>"
        elementos = document.body.getElementsByTagName("td");

    for (var is = 0, length = elementos.length; is < length; is++)
    {   

        for (var cc in goToweek)
        {
            if (elementos[is].innerHTML.indexOf(goToweek[cc]) !== -1)
            {   

                parentOfTds2 = (elementos[is]).parentNode;
                parentOfTds2.setAttribute("id", "goToThis");
            }
        };
    };
}

Example HTML:

<tr>
  <td>2016</td>
  <td>v2</td>
</tr>
<tr>
  <td>2016</td>
  <td>v4</td>
</tr>
<tr>
  <td>2016</td>
  <td>v5</td>
</tr>
<tr>
  <td>2016</td>
  <td>v6</td>
</tr>
<tr>
  <td>2016</td>
  <td>v7</td>
</tr>
<tr>
  <td>2016</td>
  <td>v8</td>
</tr>
<tr>
  <td>2016</td>
  <td>v22</td>
</tr>........

After Code Execute::

<tr id="goToThis">
  <td>2016</td>
  <td>v2</td>
</tr>
<tr id="goToThis">
  <td>2016</td>
  <td>v4</td>
</tr>
<tr id="goToThis">
  <td>2016</td>
  <td>v5</td>
</tr>
<tr id="goToThis">
  <td>2016</td>
  <td>v6</td>
</tr>
<tr id="goToThis">
  <td>2016</td>
  <td>v7</td>
</tr>
<tr id="goToThis">
  <td>2016</td>
  <td>v8</td>
</tr>
<tr id="goToThis">
  <td>2016</td>
  <td>v22</td>
</tr>........

I want:

<tr id="goToThis">
  <td>2016</td>
  <td>v2</td>
</tr>
<tr>
  <td>2016</td>
  <td>v4</td>
</tr>
<tr>
  <td>2016</td>
  <td>v5</td>
</tr>
<tr>
  <td>2016</td>
  <td>v6</td>
</tr>
<tr>
  <td>2016</td>
  <td>v7</td>
</tr>
<tr>
  <td>2016</td>
  <td>v8</td>
</tr>
<tr>
  <td>2016</td>
  <td>v22</td>
</tr>........
wiaK
  • 65
  • 6
  • 1
    You show the HTML result you want, but could you also show the HTML that actually results that you're trying to prevent? Also, `id` attributes have to be unique, so two different elements CANNOT have the same `id`. – Calvin Godfrey Jan 09 '19 at 15:12
  • 2
    `for (var cc in goToweek)` makes no sense given that `goToweek` is a *string*. What are you trying to do with that iteration? Don't you want to check `indexOf(goToweek)` with the *complete* string? – Bergi Jan 09 '19 at 15:16
  • Also the thing you're trying to do does not make sense anyway, as "id" values should be *unique* on a given page. – Pointy Jan 09 '19 at 15:17
  • You mean `result = [ 2019, 2 ]`? – yunzen Jan 09 '19 at 15:24
  • @CalvinGodfrey Updated, I know, worte that in the question. "I want it to only add "goToThis" on the first matching one." – wiaK Jan 09 '19 at 15:37
  • @Bergi Im pretty new to JS, but when I checked online it told me to do cc in goToweek. Im not sure, that's why I'm asking! – wiaK Jan 09 '19 at 15:37
  • @Pointy I know, read the description/ page again. Sorry for being unclear about it. – wiaK Jan 09 '19 at 15:37
  • @Bargros Thank you, I'll try that, regarding id, I only want it to be put in the first matching object of (td which has a innerHTML of v(weekNumber). – wiaK Jan 09 '19 at 15:38
  • @HerrSerker Output of a function called getWeekNumber, returns the value of 2019, 2. – wiaK Jan 09 '19 at 15:39
  • @wiaK Where did you check online and who told you that? No, don't loop there, that's rubbish! – Bergi Jan 09 '19 at 19:19

2 Answers2

2

Here is a quick solution I whipped up.

function setAttributes() { 
   const elementos = document.getElementsByTagName("tr");
   for (let is = 0; is < elementos.length; is++) { 
      const innerElements = elementos[is].children;
      if (innerElements[0].innerHTML === (""+result[0]) && innerElements[1].innerHTML === ("v"+result[1])) {   
          elementos[is].id = "goToThis";
          break;
      }
   }
}

The problem I found from your example is that even if you compared the innerHTML of the element against goToWeek how would you be sure that the td for the year is the same as the year in you result array?

To avoid this instead of fetching all td I got all tr elements and checked that the year and week match and add the id to the corresponding tr parent and break out of the loop. This should attach goToThis to the first element matching the year and week.

Bargros
  • 521
  • 6
  • 18
  • If we have more than one td that has 2019 and 2, how do we only set the ID to the first matching? – wiaK Jan 09 '19 at 16:12
  • Look at the `if` statement, if it matches the condition `innerElements[0].innerHTML === (""+result[0]) && innerElements[1].innerHTML === ("v"+result[1])` the if it'll set the **goToThis** as the `id` of the parent `tr` and break out of the loop, basically the function I gave you only looks for the first matching element and ignores anything else thereafter. – Bargros Jan 09 '19 at 16:15
  • I've tried the code but it didn't work. Nothing happend at all. No errors as well. – wiaK Jan 09 '19 at 16:57
  • Are you sure? I see no reason why this would not work, try printing results of `innerElements` and `elementos` with a `console.log(elementos);` before the loop and `console.log(innerElements);` before the `if` statement and report back the result. – Bargros Jan 09 '19 at 17:37
  • 1
    "*Which are two completely different types, and it'd always return false.*" - No. Strings and single-character-strings are the same type in js, and in fact it will mostly return true because each of the elements contains a `v`. – Bergi Jan 09 '19 at 19:19
  • @Bergi fair enough, upvoted, I can't believe i missed that. – Bargros Jan 09 '19 at 19:24
  • I'm getting `HTMLCollection(697) [tr, tr, tr...]` `HTMLCollection(26) [th, th, th...]` `HTMLCollection(26) [td, td, td...]` (This one is looping a couple of times.) Can you help me out here? @Bargros – wiaK Jan 10 '19 at 07:19
  • 1
    Sorry my bad! I looked through the code again and found that `innnerElements` in the if statement reffered to the first and second value of elementos children when it should have been the second and third one. My example above was a little bit incorrect. Thanks for the help @Bargros!! – wiaK Jan 10 '19 at 07:39
0

[].forEach.call(document.querySelectorAll("td"), function(el, ind, arr) { // in this string we give all td elements and iterate they
    if (el.textContent === "v2" && !arr._mutching) { // search match element and watch flag
        el.parentNode.id = "goToThis"; // set for paren id
        arr._mutching = true; set flag for break all cycle
    }else{
        return;
    }
});
    <table>
        <tr>
            <td>2016</td>
            <td>v2</td>
        </tr>
        <tr>
            <td>2016</td>
            <td>v4</td>
        </tr>
        <tr>
            <td>2016</td>
            <td>v5</td>
        </tr>
        <tr>
            <td>2016</td>
            <td>v2</td>  <!-- will not mutch -->
        </tr>
        <tr>
            <td>2016</td>
            <td>v7</td>
        </tr>
        <tr>
            <td>2016</td>
            <td>v8</td>
        </tr>
        <tr>
            <td>2016</td>
            <td>v22</td>
        </tr>
    </table>
Vadim Hulevich
  • 1,803
  • 8
  • 17
  • This isnt a very helpful answer since you dont explain what what wrong or how you fixed it or why it went wrong in the first place. Our goal is to teach, not give the OP a solution. – Marie Jan 09 '19 at 15:36
  • i dont understand what "result[1]", where you give this variable – Vadim Hulevich Jan 09 '19 at 15:41
  • i added comments in my code for more explanations and describe my tech approach – Vadim Hulevich Jan 09 '19 at 15:45
  • I still think the answer could benefit from a short paragraph describing why the OP had the issue they had and how you solution differs from theirs but the comments are a step in the right direction! – Marie Jan 09 '19 at 16:03