1

I literally started trying to teach myself javascript less than 48 hours ago. Outside of just wanting to learn it I also have a small personal project I'm working on and using as sort of my working learn as I go example. But I've hit a problem, which I'm sure is rather basic, I'm just hampered by lack of much javascript knowledge.

Basically it is just an averaging problem.
There are going to be 4 inputs fields with the 4th being a rounded to the nearest whole number average of the first three fields.
This 4 field configuration is going to get used multiple times on the page.
I want it to work in "real time" and not with a calculate button so I'm assuming "onKeyup" is needed. (no validation of any kind is needed or submit or saving or anything)

The only code I've been able to get close is really really ugly, long, and convoluted. I can't help but think there is a very simple way to do it and just get the same function to apply to each grouping of inputs. It will look like below but probably much longer.

some text
<input id="a" type="number" /><br/>
<input id="b" type="number" /><br/>
<input id="c" type="number" /><br/>
<input id="final" value="0" disabled />

some text
<input id="a" type="number" /><br/>
<input id="b" type="number" /><br/>
<input id="c" type="number" /><br/>
<input id="final" value="0" disabled />

Thanks in advance. This is part of a larger problem but I've tried to strip it down to it's essence and seeing it work and understanding it will go a long way to helping me solve some other problems.

R.Decline
  • 11
  • 2

5 Answers5

1

To start with use a different markup, there should only be a single id per page, so use classes, it make it easier to target everything too. Also if the effect is to use the last input as a display you can use readonly instead of disabled

<p>some text</p>
<div class="group">
    <input class="a" type="number" /><br/>
    <input class="b" type="number" /><br/>
    <input class="c" type="number" /><br/>
    <input class="final" value="0" readonly />
</div>
<p>some text</p>
<div class="group">
    <input class="a" type="number" /><br/>
    <input class="b" type="number" /><br/>
    <input class="c" type="number" /><br/>
    <input class="final" value="0" readonly />
</div>​

Here is an example done in jquery

$(function() {
    $('.group input').on('click', function() {
        var count = parseInt($(this).val()) || 0;
        $(this).siblings(':not(.final)').each(function() {
            if ($(this).val()) count = count + parseInt($(this).val());
        });
        $(this).siblings('.final').eq(0).val(count);
    });
});

And the demo is here: http://jsfiddle.net/4S4Vp/1/

GillesC
  • 10,647
  • 3
  • 40
  • 55
1

This should be understandable for your level. The second set of inputs will be named a-2 with calc(2) and so on.

<input id="a-1" type="number" onkeyup="calc(1)" value="0" /><br/>
<input id="b-1" type="number" onkeyup="calc(1)" value="0" /><br/>
<input id="c-1" type="number" onkeyup="calc(1)" value="0" /><br/>
<input id="final-1" value="0" disabled />

function calc( n ) {
    var a = document.getElementById("a-" + n ).value;
    var b = document.getElementById("b-" + n ).value;
    var c = document.getElementById("c-" + n ).value;
    document.getElementById("final-" + n ).value = Math.round((parseInt(a)+parseInt(b)+parseInt(c))/3);
}
Jonas Äppelgran
  • 2,617
  • 26
  • 30
  • Thank You! Much nicer looking than the mess I made. And the light bulb came on a bit brighter. thank you everyone else as well. it has all helped greatly. – R.Decline Apr 14 '12 at 00:29
0

This is really quick and dirty, but if you know how many inputs you have, this should work:

// these would instead be your textboxes
​var a = document.getElementById('a').value();
var b = document.getElementById('b').value();
var c = document.getElementById('c').value();

var avg = (a+b+b)/3;

document.getElementById('c').value() = avg;

Here is a jsfiddle so you can play with the idea and see if it works as you want it to.

Ryan
  • 3,153
  • 2
  • 23
  • 35
0

Use jquery.

see the live demo on jsfiddle

some text
<div id="div1">
<input id="a" type="number" /><br/>
<input id="b" type="number" /><br/>
<input id="c" type="number" /><br/>
<input id="final" value="0" disabled />
</div>
some text
<div id="div2">
<input id="a" type="number" /><br/>
<input id="b" type="number" /><br/>
<input id="c" type="number" /><br/>
<input id="final" value="0" disabled />
</div>​

<script type="text/javascript">

$("#div1 input").bind('change keyup click',function(){
    var final = 0;
    $("#div1 input").not("#div1 #final").each(function(idx,el){
        final += (el.value) ? parseInt(el.value) : 0;
    });
    $("#div1 #final").val(final/3);
});
$("#div2 input").bind('change keyup click',function(){
    var final = 0;
    $("#div2 input").not("#div2 #final").each(function(idx,el){
        final += (el.value) ? parseInt(el.value) : 0;
    });
    $("#div2 #final").val(final/3);
});
​</script>
pylover
  • 7,670
  • 8
  • 51
  • 73
0

I hoped to flag this as duplicate, but because this answer does not have code, enjoy:

// find all inputs in the page and gather data trying to convert it to number
var data = [].map.call( document.querySelectorAll('input'), function (v) {
    if (typeof v.value * 1 === 'NaN') {
        return 'NaN';
    }
    return v.value * 1;         
});
// not all data will be valid, so we filter it
data = data.filter( function (v) {
   return !isNaN(v);
});
// and then calculate average
var avg = data.reduce( function (v, v1) {
    return v + v1;
}) / data.length;
Community
  • 1
  • 1
c69
  • 19,951
  • 7
  • 52
  • 82