|
home / bulletins / 9 / page 4
Following Directions
It's recently been brought to our attention that HM does not display
menus properly in HTML pages in which the text direction of the HTML document was set
to rtl (right-to-left). After investigating the issues involved in the faulty
display, we found that some of the problematic behavior was due to simple bugs or
"misunderstandings" between HM and various browser's handling of rtl documents;
while other problems resulted primarily from HM not properly applying the correct
behavior to its own menus in rtl settings. On this page, we'll discuss the
behavioral adjustments we've made to HM to allow it to render rtl pages as
we believe document authors actually intend; on the next page
we'll discuss those internal problems and misunderstandings, which partially affect
both the Internet Explorer and Gecko-based browsers.
Introducing dir
For those unfamiliar with the HTML dir attribute, a
quick introduction is in order. Available since the HTML 4.0 recommendation,
the dir attribute, when placed on an element, defines the default
directionality of contained text and tables which themselves do not have
specific directionality applied; via subsequent lower level dir
settings or precise UNICODE definitions. A full description of the
dir attribute can be found here:
http://www.w3.org/TR/html4/struct/dirlang.html#adef-dir
While we won't dwell at length on the individual properties
of right-to-left language script (indeed, we would hardly be qualified, anyway),
you should know that when the dir attribute is set to rtl on
the <html> and/or <body> element of a document, the
browser significantly changes certain aspects of that page's display. It is
precisely these changes that prompted our behavioral changes in HM 5.3. While
this is certainly not an exhaustive listing (a full understanding of the
bidi--Bi-Directional Algorithm--is necessary for that, and
well beyond the scope of this document) these more general adjustments are
worthy of our immediate attention.
Most elements are right-aligned.
This includes the document's text and tables. And
since the dir attribute is automatically inherited by almost
all elements of a page, this right alignment will occur within the
page's individual container elements, as well.
Table layouts are reversed.
This is a main feature of dir. When a table
is set to dir="rtl" (or the table is neutral and one of the
table's containing elements is set to dir="rtl"), then the
individual columns of the table are reversed; that is, the first
column of the table is placed at the far right of the table layout,
the second column to the left of the first column, and so on.
The vertical scroll bar, if one is present, is moved to
the left side of the page.
This last behavior is, at least as of this writing, applied
by default only in Internet Explorer v5 or later.
HM Behavior When dir="rtl"
Not all browsers support the above dir behaviors; most
older browsers (including NS4, IE4, and IE5 Mac) will simply ignore the dir
attribute and display the page as it would normally.
For the first point, that of elements and their contents being
right-aligned, it's important to note that this right alignment will be applied
to the contents of HM menus as well; meaning that your menu item descriptions will
be right-aligned within the menu items themselves. This is due to the fact that
dir settings are inherited from parent items, and all HierMenus have, as
their immediate parent item, the document's body element. This actually
happens automatically with no changes or intepretations necessary in the HM
script, therefore no changes were necessary to accommodate this behavior.
We were tempted to ignore the second point--i.e., table layouts being
reversed--since HM doesn't create tables (menus and menu items
within them are represented internally as <div> elements). However, a
good argument could be made that our horizontal menus strongly resemble table layouts;
both in the way they are displayed and in the way they are defined (via the
HM_Arrays definitions). Therefore, horizontal menus on pages where the
direction setting is right-to-left will indeed be reversed, beginning with HM 5.3.
You needn't do anything internally in HM to accomplish this; it will happen
automatically as a result of the dir="rtl" setting of the document's
<html> and/or <body> tag. The exception will be
when HM's own HM_RightToLeft parameter is explicitly set on the menus,
a scenario that will be discussed a little later on this page.
Finally, point 3 of the above page-behavior modifications
required multiple adjustments to the HM code; but all of these were a result
of bugs in HM or incorrect interpretation of Internet Explorer behavior where
rtl processing is concerned. For those who are interested, these points
are described on the next page.
What About HM_RightToLeft?
HierMenus has long supported the global, page, and menu specific
parameter RightToLeft which indicates whether or not a menu should, by
default, spawn child menus from the left side of the menu or the right side of
the menu (and the corresponding "more" image is also positioned on the right or
left, accordingly). Prior to HM 5.3, the default setting of HM_RightToLeft
was false; but beginning with HM 5.3, HM_RightToLeft will take
on the default directionality of the document in question (assuming that you have
not specifically set HM_RightToLeft in your own configurations, in which
case your specific setting always wins). In other words, if you specify dir="rtl"
in your document, and you do not explicitly set HM_RightToLeft
on the global, page, or menu specific level, and a visitor hits your pages with a
browser capable of rtl rendering, then HM will assume that the HM_RightToLeft
setting for that scenario is true. In all other scenarios, including the
scenario where a user hits your site with a browser incapable of rtl
rendering (such as NS4), HM_RightToLeft is set as false.
Two other minor behavioral differences are being introduced
in conjunction with HM_RightToLeft. First, if the page itself is set
to right-to-left processing (i.e., dir="rtl" is set on the page's
<html> and/or <body> tag) but the HM_RightToLeft
parameter has been set to false, then the menus will be created as if there
was no rtl setting on the page. This allows page authors to set up
pages where the general directionality of the page is right-to-left, but
where the individual menus themselves--including the menu item contents--are
displayed left-to-right. Secondly, for variable width menus that display
their first child menus via the position_under parameter, those child
menus will be right-aligned with their parent menu items when displayed, instead
of left-aligned:

In this standard menu with position_under set, the page directionality
is set to ltr and the child menu aligns itself with the left side of
its parent item.

Here's the same menu; this time with page directionality set to rtl.
Note that here the child menu is aligned with the right edge of
its parent item. Note also that the menu items have been reversed; the first menu
item is displayed at the far left of the menu.
Having introduced new behaviors for the HM_RightToLeft
parameter, we need to provide a new documentation entry for it:
HM_GL_RightToLeft
and HM_PG_RightToLeft
- Description:
- Controls the cascade direction of child menus, right/left
positioning of more images, and horizontal alignment of position_under
child menus in relation to their parent items.
- Value:
- Boolean (true/false,1/0) or any expression that
evaluates to a true/false value.
- Comments:
- This parameter can also be set on the menu tree level,
as the 18th parameter in the configuration array of top level menu
items.
Prior to HM 5.3, RightToLeft had no effect on the horizontal
positioning of position_under child menus. This behavior was
added with HM 5.3.
Prior to HM 5.3, the default for RightToLeft was always
false. Beginning with HM 5.3, the default RightToLeft
setting follows the directionality setting of the document, in
combination with the browser's rtl display capabilities. i.e.,
If the browser is incapable of rtl displays, then HM_RightToLeft
is set to false by default. If the browser is capable of rtl
displays and the page is marked as an rtl page, then
HM_RightToLeft is set to true.
Prior to HM 5.3, specifying HM_RightToLeft as false
on a page where directionality is set to rtl would only affect
the placement of the more image and which side of the menu child menus
are spawned from; it would not alter the actual dir
setting of the menu, which would contnue to display right-aligned
items. Beginning with HM 5.3, when HM_RightToLeft is set to
false on a page where dir="rtl", then all menus
that it (HM_RightToLeft) pertains to are explicitly set to
dir="ltr", allowing the page author to truly override the
directionality on a menu tree by menu tree basis.
- Examples:
- RightToLeft processing should be applied to menus:
HM_GL_RightToLeft = true;
RightToLeft processing should not be applied to menus:
HM_PG_RightToLeft = 0;
- Default:
- Follows the HTML dir setting of the page. Default is
false for all browsers that do not support dir.
Advanced Topics
Adjusting Menu PopUp Location
By default, menus that pop up from an in-page link will be displayed
at the current mouse position. That is, the top-left corner of the menu will
be displayed at whereever the mouse was when the popup menu was triggered. In some cases
this isn't appropriate for pages where directionality is set to rtl, since the
links are most likely right-aligned on the page. You can therefore use the following
menu positioning code in your own HM_Arrays implementations to conditionally
place either the top-left corner of the menu at the mouse location, or
the top-right corner of the menu at the mouse location:
function HM_f_GetMenuOffset(menuNum) {
var menuID = HM_MenuIDPrefix + menuNum;
var WidthEL =
HM_DOM ? HM_MenusTarget.document.getElementById(menuID) :
HM_IE ? HM_MenusTarget.document.all(menuID) :
HM_MenusTarget[menuID];
var menuWidth = 0;
if (WidthEL) {
if (HM_NS4) {
return WidthEL.clip.width;
} else {
if (!WidthEL.sizeFixed) WidthEL.fixSize(false);
menuWidth = WidthEL.offsetWidth;
}
}
if(HM_IE&&HM_DOM) return (menuWidth+16);
else return menuWidth;
}
HM_Array1 = [
[150, // menu width
"mouse_x_position - " +
"(HM_f_RTLCheck() ? HM_f_GetMenuOffset(1) : 0)",
// left_position
, // top_position
,,,,,], // etc.
["Experts","/experts/",1,0,1],
["Contents","/index2.html",1,0,0],
...
In the above code, we use a custom routine which returns the width
of the menu specified (pass the menu array number in as the argument) and we subtract
that number from the current mouse position if the page is being displayed in rtl
mode. If the page is being displayed in standard ltr mode, then the mouse
position is used as is without any change. The page directionality check is facilitated
via a built in HM procedure, HM_f_RTLCheck, which you are welcome to call
on your own. It returns a simple true or false, and it is included
in all of the HM scripts so you can use it generically in your menu array
configurations (in the IE4 and NS4 scripts it simply returns false immediately).
Adjusting PopUps for IE Quirk
A quirk of the IE browser, which we'll go into a bit more
thoroughly on page 6, makes it extremely difficult to know if the mouse
position reported when the menu actually pops up is accurate in rtl
settings. For this reason, if you use dir="rtl" and your vertical
page scrollbar is always visible, we recommend that for Internet Explorer
you always adjust the mouse position by the width of the scrollbar (typically
about 16px). In the above solution we accomplished this by adding the 16px
within HM_f_GetMenuOffset, but you could just as easily add it
directly to your menu positioning logic:
HM_Array1 = [
[150, // menu width
"mouse_x_position - "+
"(HM_DOM&&HM_IE&&HM_f_RTLCheck() ? 16 : 0)",
// left_position
, // top_position
,,,,,], // etc.
["Experts","/experts/",1,0,1],
["Contents","/index2.html",1,0,0],
...
This is admittedly kludgey, but as we'll describe on page 6,
a more graceful means of discovering the perfect pixel location of the
mouse in Internet Explorer pages where rtl is set has so far eluded
us. Since the offset is fairly small, you might choose to subtract
about 8px from the mouse left position of popped up menus, as a compromise
solution that will look a little awkward, but still acceptable.
Having discussed HM's new behavior in regards to right-to-left
processing, we'll now turn our attention to some of the
behind-the-scenes details. Those not interested in knowing
or understanding the finer aspects of cross-browser compatibility and JavaScript
right-to-left processing might wish to jump to the last page
of this article, where we'll discuss the remaining fixes incorporated into
this HM release.
      
[previous] [next]
|