reptile7's JavaScript blog
Tuesday, March 28, 2006
 
Google It
Blog Entry #34

In the last two entries, we've discussed scripts highlighted by functions with parameters that enabled these functions to accept and act on literals sent to them by their function calls. However, we've also seen that a function can act on external information in the document without that information being 'fed' to the function. For example, the answer to the Primer #17 Assignment featured a script with a function that recognized a global variable preceding the function. In addition, the image flip functions of the Primer #16 Script and Assignment could from the document head recognize the names of image elements (e.g., "mypic" as appearing in up( )'s document.mypic.src="up.gif" statement) in the document body. We continue today in this vein as we examine HTML Goodies' JavaScript Primers #18, "Form Fields and the Value Property"; as we'll see below, the Primer #18 Script contains a function that acts on the literal value of the value property of a text object without that value being passed to the function. More generally, the values of all of the properties of form control objects (and of all other document body objects, as far as I know) are 'available' to a function.

After we work through Primer #18, you might want to revisit Blog Entry #29's hybrid prompt/confirm box script and Blog Entry #30's quadratic equation script, both of which contain functions that also act on unpassed text object values.

As noted at the end of the previous post, we'll be using the Primer #18 Script to search a search engine, namely, Yahoo!. "Yahoo!? What about Google??" Chill out - Primer #18, which unfortunately lacks a "Posted on XX/XX/199X" date, was clearly written before Google hit the big time. But even as a tool for searching Yahoo!, the Primer #18 Script is 'outdated' in a much more important sense: it doesn't work. So here's what we'll do: we'll first look over the script, as is our custom, and then make some minor modifications that will allow the script to successfully search both Yahoo! and Google with a single mouse click.

N.B. Joe's script demo works OK - try it yourself - but check the Primer #18 source code, which contains a corrected script differing from the original script below.

The Primer #18 Script

<script type="text/javascript">
function Gofindit( ) {
var searchfor = document.formsearch.findthis.value; // function command #1
{
var FullSearchUrl = "http://av.yahoo.com/bin/query?p=" + searchfor; // function command #2
location.href = FullSearchUrl; // function command #3
} }
</script>
<form name="formsearch" action="">
Search Yahoo for:
<input name="findthis" size="40" type="text">
<input type="button" value="Go Find It" onClick="Gofindit( );">
</form>

In the document body, the script codes a form, named "formsearch", comprising two controls: (1) a text box, named "findthis", in which the user types a search term of some sort, and (2) a "Go Find It" button that, when clicked, triggers the Gofindit( ) function, which conducts a search using the Yahoo! search engine. The Gofindit( ) function 'grabs' the entered search term, which is the value of the findthis text object in the formsearch form object in the current document, and assigns it to the searchfor variable in function command #1.

In function command #2, the searchfor search term is concatenated with a partial URL, "http://av.yahoo.com/bin/query?p=", of a Yahoo! search; note from our discussion of the location object in Blog Entry #19 that the "search" part (a.k.a. the query string) of a URL begins with a question mark. Where did the partial URL come from? "All I did was go to a search engine, do a search and copy the address from the Location bar. Ta Da!" Joe helpfully explains in the Primer #18 Assignment answer - as you might guess, it's this partial URL that's defective, and we'll get it sorted out below. In any case, the partial URL plus the searchfor search term composes a full URL, which is assigned to the FullSearchUrl variable.

Finally, function command #3 assigns the value of FullSearchUrl to the href property of the location object, thus setting up a link to the FullSearchUrl URL - i.e., a link to a Web page of Yahoo! search results for the searchfor search term - in the current window as we have done previously.

One more point before moving on: you've probably noticed that function commands #2 and #3 in the Gofindit( ) function are surrounded by a second set of braces ("another function inside a function," Joe tells us in the "Deconstructing the Script" section of the primer); are they necessary? Not at all - leave them out.

A new, improved script for searching both Yahoo! and Google

<script type="text/javascript">
function Gofindit(searchfor) {
var google_url = "http://www.google.com/search?q=" + searchfor;
// from the Primer #18 source:
var yahoo_url = "http://search.yahoo.com/search?p=" + searchfor;
window.open(google_url, "", "width=700,height=200,scrollbars");
window.open(yahoo_url, "", "width=700,height=200,top=325,scrollbars"); }
</script>
<form name="fx">
<b>Search Google and Yahoo! for:</b>
<input name="tx" size="40">
<input type="button" value="Go Find It" onclick="Gofindit(document.fx.tx.value);">
</form>

Try it out:

Search Google and Yahoo! for:

Giving credit where credit is due, my script above borrows in some respects from the multiple search engine script discussed in HTML Goodies' JavaScript Script Tips #42-44. Although designed to search Google and Yahoo!, the script is clearly extensible to searching as many search engines as you wish.

A couple of points:

• Unlike the original Primer #18 Script, my script directly passes document.fx.tx.value to a parameterized Gofindit(searchfor) function. It's not necessary to do this, but I like doing it this way.

• Searching more than one search engine at once requires the respective Web pages of search results to be opened in separate windows via window.open( ) commands, which can be customized as desired.

The Primer #18 Assignment

We conclude this entry with a quick comment on the Primer #18 Assignment, for which Joe asks the reader to retool the Primer #18 Script so that it searches a different search engine. In his answer script, Joe chose to search WebCrawler, which is now a "metasearch" engine (a search engine that searches other search engines); I find that this script does still work once we put the "http://webcrawler.com/cgi-bin/WebQuery?searchText=" partial URL all on one command line.

HTML Goodies' JavaScript Primers #19 features yet another script with a function that acts on text box inputs, and breaks little new ground, but I'll still have a few things to say about it in the next post.

reptile7

Monday, March 20, 2006
 
More on Function Calls/Parameterization
Blog Entry #33

Let's take stock for a moment of the various ways we've called JavaScript functions:
(a) In most cases, starting with the Primer #9 Script, we've called them with the onLoad event handler in the document <body> tag;
(b) We once, in the Primer #10 Assignment, called a function with the onUnload event handler in the document <body> tag;
(c) In the previous post, we triggered functions with hyperlinks and images via the onMouseOver and onMouseOut event handlers;
(d) We've even called functions with basic function_name( ); commands a couple of times (for example, in my answer for the Primer #9 Assignment in Blog Entry #23).

In HTML Goodies' JavaScript Primers #17 ("Calling Functions With Forms"), our focus today, we'll call a function using form control buttons and the onClick event handler and see a second example of function parameterization, which we introduced in the previous post. More generally, we can of course use any suitable combination of document body element and event handler to call a function:
<input onFocus="function_name( );">
<select onChange="function_name( );">
<textarea onSelect="function_name( );">
<form onSubmit="function_name( );"> etc.

Let's look now at the Primer #17 Script, which Joe demonstrates here:

<html><head>
<script type="text/javascript">
function newcolor(color) {
alert("You Chose " + color);
document.bgColor=color; }
</script></head>
<body>
<h1>Select a Background Color</h1>
<form>
<input type="button" value="Blue" onClick="newcolor('lightblue');">
<input type="button" value="Pink" onClick="newcolor('pink');">
</form></body></html>

In the document body, the script codes two buttons, "Blue" and "Pink"; when clicked, each button (a) pops up an alert( ) box indicating the user's color choice and then (b) resets the background color accordingly. Consider the "Blue" button:

<input type="button" value="Blue" onClick="newcolor('lightblue');">

At this point, "you should be able to pick this one apart by yourself," as Joe himself would say. The onClick attribute triggers the newcolor(color) function in the document head and assigns the string 'lightblue' to color, newcolor(color)'s variable parameter*:

var color = 'lightblue';
<!--Again, this statement doesn't appear in the code, but this is what happens.-->

Algebraically speaking, we have now chosen a specific value, 'lightblue', for color, the independent variable of the f(x)=newcolor(color) function. The newcolor(color) function then plugs 'lightblue' into its two command statements, giving the script's effect - pretty straightforward. The "Pink" button works the same way, of course.

*I should mention here that a JavaScript function's parameters are more commonly termed arguments; indeed, JavaScript has an arguments property via which a function can access and otherwise keep track of its arguments/parameters.

In case you were wondering, if you were to leave out the 'lightblue' or 'pink' function call parameter, then onClick="newcolor( );" will still call the newcolor(color) function. In this case, the alert( ) message will read "You Chose undefined"; the document background color with MSIE will stay/turn white or whatever color your background is set to in your browser preferences, but with Netscape turns (for reasons beyond my understanding) a limish green (hex code: #00ef08), or at least that's what happens on my computer.

If you would like an external reference for the function parameterization topic, then the "Functions with Parameters" section of JavaScript Kit's "Functions and creating your own functions" tutorial is as good as any I've seen.

Literals and strings

In the "Deconstructing the Script" section of Primer #17, Joe introduces and defines two new terms: literal and string. (Hmmm...I've been using the phrase "text string" here at my blog for quite some time now, assuming y'all knew what I was talking about.) The "Literals" section of Netscape's JavaScript 1.5 Core Guide is here. As Joe and Netscape point out, a literal is a fixed value of some sort: "blue", (the Boolean) false, 13, etc. When Joe says "string," he really means "string literal," discussed by Netscape here. Whereas Joe defines a string (literal) as "any run of letters or numbers within single or double quotes," Netscape makes clear that an empty string (""), having zero characters, still counts as a string literal.

Speaking of strings:
(a) JavaScript has a built-in String object for representing string literals as objects;
(b) JavaScript's built-in objects all have a toString( ) method that converts instances of these objects to string literals;
(c) JavaScript has a "top-level" (i.e., not associated with a particular object) string( ) function that also converts objects to strings.

We wrap up this entry with a quick comment on...

The Primer #17 Assignment

In the Primer #17 Assignment, Joe asks the reader to augment the Primer #17 Script with a prompt that solicits the user's name for subsequent incorporation into the alert( ) message of the newcolor(color) function. As shown in Joe's answer, in order for the prompt( ) command to execute "when the user enters the page," it must be placed outside the function:

<script type="text/javascript">
var user_name = window.prompt("Write your name in the box below","Write it here");
// the prompt command can alternately be placed after the function
function newcolor(color) { etc.

Interestingly, the user_name variable is declared outside of the newcolor(color) function but is nonetheless recognized by the function; in fact, the user_name variable can now be used anywhere in the document and is thus called a global variable. If we had placed the prompt( ) command inside of the newcolor(color) function, then the user_name variable would be tied to the function and not recognized outside of it (→ "Error: 'user_name' is not defined"), and would then be termed a local variable. Relatedly, the color variable of the newcolor(color) function is in effect declared inside of the function and is thus a local variable.

In the next post, we'll take on HTML Goodies' JavaScript Primers #18, in which we'll continue our look at the intersection of forms and JavaScript functions; specifically, in the Primer #18 Script we'll see a function that acts on a user's text box input and applies it to carrying out searches on search engines.

reptile7

Thursday, March 09, 2006
 
Image Flipping II
Blog Entry #32

We continue our foray into image flipping as we move on to HTML Goodies' JavaScript Primers #16, "Image Flip With A Function." Consistent with its title, Primer #16 uses a JavaScript function to write the image src property. Let's get right to the Primer #16 Script (I've reshaped it and cleaned it up a bit - the center and anchor tags are not closed in the primer):

<html><head>
<title>JavaScript Example</title>
<script type="text/javascript">
function up( ) {
document.mypic.src="up.gif"; }
function down( ) {
document.mypic.src="down.gif"; }
</script></head>
<body><center>
<h2>Sample Animation</h2>
<a href="http://www.htmlgoodies.com" onMouseOver="up( );" onMouseOut="down( );">
<img src="down.gif" name="mypic" border="0">
</a></center></body></html>

As you can see, this script builds only slightly on the Primer #15 Script, in which the document.image_name.src="imagefile" commands are executed directly by the onMouseOver and onMouseOut event handlers.

Now, if the script above seems inefficient to you, well, it does to me too. If we're going to go to the trouble of functionizing the image flip commands, then can't we somehow do this with just one function? It gets worse: at the end of the "Deconstructing the Script" section of the primer, Joe discusses the extension of the Primer #16 Script to "multiple" image flips; his approach thereto is to add a new function for each new image flip command. Again, is this really necessary?

It isn't, as Joe himself seems to hint in "The Concept" of Primer #16 when he says, "For multiple JavaScript statements, call a function. In the real world, you will often need multiple JavaScript image flips on a page." And sure enough, Joe's own "So, You Want A Dual Image Flip, Huh?" tutorial, which we mentioned in the previous post and which perhaps was written later than was Primer #16, does feature an approach to executing multiple image flips with a single function. The coding in this tutorial is more complicated than it needs to be for our purposes, so we'll strip it down accordingly, as follows:

The function:
<head><title>Title text</title><script type="text/javascript">
function flip(x,y) {
document.images[x].src=y; }
</script></head>

For each image flip in the document <body>:
<img name="imagename" onmouseover="flip('imagename','imagefileB');" onmouseout="flip('imagename','imagefileA');" src="imagefileA">

(Contra Primer #16, and this is the last time I'm going to comment on this, event handlers are not case-sensitive, as we learned in Blog Entry #7.)

Let's get into some 'deconstruction' of our own, shall we? As Joe often does, we first consider the document body code, in particular, the onMouseOver and onMouseOut commands in the <img> tag, e.g.:

onmouseover="flip('imagename','imagefileB');"

A mouseover event calls a function, flip( ) - so far, so normal. Unlike function calls we've seen previously, however, the "flip( );" code in this command specifies two string parameters - 'imagename' and 'imagefileB' - that will be "passed" (i.e., sent) to the flip( ) function in the document head and assigned respectively to the x and y variable parameters in the flip( ) function declaration; in other words, calling the flip( ) function also executes the commands:

var x = 'imagename';
var y = 'imagefileB';

Now charged with values for x and y, the triggered flip( ) function plugs 'imagename' and 'imagefileB' into its image flip command statement:

document.images['imagename'].src='imagefileB';
/* although not mentioned in Blog Entry #15, we can use document.images['imagename'] to reference an <img name="imagename"> element */

which then in this case replaces the 'imagefileA' image, initially set by the <img> tag, with the 'imagefileB' image. In turn and analogously, the onMouseOut function call returns us to the 'imagefileA' image by assigning 'imagename' to x and 'imagefileA' first to y and then to document.images['imagename'].src via the flip( ) function.

Using this method, the same flip( ) function, via the x and y variables, will accept and act on the names and associated source files of other flippable images on the page. Many image flips, one function, no problem. Try it out below:

Welcome to the image flip function div.

A single onMouseOver/onMouseOut-triggered function effects each image flip below; check the current page source for the coding.

Image Flip #1:

Image Flip #2:

Image Flip #3:

Image Flip #4:

I'm able to demonstrate image flips here at Blogger.com, but not using the function-based technique described in this entry.
Belated demo for Primer #15:
Roll your mouse over and away from the green square below to meet Vito and Sapphire (depending on your processor speed, this may take a few seconds).



The coding here follows the <img onmouseover="this.src='imagefileA';" onmouseout="this.src='imagefileB';" src="imagefileC"> format discussed in the previous post.

But actually, you might want your image flip commands to be in separate functions, which you can then customize with additional JavaScript code to your heart's content. Indeed, 'versatilizing' the image flip process that way was probably what Joe had in mind when he wrote Primer #16.

We will return to the image flip topic later in the HTML Goodies JavaScript Primers series. Meanwhile, in the next post we'll forge on to Primer #17, in which we'll see another application of a common function accepting and acting on value inputs from separate event handlers.

reptile7


Powered by Blogger

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