1

I am creating a web app with Django and I require some Javascript for changing styles of dynamically generated elements. I have simplified the code to just static html and javascript.

Goal: The code causing problems is acting on detail pages. There are many detail pages, each representing data from a given database entry. Each page will have 1 or more table, depending on how many protein names the database entry has. For each table, I want to change the colour of the entry for the protein name in the table heading as well as the entry for the example_id.

Attempt: I am using javascript to capture the example_id from the top level heading and the protein names from the table headings. I am then capturing the nodelist of table rows and iterating through, looking for entries that match either the protein name or the example_id.

Problem: When iterating over the nodelist of protein names taken from the table headers in a nested loop the page never loads.

HTML:

<html>
  <body>
    <h1 class="msaIdCatcher">Protein Record #example_id</h1>
    
      <h2>Multiple Sequence Alignment</h2>

        


        <h3 class= "msaProtNameCatcher">Protein_name1</h3>
          <p>The following is a multiple sequence alignment (MSA) of all sequences predicted to be Protein_name1 sequences.</p>

          <table>

            <tr class=sequenceidrow>
              <th class=sequenceid>not_example_id1</th>
              <td class="alignsequence">aaaaaaaaaaaaaaaaaaaa</td>
            </tr>
            <tr class=sequenceidrow>
              <th class=sequenceid>Protein_name1</th>
              <td class="alignsequence">aaaaaaaaaaaaaaaaaaaa</td>
            </tr>
            <tr class=sequenceidrow>
              <th class=sequenceid>not_example_id3</th>
              <td class="alignsequence">aaaaaaaaaaaaaaaaaaaa</td>
            </tr>
            <tr class=sequenceidrow>
              <th class=sequenceid>example_id</th>
              <td class="alignsequence">aaaaaaaaaaaaaaaaaaaa</td>
            </tr>
            <tr class=sequenceidrow>
              <th class=sequenceid>not_example_id4</th>
              <td class="alignsequence">aaaaaaaaaaaaaaaaaaaa</td>
            </tr>
          </table>
        <h3 class="msaProtNameCatcher">Protein_name2</h3>
          <p>The following is a multiple sequence alignment (MSA) of all sequences predicted to be Protein_name2 sequences.</p>

          <table>
            <tr class=sequenceidrow>
              <th class=sequenceid>not_example_id1</th>
              <td class="alignsequence">aaaaaaaaaaaaaaaaaaaa</td>
            </tr>
            <tr class=sequenceidrow>
              <th class=sequenceid>not_example_id2</th>
              <td class="alignsequence">aaaaaaaaaaaaaaaaaaaa</td>
              </tr>
              <tr class=sequenceidrow>
                  <th class=sequenceid>not_example_id3</th>
                  <td class="alignsequence">aaaaaaaaaaaaaaaaaaaa</td>
              </tr>
              <tr class=sequenceidrow>
                  <th class=sequenceid>example_id</th>
                  <td class="alignsequence">aaaaaaaaaaaaaaaaaaaa</td>
              </tr>
              <tr class=sequenceidrow>
                  <th class=sequenceid>not_example_id4</th>
                  <td class="alignsequence">aaaaaaaaaaaaaaaaaaaa</td>
              </tr>
              <tr class=sequenceidrow>
                  <th class=sequenceid>Protein_name2</th>
                  <td class="alignsequence">aaaaaaaaaaaaaaaaaaaa</td>
              </tr>
            </table>
  </body>
</html>




var idTitle = document.getElementsByClassName("msaIdCatcher");
id = idTitle[0].innerHTML;
id = id.replace("Protein Record #", "");

//Get protein_names from table headers
proteinnameElements = document.getElementsByClassName("msaProtNameCatcher")

//Get table rows
var sequenceidrowElements = document.getElementsByClassName("sequenceidrow");

//Loop through table rows
for (var i = 0; i < sequenceidrowElements.length; i++) {

    //Get sequence id
    var sequenceidElement = sequenceidrowElements[i].getElementsByClassName("sequenceid");
    idElement = sequenceidElement[0].innerHTML

    //Check if ID is ID from page heading
    if (idElement == id) {

        //Get sequence element and change colour of ID and sequence elemnt
        var alignsequenceElement = sequenceidrowElements[i].getElementsByClassName("alignsequence");
        sequenceidElement[0].style.color = "#b80090";
        alignsequenceElement[0].style.color = "#b80090";
    }

    //Loop through protein names in table headers and Check if ID in table matches protein name
    //Then change colour of ID and sequence
    for (var i = 0; i < proteinnameElements.length; i++) {
        proteinname = proteinnameElements[i].innerHTML
        if (idElement == proteinname) {
            var alignsequenceElement = sequenceidrowElements[i].getElementsByClassName("alignsequence");
            sequenceidElement[0].style.color = "red";
            alignsequenceElement[0].style.color = "red";
        }
    }
}

However, when using a single protein name by making proteinname equal to the innerHTML of the first element proteinnameElements and taking away the loop nesting as follows, the page loads in a fraction of a second. 

var idTitle = document.getElementsByClassName("msaIdCatcher");
id = idTitle[0].innerHTML;
id = id.replace("Protein Record #", "");

//Get protein_names from table headers
proteinnameElements = document.getElementsByClassName("msaProtNameCatcher")
proteinname = proteinnameElements[0].innerHTML
//Get table rows
var sequenceidrowElements = document.getElementsByClassName("sequenceidrow");

//Loop through table rows
for (var i = 0; i < sequenceidrowElements.length; i++) {

    //Get sequence id
    var sequenceidElement = sequenceidrowElements[i].getElementsByClassName("sequenceid");
    idElement = sequenceidElement[0].innerHTML

    //Check if ID is ID from page heading
    if (idElement == id) {

        //Get sequence element and change colour of ID and sequence elemnt
        var alignsequenceElement = sequenceidrowElements[i].getElementsByClassName("alignsequence");
        sequenceidElement[0].style.color = "#b80090";
        alignsequenceElement[0].style.color = "#b80090";
    }

    //Loop through protein names in table headers and Check if ID in table matches protein name
    //Then change colour of ID and sequence
        if (idElement == proteinname) {
            var alignsequenceElement = sequenceidrowElements[i].getElementsByClassName("alignsequence");
            sequenceidElement[0].style.color = "red";
            alignsequenceElement[0].style.color = "red";
        }
}

Can someone help me understand why nesting loops in this way causes such a large difference in runtime and help me find a way to solve my problem?

Thanks!
1
  • 1
    You are using in both loops var i Commented Sep 11, 2020 at 17:23

1 Answer 1

1

Your inner loop begins with var i, because of how scoping works in JavaScript, it will be the same i as the outer loop, and it will be changed everytime the inner loop is run (thereby never increasing the outer loop, making it endless); it's like typing this:

var i;
for (i = 0; i < length; ++i)
{
    for (i = 0; i < length2; ++i)
    {
        //...
    }
}

Either use a different variable name for the inner loop (j is a common choice), or use the let keyword (which will ensure the variables are locally scoped), this is the let keyword (note that it's relatively recent):

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

Hope this helps clear things up.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.