Cross-Browser DHTML Technote:
API For Setting CSSP Properties From JavaScript
Eric Krock, Netscape

Vladimir Ermakov, Netscape
 and
Marcell Ortutay,
Plugged In Enterprises

This document is outdated and the information in it should not be relied upon. It may no longer represent web authoring best practice. Please see the web-developer documentation index page for more up-to-date documentation.


INTRODUCTION

Positioning HTML Elements with Cascading Style Sheets (CSSP) is a W3C Working Draft (Since incorporated into Cascading style sheets, level 2) supported by Navigator 4.x ,Internet Explorer 4+ and the new Netscape Gecko browser engine implemented in Mozilla and Netscape 6 browsers. It enables you to position, hide, show, and stack HTML elements on the page using CSSP markup. Because CSSP markup is static and hard-coded, if you want to dynamically or conditionally position, hide, show, or stack HTML elements, you must access the CSSP properties of HTML elements from JavaScript through the browser's Document Object Model (DOM).

Because these browsers each offer a different Document Object Model, writing JavaScript code which sets CSSP properties and works on all of them the same way requires careful design and testing. Your JavaScript code must detect the user's browser and evaluate the appropriate code for that browser's Document Object Model. Navigator 4 had its own proprietary Layer DOM which has been deprecated and is not supported in Gecko. Netscape 6 and Mozilla are the first browsers to fully support the industry standard W3C DOM level 1, and it also has robust support in the W3C DOM level 2, including the CSS Interface which we use for CSS Positioning from JavaScript. IE4 and IE5 have partial support for the W3C DOM.  When writing code for the W3C DOM in Netscape 6 and Mozilla, not everything will work as-is in Internet Explorer 5 which also has some support of W3C DOM, so it will sometimes be necessary to use proprietary MSIE DOM features to set an application working on IE.

To make cross-browser DHTML development easier, this TechNote offers a freely downloadable, reusable, and modifiable cross-browser application programming interface (API) for setting CSSP properties from JavaScript on these three browsers. This API is based on earlier work done by Danny Goodman (see the View Source article CSS-Positioning: The Dynamic HTML Neutral Zone) and Mike Hall.

This API is being offered in the spirit of the open source initiative. It is freely downloadable, reusable, and modifiable. In order to make it easier over time to do cross-browser DHTML development by enhancing and expanding this API, Netscape requests (but does not require) that API enhancements and modifications be submitted to Netscape for possible inclusion in future revisions of this TechNote and API. If an enhancement is included in a future version of the API, the author will receive full credit and a link in the source code. For more details, see the section of this TechNote on submitting API enhancements.


CONTENTS

This TechNote is divided into the following sections:


WHAT YOU NEED TO KNOW

Before reading this TechNote, you need to understand the syntax of CSSP rules. In particular, you should know how to select elements by their ID attribute value (for example, "#fooelt" to select the element with ID=fooelt), how to declare that an element is positioned (with rules such as #fooelt { position: absolute } and #barelt { position: relative }), what the CSSP property names are (such as "left," "right," and "z-index"), and what the CSSP property values are (such as "200px" and integer z-index values).

If you need a basic introduction to CSSP, click through Netscape's Visual Tutorial on CSSP on the Dynamic HTML Presentations Page. Tutorials available elsewhere on the web are listed on Netscape's Dynamic HTML Additional Resources Page. For full details, see the CSS2 Specification on the W3C Technical Reports Page.

If you don't know how to detect what browser is being used to view the script, read the Ultimate JavaScript Client Sniffer to learn how.

To learn how to access CSSP properties from JavaScript in Navigator 4.x, click through Netscape's Visual Tutorial on Accessing CSS Properties from JavaScript via the Document Object Model on the Dynamic HTML Presentations Page.

For a general overview of the differences between the Navigator 4.x and Internet Explorer DOMs related to CSSP positioning from JavaScript and the approach this API uses to bridge them, read Danny Goodman's article CSS-Positioning: The Dynamic HTML Neutral Zone in View Source. This TechNote will not duplicate the contents of that article, so if you aren't familiar with the differences between the Navigator 4.x and Internet Explorer DOMs, please read that article now.

Finally, to learn more about the W3C DOM in Netscape Gecko and the MSIE DOM in IE5 I recommend Introduction to the DOM of IE 5/NS6 .


WHY SET CSSP PROPERTIES FROM JAVASCRIPT?

Netscape enthusiastically supports CSSP and recommends that you use CSSP markup whenever possible to position HTML elements on the page. It provides an industry-standard, cross-browser way to achieve fine control over the positioning of HTML elements. It is a far cleaner approach than the nested tables and invisible one-pixel-wide GIFs to which designers resorted for element positioning in previous versions of the browsers.

However, CSSP markup has one fundamental limitation. It is completely static and hard-coded. You cannot conditionally hide or show elements or dynamically position them using CSSP markup alone. For example, you can't create animations or hide or show text in response to mouse clicks. To do that, you must set CSSP properties from JavaScript.

Remember this rule of thumb: "What you can do with CSSP, do with CSSP. What you can't do with CSSP, do with JavaScript." In other words, if the value is static and never need change, set it with CSSP markup. If the value is conditional or must be set dynamically, set it with JavaScript.




NOTE: LAYER, ILAYER, DIV SRC= , AND LAYER DOM NOT SUPPORTED IN THE GECKO LAYOUT ENGINE

The following proprietary extensions supported by Navigator 4 are obsolete and will not be supported in the Gecko layout engine implemented in
Mozilla and Netscape 6:

  HTML extensions:

  Navigator 4.x Layer DOM extensions: These features should only be used within code that is evaluated on Navigator 4.x only to provide backward compatibility. New
code should be developed using HTML 4.0, CSS, and the W3C DOM supported in the Gecko layout engine.
For more details about how to transition code using proprietary features to support W3C standards, read  Transitioning from
Proprietary DOMs and Markup to W3C Standards.


DECLARING AN ELEMENT TO BE POSITIONED

To set an element's CSSP properties from JavaScript and have the code work compatibly across all browsers, you must do two things:

  1. Give the element a unique name.
  2. Declare the element to be positioned so that it is exposed by the Navigator 4.x DOM.
Rules for Naming Elements

You name an element by setting its ID attribute. (If the element is a LAYER tag being used for backward compatibility with Navigator 4.x, you also have the option of using the NAME attribute, but this LAYER tag attribute has been deprecated in favor of ID, so in general, use the ID attribute to assign names to all elements including the LAYER tag.) The name should comply with these guidelines:

Declaring Elements To Be Positioned

You declare an element to be positioned by using CSSP markup to specify the element's position property. (If the element is a LAYER tag, this step is not necessary; LAYER tags are used only to position content, so LAYER and ILAYER elements are considered positioned by default in Navigator 4.) Setting the element's position property to absolute (the default) or relative causes the element to be exposed in the Navigator 4.x DOM for positioning. (LAYER and ILAYER elements are automatically exposed in the Navigator 4.x Layer DOM; you do not have to declare them to be positioned elements.)

In this code sample, we declare the element "foo" to be absolutely positioned and the element "bar" to be relatively positioned:
 

<STYLE TYPE="text/css">
#foo { position: absolute; }
#bar { position: relative; }
</STYLE>
<DIV ID="foo"><P>some text</P></DIV>
<DIV ID="bar"><P>more text</P></DIV>

Elements that have been named and declared to be positioned in this way are accessible in DOM for positioning, hiding, showing, and z-order stacking.

To learn more about positioning I recommend reading Positioning with CSS2 article. It is very good at explaining differences between different positioning types, covering most important DHTML properties, and other common questions.


THREE APPROACHES TO CROSS-BROWSER DHTML MARKUP

When naming elements and declaring them to be positioned, there are three techniques you can use in your HTML markup: using a single named DIV or SPAN on all three browsers, dynamically generating a named DIV or SPAN on Internet Explorer 4.0,Mozilla and Netscape 6 and a LAYER tag on Navigator 4.x, and wrapping a named DIV or SPAN in a LAYER tag of the same name. The first approach should be your default, but sometimes the second or third approach simplifies the development of complex applications, so developers should be aware of all three techniques and use whichever is appropriate for a particular application.

Why DIV or SPAN instead of Other Elements?

DIV or SPAN are not the only elements which can be named and positioned. Other elements such as <P> can also be used in the same way. However, if the purpose of an element is to enclose content which is to be positioned, using DIV or SPAN helps to make that purpose explicit to anyone who is reading the markup, so use these two elements as your default choice for enclosing positioned content.

It is good HTML style to use DIV to enclose a section of one or more block elements (for example, <DIV ID="foo"><H1>A Header</H1><P>Some text.</P></DIV>) and to use SPAN to enclose content without block elements, such as text, inline elements, and/or images (for example, <SPAN ID="foo">Some <B>bold text</B> and an image <IMG SRC="baz.gif"></SPAN>). This complies with the two elements' intended uses in the HTML specification. However, the two elements are functionally equivalent and interchangeable in most situations. One exception: DIVs used within a TABLE may be displayed with a trailing line break; SPANs in a TABLE do not trigger a trailing line break.

Using a Single Named DIV or SPAN on all Three Browsers

Since Only Navigator 4.x supports the LAYER tag, the simplest way to create an element which is positioned in all browsers is to use a positioned, named DIV or SPAN, a technique which is supported by all browsers. In the HTML page's HEAD, you place a CSS style sheet that declares the element to be positioned:
 

<STYLE TYPE="text/css">
#foo { position: absolute }
</STYLE>

...and in the BODY, you place the named element itself:
 

<DIV ID="foo">
<H1>A header</H1>
<P>Some text</P>
</DIV>

Dynamically Generating a Named DIV or SPAN on Internet Explorer and Netscape 6, and a LAYER Tag on Navigator 4.0

For some applications, dynamically generating markup which is optimized for each browser will simplify development.

The cross-browser DHTML API included in this TechNote includes a function called genElt which generates a positioned, named DIV on Internet Explorer, Mozilla and Netscape 6, and a named LAYER or ILAYER on Navigator 4.x. Function genElt returns this markup as a string; the string can be written out by a document.write() statement, perhaps after being concatenated with other strings or enclosed in additional markup. A related function called writeElt generates the markup and writes it out in a single step. The only difference between genElt and writeElt is that genElt returns the markup as a string, whereas writeElt writes it out to the document window.

Functions genElt and writeElt have the same argument list, reproduced here for your reference:
 
name STRING. Name of element's ID
content STRING. Content written within element
left INTEGER. Left edge of element in pixels
top INTEGER. Top edge of element in pixels
z INTEGER. z-index of element
width INTEGER. width in pixels
height INTEGER. height in pixels
visibility STRING. "visible," "hidden," or "inherit"
backgroundColor STRING. Background color of element
backgroundImage STRING. Background image of element
clip STRING. Comma-delimited list (no spaces!) of 4 integers in top-right-bottom-left order. Sets clip.
relative BOOLEAN. If true, position relatively, else absolutely. On Navigator 4.x, this determines whether LAYER (absolute) or ILAYER (relative) is generated.
hideEltOnOlderBrowsers BOOLEAN. If true, return '' on Navigator 3.0, Internet Explorer 3.0, and older.
useDivInsteadOfLayer BOOLEAN. If true, generate DIV on Navigator 4.x, not I/LAYER.
classname STRING. CLASS attribute value for element

Here are some key features of genElt and writeElt to be aware of:

Here are some examples of function calls and the markup that they return on Navigator 4.0 ,Internet Explorer 4.0 and Netscape 6:
 
function call: genElt ("foo", "text")
markup on Navigator 4.0: <LAYER ID="foo">text</LAYER>
markup on Internet Explorer 4.0: <DIV ID="foo" STYLE="position:absolute; overflow:none;">text</DIV>
markup on Netscape 6 <DIV ID="foo" STYLE="position:absolute; overflow:none;">text</DIV>
function call: genElt ("foo", "<H1>header</H1><P>paragraph</P>")
markup on Navigator 4.0: <LAYER ID="foo"><H1>header</H1><P>paragraph</P></LAYER>
markup on Internet Explorer 4.0: <DIV ID="foo" STYLE="position:absolute; overflow:none;"><H1>header</H1><P>paragraph</P></DIV>
markup on Netscape 6 <DIV ID="foo" STYLE="position:absolute; overflow:none;"><H1>header</H1><P>paragraph</P></DIV>
function call: genElt ("foo", "text", 50, 25, 1, 200, 100, false, "red", false, "25,250,125,50", false, false, false)
markup on Navigator 4.0: <LAYER ID="foo" LEFT="50" TOP="25" WIDTH="200" HEIGHT="100" Z-INDEX="1" BGCOLOR="red" CLIP="50,25,250,125">text</LAYER>
markup on Internet Explorer 4.0: <DIV ID="foo" STYLE="position:absolute; overflow:none; left:50px; top:25px; height:100px; width:200px; z-index:1; background-color:red; clip:rect("25,250,125,50");">text</DIV>
markup on Netscape 6 <DIV ID="foo" STYLE="position:absolute; overflow:none; left:50px; top:25px; height:100px; width:200px; z-index:1; background-color:red; clip:rect("25,250,125,50");">text</DIV>

For more examples of using this function and elements which it can generate, see this function's autotest document testmark.html in the autotest suite.

Known Problem: Browser May Ignore Some Properties of Dynamically Generated Markup

If you are dynamically generating the markup for positioned elements via document.write() statements as these functions do, be aware of the following known problem and workaround. When you dynamically generate the markup for a positioned element, there are reports that browsers may fail to initialize some properties of the element's JavaScript object. In other words, even though you have written out the markup to set a particular property like clip, that markup may be ignored by the browser.

If you encounter this problem, the workaround is to explicitly set the property to the desired value using JavaScript after the document has loaded. (You should wait to set an element's properties until the document has loaded, because until the document has finished loading, you cannot be certain that the element's markup has been parsed and its JavaScript object has been created.) To evaluate code after the document has loaded, call the code from within the document's onload method, which is invoked when the document finishes loading.

The autotest suite for xbdhtml.js includes an example of this problem and the use of the workaround. The test document testmark.html uses function writeElt to dynamically generate the markup for several elements. One is a red rectangle with text. This element has the clip value set to hide most of its contents. In testing, I discovered that Internet Explorer 4.0 ignored the dynamically generated markup that specified the element's clip properties, so the entire element was displayed instead of the desired portion. To work around the problem, I added this code to get the element and set its clip property from JavaScript:
 

var frontElt = getElt ("frontelt");
setEltClip (frontElt, 25, 250, 125, 100);

The code is evaluated within the document's onload event handler to make sure it is called after the document loads.

Mike Hall has also reported experiencing this problem with the WIDTH and HEIGHT properties of dynamically generated LAYER elements on Navigator 4.x. The bottom line: Be aware that when you dynamically generate markup, the browser may ignore some property settings, but you can work around this problem by setting those properties from JavaScript after the document loads.

Wrapping a Named DIV or SPAN in a LAYER Tag of the Same Name

A third approach to creating a positioned element on all browsers is to wrap a positioned DIV in a LAYER tag of the same name. For example:
 

<LAYER NAME="foo">
<DIV ID="foo">Some text</DIV>
</LAYER>

Internet Explorer, Netscape 6 and Mozilla ignore the LAYER tag and processes only the DIV tag. Since the LAYER and the DIV have the same name, Navigator 4.x maps them to a single logical element. This is one more technique that is available if you wish to use a LAYER tag on Navigator 4.x and a positioned DIV on Internet Explorer, Netscape 6 or Mozilla.


DYNAMICALLY GENERATING OTHER BROWSER-DEPENDENT CONTENT

Whatever approach you choose to define the DHTML document's markup and structure (DIVs only, dynamically generated DIVs or LAYERs, or DIVs wrapped in LAYERs), you may still find it necessary to display different content on different browsers. This is particularly true if you wish to provide backward compatibility with older browsers.

For example, Navigator 4.x provides a powerful extension to the mailto: link which specifies the content of the mail message by using the syntax BODY=. If you're using Navigator 4.x now, click here to see it work. However, this BODY= argument is ignored on older versions of Navigator and can't be used reliably on Internet Explorer 4.0 because Internet Explorer 4.0 lacks an integrated email client with this functionality across platforms. So if you take advantage of this feature, you might wish to write out one mailto: link on Navigator 4.x that specifies the BODY. On Internet Explorer 4.0 and older browsers, you might write out another mailto: link that doesn't specify the body and also provide some extra text explaining what to put in the email body.

This TechNote's JavaScript code library, xbdhtml.js, provides four functions that test the browser vendor and/or version and then dynamically write out strings of text and/or HTML markup. These functions are particularly handy when used together with the is object defined by the Ultimate JavaScript Client Sniffer. Here is a table summarizing the functions:
 
Function Comments
dw(str, minVersion, maxVersion) Function name is short for "document write." Only document.write() str if browser's major version number is >= minVersion and <= maxVersion. For example, this code fragment will output "up to date" on Navigator 4.x and Internet Explorer 4 and "out of date" on older browsers:
dw("<P>up to date</P>", 4);
dw("<P>out of date</P>", 2, 3);

dwb(str, aBoolean) Function name is short for "document write boolean." Only document.write() str if boolean aBoolean is true. For example, this code fragment will output the browser vendor's name:
dwb("<P>Gecko</P>",is.gecko);
dwb("<P>Netscape</P>", is.nav);
dwb("<P>Microsoft</P>", is.ie);
dwb("<P>Opera Software</P>", is.opera);
sv(str, minVersion, maxVersion) Function name is short for "string version." Only return str if browser's major version number is >= minVersion and <= maxVersion. Otherwise, return empty string. Useful when concatenating long strings of conditional text and markup for various browser versions.
sb(str, aBoolean) Function name is short for "string boolean." Only return str if boolean aBoolean is true. Otherwise, return empty string. Useful when concatenating long strings of conditional text and markup for various browser versions.


HOW TO SET CSSP PROPERTIES FROM JAVASCRIPT ON ALL BROWSERS

All three browsers make CSSP properties of positioned, named elements accessible from JavaScript through their Document Object Model (DOM). However, the Navigator 4.x, Internet Explorer and W3C standard DOMs are different, so JavaScript code that sets CSSP properties on one browser usually won't work on the other browser.

To set an element's CSSP properties from JavaScript and have the code work compatibly across all browsers, you must do three things:

  1. Determine which browser the user has, using JavaScript browser-detect code like that in The Ultimate JavaScript Client Sniffer. Then, using code appropriate for the Document Object Model of the user's browser, you must:
  2. Get the JavaScript object representing the HTML element you wish to position.
  3. Set the element's properties to the desired values.7
This TechNote provides a library of JavaScript functions called xbdhtml.js. (If you want to look at the source code right away, skip to the section on Viewing and Downloading the API and this TechNote.) The purpose of this library is to make cross-browser DHTML development easier by providing a single set of functions which get elements and get and set their basic properties on Navigator 4.x, user agents implementing Gecko and Internet Explorer.  Here is a table summarizing the functions of xbdhtml.js. The first function, getElt, is most important because it is used to get the element's JavaScript object on Navigator 4.x, Mozilla, Netscape 6 and Internet Explorer. All of the other functions take the element as an argument and set its properties. For more details about the functions, see the comments in the source code.
 
Function Comments
getElt(name)
or
getElt(top-level-element-name ... grandparent-name, parent-name, name)
Gets the JavaScript object representing a named, positioned element. For a top-level (i.e. non-nested) element, the argument is the element's name (its ID attribute value). For a nested element, the argument list is a list of the enclosing parent element IDs, starting at the top level and going in order down to the ID of the element itself. For example, this code fragment will get the JavaScript objects for: 
  • a top-level positioned element with ID "foo" and
  • a second-level positioned element (with ID "child") which is nested inside a top-level element with ID "parent".
var fooElt = getElt("foo");
var nestedElt = getElt("parent", "child");

setEltVisibility(elt, value) Hide or show element or make it inherit visibility from parent. Argument value must be "visible," "hidden," or "inherit."
getEltVisibility(elt) Return values are strings "visible," "hidden," or "inherit."
moveEltTo(elt, x, y) Move elt to pixel location x,y within its coordinate system, which is the window content area for top-level elements or the parent element's coordinates for nested elements which have an absolutely positioned parent.
moveEltBy(elt, x, y) Offset elt's pixel location by x,y pixels.
setEltLeft(elt, x) Sets position of left edge of elt in pixels.
getEltLeft(elt) Returns left edge of elt in pixels.
setEltTop(elt, y) Sets top edge of elt in pixels.
getEltTop(elt) Returns top edge of elt in pixels.
getEltPageTop(elt) Cross browser Nav4 pageX equivalent
getEltPageLeft(elt) Cross browser Nav4 pageY equivalent
getEltWidth(elt) Returns width of elt in pixels.
setEltWidth(elt,width) Sets the width of elt in pixels
getEltHeight(elt) Returns height of elt in pixels.
setEltHeight(elt) Sets the width of elt in pixels.
setEltClip(elt, cliptop, clipright, clipbottom, clipleft) Sets element clipping area. cliptop, clipright, clipbottom, and clipleft are integers.
getEltClipLeft(elt) Returns left edge of clipping area of elt in pixels.
getEltClipTop(elt) Returns top edge of clipping area of elt in pixels.
getEltClipRight(elt) Returns right edge of clipping area of elt in pixels.
getEltClipBottom(elt) Returns bottom edge of clipping area of elt in pixels.
getEltClipWidth(elt) Returns width of clipping area of elt in pixels.
getEltClipHeight(elt) Returns height of clipping area of elt in pixels.
getCurrentWinWidth() Returns width of current window content area in pixels.
getCurrentWinHeight() Returns height of current window content area in pixels.
setEltZIndex(elt, z) Sets z-index (stacking order) of elt. z is a positive integer.
getEltZIndex(elt) Returns z-index (stacking order) of elt, which is a positive integer.
setEltBackgroundImage(elt, imageFilePath) Sets background image of elt to image at imageFilePath.
getEltBackgroundImage(elt) Returns file path or URL of background image of elt. Note: The return value strings are not identical on Navigator 4.x,Internet Explorer 4.0 and Gecko. On Navigator 4.x, we get back a string like "file:///F|/DHTML/xbdhtml/xbdhtml/images/redpole.gif". On Internet Explorer and Gecko  we get back a string like "url(images/redpole.gif)", so we trim off the leading "url(" and the trailing ")".
setEltBackgroundColor(elt, colorNumber) Sets background color of elt to colorNumber. colorNumber is an numeric color code like 0xffffff for white, or one of the 16 standard color names from CSS1 like "red."
getEltBackgroundColor(elt) Returns background color of elt as integer.


A HINT ABOUT BACKGROUND COLORS AND IMAGES

Two properties to pay special attention to for cross-browser compatibility are background color and background image, because Navigator, Gecko and Internet Explorer have significant differences in their implementations of these properties. Following are a few hints about making background colors work across all browsers.

To make the background color of a positioned element display behind the entire element area (not just the element's text) in both browsers, make the contents of the element a 1x1 TABLE with WIDTH and HEIGHT set to match the element's size in pixels. Place whatever contents you want inside the element inside the single cell of the TABLE.

If the background color of the element is static, hard coded, and never changes, you must set the attribute STYLE="background-color: red" (with the color name or number specified in place of "red") on the TABLE. If the background color of the element is to be settable from JavaScript, you must NOT set that attribute on the TABLE.

When you get the background color property for a positioned element, Navigator 4.x always returns the value as an integer color code. Internet Explorer returns a string which is either a leading "#" followed by a 6-digit hexadecimal RGB value, or a color name like "red." Netscape 6 and Mozilla return either an rgb string like "rgb(255,0,255)" or a color name like "red". To resolve this incompatibility, function getEltBackgroundColor automatically maps the return value on Internet Explorer and Gecko to the integer color codes returned on Navigator 4.x.

For more details about techniques for handling background color across browsers, see A Hint About Background Color in the TechNote on Setting CSS1 Properties from JavaScript and comments in the source of xbdhtml.js.




WHAT IS CSSP?

Shortly after publication of the W3C CSS1 recommendation, Netscape and Microsoft decided that they needed a way to position elements on the page without using tables and invisible gifs. They coauthored a draft specification for positioning elements called Cascading Style Sheet Positioning (CSSP) and submitted it to the W3C. This specification was later incorporated into the W3C CSS2 recommendation.



KNOWN PROBLEMS/BUGS

There is a serious bug in Netscape 4.74. <Style> tags have to have at least a space in between opening and closing tags <STYLE> </STYLE>, or the browser crashes. Keep this in mind when writing your script.


VIEWING AND DOWNLOADING THE API AND THIS TECHNOTE

You can view the source code of xbdhtml.js or download xbdhtml.ZIP for study (25K) or download a comment-free version of xbdhtml.js (xbdhtml.ZIP) for production use (12K). If you would like to download this TechNote to your local machine, just download this WinZIP-compatible ZIP file with all of the necessary files.


TESTING THE API

This test suite demonstrates that these API functions work compatibly across all three browsers.


SUBMIT YOUR ENHANCEMENTS!

This API is being offered in the spirit of the open source initiative. It is freely downloadable, reusable, and modifiable. In order to make it easier over time to do cross-browser DHTML development by enhancing and expanding this API, Netscape requests (but does not require) that API enhancements and modifications be submitted to Netscape for possible inclusion in future revisions of this TechNote and API.


ADDITIONAL RESOURCES