Frames Test

# 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.

1. 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.

2. 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.

   1. 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.

   2. 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.

      1. 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.

      2. 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.

      3. 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.

      4. 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.

      5. 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.

   3. 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).

   4. 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.

3. 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.

4. 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.

   1. 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.

      1. 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).

      2. 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.

      3. 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.

   2. 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.

      1. 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).

      2. 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.