We are providing HierMenus to you at no cost. HierMenus code requires a confirmed membership with internet.com. Please register by clicking here and come back soon to download your free copy of HeirMenus code.
Click Here to Register

Site Navigation
Bulletins
About
Documentation
FAQ
Samples
Known Issues
Technology Jobs

internet.commerce

Partner With Us














          
internet.com

IT
Developer
Internet News
Small Business
Personal Technology

Search internet.com
Advertise
Corporate Info
Newsletters
Tech Jobs
E-mail Offers

 
HierMenusCentral Enhance the Functionality of Your Web Site with DHTML HierMenus.
    

home / documentation / reference / mini-tutorial: menu positioning

Menu Positioning

In HierMenus version 6, all menus support direct positioning via the TopMenuX, TopMenuY, ChildMenuX, and ChildMenuY configuration parameters. Further, each of these parameters support the use of String JavaScript expressions--normal, quoted JavaScript code that returns an integer to be used by HierMenus as the menu's left or top position. For those parameters that support String JavaScript expressions, HierMenus will reevaluate the JavaScript code provided each time it is referred to (in this case, each time the menus are repositioned or displayed) making them a powerful tool for your menu positioning needs.

Positioning Basics

Of course, there's no rule that says you must use expressions in the above parameters. If you know exactly where your top level menus are to be positioned (or HierMenus' default positions are adequate), then you can simply specify those positions as the values of your parameters. For example, this configuration:

HM_f_SetMenus({
   MenuID:"MyMenu",
   IsPermanent:true,
   TopMenuX:10,
   TopMenuY:130,
   ChildOffset:10,
   ChildOverlap:20
});

creates a permanently displayed menu called MyMenu and places it at pixel location (10,130). By default, all child menus displayed from this menu will overlap the right edge of the menu by 20 pixels, and will be offset 10 pixels downward from the menu item that spawns them. This simple configuration setting is plenty adequate for a great number of menu positioning needs.

String JavaScript Expressions

Using String JavaScript expressions in the TopMenuX and TopMenuY configuration parameter settings provides a tremendous amount of flexibility in the positioning of your menus, since it allows you to specify virtually any JavaScript code you can conceive of to dynamically provide to HierMenus the exact (x,y) location that you wish to place your menus in. For example, consider this configuration, similar to the above but modified slightly to use String JavaScript expressions for positioning:

HM_f_SetMenus({
   MenuID:"MyMenu",
   IsPermanent:true,
   TopMenuX:"HM_f_GetElementXY('image1','x')",
   TopMenuY:"HM_f_GetElementXY('image1','y')",
   ChildOffset:10,
   ChildOverlap:20
});

Now we've placed our top level menu in a significantly different place. By calling the HM_f_GetElementXY method (included in the HM_Loader.js file, more below) we're now placing our menu at the same (x,y) position as the element in our HTML page that we've identified as image1. And since we specified a String JavaScript expression (we enclosed the expression in quotes), it will be reinterpreted every time HM attempts to reposition the menus; therefore, when the user resizes the browser and the position of image1 changes as a result, then the menu will automatically be adjusted to image1's new position.

Before we continue, note here a key--and very important--difference between String JavaScript expressions, and normal JavaScript expressions (these are not standard JavaScript terms; we simply use them here to differentiate the two usages). With String JavaScript expressions, HM will reinterpret the expression every time it is required. With normal JavaScript expressions, HM will interpret the expression only once, immediately when the menu is registered. From then on, it will simply use the result of that initial expression each time the menu is repositioned. In HierMenus speak, a String JavaScript expression is one that is enclosed in quotes; a normal JavaScript expression is not enclosed in quotes. Let's have a look at our example again, only this time with normal JavaScript expressions:

HM_f_SetMenus({
   MenuID:"MyMenu",
   IsPermanent:true,
   TopMenuX:HM_f_GetElementXY('image1','x'),
   TopMenuY:HM_f_GetElementXY('image1','y'),
   ChildOffset:10,
   ChildOverlap:20
});

If you were to load this menu, you would probably find that initially the menu position is correct; since the expression does, after all, retrieve the same value that the String JavaScript expression returns above. However, if you were to resize the browser window, you would immediately see the significant difference: even though your image1 element position changed on the page, HM would not move the menu to match it. This is because HM stored the results of the expression the first time it saw it (when the page loaded) and then used this stored result every time it needed it after that.

While all HM configuration parameters support the use of normal JavaScript expressions, only a select few support the use of String JavaScript expressions. These include TopMenuX, TopMenuY, ChildMenuX, ChildMenuY, TopUponDisplay, TopUponHide, ChildUponDisplay, and ChildUponHide.

Keywords

When using String JavaScript expressions in the TopMenu/ChildMenu positioning parameters mentioned above, an additional feature is available to you that will allow you to fine tune the placement of your menus in relation to HierMenus' own default menu positioning scheme and/or the dimensions of the browser's viewport (the browser window). This feature consists of a set of specialized terms--called Keywords--that you can use within String JavaScript expressions in the menu position parameters (i.e., the TopMenu/ChildMenu parameters listed at the top of this tutorial). Each Keyword represents a specific location on the page and can be utilized in your JavaScript expression as such. The available Keywords include HM_default_x_position, HM_default_y_position, HM_window_top_edge, HM_window_bottom_edge, HM_window_right_edge, and HM_window_left_edge.

Let's have a look at a two menu example configuration that includes the use of Keywords in JavaScript expressions:

HM_f_SetMenus({
   MenuID:"MyMenu",
   IsPermanent:true,
   IsHorizontal:true,
   RepositionOnScroll:true,
   TopMenuX:"HM_window_left_edge+10",
   TopMenuY:"HM_window_top_edge+10",
   PositionChild:"below",
});

HM_f_SetItems(
{MenuID:"MyMenu",DisplayText:"Menu Item 1",ChildID:"MyChild1"},
{MenuID:"MyMenu",DisplayText:"Menu Item 2",LinkURL:"item2.html"},
{MenuID:"MyMenu",DisplayText:"Menu Item 3",LinkURL:"item3.html"},
{MenuID:"MyMenu",DisplayText:"Menu Item 4",LinkURL:"item4.html"}
);

HM_f_SetMenus({
   MenuID:"MyChild1",
   ChildMenuX:"HM_default_x_position-3",
   ChildMenuY:"HM_default_y_position-4"
});

We've omitted the menu items for MyChild1 (they're irrelevant for this example). Reviewing the above configuration, we see that our top level menu has been set based on the dimensions of the browser window; specifically, the menu has been set so that it will appear 10 pixels from the top and 10 pixels from the left of the browser window's top left corner. Further, note that the RepositionOnScroll parameter has been set to true; so that this menu will automatically slide into this top left corner position each time the user scrolls the page. (Without RepositionOnScroll, the menu would initially be placed at the top left corner of the browser window, but would not be moved from there unless the user resized the browser window.) When using the window_xxx_edge Keywords, you will nearly always want to set RepositionOnScroll (and/or IsFixed) to true.

Continuing with the example, notice that the child menus of MyMenu will automatically be positioned immediately beneath their parent menu items (PositionChild:"below"). However, looking at the definition for MyChild1, we see that this position will be slightly overridden via the use of the HM_default_x_position and HM_default_y_position keywords. In other words, the default position for this menu has been specified as directly beneath its parent item, and we are overriding that default via the use of the ChildMenuX and ChildMenuY parameters. Using these String JavaScript expressions, we are able to adjust that default setting:

ChildMenuX:"HM_default_x_position-3",
ChildMenuY:"HM_default_y_position-4"

Note that we use the ChildMenu parameters here, since the menu will be interpreted as a child menu when displayed beneath its parent menu item. The above expressions, in combination with the earlier PositionChild setting, instruct HierMenus to first position the menu directly beneath its parent item, and then raise it by 4 pixels ("HM_default_y_position-4") and then shift it to the left by 3 pixels ("HM_default_x_position-3"). The menu is then displayed in its new, adjusted location.

Of course, in order to make full use of the HM_default_x_position and HM_default_y_position keywords, you must know what HM's default positions are for each type of menu. That information can be gleaned from the following list:

  • For Top Level PopUp Menus the default position is the mouse position; that is, the position of the mouse when the menu was initially popped up. Users of HM 4 or 5 may be familiar with the mouse_x_position and mouse_y_position keywords. Since the default position of popup menus is the mouse position, using the new default keywords accomplishes the same thing as the old mouse position keywords did.

  • For Permanently Displayed Top Level Menus the default positions are always (0,0) (and are therefore not particularly useful).

  • For all Child Menus the default menu position depends on the configuration settings for ChildOffset, ChildOverlap, ChildPerCentOver, and PositionChild, with PositionChild taking precedence over all others, and ChildPerCentOver taking precedence over ChildOverlap. The individual defaults for each of these parameters can be found in their reference entries.

  • In all of the above cases, note that HM's KeepInWindow behavior will override the final position of the menu--i.e., even if you do provide a precise position with the TopMenu/ChildMenu parameters, if the menu's KeepInWindow parameters are set to true (as they are by default), then the menu will be moved so that it is contained--as best as possible--within the user's browser window. Or in other words, the KeepInWindow behavior is always applied last, after all other menu positioning logic is taken into account. You can override HM's KeepInWindow behavior on a menu by menu basis by adjusting the TopKeepInWindowX, TopKeepInWindowY, ChildKeepInWindowX, and/or ChildKeepInWindowY parameters.

Custom Functions

To specifically assist you in your menu positioning endeavors, HM includes three custom functions in the HM_Loader.js file that will allow you to position menus in the center of a document, based on their dimensions (width and height), or relative to the position of a known, separate, non-HM element elsewhere on your HTML page.

HM_f_CenterMenu

HM_f_CenterMenu returns the centered left position of a menu within the user's current browser document. It is typically called from within the TopMenuX/ChildMenuX parameter settings. To use it, you pass to it the MenuID of the menu you are positioning. HM_f_CenterMenu will retrieve that menu, examine its width, compare that width to the current width of the browser document, and return the appropriate integer for use in the left (X) setting of the menu.

Example settings:

TopMenuX:"HM_f_CenterMenu('hm_m_main')",
    // center hm_m_main when displayed as a top level menu
ChildMenuX:"HM_f_CenterMenu('hm_m_products')",
    // center hm_m_products when displayed as a child menu

HM_f_GetMenuDimension

Using HM_f_GetMenuDimension, you can position the top/left corner of your menu based on the current width or height of the menu itself, and thus achieve bottom or right-edge based menu positioning. HM_f_GetMenuDimension was covered in detail in Bulletin 11, when it was introduced back in the HierMenus version 5 release cycle. We refer you to that discussion for further information. Note that when we intially released the code it was called HM_fc_GetMenuDimension, but when you refer to the function in HierMenus version 6, you must do so via HM_f_GetMenuDimension. Other than that, the new version 6 function works in the same manner as described in Bulletin 11.

HM_f_GetElementXY

A new entry for HierMenus version 6 is the inclusion of the HM_f_GetElementXY function in the HM_Loader.js file. As its name implies, HM_f_GetElementXY allows you to retrieve the (x,y) position of a non-HierMenus element within your HTML page. You can then use that position to help you decide where to place a menu. In the following example (duplicated from above):

HM_f_SetMenus({
   MenuID:"MyMenu",
   IsPermanent:true,
   TopMenuX:"HM_f_GetElementXY('image1','x')",
   TopMenuY:"HM_f_GetElementXY('image1','y')",
   ChildOffset:10,
   ChildOverlap:20
});

We place our menu at the exact position of an image in our page that we have identified as image1 (i.e., we assigned a name and id to the image of image1). You may also feel free to offset the menus from the position you retrieve by simply extending your String JavaScript expressions:

HM_f_SetMenus({
   MenuID:"MyMenu",
   IsPermanent:true,
   TopMenuX:"HM_f_GetElementXY('image1','x')-10",
   TopMenuY:"HM_f_GetElementXY('image1','y')+20",
   ChildOffset:10,
   ChildOverlap:20
});

While HM_f_GetElementXY works perfectly in many situations, there are, unfortunately, several browser specific scenarios where the (x,y) of the target element is not properly found. We present a list of those problems we know of below. To avoid these problem scenarios in general, we recommend that you target page links or images, both of which should have unique name and id attributes (necessary for Netscape 4). Further we recommend that your target link or image does not itself have a border, and that it is not itself enclosed within a positioned element (relative or absolute).

We conclude this mini tutorial with a look at those browser specific problems when using HM_f_GetElementXY that we are aware of. The list is grouped by browser. Note that in some cases the problems can be worked around by slightly altering your HTML.

Netscape 4.x
  • Only named images, named links, and layers are supported. When using images or links, note that a name attribute must be provided. For maximum compatibility with all browsers, we recommend including both the name and the id:

    <img name='myImage' id='myImage' width='10' ....
    Of course, pursuant to HTML standards, the identifier you choose for your image or link should be unique within the page.

  • Netscape 4.x will also not properly locate images or links that are themselves nested within another layer (HM_f_GetElementXY does not recursively search Netscape 4.x layers).

Netscape 6.x
  • In Netscape 6.0x, td's with single pixel rules (i.e., the default if the table has a border of any size) will not be properly located. Specifically, they will be one pixel off. A possible work around is to place something inside the td, locate that something, and then substract to get to the rule.

  • Netscape 6.x will not properly locate a non-table item that itself has an inherited border width (from a style sheet rule) or an inline border width that is set using something other than pixels. In both cases, the position returned will be off by the width of the border.

  • In Netscape 6.1-6.x the above problem extends to any object that qualifies under the inherited border width rule, as well as any element that is itself nested within an element that qualifies under the rule above.

Mozilla/Netscape 7.x
  • Elements that are, or are within, fixed position elements will not be properly located.

Internet Explorer 4 (Windows)
  • Items that are within margins that are not set using inline styles, or that are set using lengths other than pixels or percentages, will not be properly found. They'll be off by the width of the margins.

Internet Explorer 5 (Windows)
  • IE 5.0 (Windows) incorrectly calculates bordered container items (P, DIV, etc) other than tables, rows, and cells; but only if the item itself is the target. Workaround: Insert something into the container such as an image, find it, and then offset your result by the width of the container's border.

  • Items nested within a relatively positioned object without height/width settings are not properly found. Adding a specific height or width to the relatively positioned object before it is located corrects the problem.

Internet Explorer 5.5/6
  • Items nested within a relatively positioned object without height/width settings are not properly found. Adding a specific height or width to the relatively positioned object before it is located corrects the problem.

Safari 1.x
  • Safari will not properly locate any absolutely positioned element (or any element within an absolutely positioned object) unless the absolute positioning was applied directly to the position property via script, or via an inline style setting on the element itself. The position reported will be off by the width of the page margins.

Konqueror 3.1
  • If the document's default page margins are changed, and this change is accomplished using style sheet rules, or an inline style on the body tag that specified length units other than pixels or percentages, then all non-positioned objects on the page will not be found properly.

  • Related to the above, items that are themselves, or are within, absolutely positioned objects, where the absolute positioning is set via a style sheet rule and not via an inline style or directly by script, will not be reported properly. The same rule as above applies; except in this case we do not know that the item we're looking for is within an absolutely positioned object, and we therefore (incorrectly) apply the margin correction as above.

  • Absolutely positioned objects where no top or left property is set will not be properly located.

  • Any element that is not in a proper HTML container will not be properly located. (A common example is an image directly within the body of the document but itself without any valid parent container, which is invalid HTML). In most cases, Konquerer 3.1 will simply report the element's position as (0,0) no matter where it is on the page.

Internet.com
The Network for Technology Professionals

Search:

About Internet.com

Legal Notices, Licensing, Permissions, Privacy Policy.
Advertise | Newsletters | E-mail Offers

Created: 3/25/2004
Updated: 2/7/2007
URL: http://www.hiermenuscentral.com/documentation/reference/menupositioning.html