JavaScript FAQ

This FAQ is a work in progress by Andy Augustine. If you are viewing this from a mirror site, the original and most recent version of this document can be found at http://www.freqgrafx.com/411/jsfaq.phtml.

For specific Q&A on Netscape 3.0 (which is still in beta), check out the ATLAS/JavaScript FAQ. Netscape has released Navigator v2.02 to fix some JavaScript security issues (among other things). Make sure you get it and use it from now on.

If there is a topic that you think should be added to the list you can use our submission form or post it to one of the following groups and I will add it. Listed here are a collection of answers, hacks, workarounds, and kludges that have been taken from the:

Other than JavaScript 411, links to a variety of JavaScript pages on the Web can be found at Andrew Wooldridge's JavaScript Index site. If you have found your way here, I assume that you've already tried to find the information you need from Netscape's Official JavaScript Docs. NOTE: the Netscape docs that were zipped up and on-line are gone! Looks like anyone who didn't get them in time will have to buy their book when it comes out.


SECTION I. Some basics you must know before proceeding! SECTION II. Known Bugs and Workarounds SECTION III. Dealing with Forms SECTION IV. Frames and Windows SECTION V. Using arrays SECTION VI. Advanced Topics


SECTION I. JavaScript Basics before you start

There are several things about JavaScript that seem to slip past most newbies. Either they aren't documented correctly, or they are documented but just not where you'd think to look for them. Before you post a question to one of the groups above, you should consult the 'Known Bugs' list for your operating systems version of Netscape 2.0. In Windows you can find it in the Help menu under Release Notes. (On the Mac you can pull it down from the '?' menu.) If you've looked elsewhere and can't find the answer you need, read on!

HEIGHT and WIDTH tags for images
There's been a ton of people posting about having problems with their forms and JavaScript errors. Once you make the decision to start writing JavaScript code, you'd better get in the habit of using <HEIGHT> and <WIDTH> tags within all your inline images! An alternative fix that has been mentioned is adding an empty <SCRIPT> </SCRIPT> tag to the bottom of your HTML, but as far as I'm concerned the image tags have an added benefit in performance. They will make the browser load your document with placeholders for the images so that it can give the user something to look at while your pics load.


Where does the SCRIPT go in my HTML?
The safest place to put your <SCRIPT LANGUAGE="JavaScript"></SCRIPT> tags is within the <HEAD>. This will force it to be loaded into the browser's memory first. If you put code anywhere else there's always a chance that a user might click on an image or link before your code is fully loaded, resulting in chaos and errors. Here's a quick look:
    ----------
    <HTML>
    <HEAD>
    <TITLE>Example</TITLE>

    <SCRIPT LANGUAGE="JavaScript">
    <!-- HIDE FROM OLD BROWSERS

    code goes here

    // --> STOP HIDING
    </SCRIPT>
    </HEAD>

    <BODY>
    HTML goes here
    </BODY> </HTML> 
    ------------


How do I load a JavaScript library without embedding it in my HTML?
This feature is one of those that never made the Netscape Navigator 2.0 release. In 2.1 you will (hopefully) be able to save your scripts in a file with a xxx.js extension and then call them remotely from any of your web pages. This will be a very nice addition.


How do I print a frame generated by JavaScript?
Currently it is not possible to print any data (html,text,...) generated by JavaScript code. Another print-related problem with 2.0 is that if you print a page with a form on it, the form will show up but the user input will not.


How do I define a variable as global/local?
[Answer: Brendan Eich]
In Netscape 2.0, there are bugs to do with implicitly defining a global variable by setting a new name with assignment within a function. Example:
    function f() { x = 3; ... }
                   ^^^^^
where x is unbound when f's definition is parsed. The bugs may lead to wrong answers, but should not crash you (I think).

You should say what you mean here. If the intent is for x to be local, you must use var before it. To avoid trouble, you may choose a style where you always use 'var' to introduce new variables whereever you need them. If you are writing a function that wants local variables (or needs them, if it is recursive), use var. If you want to use a global in a function, make sure there is a top-level var statement that introduces the global before the function definition:

    <SCRIPT LANGAUGE="Javascript">
    <!-- hide from old browsers

    var x ...

    function f() { x = 3; var local = ... }

    // done hiding -->
    </SCRIPT>


How do I use the <APPLET> tag?
This tag is used by the Java programming language, which is separate from Javascipt. Sun and Netscape are currently working together so that in the future, code written in one language will be able to reference code written in the other. This is not yet implemented. If you're looking for information on Java, try http://java.sun.com.

If you're looking to call a JavaScript function from within a Java Applet, you can use this call (submitted by Achille Hui):

    showDocument("javascript:/**/myJSfunction()"
It appears that the /**/ is necessary to call 'myJSfunction()' instead of '/myJSfunction'. If you're interested in how Javascript reference Java in the future (Navigator 2.1), Brendan Eich wrote:
Statement of work in progress for 2.1:

You will be able to get and set Java public static fields as if they were
JavaScript properties of an object named after the package-qualified class
name, and call Java methods that are public, provided you can reach their
instances from the top-level Applet context thing.

In JavaScript, you name an applet via either document.applets[myAppletIndex]
or document.myApplet where a NAME attribute has been used.

The reflection of public fields and methods from Java into JavaScript will
be automatic and lazy.


Can I do animations with Javascript?
No, you cannot redraw only part of a page, although there are some other ways to do this. If you would like to run an animation, here are some basic suggestions:


What kind of size limits are there for the scripts that I write? (64k on Win3.1)
The windows 16-bit version of Netscape 2.x runs into a 64k segment limit fairly early. Some people have reported that they've hit this limit with scripts in the range of 20k-40k. For the technical types out there... here's some more info from Brendan Eich: -No more than 2**20 symbols among all scopes. -No more than 2**16 atoms (identifiers, numeric literals, string literals) referred to by source loaded at any instant into one context (window). There are no other static limits in the platform- independent part of the JS implementation. And the dynamic limit on runtime: 1e6 control flow transfers between "Length JavaScript running. Continue?" dialog boxes.


[ Back to top ]

SECTION II. Known Bugs and Workarounds

Although JavaScript development has come a long way in a short time, there are still a few glitches that can tie up your projects if you're unaware of them. Some of these bugs only occur on one platform. However if your system is not affected by one of those listed below, you must keep in mind that everyone viewing your pages with the afflicted platform will run into difficulties and possibly even crash. You should try and familiarize yourself with all of the problems below to make sure you're not writing buggy code.

Why do long strings generate the 'Unterminated String Literal' message?
The exact reason why this happens is unclear, but the fix is easy. If the following string was causing problems in your code:
    var mystr="This is an example of a very long sting that is just like a run-on sentence
           and may break the code.  Somebody suggested theres a 254 character limit for 
           Windows 3.1 so this example is an attempt to be at least that long.  I don't
           know who would simply define a string this long, but there are times when it's
           necessary."
you should break it into smaller peices on sepeareate lines using the + sign to concatenate it. The fix would look like this:
    var mystr="This is an example of a very long sting that is just like a run-on sentence"
           + "and may break the code.  Somebody suggested theres a 254 character limit for"
           + "Windows 3.1 so this example is an attempt to be at least that long.  I don't"
           + "know who would simply define a string this long, but there are times when it's"
           + "necessary."


I pass a variable to the parent/sibling frame, and it's fine. But when the passing frame unloads, the value gets corrupted. What's the fix?

This bug has been fixed in Navigator 3.0 with the introduction of the String object. You can now pass String objects between frames and windows without worrying about the 'weak link' bug described above. To create a String object use the 'new' keyword:
  var msg = new String("This is a string object")

If you're still interested in the fix for older browsers, this will work for Navigator 2.x: [Answer: Bill Dortch]

    ** parent **
    var myvar = ""
    function setvar (value) {
      myvar = "" + value; // create new string in parent context
    }
  
    ** child **
    parent.setvar("myvalue");


Eval() crashes Navigator on Windows 3.11 in 2.0b6 or later.
[Answer: Bill Dortch]
No direct fix. Examine navigator.appVersion to determine if user is Win16, and either don't load the offending code, or branch around it. EXAMPLE:
    if (navigator.appVersion.indexOf("Win16") == -1) { // not Win16
      eval (...); // evil!!!
    }
    else 
      doSomethingElse();


When I call window.open(), a new window is created but it's empty.
In Netscape Navigator 2.0 (MAC and X versions) the URL that is passed to window.open() fails to load. The following workaround will work:
    var newWin = window.open(myURL,'myWin')
    if (navigator.appVersion.indexOf("(X11") != -1 ||
        navigator.appVersion.indexOf("(Mac") != -1)
      newWin = window.open(myURL,'myWin')
The trick here is to call window.open() a second time to force the load.


On some X platforms, boolean options for a new window may be ignored.
It is valid to specify options for a new window by using: 'toolbar=yes', 'toolbar=1', or 'toolbar'. However, there is a X-platform-specific bug that may ignore these options no matter how you turn them on. This is a bug on X only, and it will be fixed in Navigator 2.1.


Why is my array of radio buttons indexed in reverse order?
When you create a set of radio buttons, you expect them to be placed into an array in order of creation. But if you've tried to access them, you've probably noticed that they were in reverse order. A simple fix for this is to assign an empty event handler to each radio object like this:
    <FORM NAME="radioTest">
     <INPUT TYPE="radio" NAME="testset" VALUE="A" onClick="">A
     <INPUT TYPE="radio" NAME="testset" VALUE="B" onClick="">B
     <INPUT TYPE="radio" NAME="testset" VALUE="C" onClick="">C
    </FORM>
Here's proof that it works:
A B C
I get strange numbers returned from parseFloat() and % operator.
There is a bug in Netscape Navigator 2.x the affects the parseFloat() method and the % (modulus) operator. Although there is an argument as to whether it is a bug or a platform specific problem, the skinny on it is that it will return an invalid answer most of the time. When you try to change a string like '.35' to a float using this method, you will get something like .34999999 returned, depending on which platform you are using. To see demo of this problem and a possible solution for how to format a string as a dollar value without calling parseFloat(), check out our example in the code snippet library.


When I modify document.bgColor the text on my page disappears.
The bgColor property is the only property of the document object that can change the color immediately. fgColor, linkColor, vlinkColor and alinkColor can each be set, although they will have no impact on the page itself. Even though bgColor can be used to change the background color of the current page, on some platforms it will 'hide' all of the text that is on that page. Because of this, none of these properties should be used for Netscape Navigator 2.x.

If you would like to modify the colors on your page using JavaScript, one way to do it is to store the values you would like to use as cookies and then reload the page, using JavaScript to write those attributes of the <BODY> tag from the stored cookie values. To test the bgColor property on your platform, try my example page in the tutorial section.


Why can't I use: document.write('</SCRIPT>')
There's a problem that Netscape 2.x will incorrectly parse your code when you call: document.write('</SCRIPT>') It will be read as the ending tag for your script and result in errors. The current workaround for this is to break up the string into two segments: document.write('</SCR' + 'IPT>')


The window.defaultStatus property is broken on some platforms (like Win95).
This bug causes a problem for scripters that want to use the onMouseover event handler to change the message displayed in the status bar for the links on their page. Thus, the following code (although syntactically correct) will not function properly: window.defaultStatus=""; ... <A href="foo.phtml" onMouseover="window.status='foo bar'; return false;"> When you pass the mouse over the link, the message 'foo bar' is displayed in the status bar (as it should). But when you move the mouse off the link, the defaultStatus dous not replace the message with a blank line. Instead, the window.status message will remain there. A workaround for this is to make a call to the function holdStatus() (shown below) in your onMouseover event. This function will successfully clear the status bar. <SCRIPT LANGUAGE="JavaScript"> <!-- Hide // This is the length in milliseconds that a // links 'message' will remain in the status bar. // var LINKTIME = 2000 // Call this function from a link's onMouseover handler. // Pass it the string you want displayed for the link. // EXAMPLE: // <A href="foo.phtml" onMouseOver="return holdStatus('foo bar')"> // function holdStatus(msg) { window.status = msg setTimeout("clearStatus()",LINKTIME); return true } function clearStatus() { window.status="" } // --> </SCRIPT> Try this example: foo bar


[ Back to top ]

SECTION III. Dealing with Forms


RELOAD button: how do I make a button that will reload the current document?
You can make force the current page to reload by using assigning the function below to the onClick method of a button or link like this: funtion reloadIt() { history.go(0) } ... <FORM><INPUT TYPE="button" VALUE="Reload" onClick="reloadIt()"></FORM> Also look at the Back button.


When I use myRadio.value, the value is always <undefined>.
Try myRadio[i].value for i in [0,numRadioButtons] -- because HTML says that radio-buttons all have the same NAME attribute, they reflect as an array of button objects.


How do I cancel the submission of a form if the user input was invalid?
If you have a form that you would like to validate before submitting (and cancel submission if its invalid), then you would assign the form's onSubmit event handler to call your validation function. The important part is that in order to cancel the submission, your function would have to return false and the form would have to be declared as follows:
    function validate() {
     if (**test for valid input**)
      return true
     else return false
    }
    ...
    <FORM onSubmit="return validate()">
NOTE: you do not return false from the SUBMIT button's onClick handler! The former is sufficient and relieves you from having to write N onClick handlers if your form has N submit buttons -- you write an onSubmit handler once in the <form ...> tag.


How can I control the size of the buttons I create?
The customizing of buttons is very limited at present. There are no specific button attributes that can manipulate the way in which they are drawn. The only can to adjust a button's length is to change the text within it. Adding spaces or shortening phrases should do the trick.
  <INPUT TYPE="button" VALUE="Without spaces">
  

  <INPUT TYPE="button" VALUE="       Button with spaces       ">
  


JavaScript does not support <INPUT TYPE="image"> form objects.
There is currently no object in the JavaScript Hierarchy for IMAGE form elements. This means that you can not use the onClick Event Handler for this type of field.


You cannot evaluate of modify values entered into password fields!
Due to some security concerns that Netscape had at the time that their version 2.0 browser was released, you cannot 'look at' or evaluate the value of a password field.

This should be fixed with the release of Navigator 3.0 from Netscape which will include a 'data tainting' model which will allow scripts to see the value but limit where it can be sent off to.


[ Back to top ]

SECTION IV. Frames and Windows

One of the most dynamic uses of JavaScript is in conjunction with Frames. You can make cross-frame calls to functions/objects/variables in separate frames by simply calling something like the following:
    parent.myframe.myobj
    parent.myframe.myfunction(mylocalvariable)
Note that when you call a function in another frame, the scope of the parameters that are passed is local to the calling frame. If you want to call a function on a element in another frame, you could use something like:
    mylocalfunction(parent.otherframe.myvariable)
    parent.otherframe.myfunction(parent.otherframe.myvariable)
and explicitly declare which frames you are referencing.


BACK button: how does one frame make the other go back a page?
This is a simple task. Let's suppose you have two frames defined as follows:
    <FRAMESET COLSPAN="50,*">
     <FRAME src="navigationbar.phtml" name="nav" NORESIZE>
     <FRAME src="mainframe.phtml" name="info">
    </FRAMESET>

Then you could put this code in your navigationbar.phtml page to manipulate the info frame:
    <FORM NAME="buttonbar">
     <INPUT TYPE="button" VALUE="Go Back" onClick="parent.info.history.back()">
     <INPUT TYPE="button" VALUE="Go Home" onClick="parent.info.loaction="home.phtml">
     <INPUT TYPE="button" VALUE="Go Next" onCLick="parent.info.history.forward()">
    </FORM>

Alternatively, you could use the history.go(-1) and history.go(1) functions, as stated in the Netscape docs. Also look at the Reload button


What is the best way to synchronize the loading of frames
in order to avoid JavaScript error messages?

[Answer: Brendan Eich]
Sure, you can synch framed JavaScript execution to start only when the
whole frameset is loaded, but you have to write some JavaScript to do it.

In the top-most FRAMESET's ONLOAD handler, you can set a variable or
property of that window ("self.loadDone = true").  In all descendent
frame documents, you can make their first SCRIPT tag (or if there are no
SCRIPT tags only event handlers, in their BODY or FRAMESET tag's ONLOAD
handler) call the following function:

    function topWait(expr) {
       if (!top.loadDone) {
         // XXX expr had better not contain unescaped single quotes!
         setTimeout("topWait('" + expr + "')", 500)
       } else {
         eval(expr)
       }
     }

to do whatever work (expr, a string containing JavaScript code, most likely a
call to the "main" function for that document) needs to be done only
after the whole frame tree is loaded.

There are more complicated schemes that involve code in different frame
documents being very careful to test (parent.otherframe.forms != null &&
parent.otherframe.forms.length == 2), e.g., and not look for properties
or members of such object references until the test succeeds.


I've used window.open() to create a new window.
How do I reference my original window from the new one?
The method thats I've adopted to do this defines a new property for the window object that you can create in the following manner:
    var popWindow = window.open(myUrl,'myWindow')
    popWindow.creator = self
Now you can reference the original window and all its properties/functions/... from 'myWindow' with standard Javascipt syntax:
    ***code goes in popWindow's source***
    creator.document.myform.myfield.value = aNewValue;
Be sure you're aware of the known bug with window.open().


I've got a page that uses frames, how do I make a link that will come up in the whole window, erasing the frames?
If you've used the <FRAMESET> tag to create a framed web page, it is simple to have any of the links come up in the entire window. To erase the frames and utilize the entire window, try this:
    <A href="mypage.phtml" TARGET="_top">Go to my non-framed page</A>


How do I create a link that will update multiple frames?
You can easily use this method to update any number of frames you choose. They key is to utilize the link's onClick() event handler to call a function that will update the other frames. It could look like this: function changeFrames() { parent.frames[1].location = 'foo.phtml' parent.frames[2].location = 'bar.phtml' parent.frames[3].location = 'foobar.phtml' } ... <A href="#" onClick="changeFrame()">Change several other frames</A> Using a href="#" causes the location of the frame with the link not to change. However, if you wanted to load a new page in the current frame also, you could use this: <A href="nextpage.phtml" onClick="changeFrame()">Change this frame and others</A>


[ Back to top ]

SECTION V. Using arrays


How do I create/initialize an array in Javascript?

Netscape Navigator 3.0 will support a new object of type 'Array'. To create an array in 3.0, you can use any of the following:


How do I modify myArray.length?

To set an array's length, there's two chances for doing it: when you call the constructor, or anytime thereafter. To set the length when the array is initialized, use:
    var myArray = new Array(5)
NOTE however that you cannot directly set myArray.length with an assignment statement as it is read-only. If you'd like to change the array's length after it's already been created, you have to add an element to the array like this:
   myArray[9] = "This is the 10th element."
By adding an element in the Nth spot, you're forcing the arrays length to N+1. In this last example, myArray.length would now be set to 10.


[ Back to top ]

SECTION VI. Advanced Topics

This section will deal with concepts like efficient memory usage, arrays, and security problems to name a few.


What security risks are inherent in JavaScript?
Here's the current list of security holes and their status:

1) Read user's history -- fixed in 2.0
2) Read user's URL cache --   fixed in 2.0
3) Forge e-mail/steal e-mail address - fixed IN 2.01
4) Recursively list local disks - fixed in 2.01
5) Open 1 pixel window and log all URL accesses - STILL PRESENT IN 2.0
Netscape has done a fine job of handling security related issues with the release of Navigator 2.01. I have left the links to the *old* pages that exploited Navigator 2.0 so that users can test the fixes in 2.01.

The ability to forge e-mail/steal e-mail address from a visitor has been cut-off by disabling the submit() method on a form which has been defined as:

<FORM METHOD="POST" ACTION="mailto:foo@bar.com"> If you still want to send information in this manner, you must prompt the visitor to click on a 'submit' button. For an example of this, try our rogue example.

The only remaining concern that I am aware of is that a web page could open a 1x1 pixel window that can log all URL accesses made *after* its creation. However, I believe that on all platforms you will be capable of seeing this new window and be able to close it to prevent it from stealing your session of URLs. To see an example of this, go to http://www.osf.org/~loverso/javascript/track-me.phtml.

If you would like to reassure yourself that Netscape has corrected past problems, try these links to scripts that do not affect Navigator 2.01:

   Send a local directory listing to a remote server:
   http://www.osf.org/~loverso/javascript/dir.phtml

   Capture users history and cache files:
   http://www.c2.org/~aelana/javascript.phtml


How do I use JavaScript with Client-Side Image Maps?
While JavaScript currently doesn't have objects for the <MAP> and <AREA> tags, there is still a way to work around this. The workaround involves calling a JavaScript function from within the <AREA>'s HREF attribute. Be warned however that any time you use a href="javascript:foobar()" function call, you are burning ALL visitors that don't have JavaScript capable browser. They will get an error message when clicking on the link. Warnings aside, here's how you set up a Client-Side Image Map with JavaScript: <MAP NAME="foo"> <AREA SHAPE="circle" COORDS="169,169,7" href="javascript:bar(1)"> <AREA SHAPE="poly" COORDS="46,107 72,72 79,79 57,112 46,107" href="javascript:bar(2)"> </MAP> <IMG src="fooimage.gif" BORDER=0 USEMAP="#foo"> NOTE: There is currently no workaround for the problem that you can't use onMouseover with <AREA> tags. As far as I know it can NOT be done with Netscpae 2.x!


How do I automatically redirect visitors to the right page depending on whether they can/can't use JavaScript? [Answer: Brian Stoler]
This Snippet explains how to have one page for people viewing with JavaScript, and a different page for those blessed with the ability to run JS code. (Note that Netscape 2.01+ will correctly see the non-JavaScript page if JavaScript is disabled!) 1. Make a page with the "get a new browser" message. This is the one that will be seen by non-JS browsers. 2. At the top of this page, in the <HEAD> section, put the following: <SCRIPT LANGUAGE="JavaScript"> <!-- Hide the code from all well-behaved non-JS browsers location = 'URL to your JavaScript-ified page' // Unhide. --> </SCRIPT> That's it. Now any browser that does not execute the JS code (Even Netscape 2.01+ with JavaScript disabled,) will see the "get a browser with JavaScript" message, and all those with JavaScript will get to your page with the "goodies".


What happens when I recursively call setTimeout()?
[Answer: Brendan Eich]
A recursive function is one that calls itself under given circumstances or within set bounds. With a setTimeout() call, you can have a function seed itself (repeat a process). The following short example shows this best. (NOTE: This function should not be used as is, because it does not provide a means of checking if clock() is already running, along with other hazardous quirks. If you want, look here for a working example.)
    function clock() {
     new_date = new Date()
     window.document.form1.f_clock.value = new_date.getSeconds()
     id = setTimeout("clock()",1000)
    }

    <BODY onLoad="clock()">
In 2.0, the quoted expressions passed to eval() and setTimeout() are compiled into bytecode and retained for the life of the current document. So if you use setTimeout to arm another timeout, your application will bloat navigator over time. This bug will be fixed in 2.1.


How do I detect if a user has a certain plug-in?
Netscape Navigator 3.0 will support a new object called navigator.plugins[n] which is actually an array that holds a list of all the plug-ins and mimetypes that a visitors browser can handle. You can test this array to check it a user has a particular plug-in installed, and write their web-page dynamically based upon this information. Here's a few quick examples I've borrowed from the JavaScript Authoring Guide at Netscape:

The following script checks to see whether the Shockwave plug-in is installed and displays an embedded Shockwave movie if it is:

var plugin = navigator.plugins["Shockwave"]; if (plugin) document.writeln("<EMBED src="Movie.dir" HEIGHT=100 WIDTH=100>") else document.writeln("You don't have Shockwave installed!")

The following script checks to see whether the client is capable of displaying QuickTime movies.

var mimetype = navigator.mimeTypes["video/quicktime"] if (mimetype) document.writeln("Click <A href="movie.qt">here</A> to see a " + mimetype.description) else document.writeln("Too bad, can't show you any movies.")

For those of you interested, here's the old hack that was originally listed here.

    function probePlugIn(mimeType) {
      var havePlugIn = false
      var tiny = window.open("", "teensy", "width=1,height=1")
      if (tiny != null) {
        if (tiny.document.open(mimeType) != null)
          havePlugIn = true
        tiny.close()
      }
      return havePlugIn
    }

    var haveShockWavePlugIn = probePlugIn("application/x-director")

/be
NOTE: this suggestion is outdated and will cause the client to be prompted (whether to 'Pick an App', 'Save', or 'Cancel') if they do not have the plug-in. This message was posted as a means of reference for others to think about.


Send comments to Andy Augustine
© 1996 Frequency Graphics