reptile7's JavaScript blog
Tuesday, February 28, 2006
 
Introduction to Image Flipping
Blog Entry #31

I see that HTML Goodies is launching a new JavaScript primer series - as of this writing, Primers Number 1 and 2 have been posted. I've read through them both, with some disappointment; without offering a detailed critique, I'll point out that if the series' author, Mark Kahn, is going to hit the reader with the -= assignment operator and the parseInt( ) function in his first primer, then he is clearly not writing for the newbie (or so it would seem, anyway - I can't claim to read his mind on the matter). As I made clear in my first blog entry, the great strength of HTML Goodies is that it targets "Weekend Silicon Warriors" who are indeed often starting from scratch. Largely for this very reason, Joe Burns' 'classical' JavaScript primers, taken as a whole and notwithstanding their faults, still constitute the best JavaScript instructional material on the Web, and one can only hope that they are not eventually deleted from the HTML Goodies site.

And now, back to our regularly scheduled program...

In Blog Entry #15, we discussed the Image object and its properties, which collectively were once part of JavaScript but are now handled by the Document Object Model. We noted that many of the Image object's properties are read/write and also put together a demo that sets on command new values for the width, height, hspace, vspace, and border properties of a thumbnail image. However, we did not in that entry write the all-important Image src property, and we'll do that today as we dissect HTML Goodies' JavaScript Primers #15, "Image Flip Using OnMouseOver." The process of "image flip" (a.k.a. "image rollover"), in which one image is swapped for another by changing the source URL of an HTML <img> placeholder, receives its fair share of attention at HTML Goodies:
(a) In the HTML Goodies JavaScript Primers series, image flipping crops up in Primer #15, Primer #16, the Primer #23 Assignment, Primer #27, and Primer #28;
(b) The HTML Goodies "Web Graphics" section sports "So, You Want An Image Flip, Huh?" and "So You Want Another Image Flip, Huh?" tutorials;
(c) The Beyond HTML: JavaScript section of HTML Goodies features a "So, You Want A Dual Image Flip, Huh?" tutorial;
and this might not even be a complete list.

But back to Primer #15, which serves as a suitably straightforward introduction to the image flip topic; its simple script appears below:

<A HREF="http://www.cnn.com"
onMouseOver="document.pic1.src='menu1on.gif'"
onMouseOut="document.pic1.src='menu1off.gif'">
<IMG SRC="menu1off.gif" BORDER=0 NAME="pic1">
</a>

As illustrated on Joe's demo page, the script uses mouseover and mouseout events to toggle back and forth between two image files, "menu1on.gif" and "menu1off.gif":

The "menu1on.gif" image =
The "menu1off.gif" image =

The image that initially loads along with the rest of the demo page, "menu1off.gif", is set by the <img> tag:

<IMG SRC="menu1off.gif" BORDER=0 NAME="pic1">

This image element is itself a hyperlink whose anchor tag holds onMouseOver and onMouseOut commands for changing the image source. Consider the onMouseOver command, which replaces the "menu1off.gif" image with the "menu1on.gif" image:

onMouseOver="document.pic1.src='menu1on.gif';"

In accord with the right-to-left complexion of assignment statements, which we discussed in the previous post, this command says, "We will assign the value 'menu1on.gif' to the src property of the pic1 image object in the current document when we move the mouse cursor over this link." Operationally, there's nothing really new here: flipping images by assigning a new file to an image's src property is very much like linking to a Web page by assigning a new file to the window's location property (we covered window.location="http://www.some_web_page.com" commands in the onSubmit section of Blog Entry #10).

Finally, moving the mouse cursor away from the "menu1on.gif" image triggers the onMouseOut="document.pic1.src='menu1off.gif';" command, which reinstalls the "menu1off.gif" image. Pretty painless for our first image flip, eh?

Other code possibilities

(1) In the "Deconstructing the Script" section of Primer #15, Joe says, "Notice the IMG command is linked to the onMouse Event Handlers in the HREF command through that NAME='pic1' command. You'll need that to link the two commands together." However, we saw in Blog Entry #15 that it's not necessary to name an image object in order to write its properties; checking the source code of the demo page, we see that the "pic1" <img> is the third image of the document, allowing us, if desired, to retool the onMouseOver and onMouseOut commands as:

onMouseOver="document.images[2].src='menu1on.gif';" onMouseOut="document.images[2].src='menu1off.gif';"

and then leave out the NAME="pic1" in the <img> tag.

(2) On your own page, you might not want a flippable image to double as a link, in which case you have several options:

(a) You can leave the href attribute blank (href=""), as is done in the Primer #15 Assignment answer;

(b) You can replace the anchor tags with corresponding span tags
(<span onmouseover="document.images[x].src='imageA.gif';" onmouseout="document.images[x].src='imageB.gif';">
<img src="imageB.gif"></span>);

(c) For that matter, you can bring the onMouseOver and onMouseOut commands into the <img> tag itself and thus simplify their hierarchy statements as follows:

<img onmouseover="this.src='imageA.gif';" onmouseout="this.src='imageB.gif';" src="imageB.gif">

(The "this" special operator is briefly described here in Netscape's JavaScript 1.5 Core Reference.)

HTML Goodies' JavaScript Primers #16 is a close companion to Primer #15 - if truth be told, it does little more than functionize the Primer #15 Script - and we'll look at it briefly in the next post.

reptile7

Sunday, February 19, 2006
 
JavaScript and Math
Blog Entry #30

d(f(x)) = ∫exsin2x dx
Today at reptile7's JavaScript blog we'll discuss advanced integration techniques - no, just kidding - but seriously, folks, we are going to talk about the intersection of mathematics and JavaScript as we look over HTML Goodies' JavaScript Primers #14, "Math Variables". JavaScript has a built-in Math object whose read-only properties provide numerical constants - e.g., Math.PI returns π, or 3.1415... - and whose methods can be used to carry out various mathematical operations - e.g., Math.sqrt(x) returns √x, or the square root of x. Rather oddly, Primer #14, notwithstanding its title, makes no mention of the JavaScript Math object (which is at least listed on the HTML Goodies JavaScript objects keyword reference page), and the math it does feature is simple in the extreme, so we will flesh things out a bit after we examine the Primer #14 Script, which is reproduced below:

<BODY>
<SCRIPT type="text/javascript">
var numsums = 10 + 2
alert("10 + 2 is " + numsums)
var x = 10
alert("ten is " + x)
var y = x * 2
alert("10 X 2 = " + y)
var z = "Hello " + "Good Bye"
alert(z)
</SCRIPT>
</BODY>

Most of the issues that Joe takes up directly or indirectly in the "Deconstructing the Script" section of the primer we've covered previously.

• We introduced the role in JavaScript of the equals sign (=) as an assignment operator, by which the right side of the 'equation' is actively assigned to the left side, in Blog Entry #5. Perhaps I should state the concept here more 'melodramatically' to drive home the point that an equals sign in a JavaScript statement does not signify a passive condition of equality; rather, when you see:

some_entity_x = some_value_y;

the scriptwriter in effect is saying, "I hereby decree that y, as a value, is now assigned to x." This right-to-left reading of JavaScript statements is discussed in a recently posted "Understanding Operators" article at HTML Goodies.

• We discussed in Blog Entry #6 the use of a plus sign (+) as both an arithmetic addition operator and a concatenating string operator in the Primer #3 Script.

• We've been putting variables in the instance of the alert( ) method as far back as the Primer #9 Assignment.

• Joe revisits in some detail the topic of variables in JavaScript in the "Here's the Deal:" subsection of Primer #14 - indeed, the primer seems generally to be as much about variables as it is about math - and admittedly he does a better job here than he did back in Primer #6 ("Prompts & Variables"). (For those of you who prefer to get your information straight from the horse's mouth, the "Variables" section in Netscape's JavaScript 1.5 Core Guide is here; MSDN's "JScript Variables" page, to which I linked in Blog Entry #5 during my own discussion of JavaScript variables, is here.) One point of correction: variable statements do not need to have "[after the variable name] an equal sign, and a value." It's not at all uncommon to see JavaScript scripts begin with variable declarations of the form:

var variable_name;
/* more than one variable can be declared here: var variable_name_0, variable_name_1, variable_name_2, etc; */

The idea is to load the variable into the user's RAM in order to facilitate its subsequent use in the script, although I for my part suspect that such declarations are unnecessary more often than not.

Well, then, is there anything new here? Joe does introduce the - (short dash), * (asterisk), and / (solidus) characters as arithmetic operators for subtraction, multiplication, and division, respectively. Netscape notes that these (and the +) operators are not unique to JavaScript, but also appear in other programming languages.

Two more comments about two of the "Here's the Deal:" list items:

(1) "The value assigned to text variables must be surrounded by quotes. No quotes are allowed for numeric variables. If you do put quotes around a number, it becomes text with a numeric value of 0. YIKES!" On my computer, however, quoted numbers are not valuewise equivalent to 0 in arithmetic operations. In an addition, a quoted operand is simply concatenated; for example:

var eig = "6" + 2;
window.alert("6 plus 2 is: " + eig);

displays 6 plus 2 is: 62 (not 2 or 8) on the alert( ) box, when using either MSIE or Netscape. In a subtraction, multiplication, or division, a quoted operand is interpreted as a number (not a string) data type, and the calculation proceeds normally:

var thr = "6" / "2";
window.alert("6 divided by 2 is: " + thr);

displays 6 divided by 2 is: 3 on the alert( ) box. In sum, quotes are indeed "allowed" for numeric variables but are nonetheless unnecessary, even if you're concatenating a number with a text string, so leave them out.

(2) "All programming languages have Reserved Words and so does JavaScript. Any JavaScript book will list them. Using Reserved Words as variable names will cause errors. For example, using onMouseOver as a variable name is not a good idea." JavaScript's reserved words are listed in Appendix A of Netscape's JavaScript 1.5 Core Reference; "onMouseOver" isn't one of them, but we can make a larger point here: any of JavaScript's recognized keywords - including not only the reserved words but also those words that are used for JavaScript objects, properties, methods, and event handlers - are poor choices for variable names.

I use the word "poor" as I am not going to tell you that you can't get away with using some of these words for variable names some of the time - you can. Netscape won't allow you to use any of the reserved words for variable names ("Error: missing variable name") but MSIE will; for example, on my computer when using MSIE, var volatile = 4 * 8; window.alert(volatile); uneventfully pops up an alert( ) box displaying 32. Perhaps unsurprisingly, neither browser will let me use "window" for a variable name; however, my trial runs with "confirm", "fgColor", and yes, "onMouseOver" as variable names in simple examples all worked OK with both browsers. But in the name of writing unconfusing code and avoiding errors as often as possible, you should still steer clear of using JavaScript keywords for variable names.

At this point, you are in exasperation wondering, "When are we going to get to some real math?" Calm down, real math coming right up...

Some methods of the JavaScript Math object

Exponentiation

We can raise a number x to the "yth" power with the pow( ) method:

Math.pow(x,y); // Math.pow(2,5) returns 32 (25)

A separate exp( ) method exponentiates the constant e (2.718..., the base of the natural logarithm) to a given power:

Math.exp(x);

We can adapt the pow( ) method to finding the yth root of x, , by using a fractional second parameter; for example:

Math.pow(100,1/3);

returns the cube root of 100, or 4.641...

Also, square roots can be extracted by the sqrt( ) method, as noted earlier.

Application: solving quadratic equations

A quadratic equation of the form ax2 + bx + c = 0 has two roots, given by:

x = (-b ± (b2 - 4ac)½) ÷ 2a

We can easily write a script that accepts inputs for a, b, and c and solves the above for x. Consider the equation 3x2 + 9x - 30 = 0, whose roots are seen to be x = 2 and x = -5 by factoring it to (3x - 6)(x + 5) = 0. Plug 3, 9, and -30 into the appropriate boxes below, and then click (twice if necessary, depending on your browser) the "Solve it" button:

a: b: c:



Root #1: Root #2:


Here's my code in its original form (I had to modify it somewhat for the demo above in order to show its effect here at Blogger.com):

<form>
a: <input size="10"> b: <input size="10"> c: <input size="10"><p>
<input type="button" value="Solve it" onclick="qua( );"><p>
Root #1: <input size="10"> Root #2: <input size="10"><p>
<input type="reset">
</form>
<script type="text/javascript">
function qua( ) {
var a = document.forms[0].elements[0].value;
var b = document.forms[0].elements[1].value;
var c = document.forms[0].elements[2].value;
var b2 = Math.pow(b,2);
var d = 4*a*c;
var e = b2-d;
var f = Math.sqrt(e);
var r1 = (-b+f)/(2*a);
var r2 = (-b-f)/(2*a);
document.forms[0].elements[4].value = r1;
document.forms[0].elements[5].value = r2; }
</script>

Logarithms

The Math object has a log( ) method for obtaining the base-e natural logarithm of a number x:

Math.log(x); // returns ln x

It doesn't have a method for finding the base-10 common logarithm of a number, but it is simple enough to calculate a base-10 logarithm by dividing the natural logarithm by 2.303:

log10 x = (Math.log(x))/2.303;

Logarithmic calculations often involve very large or very small numbers, which are best expressed as "floating-point literals" using exponential notation as in the following example:

Express 529,000 = 5.29 × 105 as 5.29E5 (or 5.29e5)

Application: calculating the pH of a solution

What is the pH of 0.0035 M hydrochloric acid?

Recall from general chemistry that pH = -log10 [H3O+] and that hydrogen chloride dissociates to give hydronium (H3O+) and chloride (Cl-) ions quantitatively in aqueous solution. So, for 0.0035 M HCl, [H3O+] = 0.0035 M, and:

var pH = -(Math.log(3.5E-3))/2.303; // this gives pH = 2.455...
document.write("The pH of 0.0035 M HCl is: " + pH);

Trigonometry

Ah, we wouldn't want to leave out the trig fans in the audience...the Math object has methods for the following three basic trigonometric functions:

For sine: Math.sin(x);
For cosine: Math.cos(x);
For tangent: Math.tan(x);

Taking reciprocals of the above gives methods for the cosecant (1/Math.sin(x)), secant (1/Math.cos(x)), and cotangent (1/Math.tan(x)) functions.

For these methods, the inputted angle must be in units of radians (not degrees), where a 1-radian angle ≅ 57.3°. For example, if you want to calculate the cosine of a 60° angle, the code would be:

var sixty = Math.cos(Math.PI/3);
// as noted above, Math.PI returns π; 60° = π/3 radians
window.alert(sixty); // answer: 0.500...

The Math object also has methods for the 'inverse' arc sine (Math.asin(x);), arc cosine (Math.acos(x);), and arc tangent (Math.atan(x);) functions that output angle values, in radians, corresponding to an inputted length ratio x.

Calculus

As far as I am aware, there are no calculus-related Math object methods, and as I recall, I told you that calculus isn't my forte anyway. But as an exercise, you should now be able to write a script for differentiating a polynomial function of the form f(x) = axn + bxn-1 + cxn-2 + ..., given that d(xn) = nxn-1 dx and d(u(x) + v(x)) = (du(x)/dx + dv(x)/dx) dx.

Handling data and the JavaScript Number object

My demos in this post return in most cases numbers that trail many digits past the decimal point, and my guess is that you probably don't want that; fortunately, JavaScript has a built-in Number object having two methods, toFixed( ) and toPrecision( ), that are useful for expressing a number with a given number of significant figures. As illustrated in JavaScript Kit's "Formatting numbers for decimals and significant digits in JavaScript" tutorial, the toFixed( ) method sets a specific number of digits after the decimal point, whereas the toPrecision( ) method sets a total number of significant figures; for example:

(-(Math.log(3.5E-3))/2.303).toFixed(2) returns: 2.46
(Not quite as unwieldy as 2.4554894965205247, eh? Note that the digit in the hundredths place is rounded up.)

(Math.cos(Math.PI/3)).toPrecision(3) returns: 0.500
(The 'cosmetic' 0 to the left of the decimal point is not a significant digit.)

I think that's enough math for the time being. In the next entry, we'll return to the topic of images as we check out HTML Goodies' JavaScript Primers #15 and get our first taste of the "image flip" process briefly mentioned in Blog Entry #15.

reptile7

Tuesday, February 07, 2006
 
Custom Pop-Up Boxes
Blog Entry #29

In the course of a quest to find out if ×, ÷, and various other mathematical symbols (specifically, those besides +, -, and =) can appear in alert box messages, I stumbled across the following sentence in the alert( ) method section of the window object page of Netscape's JavaScript 1.3 Client-Side Reference:

"You cannot specify a title for an alert dialog box, but you can use the open( ) method to create your own alert dialog box."

A light bulb switched on in my head as I grasped a missing link between the last few posts: "Aha! Here's how we can make custom pop-up boxes." In this entry, we'll show how we can use the window.open( ) and related commands to create alert, prompt, and confirm boxes that are not 'held hostage' by the limitations of the alert( ), prompt( ), and confirm( ) methods - boxes with custom titles, background colors, buttons, or other features limited perhaps only by your imagination. Appearing below is sample code for two examples: (1) a custom alert box, and (2) a hybrid prompt/confirm box whose "OK" and "Cancel" buttons, when clicked, trigger alternate functions.

A custom alert box

Here's my code, which makes use of the two windows-one document method for opening new windows outlined in HTML Goodies' JavaScript Primers #12:

<script type="text/javascript">
function custom_alert( ) {
var ale = window.open("", "", "width=430,height=170");
ale.document.open( );
ale.document.write("<html><head>");
ale.document.title = "Alert! Alert!";
ale.document.write("</head><body>");
ale.document.bgColor = "navy"; ale.document.fgColor = "white";
ale.document.write("<b>You don't have to settle for gray alert boxes anymore.</b>");
ale.document.write("<br><br><br><br><br><br><form>");
ale.document.write("<input type='button' style='position:absolute;left:325px;width:75px;border: medium double;' value='OK' onclick='window.close( );'>");
ale.document.write("</form></body></html>");
ale.document.close( ); }
</script>

Here's the output:


White on navy blue - a much nicer color scheme than the drab gray of an alert( ) box, eh? A curious aside: I was initially going to describe the alert( ) box color as "Soviet gray"; however, from a quick Google search I learned that there is actually a recognized color called "Soviet gray" whose hex code is "#434a4c" and that is a darker shade of gray than 'pop-up box gray,' whose hex code, I determine from the DigitalColor Meter utility on my iMac, is "#dedede".

I have positioned and bordered the "OK" button to give it a 'normal feel' with the following code:

style='position:absolute;left:325px;border: medium double;'

Check out HTML Goodies' "So, You Want Positioning, Huh?" and "CSS and Borders" tutorials for more information in this regard. Of course, only slight modifications of code are needed to left-justify or center the "OK" button, or to border it differently. Also, we can just as easily add color to the button's text or background, e.g.:

<form><input type='button' style='color:lime;background:crimson;' value='Click Here'></form>

gives:
(For those of you with an historical bent, Joe Burns' "So, You Want A Colored Link Button, Huh?" tutorial discusses the creation of colored buttons in the pre-CSS days.)

N.B. Speaking of 'normal' "OK" buttons, if you typically 'click' an "OK" button by hitting the return/enter key, as I do, well, that won't work here; on a custom pop-up box, to choose "OK" you'll have to either (a) actually click the "OK" button with the mouse cursor, or (b) use the tab key to bring focus to the "OK" button and then hit the return/enter key.

A hybrid prompt/confirm box

For this example, we'll use the two windows-two documents new window method of Primer #11.

In the opener document:
<script type="text/javascript">
window.open("custom_prompt1.html", "", "width=430,height=150,top=300");
</script>

custom_prompt1.html code:
<html><head>
<title>Hello There</title>
<script type="text/javascript">
function ok_true( ) {
window.alert("Welcome, " + document.forms[0].elements[0].value + ", to my way cool Web site!"); }
function cancel_false( ) {
window.alert("\"Cancel\" is not an acceptable response - try it again.");
window.opener.history.go(0); }
</script></head>
<body bgcolor="gold" style="text-align:center;">
Kindly tell us your first name:<p>
<form>
<input size="40"><p>
<input type="button" style="width:75px;border: medium double;" value="OK" onclick="ok_true( ); window.close( );">&nbsp;&nbsp;
<input type="button" style="width:75px;" value="Cancel" onclick="cancel_false( ); window.close( );">
</form></body></html>

Here's the output:



Everything is centered this time, courtesy of the style="text-align:center;" attribute-property-value in the <body> tag.

The "OK" and "Cancel" buttons of a prompt( ) box on my computer are aligned horizontally, with the "OK" button to the right of the "Cancel" button; I have reversed the button order in the example above, as it makes more sense to me to put the "OK" button 'first.' (DevGuru shows at its window.prompt( ) page that these buttons are aligned vertically on a PC, with the "OK" button appropriately on top.) Also, I have equalized the buttons' widths by putting style="width:75px;" in their respective <input> tags.

Unlike a prompt( ) box but like a confirm( ) box, the "OK" and "Cancel" buttons of the custom_prompt1.html box are set up to execute alternate units of code. Clicking the "OK" button triggers the ok_true( ) function, which incorporates the user's text box input, document.forms[0].elements[0].value, into a 'Welcome' message on an alert( ) box; after the alert( ) "OK" is clicked, the custom_prompt1.html window closes via the window.close( ) command that is also assigned to its "OK" button onclick event handler.

Clicking the custom_prompt1.html "Cancel" button triggers the cancel_false( ) function, which first pops up an alert( ) message and then reloads the opener page with the following command:

window.opener.history.go(0);

We made brief mention of the go( ) method of the history object in Blog Entry #19; I refer you to DevGuru's history.go( ) page for more information. In the "Cancel" button code, the cancel_false( ) function is again followed by a window.close( ) command that closes the original custom_prompt1.html window, with a new custom_prompt1.html window popping up from the reloading of the opener page.

The ok_true( ) and cancel_false( ) functions must be put in the openee document source code; if they're placed in the opener document source, then the "OK" and "Cancel" buttons won't recognize them. As a result, applying the two windows-one document method of Primer #12 to this example is a bit complicated, but is certainly doable - try it out below. We'll need to put the ok_true( ) and cancel_false( ) functions in a nested script (a script within another script), which in turn requires a programming trick that I don't quite understand - click here to display the code.

<title>Custom Pop-Up Boxes</title>

Welcome to the Custom Pop-Up Prompt Box Page.


The interesting part of the nested script is its last, curious line:

pro.document.write("</scr" + "ipt>");

My attempts to find on the Web reference material on nested JavaScript scripts were largely unsuccessful - Netscape's manuals don't have anything to say about them, for example - but at least this page, hosted by the School of Computing and I.T. at the University of Wolverhampton, notes: "The occurence of the string '</script>' within a script will, however, confuse [read: throw errors with] most browsers," which was certainly the case on my computer when I tried to end the nested script with pro.document.write("</script>");. The 'solution' is to split "</script>" in two - a trick I've taken from the script in the HTML Goodies "Hello Goodbye" tutorial and that I've also seen used in the source code of pop-up/under ads. Again, I can't tell you why pro.document.write("</scr" + "ipt>"); works and pro.document.write("</script>"); doesn't - perhaps someone more knowledgeable than myself can weigh in with an explanation...

March 2017 note:
If the nested </script> tag is intact, then the browser (a) interprets the tag as the end of the parent script element and (b) throws an "unterminated string literal" SyntaxError. An alternative way to get around this problem is to write the tag as <\/script> so as to escape its </ part.

That'll do it for this entry. Next up: Primer #14.

reptile7


Powered by Blogger

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