reptile7's JavaScript blog

Sunday, April 18, 2021

The Arc of the Trigonometric Covenant

Blog Entry #414

At the end of our last episode we pointed out that the Super Calculator's sine, cosine, and tangent functionality does not have an arcsine, arccosine, and arctangent counterpart - we will rectify this omission with a bit of help from our friends in Mountain View in today's post.

**Invert it**

A calculator Google search brings up a calculator widget, pictured below, when using Google Chrome or Opera on my computer.

The widget has sin, cos, and tan keys

and Rad and Deg keys for toggling between RAD (the default in this case) and DEG modes.

The widget also has an Inv key that when clicked changes inter alia* the sin, cos, and tan keys to sin

^{-1}, cos

^{-1}, and tan

^{-1}keys

for getting the arcsine, arccosine, and arctangent of a number, respectively;

the click also changes the Inv key's background color from #dadce0 to #f1f3f4.

(The backgrounds and borders of the widget keys are discussed below.)

Reclicking the clicked Inv key brings back

the sin, cos, and tan keys and

the original Inv key.

*The Inv key also toggles

the ln key with an e

^{x}key,

the log key with a 10

^{x}key,

the √ key with an x

^{2}key,

the Ans key (see here) with a Rnd key that generates a random number between 0 and 1, and

the x

^{y}key with a

^{y}√x key.

All of the widget keys are coded as

`<div>`

s rather than `<button>`

s or `<input>`

s.The Inv-controlled keys are housed in 16 separate divs

versus 8 divs whose labels and underlying behaviors are switched back and forth;

however, the Inv/Inv key is just one div.

We previously added a DEG capability to the SC's native RAD mode, and we can do the Inv/arc thing too (and in a much more straightforward way than Google does). Let's start by adding our own key

to either a new

**Trigonometry**section or

to the

**Special functions**section if we want to use the key in a more general way.

`<button id="invButton" type="button" onclick="invert( );">Inv</button>`

We'll bind the button to an

`invert( )`

function that toggles the trig key labels according to an inverted boolean flag.`var inverted = 0;`

function invert( ) {

var trigButtons = document.getElementsByClassName("trigButton");

if (! inverted) {

for (var i = 0; i < trigButtons.length; i++) trigButtons[i].innerHTML += "<sup>-1<\/sup>";

inverted = 1; }

else {

for (var i = 0; i < trigButtons.length; i++) trigButtons[i].innerHTML = trigButtons[i].innerHTML.substring(0, 3);

inverted = 0; } }

<button class="trigButton" type="button" onclick="getinput(sine);">sin</button>

<button class="trigButton" type="button" onclick="getinput(cosine);">cos</button>

<button class="trigButton" type="button" onclick="getinput(tangent);">tan</button>

• Grouping the trig buttons via a class identifier allows us to ordinally collect them with the DOM

`getElementsByClassName( )`

method.• We can append a

^{-1}

`<sup>`

erscript to the trig button labels with the DOM innerHTML property: note that the </ character sequence of the sup element's end tag is escaped with a backslash.• For reverting to the original trig labels, the

^{-1}superscripts can be easily shaved off via the String object's

`substring( )`

method.And of course, we'll need

`Math.asin( )`

-, `Math.acos( )`

-, and `Math.atan( )`

-based counterparts to the DEG-RAD `sine( )`

function we crafted earlier, e.g.:`function arcsine(mode, obj) {`

var trig_mode, alert_message, aa, a;

trig_mode = document.mainform.trig_mode[0].checked ? 1 : 0;

if (trig_mode) alert_message = "In DEG mode, this function maps a sine input to the corresponding angle in degrees.";

else alert_message = "In RAD mode, this function maps a sine input to the corresponding angle/arc length in radians.";

if (mode) window.alert(alert_message);

if (obj.value != "" && obj.value != "0") {

aa = window.prompt("Do you want to find the arcsine of the number in the total text box?", "y or n");

if (aa == "y") {

a = trig_mode ? Math.asin(obj.value) * 180 / Math.PI : Math.asin(obj.value);

doit(a, obj); }

else {

a = window.prompt("Enter a number to find the arcsine of:", "");

a = trig_mode ? Math.asin(a) * 180 / Math.PI : Math.asin(a);

more("(" + a + ")", obj); } }

else {

a = window.prompt("Enter a number to find the arcsine of:", "");

a = trig_mode ? Math.asin(a) * 180 / Math.PI : Math.asin(a);

doit(a, obj); } }

Note that the

`Math.asin( )`

*outputs*are DEG-RAD bifurcated.

The preceding

`arcsine( )`

function can be called from the `getinput( )`

function`if (func == sine) {`

if (! inverted) return sine(mode, a);

else return arcsine(mode, a); }

or from the

`sine( )`

function itself.`function sine(mode, obj) {`

if (inverted) return arcsine(mode, obj); ...

__Number validation__

Google will generate an interactive graph of a y = f(x) function (e.g., y = x^3, y = ln(x), y = tan(x)) upon searching for that function, again when using Google Chrome or Opera - a very cool feature if I do say so myself.

The y = sin(x) and y = cos(x) functions crest at 1 and trough at -1;

`Math.asin(x)`

and `Math.acos(x)`

consequently return NaN if x lies outside the -1 ≤ x ≤ 1 range. Per the __Non-empty, non-numeric__subsection of Blog Entry #411, we can use a suitable while gate to stop outsiderly xs, e.g., something like:

`/* Place this guy just before each Math.asin(a) DEG-RAD bifurcation: */`

while (Number(a) < -1 || 1 < Number(a) || isNaN(a))

a = window.prompt("Your sine input must be a number in the range:\n-1 \u2264 x \u2264 1", "");

• The

`Number( )`

operations are actually unnecessary as the JavaScript engine will automatically convert the a string to a number for the while comparisons - remove them if you like, or keep them if you feel that they add readability to the code.• \u2264 is the Unicode escape sequence for the ≤ symbol.

__Style extras__

As noted earlier, the widget's Inv key has a #dadce0 background color whereas the 'inverse' Inv key has an #f1f3f4 background color.

The 16 Inv-controlled keys have a #dadce0 background color, as do the remaining operation keys except the = key, which has a #4285f4 background color.

The widget's 11 number keys have an #f1f3f4 background color.

Each widget key has a 1px solid border whose color is the same as the background color and is therefore not noticeable.

Each key has a 4px border radius that slightly rounds the key corners.

Lastly, the key label color is #202124 (why someone would use an off-black text color rather than black itself is beyond me).

A detailed discussion of the backgrounds and shapes of the SC keys would take up more space than it's worth: suffice it to say that

the SC keys typically have a non-uniform off-white background color in the neighborhood of #eee

and they are usually stadium-shaped but sometimes they are perfectly rectangular

depending on the browser and on the browser's zoom level.

Moreover, all of the SC keys have borders and those borders have an outset(-like) style in a majority of cases.

We can apply all, some, or none of the widget's key styles to the SC keys.

At the least I reckon we should toggle the button's background color.

Toward this end, I would explicitly set the initial key backgrounds to white (#fff)

and then switch the Inv background to #c8c8c8 and back to white respectively via

`document.getElementById("invButton").style.backgroundColor = "#c8c8c8";`

and`document.getElementById("invButton").style.backgroundColor = "white";`

statementsin the if and else clauses of the

`invert( )`

function.But why stop there? Upon giving the SC keys a good solid border

and imparting a good rounding to the border

and

**bolding the labels**as per the border

I liked how it all looked:

`button { background-color: white; border: solid 2px black; border-radius: 10px; font-weight: bold; }`

**Trigonometry:**

DEG RAD

Adding the

^{-1}superscript to the , , and buttons increases their widths by 12px or so - try it out above by clicking the button - this effect can be smoothed out by stretching the

**Trigonometry**buttons a bit with an

`#invButton, .trigButton { width: 48px; }`

styling.__Operational oddity__

One last point regarding an unexpected something that I have only recently noticed...

Clicking the widget's sin

^{-1}key duly enters

an arcsin( string

into the user input field but it also switches all of the Inv-toggled keys and the Inv key itself back to their predecessor keys.

This doesn't happen with my code: the , , , and keys stay in place until the key is clicked.

We'll cover the SC's key and its

**Memory**section keys in the following entry.

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