Dynamic Synchronized Frames the Navigator 4 version, cont'd
The SCROLLING= Attribute
The attribute that determines the placement of scrollbars for a frame is SCROLLING. The choice of word is important. It implies that scrolling should or should not be allowed. The appearance of scrollbars is secondary, being a visual representation of the frame's ability to scroll. Netscape invented the attribute and Navigator's handling of it is exactly as one would expect from the word chosen. If SCROLLING is set to "no", then the frame cannot be scrolled under any circumstances, not even through a script.
Explorer, as we have seen, allows scrolling, regardless of the attribute's value, programatically. On first glance, this would seem to be a fortuitous, but erroneous rendering of the attribute. Or is it?
In the Netscape HTML guide, we find the following definition for SCROLLING:
SCROLLING
specifies whether scrollbars are available on a frame:
YES specifies that scrollbars are always available. NO specifies that scrollbars are never available. AUTO specifies that the browser determines whether to display scroll bars based on the size of the frame and its content. If you do not specify a value for SCROLLING, the default value is AUTO.
According to the above, SCROLLING determines display, not functionality.
Conclusion: Navigator handles SCROLLING based on the attribute's presumed initial intention, not on Netscape's own specification.
In, Microsoft's SDK, this definition is given:
SCROLLING=AUTO | NO | YES
Specifies that the frame can be scrolled. If set to "AUTO," the browser determines whether scrollbars are necessary.
Here, SCROLLING determines functionality, regardless of display.
Conclusion: Explorer handles SCROLLING as a display property, allowing scripted scrolling, contrary to Microsoft's specification.
Luckily, a standard has been developed by the W3C. In the HTML4.0 Specification, the SCROLLING attribute has this definition:
scrolling = auto|yes|no
This attribute specifies scroll information for the frame window. Possible values
auto: This value tells the user agent to provide scrolling devices for the frame window when necessary. This is the default value. yes: This value tells the user agent to always provide scrolling devices for the frame window. no: This value tells the user agent not to provide scrolling devices for the frame window.
This definition is closer to Netscape's documentation, but reflects Explorer's implementation of the attribute. Confused? Welcome to the world of DHTML! To conform to the standard, Navigator will have to change its implementation and Microsoft its documentation. And the standard is left with a misnomer, since a better attribute would have been SCROLLBARS=.
The Navigator Workaround
The LAYER tag to the rescue! Yes, you read correctly. The LAYER tag makes its first appearance in these columns.
Even though we cannot scroll the frame, we can still move (scroll) positioned elements, within the frame. If we place the complete contents of the frame into a positioned element, and move the element vertically, we have a scrolling frame! We could use the DIV tag, as usual, but it requires more typing, is more prone to error, and is also interpreted by Explorer.
LAYER is ignored by Explorer and defines a positioned element through the tag alone for Navigator. We, therefore, enclose the BODY of the left frame and the top frame in a LAYER. Place a LAYER start tag (<LAYER>) immediately after <BODY>, and a LAYER end tag (</LAYER>) immediately before </BODY>. No attributes are necessary:
Left Frame HTML:
<HTML>
<HEAD>
<TITLE>Left Frame</TITLE>
</HEAD>
<BODY MARGINWIDTH=0 MARGINHEIGHT=0
LEFTMARGIN=0 TOPMARGIN=0>
<LAYER>
...page HTML as is...
</LAYER>
</BODY>
</HTML>
Top Frame HTML:
<HTML>
<HEAD>
<TITLE>Top Frame</TITLE>
</HEAD>
<BODY MARGINWIDTH=0 MARGINHEIGHT=0
LEFTMARGIN=0 TOPMARGIN=0>
<LAYER>
...page HTML as is...
</LAYER>
</BODY>
</HTML>
Moving the LAYER
Since the LAYER is the first positioned element in the frame's page, it can easily be referenced by its page-placement index. That is, document.layers[0]. Its original default page coordinates are 0,0. Depending on which frame it is in, it must move up or left, depending on the main frame's scroll offsets. For example, if the main frame has a pageYOffset of 53, the left frame's LAYER must be moved up by 53 pixels. In other words, the LAYER's top property must be incremented by minus 53 pixels, moving it up past the browser client window. This logic creates the following script for frames without scrollbars:
<SCRIPT LANGUAGE="Javascript1.2">
<!--
NS4 = (document.layers) ? 1 : 0;
leftFrame = parent.frames.leftGuy;
topFrame = parent.frames.topGuy;
if (NS4) onload = checkScroll;
function checkScroll() {
setInterval("scrollLayer()",10);
}
function scrollLayer() {
topFrame.document.layers[0].left = -pageXOffset;
leftFrame.document.layers[0].top = -pageYOffset;
}
//-->
</SCRIPT>
Determining Scrollbar Visibility
We of course, need a script compatible with the scrollbar visibility toggle, to be used in different applications, some with scrollbars, others without. Navigator 4 introduces the scrollbars property for the window object. scrollbars, in turn, has a single property of its own: visible. The purpose of scrollbars.visible is to enable authors to control scrollbar visibility through signed scripts, particularly if they are working in canvas mode. The visible property also stores the current visibility of scrollbars in a window as a Boolean value:
windowReference.scrollbars.visible = true/false;
Note: scrollbars.visible will store true if SCROLLING is set to "auto", or omitted. It stores false if SCROLLING is "no". SCROLLING="yes" is not properly reflected. Toggle your frame scrollbars with "auto" and "no".
The two Navigator scripts are easily combined into one using the value of scrollbars.visible to direct script execution:
<SCRIPT LANGUAGE="Javascript1.2">
<!--
NS4 = (document.layers) ? 1 : 0;
leftFrame = parent.frames.leftGuy;
topFrame = parent.frames.topGuy;
if (NS4) onload = checkScroll;
function checkScroll() {
if (leftFrame.scrollbars.visible) {
setInterval("scrollFrame()",10);
}
else {
setInterval("scrollLayer()",10);
}
}
function scrollFrame() {
leftFrame.scrollTo(leftFrame.pageXOffset,pageYOffset);
topFrame.scrollTo(pageXOffset,topFrame.pageYOffset);
}
function scrollLayer() {
topFrame.document.layers[0].left = -pageXOffset;
leftFrame.document.layers[0].top = -pageYOffset;
}
//-->
</SCRIPT>
Now let's create a cross-browser script and repeat the process for creating synchronized frames, step-by-step.
|