The Web Design Group

... Making the Web accessible to all.

Welcome Guest ( Log In | Register )

 
Reply to this topicStart new topic
> Get the number of edited inputs
RainLover
post Mar 5 2019, 08:19 AM
Post #1


Advanced Member
****

Group: Members
Posts: 216
Joined: 16-November 09
Member No.: 10,346



Scenario

Every semester my students need to take at least one test. The following form gives the right average grade of a student:
CODE
<!DOCTYPE html>
<html lang="en">
  <head>
    <title>Average Grade</title>
  </head>
  <body>
   <form>
Math: <input type="number" id="test1">
    <input type="number" id="test2">
    <input type="number" id="test3">
    <output id="average"></output>
    <br>
    <input type="button" value="Calculate" id="calcBtn">
   </form>
   <script>
    document.getElementById('calcBtn').addEventListener('click', function() {
     var test1 = document.getElementById('test1').value;
     var test2 = document.getElementById('test2').value;
     var test3 = document.getElementById('test3').value;
     var average = document.getElementById('average');
     average.value = (Number(test1)+Number(test2)+Number(test3)) / 3;
    });
   </script>
  </body>
</html>

The problem is it works right only if all the fields are edited. If the student doesn't take some tests, the average grade won't show the right value. I know it's because of dividing by the fixed number 3 when it calculates the average grade:
CODE
average.value = (Number(test1)+Number(test2)+Number(test3)) / 3;


Question

What is a simple approach to get the number of changed input fields?
User is offlinePM
Go to the top of the page
Toggle Multi-post QuotingQuote Post
Christian J
post Mar 5 2019, 03:44 PM
Post #2


.
********

Group: WDG Moderators
Posts: 8,238
Joined: 10-August 06
Member No.: 7



QUOTE(RainLover @ Mar 5 2019, 02:19 PM) *

If the student doesn't take some tests, the average grade won't show the right value. I know it's because of dividing by the fixed number 3 when it calculates the average grade:

You mean the number of entered test fields are allowed to vary? Then you might use say getElementsByTagName to count the number of form fields with non-empty values, and divide them with the the length property.

User is offlinePM
Go to the top of the page
Toggle Multi-post QuotingQuote Post
RainLover
post Mar 5 2019, 10:34 PM
Post #3


Advanced Member
****

Group: Members
Posts: 216
Joined: 16-November 09
Member No.: 10,346



QUOTE(Christian J @ Mar 5 2019, 03:44 PM) *

QUOTE(RainLover @ Mar 5 2019, 02:19 PM) *

If the student doesn't take some tests, the average grade won't show the right value. I know it's because of dividing by the fixed number 3 when it calculates the average grade:

You mean the number of entered test fields are allowed to vary? Then you might use say getElementsByTagName to count the number of form fields with non-empty values, and divide them with the the length property.


Dear Christian,
I'm afraid I don't know how to do it. Would you mind helping me with this:
QUOTE
count the number of form fields with non-empty values


This post has been edited by RainLover: Mar 5 2019, 10:34 PM
User is offlinePM
Go to the top of the page
Toggle Multi-post QuotingQuote Post
Christian J
post Mar 6 2019, 11:55 AM
Post #4


.
********

Group: WDG Moderators
Posts: 8,238
Joined: 10-August 06
Member No.: 7



Here's an idea:

CODE
Math:
<input type="number" class="test">
<input type="number" class="test">
<input type="number" class="test">

Average grade:
<output id="average"></output>
<br>
<input type="button" value="Calculate" id="calcBtn">

<script>
document.getElementById('calcBtn').addEventListener('click', function()
{
    // any number of elements
    var test_input=document.getElementsByClassName('test');

    var grades_arr=new Array();

    for(var i=0; i<test_input.length; i++)
    {
        var val=test_input[i].value;
        //alert('Value: '+val+'\nType: '+typeof val);

        if(val.length>0) // at least one character must be entered
        {
            val=val*1; // try to convert string type of form field  to number

            if(!isNaN(val) && typeof val=='number') // try to check if type conversion was successful
            {
                grades_arr.push(val); // add valid number values to array
                //alert('Row '+i+' is a number');
            }
            else
            {
                //alert('Row '+i+' is not a  number');
            }
        }
        else
        {
            //alert('Row '+i+' is empty');
        }
    }

    // calculate average
    if(grades_arr.length>0) // at least one form field must be filled in correctly by user
    {
        var grades=0;
        for(var i=0; i<grades_arr.length; i++)
        {
            grades=grades+grades_arr[i];
        }
        grades=grades/grades_arr.length;
        document.getElementById('average').value=grades;
    }
    else
    {
        //alert('No valid data was entered');
    }
}
);
</script>

You can use any number of form fields with the CLASS "test", and the user can fill in as many of them as he wants. I haven't added any rounding of the resulting average.

There are a few gothas about the type conversion though. Currently it seems only IE11 and Chrome-based browsers prevent the user from entering non-digit characters in number INPUTs. Edge and Firefox still seem to allow it, but will consider such user data as an empty string. Older browsers that don't support HTML5 number INPUTs will regard the form fields as text INPUTs, and pass along the whole string to the javascript.

Despite the above, javascript still considers INPUT data to be of "string" type, even when numbers have been entered by the user into a number INPUT. I tried to consider all the scenarios in the script, but don't trust me on this.
User is offlinePM
Go to the top of the page
Toggle Multi-post QuotingQuote Post
pandy
post Mar 6 2019, 03:40 PM
Post #5


Don't like donuts. Don't do MySpace.
********

Group: WDG Moderators
Posts: 18,402
Joined: 9-August 06
Member No.: 6



Is checking for NaN really needed? Provided browser support is there I think input type="number" does its own validation and sends nothing if the input isn't a number. This sounds like a controlled environment so... unsure.gif
User is offlinePM
Go to the top of the page
Toggle Multi-post QuotingQuote Post
Christian J
post Mar 6 2019, 04:52 PM
Post #6


.
********

Group: WDG Moderators
Posts: 8,238
Joined: 10-August 06
Member No.: 7



QUOTE(pandy @ Mar 6 2019, 09:40 PM) *

Is checking for NaN really needed? Provided browser support is there I think input type="number" does its own validation and sends nothing if the input isn't a number. This sounds like a controlled environment so... unsure.gif

I agree, but thought it didn't hurt to include it.
User is offlinePM
Go to the top of the page
Toggle Multi-post QuotingQuote Post
pandy
post Mar 7 2019, 05:52 AM
Post #7


Don't like donuts. Don't do MySpace.
********

Group: WDG Moderators
Posts: 18,402
Joined: 9-August 06
Member No.: 6



No, it doesn't. I asked mainly because I wasn't sure I had understood this right.
User is offlinePM
Go to the top of the page
Toggle Multi-post QuotingQuote Post
Christian J
post Mar 7 2019, 06:10 AM
Post #8


.
********

Group: WDG Moderators
Posts: 8,238
Joined: 10-August 06
Member No.: 7



Then again NaN is a tricky property that I don't understand very well, for example it can sometimes be of the type "number".

isNaN() or Number.isNaN() is supposedly better: https://developer.mozilla.org/en-US/docs/We...l_Objects/isNaN
User is offlinePM
Go to the top of the page
Toggle Multi-post QuotingQuote Post
Christian J
post Mar 7 2019, 10:56 AM
Post #9


.
********

Group: WDG Moderators
Posts: 8,238
Joined: 10-August 06
Member No.: 7



Seems IE11 does need checking with isNaN(), since the browser lets through user values like "1a" (but not "a1"). Also IE11 doesn't support the OUTPUT element.

Firefox does warn the user of invalid form field input (by creating a red selection rectangle), but not until the user clicks outside the field. Edge never gives any warning at all.
User is offlinePM
Go to the top of the page
Toggle Multi-post QuotingQuote Post
pandy
post Mar 7 2019, 05:30 PM
Post #10


Don't like donuts. Don't do MySpace.
********

Group: WDG Moderators
Posts: 18,402
Joined: 9-August 06
Member No.: 6



Always IE, eh? Still.

Anyway, I have this page bookmarked.
http://adripofjavascript.com/blog/drips/th...javascript.html

I don't understand the discussion, because when he for instance wants to demonstrate why isNaN isn't reliable, the example he gives returns the wanted result. wacko.gif But, the solution at the bottom of the page is interesting!
User is offlinePM
Go to the top of the page
Toggle Multi-post QuotingQuote Post
Christian J
post Mar 8 2019, 06:16 AM
Post #11


.
********

Group: WDG Moderators
Posts: 8,238
Joined: 10-August 06
Member No.: 7



I didn't understand that example either.

As an alternative to the NaN confusion one might use a regular expression to look for non-numerical characters, and then flag an error. (One shouldn't just strip non-numbers out though, since then something like "1foo2" might be changed to "12".)
User is offlinePM
Go to the top of the page
Toggle Multi-post QuotingQuote Post
Christian J
post Mar 8 2019, 02:12 PM
Post #12


.
********

Group: WDG Moderators
Posts: 8,238
Joined: 10-August 06
Member No.: 7



Here's one with a regex instead of isNaN:

CODE
Math:
<input type="number" class="test">
<input type="number" class="test">
<input type="number" class="test">

Average grade:
<span id="average"></span>
<br>
<input type="button" value="Calculate" id="calcBtn">

<script>
document.getElementById('calcBtn').addEventListener('click', function()
{
    // any number of elements
    var test_input=document.getElementsByClassName('test');

    var grades_arr=new Array();

    for(var i=0; i<test_input.length; i++)
    {
        var val=test_input[i].value;

        // remove numerical characters from sample, to see if any invalid characters remain
        var invalid=val.replace(/[0-9]/g,'');

        if(val.length>0 && invalid.length==0) // at least one character must be entered, but no invalid characters
        {
            val=1*val; // convert to number type
            grades_arr.push(val); // add valid number values to array
        }
        else
        {
            //alert('Field '+i+' is empty or invalid');
        }
    }

    // calculate average
    if(grades_arr.length>0) // at least one form field must be filled in correctly by user
    {
        var grades=0;
        for(var i=0; i<grades_arr.length; i++)
        {
            grades=grades+grades_arr[i];
        }
        grades=grades/grades_arr.length;
        document.getElementById('average').innerHTML=grades;
    }
    else
    {
        //alert('No valid data was entered');
    }
}
);
</script>
User is offlinePM
Go to the top of the page
Toggle Multi-post QuotingQuote Post
RainLover
post Mar 9 2019, 10:41 AM
Post #13


Advanced Member
****

Group: Members
Posts: 216
Joined: 16-November 09
Member No.: 10,346



QUOTE(Christian J @ Mar 8 2019, 02:12 PM) *

Here's one with a regex instead of isNaN:

CODE
Math:
<input type="number" class="test">
<input type="number" class="test">
<input type="number" class="test">

Average grade:
<span id="average"></span>
<br>
<input type="button" value="Calculate" id="calcBtn">

<script>
document.getElementById('calcBtn').addEventListener('click', function()
{
    // any number of elements
    var test_input=document.getElementsByClassName('test');

    var grades_arr=new Array();

    for(var i=0; i<test_input.length; i++)
    {
        var val=test_input[i].value;

        // remove numerical characters from sample, to see if any invalid characters remain
        var invalid=val.replace(/[0-9]/g,'');

        if(val.length>0 && invalid.length==0) // at least one character must be entered, but no invalid characters
        {
            val=1*val; // convert to number type
            grades_arr.push(val); // add valid number values to array
        }
        else
        {
            //alert('Field '+i+' is empty or invalid');
        }
    }

    // calculate average
    if(grades_arr.length>0) // at least one form field must be filled in correctly by user
    {
        var grades=0;
        for(var i=0; i<grades_arr.length; i++)
        {
            grades=grades+grades_arr[i];
        }
        grades=grades/grades_arr.length;
        document.getElementById('average').innerHTML=grades;
    }
    else
    {
        //alert('No valid data was entered');
    }
}
);
</script>



Many thanks for the answers! 🌹
User is offlinePM
Go to the top of the page
Toggle Multi-post QuotingQuote Post
Christian J
post Mar 9 2019, 12:43 PM
Post #14


.
********

Group: WDG Moderators
Posts: 8,238
Joined: 10-August 06
Member No.: 7



You're welcome!
User is offlinePM
Go to the top of the page
Toggle Multi-post QuotingQuote Post

Reply to this topicStart new topic
1 User(s) are reading this topic (1 Guests and 0 Anonymous Users)
0 Members:

 



- Lo-Fi Version Time is now: 18th October 2019 - 01:25 PM