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.html.
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.
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:
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.html" 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.
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) } ...
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.
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.html" name="nav" NORESIZE>
<FRAME SRC="mainframe.html" name="info">
</FRAMESET>
Then you could put this code in your navigationbar.html 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.html">
<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.html" 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.html' parent.frames[2].location = 'bar.html'
parent.frames[3].location = 'foobar.html' } ... Change
several other frames 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: Change
this frame and others
[ 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:
-
var tmp = new Array() // creates a new empty array object
-
var tmp = new Array(5) // creates an array with (tmp.length==5)
and elements (tmp[0]..tmp[4]) all set to null
-
var tmp = new Array("hi", 15.3, myVay)
// creates a 'dense' array with (foobar.length==3)
and elements (tmp[0]..tmp[2])
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.html.
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.html
Capture users history and cache files:
http://www.c2.org/~aelana/javascript.html
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: { image missing }
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:
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