简体   繁体   中英

Optimise my Javascript percentage calculator

I have a javascript that calculates the percentage from two fields (retail and network) and then dumps that percentage into another field (markup).

As I am relatively new to the world of JS I have ended up reusing the code for several rows of fields. This goes against DRY and KISS principles so I was wondering if you could give me some input on how to optimise my code so that it can handle any two fields and then dump a value to a third field.

Here is a screenshot of my form segment that is using it.

http://i.imgur.com/FHvDs.png

在此处输入图片说明

Here is my code I am using, I have had to reuse it four times and place the code in four functions eg (percentage1, percentage2, percentage3, percentage4) each one of these functions deals with a row of fields show in the screenshot.

    function percentage1()
                {


                //the dividee
                x = document.getElementById('tariff_data');
                //the divider
                y = document.getElementById('network_data');

                    //if the first value is lower than the second, append a "-" sign
                    if (x.value < y.value)
                    {
                        z = "-"+(x.value/y.value)*100;
                        document.getElementById('markup_data').value = z;
                    }
                    //not a negative percentage
                    else
                    {
                        z = (x.value/y.value)*100;
                        document.getElementById('markup_data').value = z;


                    }

                }   
function percentage2()
                {


                //the dividee
                x = document.getElementById('tariff_rental');
                //the divider
                y = document.getElementById('network_rental');

                    //if the first value is lower than the second, append a "-" sign
                    if (x.value < y.value)
                    {
                        z = "-"+(x.value/y.value)*100;
                        document.getElementById('markup_rental').value = z;
                    }
                    //not a negative percentage
                    else
                    {
                        z = (x.value/y.value)*100;
                        document.getElementById('markup_data').value = z;


                    }

                }
etc etc.... 

These functions are called using the onchange HTML attribute

Also when I divide by a decimal number it gives the wrong value, any Ideas how to make it calculate the correct percentage of a decimal number?

My code also gives out these strange outputs:

NaN , Infinity

Thanks

Rather than optimization, let's focus on correctness first =)

Note that the HTMLInputElement.value property has type "string", so your arithmetic operators are doing implicit type conversion which means you are likely often doing string concatenation instead of the numeric operations you expect.

I strongly recommend explicitly converting them to numbers first and checking for invalid input, also, don't forget to declare your variables first using var so they don't potentially clobber globals, eg:

var x = Number(document.getElementById('tariff_data'));
var y = Number(document.getElementById('network_data'));
if (!isFinite(x) || !isFinite(y)) {
  // Handle non-numerical input...
}

You can also use the parseFloat function if you prefer, eg:

var x = parseFloat(document.getElementById('tariff_data'), 10);

I highly recommend doing some formal learning about the JavaScript language; it is full of pitfalls but if you stick to the "good parts" you can save yourself a lot of hassle and headache.

With regard to DRYing your code out; remember that you can:

  • Pass parameters to your functions and use those arguments within the function
  • Return values using the return keyword

In your case, you've got all your multiplication code repeated. While trying to fix the string vs. number problems maerics has already mentioned, you could do something like this:

// We're assuming 'dividee' and 'divider' are numbers.
function calculatePercentage(dividee, divider) {
    var result;

    // Regardless of the positive/negative result of the calculation,
    // get the positive result using Math.abs().
    result = Math.abs((dividee.value / divider.value) * 100);

    // If the result was going to be negative...
    if (dividee.value < divider.value) {
        // Convert our result to negative.
        result = result * -1;
    }

    // Return our result.
    return result;
}

Then, in your percentage functions, you can just call this code like so:

function percentage1() {
    var tariff, network, markup;

    tariff = parseFloat(document.getElementById('tariff_data').value, 10);
    network = parseFloat(document.getElementById('network_data').value, 10);
    markup = document.getElementById('markup_data');

    markup.value = calculatePercentage(tariff, network);
}

Obviously, you could take this further, and create a function which takes in the IDs, extracts the values from the elements etc., but you should try and build that yourself based on these tips.

Maerics also makes a very good point which you should take note of; learn more about the Good Parts of JavaScript. Douglas Crockford's book is excellent, and should be read and understood by all JS developers, IMHO.

Hope this helps you clean your code up!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM