skip to Main Content

i have an HTML Table which i generate out of my database.
It contains information about machines and their status etc., these informations are parsed out of emails that contain HTML Tables about the machines

That is why i have a click to open/hide <td> in every tr where i show the "original" HTML Table of the Mail for more details and to better traceability of the results.

All java script functions worked until i added the HTML. Because my filter and search functions iterate through the <tr> and the <td> tags, so instead of td.length = 2000 i now have something like td.length = 200000, but i don’t want to iterate through them , because i already parsed that info in the Table with filters etc

So my questions is what is the best way to ignore the HTML in my search function ?

I tried a class like <td id ="ignore me"> or should i do something different like removing it from the table and make a pop up window for it ?

Here is a very simplified version of my HTML Table:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Nested Table Example</title>
    <style>
        table, th, td {
            border: 1px solid black;
            border-collapse: collapse;
            padding: 8px;
        }
    </style>
</head>
<body>
    <table>
        <thead>
            <tr>
                <th>machine</th>
                <th>status</th>
                <th>timesinceLastCheck 3</th>
                <th>Original HTML from Email (Inner Table)</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>Row 1, Cell 1</td>
                <td>Row 1, Cell 2</td>
                <td>Row 1, Cell 3</td>
                <td>
                    <table>
                        <thead>
                            <tr>
                                <th>Inner Table Header 1</th>
                                <th>Inner Table Header 2</th>
                            </tr>
                        </thead>
                        <tbody>
                            <tr>
                                <td>Row 1, Inner Cell 1</td>
                                <td>Row 1, Inner Cell 2</td>
                            </tr>
                        </tbody>
                    </table>
                </td>
            </tr>
            <tr>
                <td>Row 2, Cell 1</td>
                <td>Row 2, Cell 2</td>
                <td>Row 2, Cell 3</td>
                <td>
                    <table>
                        <thead>
                            <tr>
                                <th>Inner Table Header 1</th>
                                <th>Inner Table Header 2</th>
                            </tr>
                        </thead>
                        <tbody>
                            <tr>
                                <td>Row 2, Inner Cell 1</td>
                                <td>Row 2, Inner Cell 2</td>
                            </tr>
                        </tbody>
                    </table>
                </td>
            </tr>
            <tr>
                <td>Row 3, Cell 1</td>
                <td>Row 3, Cell 2</td>
                <td>Row 3, Cell 3</td>
                <td>
                    <table>
                        <thead>
                            <tr>
                                <th>Inner Table Header 1</th>
                                <th>Inner Table Header 2</th>
                            </tr>
                        </thead>
                        <tbody>
                            <tr>
                                <td>Row 3, Inner Cell 1</td>
                                <td>Row 3, Inner Cell 2</td>
                            </tr>
                        </tbody>
                    </table>
                </td>
            </tr>
            <tr>
                <td>Row 4, Cell 1</td>
                <td>Row 4, Cell 2</td>
                <td>Row 4, Cell 3</td>
                <td>
                    <table>
                        <thead>
                            <tr>
                                <th>Inner Table Header 1</th>
                                <th>Inner Table Header 2</th>
                            </tr>
                        </thead>
                        <tbody>
                            <tr>
                                <td>Row 4, Inner Cell 1</td>
                                <td>Row 4, Inner Cell 2</td>
                            </tr>
                        </tbody>
                    </table>
                </td>
            </tr>
        </tbody>
    </table>
</body>
</html>

that is my search/filter function

   function searchTable() {
        var input, filter, table, tr, td, i, txtValue;
        input = document.getElementById("searchInput");
        filter = input.value.toUpperCase();
        table = document.getElementById("machineTable");
        tr = table.getElementsByTagName("tr");
        
       

        // Get selected radio button value for filter
        var selectedFilter = document.querySelector('input[name="filter"]:checked').value.toUpperCase();
        // Get selected radio button value for days
        var selectedDays = document.querySelector('input[name="days"]:checked').value;

        // Loop through all table rows
        for (i = 0; i < tr.length; i++) { 
            if (i !== 0) { // Check if the row is not the first row (header row)
                td = tr[i].getElementsByTagName("td");
                alert("länge der tr")
                alert (tr.length)
                var matchFound = false;
                // Loop through all table columns
                //td.length -1 entfernt
                for (var j = 0; j < 9 ; j++) { 
                    
                    var cell = td[j];
                    if (cell) {
                        txtValue = cell.textContent || cell.innerText;
                        // Check if the cell text contains the filter text, matches the selected filter, and days condition
                        alert(td[i]);
                        alert(i);
                        if ((selectedFilter === "ALL" || td[4].innerText.toUpperCase() === selectedFilter) && 
                            txtValue.toUpperCase().indexOf(filter) > -1 &&
                            (selectedDays === "ALL" || parseInt(td[7].innerText) >= parseInt(selectedDays))) {
                            matchFound = true;
                            break;
                        }
                    }
                }
                // Hide or show the row based on match
                if (matchFound) {
                    tr[i].style.display = "";
                } else {
                    tr[i].style.display = "none";
                }
            }
        }
    }

Edit: the idea of using the querySelectorAll() from James was very good

i then used the solution given in the comments by CarstenMassmann:

let tr = table.querySelectorAll(":scope > tbody > tr");

this gives me the correct number of rows, in the innerloop i just iterate every tr with the numberOfColumns because i still get too much td elements, and i did not figure it out yet how

but with the static numberOfColumns it works for me, but my search function will still search through the inner HTML what can cause performance issues

2

Answers


  1. You can get only tds which are direct children of the main table like this

    let tr = table.querySelectorAll(":scope > tbody > tr > td");

    let table = document.getElementById("machineTable");
    let tr = table.querySelectorAll(":scope > tbody > tr > td");
    console.log(tr.length) // 16 - there are 16 tds in the root table
    table, th, td {
                border: 1px solid black;
                border-collapse: collapse;
                padding: 8px;
            }
    <table id="machineTable">
            <thead>
                <tr>
                    <th>machine</th>
                    <th>status</th>
                    <th>timesinceLastCheck 3</th>
                    <th>Original HTML from Email (Inner Table)</th>
                </tr>
            </thead>
            <tbody>
                <tr>
                    <td>Row 1, Cell 1</td>
                    <td>Row 1, Cell 2</td>
                    <td>Row 1, Cell 3</td>
                    <td>
                        <table>
                            <thead>
                                <tr>
                                    <th>Inner Table Header 1</th>
                                    <th>Inner Table Header 2</th>
                                </tr>
                            </thead>
                            <tbody>
                                <tr>
                                    <td>Row 1, Inner Cell 1</td>
                                    <td>Row 1, Inner Cell 2</td>
                                </tr>
                            </tbody>
                        </table>
                    </td>
                </tr>
                <tr>
                    <td>Row 2, Cell 1</td>
                    <td>Row 2, Cell 2</td>
                    <td>Row 2, Cell 3</td>
                    <td>
                        <table>
                            <thead>
                                <tr>
                                    <th>Inner Table Header 1</th>
                                    <th>Inner Table Header 2</th>
                                </tr>
                            </thead>
                            <tbody>
                                <tr>
                                    <td>Row 2, Inner Cell 1</td>
                                    <td>Row 2, Inner Cell 2</td>
                                </tr>
                            </tbody>
                        </table>
                    </td>
                </tr>
                <tr>
                    <td>Row 3, Cell 1</td>
                    <td>Row 3, Cell 2</td>
                    <td>Row 3, Cell 3</td>
                    <td>
                        <table>
                            <thead>
                                <tr>
                                    <th>Inner Table Header 1</th>
                                    <th>Inner Table Header 2</th>
                                </tr>
                            </thead>
                            <tbody>
                                <tr>
                                    <td>Row 3, Inner Cell 1</td>
                                    <td>Row 3, Inner Cell 2</td>
                                </tr>
                            </tbody>
                        </table>
                    </td>
                </tr>
                <tr>
                    <td>Row 4, Cell 1</td>
                    <td>Row 4, Cell 2</td>
                    <td>Row 4, Cell 3</td>
                    <td>
                        <table>
                            <thead>
                                <tr>
                                    <th>Inner Table Header 1</th>
                                    <th>Inner Table Header 2</th>
                                </tr>
                            </thead>
                            <tbody>
                                <tr>
                                    <td>Row 4, Inner Cell 1</td>
                                    <td>Row 4, Inner Cell 2</td>
                                </tr>
                            </tbody>
                        </table>
                    </td>
                </tr>
            </tbody>
        </table>
    Login or Signup to reply.
  2. Instead of writing further comments I decided to demonstrate the whole filtering mechanism here:

    const [filt,days,tbody]=["input","select","#machineTable tbody"].map(sel=>document.querySelector(sel)),
          trs=[...tbody.children];
          
    function filtTable(){
      const filtRX=new RegExp(filt.value,"i"), daysval=days.value;
      trs.forEach(tr=>{
        const tds=tr.children;
        tr.style.display = filtRX.test(tds[3].textContent) && (daysval=="all" || tds[6].textContent==daysval) 
          ? ""       // show
          : "none";  // hide      
      })
    }
    
    document.body.addEventListener("input",filtTable);
    filtTable();
    table, th, td {
                border: 1px solid black;
                border-collapse: collapse;
                padding: 8px;
            }
    <input placeholder="please enter a filter string" value="hello">
    <select><option>all</option><option>2</option><option>3</option><option>4</option><option>5</option><option>6</option></select> days
    <table id="machineTable">
            <thead>
                <tr>
                    <th>machine</th>
                    <th>status</th>
                    <th>timesinceLastCheck 3</th>
                    <th>Original HTML from Email (Inner Table)</th>
                    <th>something</th>
                    <th>else</th>
                    <th>column 7</th>
                </tr>
            </thead>
            <tbody>
                <tr>
                    <td>Row 1, Cell 1</td>
                    <td>Row 1, Cell 2</td>
                    <td>Row 1, Cell 3</td>
                    <td>Hello ...
                        <table>
                            <thead>
                                <tr>
                                    <th>Inner Table Header 1</th>
                                    <th>Inner Table Header 2</th>
                                </tr>
                            </thead>
                            <tbody>
                                <tr>
                                    <td>Row 1, Inner Cell 1</td>
                                    <td>Row 1, Inner Cell 2</td>
                                </tr>
                            </tbody>
                        </table>
                    </td>
                    <td>Row 1, Cell 5</td>
                    <td>Row 1, Cell 6</td>
                    <td>4</td>
                </tr>
                <tr>
                    <td>Row 2, Cell 1</td>
                    <td>Row 2, Cell 2</td>
                    <td>Row 2, Cell 3</td>
                    <td>... my friends and also the group "AbC"!
                        <table>
                            <thead>
                                <tr>
                                    <th>Inner Table Header 1</th>
                                    <th>Inner Table Header 2</th>
                                </tr>
                            </thead>
                            <tbody>
                                <tr>
                                    <td>Row 2, Inner Cell 1</td>
                                    <td>Row 2, Inner Cell 2</td>
                                </tr>
                            </tbody>
                        </table>
                    </td>
                    <td>Row 2, Cell 5</td>
                    <td>Row 3, Cell 6</td>
                    <td>5</td>
                </tr>
                <tr>
                    <td>Row 3, Cell 1</td>
                    <td>Row 3, Cell 2</td>
                    <td>Row 3, Cell 3</td>
                    <td>This is just ...
                        <table>
                            <thead>
                                <tr>
                                    <th>Inner Table Header 1</th>
                                    <th>Inner Table Header 2</th>
                                </tr>
                            </thead>
                            <tbody>
                                <tr>
                                    <td>Row 3, Inner Cell 1</td>
                                    <td>Row 3, Inner Cell 2</td>
                                </tr>
                            </tbody>
                        </table>
                    </td>
                    <td>Row 3, Cell 5</td>
                    <td>Row 3, Cell 6</td>
                    <td>4</td>
                </tr>
                <tr>
                    <td>Row 4, Cell 1</td>
                    <td>Row 4, Cell 2</td>
                    <td>Row 4, Cell 3</td>
                    <td>... an example.
                        <table>
                            <thead>
                                <tr>
                                    <th>Inner Table Header 1</th>
                                    <th>Inner Table Header 2</th>
                                </tr>
                            </thead>
                            <tbody>
                                <tr>
                                    <td>Row 4, Inner Cell 1</td>
                                    <td>Row 4, Inner Cell 2</td>
                                </tr>
                            </tbody>
                        </table>
                    </td>
                    <td>Row 4, Cell 5</td>
                    <td>Row 4, Cell 6</td>
                    <td>3</td>
                </tr>
            </tbody>
        </table>

    I have used a few slightly more advanced concepts here too:

    • destructuring assignment: [filt,days,tbody]=["input","select","#machineTable tbody"].map(sel=>document.querySelector(sel)) with Array.map() (see map)
      Is an easy way to run a loop and assign the results to an array of constants or variables

    • the RegExp class offers a possibility of comparing case insensitively when using "i" as a second argument

    • I used tr.children (see children property) here to get an HTMLcollection of elements. This is an alternative to using tr.querySelectorAll(":scope td") which would have returned a NodeList. Both lists are slightly different and are not of type "Array"

    • the ... ("spread syntax") is then used to convert the tr.children collection into a proper array.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search