1
\$\begingroup\$

So, I have been recently heavily focusing on Front-End, for data validation, showing errors etc. And a big thank you to CertainPerformance for many reviews hes done for me :)

I have created a Report template using handlebars and a MySQL database to store the data, using Node JS to interact between the 2. I have now gained understanding how Node JS can interact with the front end, grab data and send it to a database.

I'd like to hear some reviews to my current code - front, and back end. For me, personally it works and I am extremely happy that I am able to create such thing, whereas before I never thought I could :D

Just want to hear some reviews - where I can improve, where I'm I lacking, what can be simplified etc..

Node JS

Note: this function is triggered at routing stage, I haven't included it here.

// 21-TEMP-01a
exports.TEMP01A21 = async function(req, res) {

    // Array to store actual temperature
    var actualTemp = [];
    // Array to store minimum temperature
    var minTemp = [];
    // Array to store maximum temperature
    var maxTemp = [];

    // Array to store actual humidity
    var actualHumid = [];
    // Array to store minimum humidity
    var minHumid = [];
    // Array to store maximum humidity
    var maxHumid = [];

    // Get drying room names
    var roomNames = [];



    // Loop thorugh each req.body values
    for(var key in req.body) {
        // Store req.body key to value var
        var value = req.body[key];

        // For each key that starys with ActualTemp store into array
        if(key.startsWith("actualtemp")) {
            actualTemp.push(value);
        }

        // minTemp
        if(key.startsWith("mintemp")) {
            minTemp.push(value);
        }

        // maxTemp
        if(key.startsWith("maxtemp")) {
            maxTemp.push(value);
        }

        // actualHumidity
        if(key.startsWith("actualhumid")) {
            actualHumid.push(value);
        }

        // minHumidity
        if(key.startsWith("minhumid")) {
            minHumid.push(value);
        }

        // maxHumidity
        if(key.startsWith("maxhumid")) {
            maxHumid.push(value);
        }

        // Room Names
        if(key.startsWith("dryingroom")) {
            roomNames.push(value);
        }
        
    }


    // Get todays date
    var today = new Date();
    // Format the date
    var formatDay = today.toISOString().substring(0, 10);

    // Create an array to create custom MySQL query
    var values = [];

    // For each temperature value, store its output to values array
    for(var i = 0; i < actualTemp.length; i++) {
    values.push([roomNames[i] , actualTemp[i],
                minTemp[i], maxTemp[i],
                actualHumid[i], minHumid[i],
                maxHumid[i], formatDay, 
                res.locals.user.id]);
    }

    db.query("insert into 21TEMP01a (room_name, actual_temperature, min_temperature, max_temperature, actual_humidity, min_humidity, max_humidity, time, user) values ?", [values], (error, result) => {
        if(error) {
            console.log(error);
       }
       else{
           res.redirect('/reports/daily');
       }
     });
}

Front-End

<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z" crossorigin="anonymous">

<div class="container mt-4">


    <h3>Form:</h3>
    <form id="form" class="mt-4 mb-4" action="/reports_send/21-TEMP-01a" method="POST">

        <div style="border: 1px solid black; padding: 40px; border-radius: 25px;">

            <h4>Select Room</h4>
            <div id="RoomSelect">
                <select id="RoomMenu" class="form-control mb-4"> 
                    <!-- Drying Room 1 -->
                    <option value="dry-1">Drying Room 1</option>
                    <!-- Drying Room 2 -->
                    <option value="dry-2">Drying Room 2</option>
                    <!-- Dry Store-->
                    <option value="dry-3">Dry Store</option>
                </select>
            </div>
            
            <div id="RoomInputs">

                <!-- Drying Room 1 -->
                <div class="form-group" id="dry-1">
                    <!-- Title -->
                    <h4>Drying Room 1</h4>
                    <input type="hidden" name="dryingroom1" value="Drying Room 1">

                    <!-- All temperatures -->
                    <div class="temperatures">
                     
                        <label>Temperature °C - <strong>Actual</strong></label>
                        <input type="number" class="form-control" name="actualtemp1" step=0.01>

                      
                        <label>Temperature °C - <strong>Minimum</strong></label>
                        <input type="number" class="form-control" name="mintemp1" step=0.01>

                    
                        <label>Temperature °C - <strong>Maximum</strong></label>
                        <input type="number" class="form-control" name="maxtemp1" step=0.01>
                    </div>
                    <br>
                    <br>
                    <!-- All humidity -->
                    <div class="humidity">
                         
                        <label>Relative Humidity - <strong>Actual</strong></label>
                        <input type="number" class="form-control" name="actualhumid1">
                        
                        <label>Relative Humidity - <strong>Minimum</strong></label>
                        <input type="number" class="form-control" name="minhumid1">
                         
                        <label>Relative Humidity - <strong>Maximum</strong></label>
                        <input type="number" class="form-control" name="maxhumid1">
                    </div>
                </div>


                <!-- Drying Room 2 -->
                <div class="form-group" id="dry-2">
                    <!-- Title -->
                    <h4>Drying Room 2</h4>
                    <input type="hidden" name="dryingroom2" value="Drying Room 2">

                    <!-- All temperatures -->
                    <div class="temperatures">
                       
                        <label>Temperature °C - <strong>Actual</strong></label>
                        <input type="number" class="form-control" name="actualtemp2" step=0.01>

                       
                        <label>Temperature °C - <strong>Minimum</strong></label>
                        <input type="number" class="form-control" name="mintemp2" step=0.01>

                       
                        <label>Temperature °C - <strong>Maximum</strong></label>
                        <input type="number" class="form-control" name="maxtemp2" step=0.01>
                    </div>
                    <br>
                    <br>
                    <!-- All humidity -->
                    <div class="humidity">
                         
                        <label>Relative Humidity - <strong>Actual</strong></label>
                        <input type="number" class="form-control" name="actualhumid2">
                        
                        <label>Relative Humidity - <strong>Minimum</strong></label>
                        <input type="number" class="form-control" name="minhumid2">
                         
                        <label>Relative Humidity - <strong>Maximum</strong></label>
                        <input type="number" class="form-control" name="maxhumid2">
                    </div>
                </div>

                <!-- Dry Store -->
                <div class="form-group" id="dry-3">
                    <!-- Title -->
                    <h4>Dry Store</h4>
                    <input type="hidden" name="dryingroom3" value="Dry Store">

                    <!-- All temperatures -->
                    <div class="temperatures">
                        
                        <label>Temperature °C - <strong>Actual</strong></label>
                        <input type="number" class="form-control" name="actualtemp3" step=0.01>

                        
                        <label>Temperature °C - <strong>Minimum</strong></label>
                        <input type="number" class="form-control" name="mintemp3" step=0.01>

                        
                        <label>Temperature °C - <strong>Maximum</strong></label>
                        <input type="number" class="form-control" name="maxtemp3" step=0.01>
                    </div>
                    <br>
                    <br>
                    <!-- All humidity -->
                    <div class="humidity">
                         
                        <label>Relative Humidity - <strong>Actual</strong></label>
                        <input type="number" class="form-control" name="actualhumid3">
                         
                        <label>Relative Humidity - <strong>Minimum</strong></label>
                        <input type="number" class="form-control" name="minhumid3">
                         
                        <label>Relative Humidity - <strong>Maximum</strong></label>
                        <input type="number" class="form-control" name="maxhumid3">
                    </div>
                </div>

                <div id="errors" class="mt-2 alert alert-danger" style="opacity: 0; transition: all .5s;">
                    <p>Please complete all required fields</p>
                </div>

                <button id="submit-btn" class="btn btn-primary">Submit</button>
            </div>
            
        </div>
    </form>

</div>


<!-- Errors -->

<div id="myModal" class="modal" tabindex="-1" role="dialog">
  <div class="modal-dialog" role="document">
    <div class="modal-content">
      <div class="modal-header">
        <h5 class="modal-title">Targets not met</h5>
        <button type="button" class="close" data-dismiss="modal" aria-label="Close">
          <span aria-hidden="true">&times;</span>
        </button>
      </div>
      <div class="modal-body">
        <p>Some temperatures or humidity values have not met their targets.</p>
        <p>- Re-check or continue submitting current data.</p>
      </div>
      <div class="modal-footer">
        <button id="submit-email" type="button" class="btn btn-primary">Submit</button>
        <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
      </div>
    </div>
  </div>
</div>

<script>

// Store DOM Strings
var DOMStrings = {
    room_options: '#RoomMenu'
};

// On selected option, show specific div element
showActiveElement = () => {
    

    for(const option of document.querySelector(DOMStrings.room_options).options) {
        document.querySelector(`#${option.value}`).style.display = "none";
    }

    if(document.querySelector(DOMStrings.room_options).value === 'dry-1') {
        document.querySelector('#dry-1').style.display = "block";
    } else if (document.querySelector(DOMStrings.room_options).value === 'dry-2') {
        document.querySelector('#dry-2').style.display = "block";
    } else if (document.querySelector(DOMStrings.room_options).value === 'dry-3') {
        document.querySelector('#dry-3').style.display = "block";
    }

}



// Show selected div element from options
document.querySelector(DOMStrings.room_options).addEventListener('change', () => {
    showActiveElement();
});


// Validate data
document.getElementById("form").addEventListener("submit", (e) => {
        
    const inputs = document.querySelectorAll('#form input');
    
    let bool;
        // 1. Check if input fields are empty
        const empty = [].filter.call(inputs, e => e.value === "");

        let notEmpty;

        if(empty.length === 0) {
            notEmpty = true;
        } else {
            e.preventDefault();

            document.getElementById('errors').style.opacity = 1;
     
            empty.forEach(element => {
                element.style.borderColor = "red";
                element.placeholder = "Required";
                element.addEventListener("input", (e) => {
                    if(element.value === "") {
                        bool = false;
                        element.style.borderColor = "red";
                        element.placeholder = "Required";
                    } else {
                        element.style.borderColor = "#fff";
                    }

                    const empty = [].filter.call(inputs, e => e.value === "");

                    if(empty.length === 0) {
                        document.getElementById('errors').style.opacity = 0;
                    } else {
                        document.getElementById('errors').style.opacity = 1;
                    }
                });
            });
        }

    // Validate Temperature and humidity values
    if(notEmpty == true) {
        for (var i = 0; i < inputs.length; i++) {

            // Validate Temperatures for Drying room 1 & 2
            if(inputs[i].name.match(/^(actual|min|max)-temp-(1|2)$/)) {
                validateTempDryingRoom(parseFloat(inputs[i].value), inputs[i], e);
            }

            // Validate Humidity for Drying room 1 & 2
            if(inputs[i].name.match(/^(actual|min|max)humid(1|2)$/)) {
                validateHumidityDryingRoom(parseFloat(inputs[i].value), inputs[i], e);
            }

            // Validate Temp. for Dry Store
            if(inputs[i].name.match(/^(actual|min|max)temp(3)$/)) {
                validateTempDryStore(parseFloat(inputs[i].value), inputs[i], e);
            }

            // Validate humidity for Dry Store
            if(inputs[i].name.match(/^(actual|min|max)humid(3)$/)) {
                validateHumidityDryStore(parseFloat(inputs[i].value), inputs[i], e);
            }
        }
    }
});


function validateTempDryingRoom(value, item, e) {

    if(value < 39.4 || value > 49) {
        e.preventDefault();
        item.style.backgroundColor = 'red';
        $("#myModal").modal();
    } else {
        item.style.backgroundColor = '#fff';
    }
}

function validateHumidityDryingRoom(value, item ,e) {

    if(value < 14 || value > 30) {
        e.preventDefault();
        item.style.backgroundColor = 'red';
        $("#myModal").modal(); 
    } else {
        item.style.backgroundColor = '#fff';
    }
}

function validateTempDryStore(value, item, e) {
    if(value < 10 || value > 27.2) {
        e.preventDefault();
        item.style.backgroundColor = 'red';
        $("#myModal").modal();
    } else {
        item.style.backgroundColor = '#fff';
    }
}

function validateHumidityDryStore(value, item ,e) {

    if(value < 40 || value > 70) {
        e.preventDefault();
        item.style.backgroundColor = 'red';
        $("#myModal").modal(); 
    } else {
        item.style.backgroundColor = '#fff';
    }
}

document.getElementById('submit-email').addEventListener('click', () => {
    const form = document.getElementById('form');
    form.submit();
});


// On load
window.onload = () => {
    showActiveElement();
}


</script>

\$\endgroup\$

1 Answer 1

3
\$\begingroup\$

First, your code seems globally ok, and much of what I'll write here are details. Also of course, it does reflect my personnal opinion. While I try not to discuss points about my personnal opinion, but more generic matters, my personnals opinion may impact what I consider generic matters or not.

About comments

Far from me the idea to discourage you to comment your code, but comments may not always be a good idea.

You've probably learnt that commenting code is good, it feels obvious, so obvious that you don't even understand why commenting may harm your code. The only drawback you probably see to commenting your code may be that you took time to do it.

Well, if you never go back to your code again, you don't need to comment it. Well most of code are "maintained" and evolve anyway. And that's the problem. In general, when the code change, the comments around the code tends not to change. When there is a problem in the code, you'll correct the code until the problem is resolved. When there is a problem in a comment, nothing will be done because no one will notice.

Also comments should be meaningful. Usually you can replace some useless comments by correct variable/function/classe names. An example (that is much worse than your code, but to show the real difference)

// store an empty array in the variable a
let a = [];

// [...]

// if the string k starts with "at", append the content of the value v at the end of the array a
if (k.startsWith("at")) {
    a.push(v);
}

And now compare it to the following uncommented code:

let actualTemperatureArray = [];

// [...]

if (queryParameterKey.startsWith("actualTemperature")) {
    actualTemperatureArray.push(value);
}

The idea is that the name of your variable should reflect what the variable does. And if it's it, you don't need to comment it. Same for the "parsing" code. The fact that you look at the query parameter key and look if it starts with a certain string is obvious, it's literally what the code is saying. An interesting comment would not be what's your doing in, but why you're doing it. If it's not obvious. If it's obvious perhaps the comment is useless.

But comment your tricks. For example, if you're skipping one value in a loop because "the first value should be ignored", this is the kind of thing that should be commented. There is a trick here that the future reader must know.

But still you may want to comment your variable declaration. So if you do so, at least use JSDoc (https://jsdoc.app/). JSDoc let you add some static type definition that:

  • Can be used by type checkers to validate javascript like static type languages
  • Is used by modern IDE (Visual Code, WebStorm, etc.) to provide information about code.

Now let's study examples from your code.

    // Array to store actual temperature
    var actualTemp = [];

Do you thing actualTemp is enough for someone to understand what the variable does ? I'm not saying it isn't. But you have to decide. I'll take a conservative point of view, and consider that actualTemperatureArray is better (but know better the context, and perhaps in your field you thing that temp is enough, and nobody will think that in that context, it may mean temporary).

And because actualTemperatureArray carry all the meaning you need, a comment is not necessary.

    var actualTemperatureArray = [];

Of course, you'll store actual temperature in that array. No need to say it.

But, if you want to say it, use JSDoc.

    /** @type {string[]} Array to store actual temperature */
    var actualTemperatureArray = [];

In your code, VS Code will show me the following tooltip, when I put my cursor over actualTemp:

(local var) actualTemp: any[]

So I know that this variable a local one, and it's an array of I don't know what.

In the last example, will show me the following tooltip, when I put my cursor over actualTemperatureArray:

(local var) actualTemperatureArray: string[]
@type — {string[]} Array to store actual temperature

This said, I don't want to discourage you from commenting, but to think about what you can bring to the reader that the code is not obiously providing. If you are just repeating what the code says, perhaps the comment is not necessary. If you bring insight about why you did this, it's probably an helpful comment.

Repetitions

The following block tend to have a lot of similar lines:

        // For each key that starys with ActualTemp store into array
        if (key.startsWith("actualtemp")) {
            actualTemperatureArray.push(value);
        }

        // minTemp
        if (key.startsWith("mintemp")) {
            minimalTemperatureArray.push(value);
        }

        // maxTemp
        if (key.startsWith("maxtemp")) {
            maximalTemperatureArray.push(value);
        }

        // actualHumidity
        if (key.startsWith("actualhumid")) {
            actualHumidityArray.push(value);
        }

        // minHumidity
        if (key.startsWith("minhumid")) {
            minimalHumidityArray.push(value);
        }

        // maxHumidity
        if (key.startsWith("maxhumid")) {
            maximalHumidityArray.push(value);
        }

        // Room Names
        if (key.startsWith("dryingroom")) {
            roomNames.push(value);
        }

It may be a good idea to factorize that.

Each block manipulate a different variable. So let's create an object containing all those variables, so we can be more generic when accessing those array variables.

We need a data structure to "describe" the data we need. I consider that names like "actualtemp" or "mintemp" are part of the protocol and can't be changed.

I could use that as index, but I'll use more explicit names, but that part can be simplified.

We first create a structure describing the data we need (note that the order is important, it's the one in the query, as I'll reuse that order later to create the query).

    /**
     * @type {Object.<string, string>} The prefix of all body.req referenced by the name of the parameter
     */
    var paramKeyPrefixesByParamName = {
        roomName: "dryingroom",
        actualTemperature: "actualtemp",
        minimalTemperature: "mintemp",
        maximalTemperature: "maxtemp",
        actualHumidity: "actualhumid",
        minimalHumidity: "minhumid",
        maximalHumidity: "maxhumid",
    };
    /** @type{string[]} The parameter names */
    const parameterNames = Object.keys(paramKeyPrefixesByParamName);

Now let's create the arrays:

    /**
     * @type {Object.<string, string[]>} The array of values for each parameter, indexed by the name of the parameter
     */
    var valueArraysByParamName = {};

I haven't created the arrays here, I create them later. I could have done it here.

    // Loop thorugh each req.body values
    for (var key in req.body) {
        // Store req.body key to value var
        var value = req.body[key];

        // We iterate over all the
        // parameter names
        // (roomName, actualTemperature, ...)
        parameterNames.forEach((parameterName) => {
            // We extract the prefix
            // from the parameter names
            // (dryingroom, actualtemp, ...)
            const prefix = paramKeyPrefixesByParamName[parameterName];
            if (key.startsWith(prefix)) {
                // We make sure the array exists.
                // If it doesn't exist, we create it.
                if (! valueArraysByParamName[parameterName]) {
                    valueArraysByParamName[parameterName] = [];
                }
                // We append the value in the correct array.
                valueArraysByParamName[parameterName].push(value);
            }
        })
    }

We can now create the query:

    /** @type {string[][]} An array to create custom MySQL query */
    var values = [];

    // For each temperature value, store the values associated to that temperature
    for (var i = 0; i < actualTemperatureArray.length; i++) {
        values.push([
            ...parameterNames.map((parameterName)=>valueArraysByParamName[parameterName][i]),
            formatDay,
            res.locals.user.id
        ]);
    }

So now, the server code look like:

// 21-TEMP-01a
exports.TEMP01A21 = async function (req, res) {

    /**
     * @type {Object.<string, string>} The prefix of all body.req referenced by the name of the parameter
     */
    var paramKeyPrefixesByParamName = {
        roomName: "dryingroom",
        actualTemperature: "actualtemp",
        minimalTemperature: "mintemp",
        maximalTemperature: "maxtemp",
        actualHumidity: "actualhumid",
        minimalHumidity: "minhumid",
        maximalHumidity: "maxhumid",
    }
    /**
     * @type {Object.<string, string[]>} The array of values for each parameter, indexed by the name of the parameter
     */
    var valueArraysByParamName = {};

    // Loop thorugh each req.body values
    for (var key in req.body) {
        // Store req.body key to value var
        var value = req.body[key];

        // We iterate over all parameter names (roomName, actualTemperature, ...)
        Object.keys(paramKeyPrefixesByParamName).forEach((parameterName) => {
            // We extract the prefix from the parameter name (dryingroom, actualtemp, ...)
            const prefix = paramKeyPrefixesByParamName[parameterName];
            if (key.startsWith(prefix)) {
                // We make sure the array exists. If it doesn't exist, we create it.
                if (! valueArraysByParamName[parameterName]) {
                    valueArraysByParamName[parameterName] = [];
                }
                // We append the value in the correct array.
                valueArraysByParamName[parameterName].push(value);
            }
        })
    }


    // Get todays date
    var today = new Date();
    // Format the date
    var formatDay = today.toISOString().substring(0, 10);

    /** @type {string[][]} An array to create custom MySQL query */
    var values = [];

    // For each temperature value, store the values associated to that temperature
    for (var i = 0; i < actualTemperatureArray.length; i++) {
        values.push([
            ...Object.keys(paramKeyPrefixesByParamName).map((parameterName)=>valueArraysByParamName[parameterName][i]),
            formatDay,
            res.locals.user.id
        ]);
    }

    db.query("insert into 21TEMP01a (room_name, actual_temperature, min_temperature, max_temperature, actual_humidity, min_humidity, max_humidity, time, user) values ?", [values], (error, result) => {
        if (error) {
            console.log(error);
        }
        else {
            res.redirect('/reports/daily');
        }
    });
}

Repetition of the front side

In the front side you have some repetitions:

function validateTempDryingRoom(value, item, e) {

    if(value < 39.4 || value > 49) {
        e.preventDefault();
        item.style.backgroundColor = 'red';
        $("#myModal").modal();
    } else {
        item.style.backgroundColor = '#fff';
    }
}

function validateHumidityDryingRoom(value, item ,e) {

    if(value < 14 || value > 30) {
        e.preventDefault();
        item.style.backgroundColor = 'red';
        $("#myModal").modal(); 
    } else {
        item.style.backgroundColor = '#fff';
    }
}

function validateTempDryStore(value, item, e) {
    if(value < 10 || value > 27.2) {
        e.preventDefault();
        item.style.backgroundColor = 'red';
        $("#myModal").modal();
    } else {
        item.style.backgroundColor = '#fff';
    }
}

function validateHumidityDryStore(value, item ,e) {

    if(value < 40 || value > 70) {
        e.preventDefault();
        item.style.backgroundColor = 'red';
        $("#myModal").modal(); 
    } else {
        item.style.backgroundColor = '#fff';
    }
}

It look like you're doing the same thing again and again.

Let's rewrite this.

function createValidateElement(minValue, maxValue) {
    return function (value, item, e) {

        if(value < minValue || value > maxValue) {
            e.preventDefault();
            item.style.backgroundColor = 'red';
            $("#myModal").modal();
        } else {
            item.style.backgroundColor = '#fff';
        }
    }
}

const validateTempDryingRoom = createValidateElement(39.4, 49);
const validateHumidityDryingRoom = createValidateElement(14, 30);
const validateTempDryStore = createValidateElement(10, 27.2);
const validateHumidityDryStore = createValidateElement(40, 70);

I created a function that create a function.

Be careful, because validateTempDryingRoom, validateHumidityDryingRoom, validateTempDryStore, validateHumidityDryStore are now classical variable and not functions, they should be declared before being used.

But still, the usage of those validators is also a repetition:

            // Validate Temperatures for Drying room 1 & 2
            if(inputs[i].name.match(/^(actual|min|max)-temp-(1|2)$/)) {
                validateTempDryingRoom(parseFloat(inputs[i].value), inputs[i], e);
            }

            // Validate Humidity for Drying room 1 & 2
            if(inputs[i].name.match(/^(actual|min|max)humid(1|2)$/)) {
                validateHumidityDryingRoom(parseFloat(inputs[i].value), inputs[i], e);
            }

            // Validate Temp. for Dry Store
            if(inputs[i].name.match(/^(actual|min|max)temp(3)$/)) {
                validateTempDryStore(parseFloat(inputs[i].value), inputs[i], e);
            }

            // Validate humidity for Dry Store
            if(inputs[i].name.match(/^(actual|min|max)humid(3)$/)) {
                validateHumidityDryStore(parseFloat(inputs[i].value), inputs[i], e);
            }

So we need a data structure that describe the items being repeated.

const dryDatas = {
    TempDryingRoom: {
        pattern: /^(actual|min|max)-temp-(1|2)$/,
        minValue: 39.4,
        maxValue: 49,
    },
    HumidityDryingRoom: {
        pattern: /^(actual|min|max)humid(1|2)$/,
        minValue: 14,
        maxValue: 30,
    },
    TempDryStore: {
        pattern: /^(actual|min|max)temp(3)$/,
        minValue: 10,
        maxValue: 27.2,
    },
    HumidityDryStore: {
        pattern: /^(actual|min|max)humid(3)$/,
        minValue: 40,
        maxValue: 70,
    },
}

And then we can create the validators:

const dryDataValidators = Object.fromEntries(Object.entries(dryDatas).map(([dryDataKey,dryDataValue])=>[dryDataKey, createValidateElement(dryDataValue.min, dryDataValue.max)]));

If you think it unreadable, you can use some more readable:

const dryDataValidators = {};
for (let dryDataKey of Object.keys(dryDatas)) {
    const dryDataValue = dryDatas[dryDataKey];
    dryDataValidators[dryDataKey] = createValidateElement(dryDataValue.min, dryDataValue.max);
}

It does the same thing...

And then replace

    // Validate Temperature and humidity values
    if(notEmpty == true) {
        for (var i = 0; i < inputs.length; i++) {

            // Validate Temperatures for Drying room 1 & 2
            if(inputs[i].name.match(/^(actual|min|max)-temp-(1|2)$/)) {
                validateTempDryingRoom(parseFloat(inputs[i].value), inputs[i], e);
            }

            // Validate Humidity for Drying room 1 & 2
            if(inputs[i].name.match(/^(actual|min|max)humid(1|2)$/)) {
                validateHumidityDryingRoom(parseFloat(inputs[i].value), inputs[i], e);
            }

            // Validate Temp. for Dry Store
            if(inputs[i].name.match(/^(actual|min|max)temp(3)$/)) {
                validateTempDryStore(parseFloat(inputs[i].value), inputs[i], e);
            }

            // Validate humidity for Dry Store
            if(inputs[i].name.match(/^(actual|min|max)humid(3)$/)) {
                validateHumidityDryStore(parseFloat(inputs[i].value), inputs[i], e);
            }
        }
    }

by

    // Validate Temperature and humidity values
    if(notEmpty == true) {
        for (var i = 0; i < inputs.length; i++) {
            // Iterate over all type of dryDatas (TempDryingRoom, HumidityDryingRoom, TempDryStore, ...)
            for (let dryDataKey of Object.keys(dryDatas)) {
                const pattern = dryDatas[dryDataKey].pattern;
                const validator = dryDataValidators[dryDataKey];
                if(inputs[i].name.match(pattern)) {
                    validator(parseFloat(inputs[i].value), inputs[i], e);
                }
            }
        }
    }
\$\endgroup\$
1
  • \$\begingroup\$ I realized in the or (var i = 0; i < actualTemperatureArray.length; i++) { this actualTemperatureArray does not exist. \$\endgroup\$ Commented Sep 30, 2020 at 11:24

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.