Search code examples
javascripthtmlnode.jsejs

How to calculate average of each column in a HTML table using the <script> tag or using aggregate()


I have this .ejs page which contains a table. In that table, there are 4 columns which contain numbers. I want to display an average of each of these columns on the same page.

I have managed to get the averages, but it is very inefficient and is taking up a lot of space in the .ejs file.

This is what the page looks like.

1

Here is my code for the .ejs file (including my poorly coded average "calculator"):

<!DOCTYPE html>
<html lang="en">

<html>

<head>

    <title>MTU Phone Usage Monitor</title>
    <link rel="stylesheet" href="/stylesheets/styleTable.css"></link>
</head>


<body>
    <div class="banner">
        <div class="navbar">
            <img src="\images\logo.png" class="logo">
            <ul>
                <li><a href="/">Home</a></li>
                <li><a href="/phone/create">New Entry</a></li>
                <li><a href="/table">View Data</a></li>
                <li><a href="/help">Help</a></li>
            </ul>
        </div>
        <form action="/phone/find" method="post"></form>
        <div class="table-wrapper">
            <table class="tableData" id="table">
                <caption>
                    <%= title %>
                </caption>
                <thead>
                    <tr>
                        <th>Name</th>
                        <th>Education Usage</th>
                        <th>Shopping Usage</th>
                        <th>Searching/Browsing usage</th>
                        <th>Social Media usage</th>
                        <th>Date and Time</th>
                        <th></th>

                    </tr>
                </thead>

                <tbody>
                    <% for(var i=0; i < phonelist.length; i++) { %>
                        <tr>

                            <td>
                                <%= phonelist[i].name %>
                            </td>
                            <td>
                                <%= phonelist[i].timeEducation %>
                            </td>
                            <td>
                                <%= phonelist[i].timeShopping %>
                            </td>
                            <td>
                                <%= phonelist[i].timeBrowsing %>
                            </td>
                            <td>
                                <%= phonelist[i].timeSocial %>
                            </td>
                            <td>
                                <%= phonelist[i].createdAt %>
                            </td>
                            <td>
                                <div class="secret">
                                    <form action="/phone/delete" method="post"> <input type="String" value="<%= phonelist[i].id%>" name="id" readonly><button type="Submit">Delete</button></form>
                                    <form action="/phone/update" method="post"> <input type="String" value="<%=phonelist[i].id%>" name="id" readonly><button type="Submit">Update</button></form>
                                </div>
                            </td>


                        </tr>
                        <% } %>

        </div>
        <span id="education"></span><br>
        <span id="shopping"></span><br>
        <span id="browsing"></span><br>
        <span id="social"></span>
        <script>
            var table = document.getElementById("table"),
                avgVal, sumVal = 0,
                rowCount = table.rows.length - 1; // minus the header

            //calculate average education usage
            for (var i = 1; i < table.rows.length; i++) {
                sumVal = sumVal + parseInt(table.rows[i].cells[1].innerHTML);
            }

            document.getElementById("education").innerHTML = "Average Education = " + parseFloat(sumVal / rowCount);
            avgVal, sumVal = 0;

            //calculate average shopping usage
            for (var i = 1; i < table.rows.length; i++) {
                sumVal = sumVal + parseInt(table.rows[i].cells[2].innerHTML);
            }

            document.getElementById("shopping").innerHTML = "Average Shopping = " + parseFloat(sumVal / rowCount);
            avgVal, sumVal = 0;

            //calculate average browsing usage
            for (var i = 1; i < table.rows.length; i++) {
                sumVal = sumVal + parseInt(table.rows[i].cells[3].innerHTML);
            }

            document.getElementById("browsing").innerHTML = "Average Shopping = " + parseFloat(sumVal / rowCount);
            avgVal, sumVal = 0;

            //calculate average browsing usage
            for (var i = 1; i < table.rows.length; i++) {
                sumVal = sumVal + parseInt(table.rows[i].cells[3].innerHTML);
            }

            document.getElementById("browsing").innerHTML = "Average Shopping = " + parseFloat(sumVal / rowCount);

            avgVal, sumVal = 0;
            //calculate average social usage
            for (var i = 1; i < table.rows.length; i++) {
                sumVal = sumVal + parseInt(table.rows[i].cells[4].innerHTML);
            }

            document.getElementById("social").innerHTML = "Average Shopping = " + parseFloat(sumVal / rowCount);
        </script>

</body>



</html>

Here is the code for where the data comes from:


phoneRouter.route('/find')
    .post((req, res, next) => {
        phones.find({ name: req.body.name })
            .then((phonetaken) => {
                phones.find(req.body)
                    .then((phonefound) => {
                        res.render('oneFound.ejs', { 'phonelist': phonefound, title: 'All data recieved from user: ' + req.body.name }); //can use datadisplay
                    }, (err) => next(err));
            })
    })

I believe it is the aggregate method that would be used to calculate the averages here. How do I implement it? How do I shorten that code, make it more presentable and more readable. I think I could put a for loop inside of a for loop, but I'm not sure how to implement it and get all 4 averages displaying.

With this, I also want to generate a bar graph of the averages at the bottom of the page.

How would I shorten my code/make it more efficient? How would I generate a bar graph of the averages?


Solution

  • I have managed to embed 2 for loops. Makes the script look much cleaner this way.

    Check it out:

    <script>
        var table = document.getElementById("table"),
            avgVal, sumVal = 0,
            rowCount = table.rows.length - 1;
    
        for (var x = 1; x < 5; x++) {
            for (var i = 1; i < table.rows.length; i++) {
                sumVal = sumVal + parseInt(table.rows[i].cells[x].innerHTML);
    
            }
            if (x == 1) {
                var text = "Average Education = ";
            } else if (x == 2) {
                var text = "Average Shopping = ";
            } else if (x == 3) {
                var text = "Average Browsing = ";
            } else if (x == 4) {
                var text = "Average Social = "
            }
            document.getElementById(String(x)).innerHTML = text + parseFloat(sumVal / rowCount);
            avgVal, sumVal = 0;
    
        }
    </script>
    

    Then span tags looked like this:

    <span id="education"></span><br>
    <span id="shopping"></span><br>
    <span id="browsing"></span><br>
    <span id="social"></span>
    

    Now they look like this:

    <span id="1"></span><br>
    <span id="2"></span><br>
    <span id="3"></span><br>
    <span id="4"></span>