body.htm in the "body" frame
This is a demonstration of using version 5 of Milonic DHTML Menus across standard frames (i.e., not iFrames).
The Frame Setup for this Sample
There are three frames in this example, meant to illustrate typical frame setups where navigation controls
are in a top frame and/or a side frame; this example shows both. Here, the "header" frame contains the
file header.htm, which holds the main menu at the top
of the browser window. The "side" frame contains the file side.htm, which holds the main menu shown
at the left side of the browser window. The "body" frame is meant to show your site's content; it currently
holds the file body.htm, which is what you're reading right now. Moreover, the "body" frame also contains
the the Milonic base .js files — milonic_src.js, mmenudom.js/mmenuns4.js
— along with standard "menu_data"
definitions for the submenus; defined in a file called menu_data_body.js for this example.
The frameset for the index.htm file is defined as follows:
<frameset framespacing="0" border="0" frameborder="0" rows="24,*">
<frame name="header" scrolling="no" noresize src="header.htm">
<frameset framespacing="0" border="0" frameborder="0" cols="129,99%">
<frame name="side" scrolling="no" noresize src="side.htm">
<frame name="body" src="body.htm">
</frameset>
<noframes>
<body>
<p>This page uses frames, but your stone-aged browser doesn't support them.</p>
</body>
</noframes>
</frameset>
Why is this Approach Necessary for Frames?
Each frame holds its own HTML page. A DHTML object, like a menu, only exists within the page
where it is defined. So, if you have all of your menus (main plus subs) in a navigation frame,
then those menus can only be displayed in the navigation frame. Since a dhtml object cannot
occupy two frames at once, if the menu is too big to fit in the frame, it gets clipped
("cut off") by the browser.
The way to avoid clipping is to have your main menu in the navigation frame, and open your submenus
in the content frame.
How this System Works
You have a main menu in a navigation frame that targets a content frame, where you will display your
content. If a main menu item opens a submenu, then the submenu will open in the content
frame, not in the navigation frame. The add-on module, mm_navframe.js, does
the work: It figures out which submenu to open, figures out where in the content frame to open the
submenu, opens it, and then closes it when appropriate.
Design and Layout Considerations
A main menu and its submenus open in different frames, but you do not want that fact to be obvious to
the user. You want the menuing system to appear as a seamless, visually unified menu. To achive
that effect, you must address various design and layout issues.
- No Frame Borders.
Make sure that you turn your frame borders off (see
the frameset code above). With the borders off, there will be no visible demarcation between
the main menu in the navigation frame and the submenu in the content frame.
- No Frame Scrolling.
Turn scrolling off in your navigation frames (see the frameset code above).
You wouldn't want your user to scroll the main menu out of sight!
- No Frame Resizing.
Turn resizing off in your navigation frames (see the frameset code above).
If your user could resize the navigation frame, it would spatially separate the main menu from its submenus.
- Frame Layout.
Your navigation frame should be adjacent to your content frame, with no
intervening frame.
- Menu Placement.
In a standard cascading menu system, one side of the main menu "touches"
one side of the first-level submenus that open from it. For example, suppose you have a horizontal main
menu at the top of the page, with vertical submenus that open beneath the main menu (like the menu at the
top of this page). In that case, the bottom of the main menu is adjacent to the tops of the first-level
submenus. To present a visually unified menu system that works across frames, you should place the
main menu in the navigation frame so that the side from which its submenus open touches the border between
the navigation frame and the content frame where the submenus will open.
Instructions
The following instruction tell you what you need to do to make the system work.
- Define your Main Menu and your Submenus Separately.
In this system, the main menu code and the submenu code must be defined separately, because they are loaded
into separate pages; the main menu in the navigation frame and the submenus in the content frame.
In this sample, we have two main menus, one for the "header" frame and one for the "side" frame.
Each of these main menus is defined in its own file; the main menu in the "header" frame is defined in
menu_data_header.js, while the main menu in the "side" frame is defined in
menu_data_side.js. The submenus, destined to appear in the content frame, are defined
in a third file, called menu_data_body.js.
- Coding a Main Menu.
Each main menu file should contain the menu style code and aI() item definitions for its respective
main menu; you do not define submenus or submenu styles in these files.
- Menu Styles.
Menu styles are not affected by the fact that the menu is in a frame, so define the menu style code
for the main menu just as you would any other menu.
- Menu Items.
The main consideration in coding the main menu is the coding
for the menu items; i.e., the aI() strings. How you code an item's aI() string depends on what you want
to do with that particular menu item. The following examples show how to code a menu item's aI() string
for various common tasks. For the most part, the aI() coding is the same
as with any other Milonic Menu system, with one exception: items that open a submenu must include
the onfunction and offfunction menu item properties, and those properties must be
set exactly as shown in the examples below.
- An Item that Opens a Submenu (no link).
An item that opens a submenu should be coded as follows:
aI("text=itemText;showmenu=submenuName;target=contentFrame;onfunction=openSubmenu();offfunction=closeSubmenu();");
where itemText is the text that you want to appear in the menu item,
submenuName is the name of the submenu you want to open,
and contentFrame is the name of the frame where you want the submenu to appear.
The onfunction and offfunction properties must be set exactly as shown in the code above.
- An Item that Opens a Page in the Content Frame (no submenu).
An item that opens a page in the content frame should be coded as follows:
aI("text=itemText;url=theUrlToOpen.htm;target=contentFrame;");
where itemText is the text that you want to appear in the menu item,
theUrlToOpen is the href to the url that you want to open,
and contentFrame is the name of the frame where you want the new page to appear.
- An Item that Opens a Submenu and Links to a New Page.
An item that opens a submenu when moused over, or links to a new page when clicked should be coded as follows:
aI("text=itemText;showmenu=submenuName;url=theUrlToOpen.htm;target=contentFrame;onfunction=openSubmenu();offfunction=closeSubmenu();");
where itemText is the text that you want to appear in the menu item,
submenuName is the name of the submenu you want to open,
theUrlToOpen is the href to the url that you want to open,
and contentFrame is the name of the frame where you want the submenu to appear when the item is moused over, or
the new page to appear when the item is clicked.
The onfunction and offfunction properties must be set exactly as shown in the code above.
- An Item that Opens a Page in a New Window.
You can have main menu items that open a page in a new window. Such an item would be coded the same way as you would
if you were not using frames.
aI("text=itemText;url=theUrlToOpen.htm;target=_new;");
where itemText is the text that you want to appear in the menu item,
theUrlToOpen is the href to the url that you want to open,
and _new causes the url to open in a new page.
- An Item that Opens a Submenu and Links to a New Page in a New Window.
OK... so you want it all. This can be done, but not within the scope of this system. To
do this, you'd need to open the url in a new window using a custom javascript function that you'd call
with the item's clickfunction property. Why? Because you cannot set two target properties in one
aI() string. If you really want to do this, post a question in the Milonic v5.0 Help Forum and I'll help you.
- Offsets for Submenus.
Using menus across frames intruduces some positioning issues that you do not face in a non-framed site.
We have to compensate for any positional offsets that are introduced by the frames themselves.
Depending on your frame layout, you may have to apply some positional offsets to make the submenus
open in the correct spot. You can adjust the location of where a main menu's submenus open by setting the
standard global properties, _subOffsetTop and _subOffsetLeft, in the menu_data code for the main
menu in question.
For example, the "side" frame in this sample is 130 pixels wide, but the
"header" frame occupies 100% of the browser window's width. This essnetially pushes the "body"
frame 130 pixels to the right. As a result, without an adjustment, a submenu opened from the main
menu in the "header" frame would open 130 pixels too far to the right. To compensate,
_subOffsetLeft is set to -130 in
menu_data_header.js, where the main menu in the "header" frame is defined.
Note that negative values offset to the left, positive values offset to the right, and a 0 does nothing.
Setting _subOffsetTop and _subOffsetLeft in
a main menu's javascript code (e.g., in menu_data_header.js) only affects
first-level submenus. Second-level submenus (sub-submenus) and higher derive their offsets from the
_subOffsetTop and _subOffsetLeft settings in the
javascript code for the submenus (e.g., menu_data_body.js).
- Delays.
With the framed approach, the standard global properties, _menuOpenDelay and
_menuCloseDelay, have no effect in the code for a main menu. Even though they
have no effect, these properties must still be defined in the main menu code (e.g., set them to 0) so
that you don't get " variable is undefined" errors.
- Coding the Submenus.
Define your submenu styles and aI() items separately from the main menu (i.e., in a separate file).
In this sample, the submenus that appear in the "body" frame, are defined in a separate file
named menu_data_body.js. The file for the submenu definitions should
contain the menu style code and the aI() item definitions for submenus only; you do
not define main menu styles or items in this file. There are no special, frame-related
considerations for coding the menu styles and menu items; code them as you would in any non-framed
Milonic Menuing system.
- Loading the .js Files into your Pages.
So... no you have all of your menus coded an in their separate files. Where do you load them? Some files
are loaded into the navigation frame, some are loaded into the content frame, and some are loaded into both.
- Files to Load into a Navigation Frame.
The main menu resides in the navigation frame. The page that you put in the navigation frame must therefore
load all of the javascript code that defines your main menu and makes it run. This code includes (a) the
base Miloinic menu code, (b) the menu_data code that defines your main menu, and
(c) the mm_navframe.js module.
- Load the Base Milonic Script Files.
Your navigation frame, which will contain your main menu, must contain the standard javascript code for loading
the Milonic base scripts (milonc_src.js and mmenudom.js/mmenns4.js).
- Load the menu_data_xxxx.js File that Defines your Main Menu.
After loading the base Milonic script files, you will load the menu_data_xxxx.js
file where you defined the main menu that you want to have in this particular navigation frame.
- Load the mm_navframe.js File.
After loading your menu_data file, you will load the mm_navframe.js file that you
got along with this sample. The mm_navframe.js file contains the code that lets the
menus work across frames. The file does not contain user-editable code, so do not edit the
mm_navframe.js file.
The code that you use to load all of this stuff into your navigation frame is fairly standard code. In this
sample, the header.htm file contains the following code, which is used to load the
.js files needed to place a main menu in the "header" frame.
<script type="text/javascript" src="../../milonic_src.js"></script>
<script type="text/javascript">
if(ns4)_d.write("<scr"+"ipt type=text/javascript src=../../mmenuns4.js><\/scr"+"ipt>");
else _d.write("<scr"+"ipt type=text/javascript src=../../mmenudom.js><\/scr"+"ipt>");
</script>
<script type="text/javascript" src="menu_data_header.js"></script>
<script type="text/javascript" src="mm_navframe.js"></script>
Line 1 of the above code loads one of the base scripts: milonic_src.js. Lines 2 through 5 of the above code
load the remaining base script: either mmenudom.js or mmenns4.js, depending on the browser that is being
used. Line 6 of the above code loads menu_data_header.js, which contains the
definitions for the main menu to be displayed in the "header" frame. Line 7 of the above code loads the
mm_navframe.js module.
Directory Paths. When loading the .js file, your would of course adjust the
paths shown in the <script> tags above, to relect your own site's directory structure.
- Files to Load into the Content (Body) Frame.
The submenus reside in the content frame. Any page that you put in the content frame must therefore
load all of the javascript code that defines your sumenus and makes them run. This code includes (a) the
base Miloinic menu code and (b) the menu_data code that defines your submenus.
- Load the Base Milonic Script Files.
Your content frame, which will contain your submenus, must contain the standard javascript code for loading
the Milonic base scripts (milonc_src.js and mmenudom.js/mmenns4.js).
- Load the menu_data_xxxx.js File that Defines your Submenus.
After loading the base Milonic script files, you will load the menu_data_xxxx.js
file where you defined your submenus.
In this sample, the body.htm file contains the following code, which
is used to load the .js files needed to have submenus in the "body" frame.
<script type="text/javascript" src="../../milonic_src.js"></script>
<script type="text/javascript">
if(ns4)_d.write("<scr"+"ipt type=text/javascript src=../../mmenuns4.js><\/scr"+"ipt>");
else _d.write("<scr"+"ipt type=text/javascript src=../../mmenudom.js><\/scr"+"ipt>");
</script>
<script type="text/javascript" src="menu_data_body.js"></script>
Examine this Sample
If you don't quite understand all of the instructions, compare them against this working sample.
Examine the .htm files to see how the frames are set up and how each page in its own frame loads
the files needed to make the menus work. Look at the menu_data_xxxx.js files to see which menus
are defined where, and how they're defined. If you still have questions, feel free to visit the
v5.0 Help Forums and ask for help
JavaScript Menu Courtesy of Milonic.com
Download a zipped version of this sample.