reptile7's JavaScript blog
Tuesday, February 20, 2007
 
Google It, Part 2
Blog Entry #67

HTML Goodies' JavaScript Script Tips #42, #43, and #44 return us to the topics of search engines and scripts that search them. Back in Blog Entry #34, we discussed HTML Goodies' JavaScript Primers #18 and its script that, when brought up to date, searches the Yahoo! search engine; inspired by the Script Tips #42-44 Script, we then modified the Primer #18 Script so that it could search both Yahoo! and Google simultaneously. In this entry, we'll take a closer look at the Script Tips #42-44 Script, which, when brought up to date, can search as many as five search engines at once.

Per the discussion at the beginning of Blog Entry #64, the Script Tips #42-44 Script is located in HTML Goodies' /legacy/beyond/javascript/stips/ subdirectory (you won't find it by following the "Here's the Code (It's big. Get it all.)" links in Script Tips #42-44); the script can be accessed at http://www.htmlgoodies.com/legacy/beyond/javascript/stips/scripttip42script.html, or you can copy it from the div below:

<script language="javascript">

function wordsplit(items) 
{
var charect = "";
for (var n = 1 ; n <= items.length ; n++) 
{
if (items.substring(n-1,n) == " ") 
{ charect += "+"; }
else 
{ charect += items.substring(n-1,n); }
} // end of for loop
return charect;
}

function search( )
{
var keywords = document.searching.query.value; 
var search1;
var search2;
var search3;
var search4;
var search5;

key = wordsplit(keywords); 

if (document.searching.yahoo.checked)
{
search1 = document.searching.yahoo.value; 
search1 += key;
wind = window.open(search1,"newwindow1","width=700,height=200,scrollbars=yes");
}

else // this keyword is unnecessary

if (document.searching.altavista.checked)
{
search2 = document.searching.altavista.value; 
search2 += key;
wind = window.open(search2,"newwindow2","width=700,height=200,scrollbars=yes");
}

if (document.searching.webcrawler.checked)
{
search3 = document.searching.webcrawler.value; 
search3 += key;
wind = window.open(search3,"newwindow3","width=700,height=200,scrollbars=yes");
}

if (document.searching.lycos.checked)
{
search4 = document.searching.lycos.value; 
search4 += key;
wind = window.open(search4,"newwindow4","width=700,height=200,scrollbars=yes");
}

if (document.searching.excite.checked)
{
search5 = document.searching.excite.value; 
search5 += key;
wind = window.open(search5,"newwindow5","width=700,height=200,scrollbars=yes");
}
}
</script>

<form name="searching">
Enter the Key word : <input type="text" name="query" size="20"><BR><BR>
<b>Select the Search Engine(s):</b><br>

<input type="checkbox" name="yahoo" value="http://search.yahoo.com/search?p="> Yahoo<br>

<input type="checkbox" name="altavista" value="http://www.altavista.digital.com/cgi-bin/query?pg=q&what=web&fmt=.&q=">Altavista<br>

<input type="checkbox" name="webcrawler" value="http://www.webcrawler.com/cgi-bin/WebQuery?searchText=">WebCrawler<br>

<input type="checkbox" name="excite" value="http://www.excite.com/search.gw?trace=a&search=">Excite<br>

<input type="checkbox" name="lycos" value="http://www.lycos.com/cgi-bin/pursuit?query=">Lycos<br>

<input type="button" value="Search" onclick="search( );">
<input type="reset" value=" Clear ">

</form>
 
Introduction In the document body, the Script Tips #42-44 Script codes a form, named searching, comprising eight controls. (0) The zeroth control is a text box, named query, in which the user enters a search term. (1-5) The next five controls are checkboxes that present a 'menu' of search engines. For each checkbox, the name attribute value is set to the lowercased name of a search engine (yahoo, altavista, etc.) and the value attribute value is set to a partial URL for a page of search results obtained by that search engine. (6-7) The sixth control is a "Search" push button for triggering the script's searching action; the seventh control is a " Clear " reset button. So, the user types one or more words into the query box and selects one or more search engines from the checkbox menu; clicking the "Search" button then calls the script element's search( ) function. The user's query input, document.searching.query.value, is first assigned to the variable keywords. Second, the variables search1, search2, search3, search4, and search5 are declared, for later use, but not initialized. I find on my computer that these declarations are unnecessary; the script runs normally (no errors are thrown) if they are commented out. The next expression calls the script element's wordsplit( ) function and passes thereto the keywords value: key = wordsplit(keywords); The wordsplit( ) function will itself send a modified value to this point in the document, and that value will be assigned to the variable key. The wordsplit( ) function The wordsplit( ) function checks the user's input for space characters and replaces them with + signs, mimicking the behavior of many search engines in a normal search. (Indeed, with respect to the search engines searched by the Script Tips #42-44 Script, Yahoo!, AltaVista, and Lycos replace spaces with + signs; also, Excite escapes a space to %2B, in which 2B is the +'s ASCII hexadecimal representation.) My intuition told me that the wordsplit( ) function was also 'excess baggage,' and sure enough, I found that I could comment it out without any problems. An analysis of wordsplit( ) is thus somewhat of an academic exercise, but is still worthwhile in terms of its instructive value, so let's get into it. Consider a test case: suppose you are using the Script Tips #42-44 Script to search for information on the C programming language. So, the search( ) function assigns C programming language to keywords, and then the key=wordsplit(keywords) expression calls the wordsplit( ) function, whereupon keywords is renamed items. Subsequently, wordsplit( ) converts C programming language to C+programming+language via the following sequence of events: (1) We literally begin 'from scratch': our starting point is an empty string, assigned to the variable charect. (2) Next, the items string is tested for spaces and rebuilt on a character-by-character basis via a for loop: for (var n = 1; n <= items.length; n++) { if (items.substring(n-1,n) == " ") charect += "+"; else charect += items.substring(n-1,n); } (3) For the for loop's first iteration (n=1): (a) items.substring(0,1) returns items's zeroth character, which is a C. (b) The if condition returns false - a C is not equal to a space - so the browser proceeds to the else statement. (c) C is then assigned to charect. (We previously discussed the substring( ) method of the String object and the += shorthand assignment operator in Blog Entry #65.) (4) For the for loop's second iteration (n=2): (a) items.substring(1,2) returns items's first character, which is a space. (b) The if condition returns true, so a + is added to the right-hand end of charect; charect is now C+. (5) For the for loop's third iteration (n=3): (a) items.substring(2,3) returns items's second character, a p. (b) The if condition returns false, and the else statement adds p to the right-hand end of charect; charect is now C+p. I trust you can take it from here. After items.length=22 iterations, the for loop stops and charect is C+programming+language, which is finally returned to the wordsplit( ) function call in the search( ) function and assigned to key. "Is it necessary for the wordsplit( ) code to be in its own separate function?" Actually, no, it isn't. If desired, you can remove the wordsplit( ) function and replace the key=wordsplit(keywords) expression with: var key = ""; for (var n = 1; n <= keywords.length; n++) { if (keywords.substring(n-1,n) == " ") key += "+"; else key += keywords.substring(n-1,n); } An alternate space-to-+ conversion Somewhat more efficiently, the following regular expression-based code will also replace keywords's space characters with + signs: var key = keywords; var space = /\s/g; if (space.test(key)) key = key.replace(space, "+"); Comments • With respect to the space regexp pattern, \s matches a single space character; the g flag will allow us to match all occurrences of \s in the key string. • We discussed the test( ) method of the core JavaScript RegExp object in Blog Entry #49. • The heavy lifting here is done by the replace( ) method of the String object, which acts on key and replaces each space-in-key match with a +. And now, back to the search( ) function With key=C+programming+language in hand, it's time to get our searching underway. The search( ) function next runs through a series of if statements, one for each checkbox, that can be written in general form as: if (document.searching.checkboxName.checked) { search# = document.searching.checkboxName.value; search# += key; wind = window.open(search#,"newwindow#","width=700,height=200,scrollbars=yes"); } (Preceding the second if statement is an unnecessary else keyword that can be removed - indeed, it doesn't appear in the Script Tips #42-44 source.) If a given checkbox is checked, then the condition of its if statement (document.searching.checkboxName.checked) returns true; subsequently: (1) the checkbox value (document.searching.checkboxName.value) is assigned to one of the search# variables; (2) key is tacked onto the right-hand end of search#, giving a full URL for a page of search results obtained by the search engine associated with that checkbox/if statement; (3) the full URL is reassigned to search#, which is then plugged into a window.open( ) command, setting up a link to search# in a new browser window. Joe gives a line-by-line discussion of the Yahoo! if statement in Script Tip #44. You've probably noticed that the new windows of all five window.open( ) commands are variabilized with the identifier wind: wind = window.open(search#,"newwindow#","width=700,height=200,scrollbars=yes"); Unless you want to manipulate the new windows from the opener document (in which case they should be referenced differently - wind1, wind2, etc.), however, new window variabilization is unnecessary. Don't leave it blank, part 4 Towards the end of Script Tip #44, Joe's readers ask, But what if no checkboxes are checked? Can we put up an alert saying to post? Joe summarizes his efforts to ensure that a user chooses at least one search engine checkbox as follows:
I played around with some code, checking all of the Ifs in one shot, and it started to get to be too much code for what it produced. I'm happy with the page just sitting still if no search engines are checked. If you can find a quick method of altering the script to produce that alert and keep the function of the script the same, let me know. I'll be glad to post it.
It is with pleasure that I offer two straightforward, related solutions to this problem. Solution #1 At the beginning of the search( ) function, declare: var r = 0; In each if statement in the search( ) function, follow the window.open( ) command with: r = 1; At the end of the search( ) function (after the fifth if statement), add: if (r != 1) window.alert("Please make a selection."); My use here of the r tracking variable is based on a similar tactic appearing in the Script Tips #13-15 Script. Solution #2 In the search( ) function, comment out the search# declarations and then replace the series of if statements with: var search42 = new Array( ); var unchecked = 0; for (i=1; i<6; i++) { if (document.searching.elements[i].checked) { search42[i] = document.searching.elements[i].value; search42[i] += key; window.open(search42[i],"newwindow"+i,"width=700,height=200,scrollbars=yes"); } if (!document.searching.elements[i].checked) unchecked++; if (unchecked == 5) window.alert("Please make a selection."); } The approach here mirrors that of the code samples in Blog Entry #47. By referencing searching's checkboxes via the elements[ ] array, we can automate with a for loop the testing of checked-vs-unchecked checkbox states. As the loop proceeds, the variable unchecked counts up the number of unchecked checkboxes; if unchecked reaches a value of 5, then an alert( ) message pops up. Note that we cannot use i<=document.searching.elements.length for the for loop condition; if we did, then the alert( ) box would also pop up if the user chooses one, two, or three checkboxes - recall that the searching form contains a total of eight, and not five, control elements. Alternatively, if you'd rather not use a for loop, you can (a) put a var unchecked = 0 declaration at the beginning of the search( ) function, (b) follow each if statement with an else unchecked++ statement, and (c) put the if (unchecked == 5) alert("Please make a selection.") statement at the end of the search( ) function.

We're not through yet - up to this point, we haven't said anything about how the Script Tips #42-44 Script actually works in practice, and we'll get to that in the next entry.

reptile7

Labels:


Comments: Post a Comment

<< Home

Powered by Blogger

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