Potential Extension: Adding User Control

As mentioned earlier, this application leaves users at the “mercy” of the search engine defaults. That is, users have little or no control over customizing their searches. The only thing the user has to enter is the query text. You can code it so that users can also effect such features as the number of results to return per page, the amount of information displayed with each result, or perhaps whether to impose Boolean search rules with terms such as AND, OR, LIKE, and NOT LIKE. In this section, I’ll use the HotBot search engine as an example.

Perhaps the easiest way to extend functionality is to increase the number of results per page. You’ll need the name-value pair associated with the results per page for each search engine. Table 4.2 lists a few names and possible values for several search engines.

Table 4-2. Search Engines and Variables for Determining the Result Count

Search Engine

Field name

Possible values

Example

HotBot

DC

10, 25, 50, 100

DC=10

InfoSeek Advanced Search

Numberresults

10, 20, 25, 50

Numberresults=10

Scientific American

Docs

10, 25, 50, 100

Docs=10

Yahoo!

N

10, 20, 50, 100

n=10

I pulled these field names from the source code of each search page. Some of the fields come from the search engine’s advanced search pages, so the URLs in the engines array might not work. Keep in mind, too, that the number of results might not be adjustable. The search engine coders may have it set to a fixed number. If you don’t see a select list on the search page that allows you to change the number of results, you might contact the organization and ask someone if the results (and other features, while you’re at it) can be modified. Otherwise, you’ll have to add some type of default that doesn’t pass in a results field for certain search engines.

Notice also that the possible values vary among search engines. You’ll have to add code to compensate for that. It’s not difficult, though. Use the following procedure to add a search-results select list to your application. Then use it as a general guideline to add other feature controls.

  1. Add a select list to the frame containing the text field.

  2. Add an extra element in each new array containing the name of the results field for each corresponding search engine in the engine array.

  3. And an extra new Array() containing possible values of the corresponding search engine to each new array in the engines array.

  4. Remove the predefined name-value pair from the query string (if the name-value pair exists in the query string) .

  5. Adjust the code in function callSearch() to correctly concatenate the query string for each search engine.

Let’s stick with the HotBot example.

Step 1

Adding the select list shouldn’t be a problem. It might be wise to choose values most common to all the search engines in your application. Here is the code using 10, 25, 50, and 100:

<SELECT NAME="docs">
<OPTION VALUE="10">10
<OPTION VALUE="25">25
<OPTION VALUE="50">50
<OPTION VALUE="100">100
</SELECT>
Step 2

As it stands, each instance of new Array() in the engines array defines a search engine with three elements: element 0 is the search engine name; element 1 is the search engine query string; and element 2 is the search engine home page. Here is the HotBot record again:

new Array('HotBot',
   'http://www.hotbot.com/?MT=',
   'http://www.hotbot.com/')

Set element 3 to the name of the field associated with HotBot. Recalling the previous table, the field name is DC. Now the HotBot record looks like this:

new Array('HotBot',
  'http://www.hotbot.com/?MT=',
  'http://www.hotbot.com/',
  'DC')

If one or more of your search engines doesn’t have a results count (and, hence, a name-value pair) that you can set, place null in element 3.

Step 3

Now that you have identified the respective name, add another array containing all the allowable values. Do so by defining the new array in element 4. Referring again to the previous table, the HotBot record would look like this:

new Array('HotBot',
   'http://www.hotbot.com/?MT=',
   'http://www.hotbot.com/',
   'DC',
   new Array(10, 25, 50, 100))
Step 4

This step applies only if the default query string in element 2 contains the name-value pair of the results setting. Here is the query string for HotBot in element 2:

http://www.hotbot.com/?MT=

Since DC isn’t there, we can skip step 4. Just as an example though, the search engine for Scientific American does contain the name-value pair, which is docs=100. Take a look:

http://www.sciam.com/cgi-bin/search.cgi?' +
     'searchby=strict&groupby=confidence&docs=100&query=

You would need to take that out so it looks like this:

http://www.sciam.com/cgi-bin/search.cgi?' +
   'searchby=strict&groupby=confidence&query=

If one or more of your search engines doesn’t have a results count (and, hence, a name-value pair) that you can set, don’t create a value for element 4.

Step 5

The last item to handle is the decision-making code that constructs the query string before passing it to the awaiting search engine. You can do this all in function callSearch(). Here is the original code:

function callSearch(searchTxt, idx) {
  if (searchTxt == "") {
    parent.frames[2].location.href = engines[idx][2] +
      escape(searchTxt);
    }
  else {
    parent.frames[2].location.href = engines[idx][1] +
      escape(searchTxt);
    }
  }

If the user enters nothing in the query text form field, the application should still redirect the user to the search engine home page. So the if block can stay the same. It’s in the else block that we need to focus attention:

else {
  if(engines[idx][3] != null) {
    for (var i = 0; i < engines[idx][4].length; i++) {
      var selRef = parent.frames[4].document.forms[0].docs;
      if (selRef.options[selRef.selectedIndex].value =
        engines[idx][4][i].toString()) {
        parent.frames[2].location.href = engines[idx][1] +
          escape(searchTxt) + '&' + engines[idx][3] + '=' +
          engines[idx][4][i];
        return;
        }
      }
  parent.frames[2].location.href = engines[idx][1] +
    escape(searchTxt);
  }

Here is the line that adds the appropriate name-value pair to the query string:

parent.frames[2].location.href = engines[idx][1] +
   escape(searchTxt) + '&' + engines[idx][3] + '=' +
   engines[idx][4][i];

What you have here is the search engine URL plus the escaped searchTxt plus the name (engines[idx][3]) plus the value the user chose. However, this happens only after two conditions are satisfied. If not, the search is set to the default query string defined in element engines[idx][1]. First, the search engine must have a results feature that you can change. If so, the field is defined as the string in engines[idx][3]. Otherwise, that element is set to null. This happens in step 3. The following if statement verifies that engines[idx][3] is not null:

if(engines[idx][3] != null) {

If the value is equal to null, the first condition has failed. Therefore, the default query string is used. If engines[idx][3] does not equal null, JavaScript then iterates through the number of acceptable values defined in the array at engines[idx][4]. If the number chosen in the select list, which is represented by selRef.options[selRef.selectedIndex].value, matches one of the acceptable values in the array, JavaScript concatenates the user search engine URL and query text with the name-value pair, then loads frames[2] with the document result, and stops executing.

If the loop iterates through all acceptable values without encountering a match, the second condition has failed, and the default query string is used instead.

Get JavaScript Application Cookbook now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.