Archives
 
 
 
  Special
 
 
 
  About Us
 
 
 

Newsletter
Free E-mail Newsletter from BYTE.com

 
    
           
Visit the home page Browse the four-year online archive Download platform-neutral CPU/FPU benchmarks Find information for advertisers, authors, vendors, subscribers Request free information on products written about or advertised in BYTE Submit a press release, or scan recent announcements Talk with BYTE's staff and readers about products and technologies

ArticlesJavaScript Adventures


August 1996 / Web Project / JavaScript Adventures

Netscape's interpreted scripting language remains a frustrating work in progress.

Rex Baldazo

Editor's note: Jon Udell is working on a special assignment this month (see the cover story "Your Business Needs the Web"). He will resume writing this column next month.

At the BYTE Site, navigation is always on our minds. As our article archive gets larger, being able to help people browse or do research becomes more important. On the other hand, we have to make sure that any navigation tools we add won't undo the entire site.

I was thinking about these issues recently, and an epiphany hit: Why not build a small navigation window using Netscape's JavaScript?

The reasons to explore JavaScript were obvious. Besides the potential of producing a navigation tool, I might uncover traps and pitfalls that I could apply to other JavaScript development projects.

But I found no shortage of pitfalls: As I learned how to program in JavaScript, I also discovered its limitations and the disappointing state of Netscape's documentation for the language.

Not Another Java

While Java and JavaScript are related, it's a distant relationship. Java is a compiled and strongly typed general-purpose language, while JavaScript is an interpreted and specific-purpose scripting language. JavaScript's designers aimed its features directly at manipulating Web pages and at interacting with the user.

By the time you read this, Netscape Navigator 3.0 will be available. But I'm experimenting in 2.0, and, for the most part, these scripts should work in 3.0.One of the nicer navigating ideas Jon Udell has come up with is the notion of a tabbed menu line (for an example, see our editorial calendar at http://www.byte.com/admin/edit96.htm ). So, I began my grand JavaScript adventure by emulating that look in a month-picker ( see the screen ). My plan was to eventually move the picker to a separate frame so that when you clicked on a month, it would update the other frame with the selected issue. But first I wanted to work in a single window.

The Hypertext Markup Language (HTML) page for the month-picker is http://www.byte.com/js_menu.htm . But you can't run the script from our server--you'll need to copy it elsewhere to play with it. More on that later.

Every time you load this page, the init ial if statement checks to see if Navigator has passed along parameters in the search uniform resource locator (URL). The browser creates the search object if the URL is a query, such as http://www.byte.com/js_menu.htm?6. But the page itself creates these URLs in the first place.

The PrintMonthArray function ( see the listing ) makes an <href> tag for each month except the one that's currently selected. The <href> s are circular references back to the js_menu.htm page. The search object passes a number identifying which month you clicked. The browser redraws and reinterprets the page when you click on a month, and thus updates the currently selected month.

This discussion has probably raised two questions in your mind. First, why all this coding gymnastics to do what seems to be a simple window-redraw procedure? Second, why won't this action work from The BYTE Site? The answers to both questions rest squarely on the shoulde rs of Microsoft and Netscape.

JavaScript's documentation describes a document.clear() method that I should have been able to use to clear a document. Then I would have used two other built-in methods, document.write() and document.writeln() , to redraw the document. That would have been easier, and more direct, than using the search-object contortion.

Unfortunately, I haven't been able to get document.clear() to work as advertised on Navigator 2.0, 2.01, or 2.02 on either Windows NT or the Mac OS. I've also tried with the Atlas preview on NT. I haven't had a chance to experiment with JavaScript on Microsoft Internet Explorer 3.0, but it will be interesting to see if Microsoft can get it to work right.

This page doesn't work on The BYTE Site, but it works just fine on most of the servers that I've tried--WebStar (both the Macintosh and the Windows 95/NT versions), Netscape's FastTrack server, and even the little Web server that comes with Microsoft FrontPage . However, when I moved it over to The BYTE Site, which is powered by Microsoft's Internet Information Server, I kept getting errors. Depending on the security configuration of IIS, I got either a 403 (execute permission denied) or a 404 (not found) error. It's clear that IIS is trying to actually execute the HTML page.

According to Microsoft, the Internet specification on how to deal with queries is open to interpretation. Most vendors have settled on a common practice, while Microsoft took its own approach. That's why my script worked on most other servers but failed on Microsoft IIS. But bowing to the pressures of the market, version 2.0 of IIS will adhere to industry practice. The next version of IIS will ship with NT 4.0, so it may not be available when this article sees print, although you may be able to download a beta version from Microsoft's Web site.

One last point before we leave this script. You will notice that I use a little MakeArray function to create an array of objects. Navigator 3.0 provides a true array object, but for backward compatibility I'm using the older method.

Building a Compass

Having my client-side script fail to execute on the Microsoft IIS server unnerved me. But I had gained enough confidence in JavaScript to create the BYTECompass .

For this project, I decided I'd go whole hog, complete with frames and floating windows. The BYTECompass itself is a floating window that allows you to either browse articles by issue or run a search of BYTE's article archive. You can try out the BYTECompass by visiting http://www.byte.com/byte_js.htm .

When you point your browser at this file, the main window of your browser divides into two frames (see the screen above). The upper frame, which I call the menu frame , has a single button that you use to open or close the BYTECompass window. The lower frame points initially at the normal BYTE Site home page. As you select items in the BYTECompass, this lower frame points to the selected issue or search result. Thus, I call it the art frame , short for article frame.

This little navigation aid fulfills my main goal because it doesn't require any reworking of the existing BYTE Site. It's a totally transparent add-on for those who have a JavaScript-capable browser.

The byte_js.htm page has the functions to open and close the BYTECompass window. This page also has the code that draws the button in the menu frame. The frameset in byte_js.htm (see the listing "Main Frameset" ) points the menu frame to a document called blank.htm. That page is essentially an empty HTML page, except for a single JavaScript statement invoking the CallBack function in the parent document.

The CallBack function could actually resid e in the blank.htm document, but it's in the byte_js.htm document for historical reasons. I had tried to create a function using built-in methods, such as document.clear , that would draw on the blank document defined by blank.htm. But as I mentioned earlier, document.clear doesn't work as advertised, so I couldn't get this to work properly.

The answer was to use the history object. Each frame in a window has a history object, which stores the URLs of all the pages that have been displayed in that frame. Using the history.go method, you can tell a frame which page in its history list to display.

By using a value of zero as the argument to history.go , you tell the frame to reload the current document. In my case, reloading blank.htm into the menu frame causes the CallBack function to be called again. It can then check to see the status of the BYTECompass window--and from that determine whether to print a "Show BYTECompass" or "Hide BYTECompass" label on t he button.

When you close the BYTECompass window, it notifies the parent document, which updates the Show/Hide button. The onUnload event is the trigger that tells the BYTECompass window that it's been closed. I use the onUnload event to run the ImDead function (see the listing "The Self-Destruct Function" ).

The onUnload event is one of the built-in events, and of course there's a matching onLoad event. It's important to realize that onLoad and onUnload are associated only with body and frameset tags. In other words, you can't have a table object that uses the event. However, it's easy enough to have the body object use the onUnload event to perform some task for the table object.

The ImDead function has a couple of statements to check whether certain objects are non-null. There are two possibilities: You've either closed the BYTECompass window directly or moved the main browser window off the byte_js.htm page.

If the BYTECompass window has been closed directly, it nulls out the handle to itself (it appears as if the window.close() method doesn't do this automatically, so I included the code to do it in my function), and it then uses the history object of the menu frame to force a reload. The menu frame then updates the menu button with the correct label.

But if the user has moved off the byte_js.htm page, the KillCompass function in byte_js.htm forces the BYTECompass window to close. As it closes, there's an onUnload event that will, as in the previous case, call the ImDead function. But if ImDead then tries to manipulate objects in the parent window, they no longer exist and you'll get error messages. Thus, the if statements are protective --they make sure there are objects to manipulate before trying to manipulate them.

Tips and Tricks

There are a couple of nifty tricks I stumbled upon as I was playing with JavaScript. First, it can get difficult at times to figure out which built-in object you should be using, especially since there are so many aliases for so many objects. So, it's useful to dump out the properties of an object and see what's going on:

var info;
for (var i in obj)
  {info += i + " = "
  + obj[i] + "\n"; };

I apologize about all the semicolons--some of them are extraneous, but I just put them in to be safe. Anyway, this will iterate over an object and return a string with all the properties. I then use a little function window to print this as preformatted HTML to a trace window.

The other trick is hidden frames. If you use a frameset such as <frameset rows="10%, 90%, *"> , the third and final frame will not actually be displayed on the browser. It is there--if you move your mouse over the bottom of the display window, it should turn into a double-headed arrow. This will let you grab the border and lift it so you can actually see the third frame.

So why would you want a hidden frame? I've sometimes used this hidden frame as a way to attach code, such as my trace/debug functions, to a page. Then when the page finally works, I simply alter the frameset to remove the hidden page. You can also use this as a way to preload graphics in the background.

The more I've used JavaScript, the less enamored with it I've become. I spent several years as an Ada programmer; say what you will about the language, but if the Language Reference Manual (LRM) says that Ada behaves a certain way, then, by God, it always behaves that way.

The same cannot be said of the JavaScript documentation from Netscape. Call me old-fashioned, but I expect a vendor's own documentation to at least be correct, and ideally complete as well. If you can't get a feature like document.clear() to work, then remove it from the documentation so people won't try to use it.


For furth er Java Information:

Gamelan                    
http://www.gamelan.com

Ask the JavaScript Pro     
http://www.inquiry.com/techtips/js_pro

JavaScript Sourcebook      
http://gmccomb.com/javascript



TOOLWATCH


Open Transport 1.1 (free with System 7.5 update 2)

Apple Computer, Inc.

http://www.info.apple.com/


Finally, a stable and PowerPC-native Macintosh Open Transport networking component. It has vastly improved the performance of our Apple Workgroup Server 6150/66, and it works just fine with our NT DHCP host.


BOOKNOTE

CGI Programming on the World Wide Web by Shishir Gundavaram

O'Reilly & Associates, Inc. 
Internet: 
http://www.ora.com/

Price:    $29.95

Good coverage of an arcane but terribly useful art. Full of excellent examples.


Mai n Frameset

<frameset rows="10%,*" onUnload="KillCompass();">
 <frame src="/blank.htm" name="menu" scrolling="auto"
   marginwidth=8 marginheight=8>
 <frame src="http://www.byte.com/" name="art"
   scrolling="auto" marginwidth=0 marginheight=0>
</frameset>


The frameset points to an HTML page with a single 
JavaScript statement that invokes the callback 
function in the parent document.




The Self-Destruct Function

function ImDead() {
    if (rootWin.parent != null) {
     rootWin.parent.BYTECompass = null;
     if (rootWin.parent.menu != null) 
        { rootWin.parent.menu.history.go(0);
  };
}



The ImDead function in the BYTECompass uses a couple 
of statements to check for non-null objects.




CGI Programming on the World Wide Web

photo_link (20 Kbytes )


Tabbed Menus Not Flawless in JavaScript

screen_link (15 Kbytes)

Emulate the tabbed menu line ( top ) in JavaScript ( bottom: "PrintMonthArray Function" ), and you'll uncover technical flaws.


Now You See It, Now You Don't

screen_link (13 Kbytes)

The BYTECompass offers two frames: The single button opens and closes the window; the larger frame points to search results.


For the past year, technical editor Rex Baldazo has worked with BYTE's New Media group to help develop The BYTE Site. He recently moved to the reviews department. He can be reached at rbaldazo@bix.com .

Up to the Web Project section contentsSearchSend a comment on this articleSubscribe to BYTE or BYTE on CD-ROM  
Flexible C++
Matthew Wilson
My approach to software engineering is far more pragmatic than it is theoretical--and no language better exemplifies this than C++.

more...

BYTE Digest

BYTE Digest editors every month analyze and evaluate the best articles from Information Week, EE Times, Dr. Dobb's Journal, Network Computing, Sys Admin, and dozens of other CMP publications—bringing you critical news and information about wireless communication, computer security, software development, embedded systems, and more!

Find out more

BYTE.com Store

BYTE CD-ROM
NOW, on one CD-ROM, you can instantly access more than 8 years of BYTE.
 
The Best of BYTE Volume 1: Programming Languages
The Best of BYTE
Volume 1: Programming Languages
In this issue of Best of BYTE, we bring together some of the leading programming language designers and implementors...

Copyright © 2005 CMP Media LLC, Privacy Policy, Your California Privacy rights, Terms of Service
Site comments: webmaster@byte.com
SDMG Web Sites: BYTE.com, C/C++ Users Journal, Dr. Dobb's Journal, MSDN Magazine, New Architect, SD Expo, SD Magazine, Sys Admin, The Perl Journal, UnixReview.com, Windows Developer Network