Weight and Balance Calc?

Hello everyone,

I’m building a site for the local flight school and they would like me to develop a weight and balance calculator for the site. The Calculator is very simple, it would be laid out like this:


                  Weight      Arm     Moment
Empty Plane            #        #          #
Fuel                   #        #          #
Passengers             #        #          #
____________________________________________
Total                  #        #          #

The #'s would be fields that visitors would enter into the form, as soon as two of the three (weight, arm, moment) are entered, the third would be calculated, using Arm = Moment / Weight.

The “Total” row would divide the total moment by the total weight and give the total arm (Center of Gravity).

The other twist is, I’d like to be able to take the “Total weight” and “Total Arm” data that was calculated, and use it for a css value on the same page. For example, (<div style=“position: absolute; left: ~TOTAL WEIGHT~; top: ~TOTAL ARM~;”>).

I hope this is possible and thanks in advance for any help!

yep, pretty straight forward to do.

post the code you have so far and we can try to help you debug it if you are stuck.

Ahh, well, I don’t actually have any code yet. I’m not very versed in javascript, I can manipulate existing code decently, but writing it from scratch is a bit out of my league.

I could create the html form I would like, and post it here? Then you could just inject the javascript where it needs to go?

nice try :slight_smile: but I normally try to avoid spoon feeding code (for free at least ;)) and instead prefer to help people I can see at least have had a go at coding up what they need.

Ok that’s understandable. Could you at least offer some advice on what I should look for on google as far as instructions on how to do this?

I am assuming you want to learn how to do this yourself and are not simply looking for some code to copy and paste into some school homework or whatever.

If so, then imho the w3schools javascript tutorials is one of many good places on the www to start.

No this definitely isn’t a school assignment. I’m a freelance developer. Ok I’ll look at the J3 schools. They taught me a lot of php. BTW, could this be done in php? I’m much more familar with it.

no offence, but the fact you’re asking if it can be done in php I’m wondering just how much they taught you because you can do it all with some basic php instead of javascript.

Oooook, well, thanks for all the “help”, but I think I’ve had enough criticism for one day.

ps. it’s offenSe.

ok I aplogise.

as I said it wasn’t meant to be an attack on you but I can see how it could have been taken that way.

so to answer your question

BTW, could this be done in php? I’m much more familar with it
.

yes it can and it should take no more than a dozen lines or so of some basic php number crunching and then output the results to css or wherever they need to go.

I’ve had a go at this for you.

Calculating the x and y offsets can become tricky, but it can be done for each axis by using two values from the image, and the corresponding pixel positions from your intended image.

For example: the image has horizontal lines for 1600 pounds and 1800 pounds.

The 1600 line is at 250 pixels, and the 1800 line is at 170 pixels.

A difference of 200 pounds results in a change of 80 pixels, so the scaling factor is 80/200. Because we want the vertical scale to have numbers on the bottom, we use a negative scale, resulting in a vertical scale of -80/200

Then we just need an offset.
1600 * -80/200 = -640
We need it to get to 250 pixels, so we need to add 890.

Check for 1800, which needs to get to 170 pixels
1800 * -80/200 = -720
-720 + 890 = 170

In this manner, we can calculate a scale and offset for both the x and y coordinates.


var targetConfig = {
    x: {'scale': 40, 'offset': -3300},
    y: {'scale': -80/200, 'offset': 890}
};

If you don’t mind leaving in my byline, or at least some way for people to get in touch with me, I’ve coded up a complete solution here for you.

this might also help you get started if doing it in php.

I am assuming you already have the html input form done.

 
<?php
 
/*
* put your form data validation
* and variable assignments code here
*/
 
//calculate the missing value for empty plane
if (!isset($ep_weight) || empty($ep_weight)) {
       $ep_weight = $ep_moment / $ep_arm;
} else if (!isset($ep_arm) || empty($ep_arm)) {
       $ep_arm = $ep_moment / $ep_weight;
} else if (!isset($ep_moment) || empty($ep_moment)) {
       $ep_moment = $ep_arm * $ep_weight;
}
 
/*
* repeat the above if-elseif to calculate the missing values
* for fuel and passengers
*/
 
//at this stage all 9 values should exist
//now calculate the totals
 
$total_weight = $ep_weight + $f_weight + $p_weight;
$total_arm = $ep_arm + $f_arm + $p_arm;
$total_moment = $ep_moment+$f_moment+$p_moment
 
?>

if you need any more help, post your code and we can try to help you fix it.

Thanks for the help guys! Sorry if I was getting snippy. I’ll look at this tonight and post back with what I have.

Ok guys, I got a chance to work on this today and I’ve made some major progress building on pmw57’s code. Here’s what I have so far…

<html>
<head>
<style type="text/css">
.numeric {
    text-align: right;
}
.numeric input {
    text-align: right;
}
#balancegraph {
    position: relative;
}
#target {
    position: absolute;
    left: 0;
    top: 0;
}
</style>
</head>
<body>
<form id="weightbalance">
    <table cellspacing="0" border="0" cellpadding="2">
            <tr>
                <td></td>
                <td style="text-align: center;">Weight</td>
                <td style="text-align: center;">Moment</td>
                <td style="text-align: center;">Arm</td>
            </tr>
            <tr>
                <td style="padding-right: 50px;"><label for="emptyweight">Basic Empty Weight</td>
                <td class="numeric"><input id="emptyweight" name="emptyweight" value="" size="15" onClick="this.value='';" onKeyPress="return onlyNumbers();"></td>
                <td class="numeric"><input name="emptymoment" value="" size="15" onClick="this.value='';" onKeyPress="return onlyNumbers();"></td>
                <td class="numeric"><input name="emptyarm" value="" size="15" readonly=true tabindex="-1"></td>
            </tr>
            <tr>
                <td><label for="fuelweight">Usable Fuel</td>
                <td class="numeric"><input id="fuelweight" name="fuelweight" value="" size="15" onClick="this.value='';" onKeyPress="return onlyNumbers();"></td>
                <td class="numeric"><input name="fuelmoment" value="" size="15" onClick="this.value='';" onKeyPress="return onlyNumbers();"></td>
                <td class="numeric"><input name="fuelarm" value="" size="15" readonly=true tabindex="-1"></td>
            </tr>
            <tr>
                <td><label for="passengersweight">Front Passenger</td>
                <td class="numeric"><input id="passengersweight" name="passengersweight" value="" size="15" onClick="this.value='';" onKeyPress="return onlyNumbers();"></td>
                <td class="numeric"><input name="passengersmoment" value="" size="15" onClick="this.value='';" onKeyPress="return onlyNumbers();"></td>
                <td class="numeric"><input name="passengersarm" value="" size="15" readonly=true tabindex="-1"></td>
            </tr>
            <tr>
                <td><label for="passengersweight">Rear Passengers</td>
                <td class="numeric"><input id="passengersrearweight" name="passengersrearweight" value="" size="15" onClick="this.value='';" onKeyPress="return onlyNumbers();"></td>
                <td class="numeric"><input name="passengersrearmoment" value="" size="15" onClick="this.value='';" onKeyPress="return onlyNumbers();"></td>
                <td class="numeric"><input name="passengersreararm" value="" size="15" readonly=true tabindex="-1"></td>
            </tr>
            <tr>
                <td><label for="passengersweight">Baggage Area 1</td>
                <td class="numeric"><input id="baggageoneweight" name="baggageoneweight" value="" size="15" onClick="this.value='';" onKeyPress="return onlyNumbers();"></td>
                <td class="numeric"><input name="baggageonemoment" value="" size="15" onClick="this.value='';" onKeyPress="return onlyNumbers();"></td>
                <td class="numeric"><input name="baggageonearm" value="" size="15" readonly=true tabindex="-1"></td>
            </tr>
            <tr>
                <td><label for="passengersweight">Baggage Area 2</td>
                <td class="numeric" style="padding-bottom: 10px;"><input id="baggagetwoweight" name="baggagetwoweight" value="" size="15" onClick="this.value='';" onKeyPress="return onlyNumbers();"></td>
                <td class="numeric" style="padding-bottom: 10px;"><input name="baggagetwomoment" value="" size="15" onClick="this.value='';" onKeyPress="return onlyNumbers();"></td>
                <td class="numeric" style="padding-bottom: 10px;"><input name="baggagetwoarm" value="" size="15" readonly=true tabindex="-1"></td>
            </tr>
            <tr>
            	<td>&nbsp;</td>
                <td class="numeric" style="text-align: center; background-color: #ececec;"><strong>Total Weight</strong><br><input name="weighttotal" value="" size="15" readonly="readonly"></td>
                <td class="numeric" style="text-align: center; background-color: #ececec;"><strong>Total Moment</strong><br><input name="momenttotal" value="" size="15" readonly="readonly"></td>
                <td class="numeric" style="text-align: center; background-color: #ececec;"><strong>Total Arm (C.G.)</strong><br><input name="armtotal" value="" size="15" readonly="readonly"></td>
        </tbody>
    </table>
</form>
<div id="balancegraph">
    <div style="z-index: 300000; width: 20px; height: 20px; background-color: white; position: absolute; left: 0; top: 0;"></div>
    <img src="172s.jpg">
    <img id="target" src="target.gif">
</div>
<script>
// This script calculates 
function calculateBalance(row, targ) {
    // arm = moment / weight
    var inputs = row.getElementsByTagName('input'),
        weight = inputs[0],
        arm = inputs[2],
        moment = inputs[1];
    if (weight.value > 0 && arm.value > 0 && targ !== moment) {
        moment.value = weight.value * arm.value;
    } else if (weight.value > 0 && moment.value > 0 && targ !== arm) {
        arm.value = moment.value / weight.value;
    } else if (arm.value > 0 && moment.value > 0 && targ !== weight) {
        weight.value = moment.value / arm.value;
    }
}
function updateTotals(form) {
    var els = form.elements;
    els.weighttotal.value = Number(els.emptyweight.value) + Number(els.fuelweight.value) + Number(els.passengersweight.value) + Number(els.passengersrearweight.value) + Number(els.baggageoneweight.value) + Number(els.baggagetwoweight.value);
    els.momenttotal.value = Number(els.emptymoment.value) + Number(els.fuelmoment.value) + Number(els.passengersmoment.value) + Number(els.passengersrearmoment.value) + Number(els.baggageonemoment.value) + Number(els.baggagetwomoment.value);
    els.armtotal.value = Number(els.momenttotal.value) / Number(els.weighttotal.value);
    return {
        'weight': els.weighttotal.value,
        'moment': els.momenttotal.value,
        'arm': els.armtotal.value
    }
}
function upTo(el, tagName) {
    tagName = tagName.toUpperCase();
    while (el.nodeName !== tagName && el.nodeName !== 'BODY') {
        el = el.parentNode;
    }
    return el;
}
function updateTarget(target, config, totals) {
    x = totals.arm * config.x.scale + config.x.offset;
    y = totals.weight * config.y.scale + config.y.offset;
    target.style.left = (x - target.width / 2) + 'px';
    target.style.top = (y - target.height / 2) + 'px';
}
var targetConfig = {
    x: {'scale': 26.7, 'offset': -806},
    y: {'scale': -.535, 'offset': 1510}
};
var form = document.getElementById('weightbalance');
var target = document.getElementById('target');
form.onchange = function (evt) {
    var targ, row, totals;
    
    evt = evt || window.event;
    targ = evt.target || evt.srcElement;
    row = upTo(targ, 'TR');
    calculateBalance(row, targ);
    totals = updateTotals(form);
    updateTarget(target, targetConfig, totals);
}
function onlyNumbers(evt)
{
    var e = event || evt; // for trans-browser compatibility
    var charCode = e.which || e.keyCode;

    if (charCode > 31 && (charCode < 48 || charCode > 57))
        return false;

    return true;

}
</script>
</body>
</html>

Here’s what I’m still working out…

  1. How do I hide the marker when it’s position is outside of the graph? For example, load up the above code, and set empty plane weight for 3000 and empty plane moment to 80000.
  2. Do you see any code consolidation opportunities in what I have? I know I have onclick=, onKeyPress, and readonly=true on several <input>s. Is there a way to consolidate these?
  3. Where would I put
.toFixed(2)

in order to have the arm’s only calculate to two decimal places?

Other than those three things I’d say we’re pretty much there! Thank you guys both so much for the help!

We can do this work for you too.

By setting up min and max values, hiding the target, and only showing it when it falls within that range.


var targetConfig = {
    x: {'scale': 26.7, 'offset': -806, min: 84, max: 96},
    y: {'scale': -.535, 'offset': 1510, min: 1400, max: 2200}
};

Here we hide the target, and only when we’re within the range do we show it.


function updateTarget(target, config, totals) {
    target.style.display = 'none';
    x = ...
    y = ...
    if (x < config.x.min || x > config.x.max) {
        return;
    }
    if (y < config.y.min || x > config.y.max) {
        return;
    }
    target.style.display = '';
    target.style.left = ...
    target.style.top = ...
}

Yes there is. Get those [censored] inline scripting events out of your [redacted] HTML code.

Instead of those, you could use something like this instead:


form.onclick = function (evt) {
    evt = evt || window.event;
    var targ = evt.target || ev.srcElement;
    if (targ.nodeName === 3) { // #text node
        targ = targ.parentNode;
    }
    if (targ.type !== 'text') {
        return;
    }
    // check for moment or weight
    if (targ.name.search('moment') > -1 || targ.name.search('weight') > -1) {
        targ.value = '';
    }
}

But you don’t want to do that, (which is why it’s only in a code block) as there will be a lot of duplication with the onkeypress event too. Instead you want to move the moment/weight check out to a separate function:


function whenMomentOrWeight(evt, func) {
    evt = evt || window.event;
    var targ = evt.target || ev.srcElement;
    if (targ.nodeName === 3) { // #text node
        targ = targ.parentNode;
    }
    if (targ.type !== 'text') {
        return;
    }
    // check for moment or weight
    if (targ.name.search('moment') > -1 || targ.name.search('weight') > -1) {
        return func(evt, targ);
    }
}

So that you can give each event a separate function to do the needed work:


form.onclick = whenMomentOrWeight(function (evt, targ) {
    targ.value = '';
});
form.onkeypress = whenMomentOrWeight(function (evt, targ) {
    return onlyNumbers(evt);
});

That would be in the updateTotals function:


els.armtotal.value = (Number(els.momenttotal.value) / Number(els.weighttotal.value)).toFixed(2);

You are a golden god. I’ll implement these changes shortly and get back to you. Do you have any recommendations for javascript training? I really need to step my game up on javascript. I’m familiar with both javascript and php as far as pushing it around, (I do primarily wordpress sites) but I’m terrible at writing it. Lynda.com?

What I hear about that website is less than inspiring.

The effective way to train is to write your own code, and invite feedback on the code from other experienced people. The training occurs as you realise that there are better ways to do things, or that there are tradeoffs that you want to balance in some way.

It is the process of improving your code which is how a lot of valuable learning occurs.

Wise words. That definitely makes sense. I can say that for CSS. I never really attained full “mastery” of the language until I started forcing myself to optimize, and do things the right way. With CSS, that’s really the only way to do it considering cross-browser issues.

imho w3schools tutorials is one of the better places to start

but there are many tutes on the www