reptile7's JavaScript blog
Thursday, May 09, 2019
 
The Whole of a Circle
Blog Entry #398

We continue today our discussion of the Java/JavaScript Goodies Circle Calculator. Having taken stock of the calculator's HTML structure and metafunctionality in the previous post, we are ready to do some actual calculating - let's get to it, shall we?

Area, diameter, circumference

Suppose the user changes the area field's 0 value to 10. Subsequently blurring the field calls a circle( ) function and passes thereto a this.form reference to the field's containing form and a this.name reference to the field's name, which are respectively assigned to form and changed variables.

function circle(form, changed) { /* circle( ) function body */ }
...
<input type="text" name="area" value="0" onchange="circle(this.form, this.name);">


I trust y'all know that for a circle
A = π × r² and C = π × d
where A, r, C, and d are the circle's area, radius, circumference, and diameter, respectively.

The parts of a circle
(I previously used this image here in Blog Entry #361 and originally got it from this USF page.)

Spikeman put all of the circle( ) value-getting and -setting code in a
with (Math) { ... }
carrier so he could use the JavaScript PI property and sqrt( ) method without a calling Math. object reference. (Although Mozilla's current with statement page details a number of problems with with, Netscape raised no with red flags back in the day.)

The with block begins by reading the area, diameter, and circumfrence fields' values and assigning them respectively to area, diameter, and circumfrence variables.

var area = form.area.value;
var diameter = form.diameter.value;
var circumfrence = form.circumfrence.value;


(Is it necessary to scoop up all three values? Two of them are 0, after all. A basic
var area, diameter, circumfrence;
declaration would suffice if we were to pass this itself to circle( ) and give it, say, an inputObject identifier and then use an inputObject.value expression in place of area, diameter, and circumfrence in the calculations below.)

Moving on, the above area/diameter/circumfrence assignments are followed by an if statement that tests if the area field has been changed and if so maps the area to the corresponding diameter and circumfrence via the formulae given earlier.

if (changed == "area") {
    var radius = sqrt(area / PI);
    diameter = 2 * radius;
    circumfrence = PI * diameter; }


Changes to the diameter and circumfrence fields are processed by analogous conditionals.

if (changed == "diameter") {
    area = PI * (diameter / 2) * (diameter / 2);
    circumfrence = PI * diameter; }
if (changed == "circumfrence") {
    diameter = circumfrence / PI;
    area = PI * (diameter / 2) * (diameter / 2); }


That's it for the math. The area, diameter, and circumfrence are lastly loaded into their designated form fields.

form.area.value = area;
form.diameter.value = diameter;
form.circumfrence.value = circumfrence; } /* End of with block */ } /* End of circle( ) function */


As regards the area = 10 input
the final outputs are:

Area:
Diameter:
Circumfrence:


In the name of completeness

Immediately after the circle( ) function are

var toDegrees = 360 / (Math.PI * 2);
var toRadians = (Math.PI * 2) / 360;


statements of which no use is made: throw them out.

Demo + notes

We're just about ready to wrap this guy up, and as is our custom, we do so by addressing the age-old question: "How might we improve things?"

I noted early on that the calculator's onchange action rubs me the wrong way.
Relatedly, the use of the area, diameter, and circumfrence fields for both inputting and outputting data strikes me as poor design.
I gave some thought to what I would like the calculator to be and here's what I came up with:

Circle Math

Another parts of a circle image - I myself made this one
C = π × d
A = π × r²
Calculation of Area, Circumference, and Diameter
Choose a term



and then enter a value:


The user initially interacts with a set of three radio buttons vis-à-vis a somewhat-confusing 'menu' of text boxes.
Clicking a radio button

<label><input type="radio" name="termName" value="Diameter:" onclick="chooseTerm(this.form, this.value);" /> Diameter</label>

calls a chooseTerm( ) function that
writes a corresponding label to the rows[1].cells[0] cell and
sends focus to a name="input3" text box in the rows[1].cells[1] cell.

var inputLabels = circleTable.getElementsByTagName("label");
function chooseTerm(form, inputLabel) {
    inputLabels[3].textContent = inputLabel;
    form.input3.focus( ); }


The user enters a value into the input3 field
and then clicks a button

<button type="button" onclick="getValues(this.form, this.form.input3.value);">Calculate the Remaining Terms</button>

thereby calling a getValues( ) function that outputs labels and values for the remaining circle parts in the rows[3] and rows[4] rows.

function getValues(form, inputValue) {
    if (inputLabels[3].textContent == "Diameter:") {
        inputLabels[4].textContent = "Circumference:";
        inputLabels[5].textContent = "Area:";
        form.input4.value = Math.PI * inputValue;
        form.input5.value = Math.PI * Math.pow(inputValue / 2, 2); } ... }


The inputValue is validated: the empty string and other non-numeric strings

else if (isNaN(inputValue)) { /* The isNaN( ) function was implemented for "all platforms" in JavaScript 1.1. */
    window.alert("Your input must be a bona fide number."); form.input3.value = ""; form.input3.focus( ); }


and non-positive numbers are all flagged and turned away by tests that Spikeman could have made use of.

The form.input4.value and form.input5.value are truncated/rounded at the thousandths place.

form.input4.value = Number(form.input4.value).toFixed(3);
form.input5.value = Number(form.input5.value).toFixed(3);


(Spikeman didn't have access to the toFixed( ) method but he could've easily accomplished the same via some decimal-point shifting and Math.round( )ing, e.g.:
form.area.value = Math.round(area * 1000) / 1000;)

Check the page source for the full coding. BTW, most but not all of the stylings

for (var i = 3; i < inputLabels.length; i++) inputLabels[i].style.color = "silver";

are effected JavaScriptically.
Math Check is up next.

Comments: Post a Comment

<< Home

Powered by Blogger

Actually, reptile7's JavaScript blog is powered by Café La Llave. ;-)