HierMenus CENTRAL: HierMenus In Progress. HierMenus 5.3 Release Notes (5/7) | WebReference

HierMenus CENTRAL: HierMenus In Progress. HierMenus 5.3 Release Notes (5/7)

To page 1To page 2To page 3To page 4current pageTo page 6To page 7
[previous] [next]

dir="rtl" Implementation Notes

As we worked through the various HM behavior problems that we saw in pages where directionality was set specifically to rtl, we discovered a number of cross-browser JavaScript/DOM quirks that may be of interest to all DHTML developers. Those quirks are the subject of the next two pages, and we'll divide 'em up by major browsers.

dir="rtl" in Internet Explorer

By far, the greater number of dir landmines sent our way was presented in Internet Explorer for Windows, version 5.0 or later (IE5 Mac doesn't seem to support rtl mode documents at all; nor does IE4 or earlier on Windows platforms). Some of the problems we encoutered in this particular browser were the result of coding assumptions on our part that probably shouldn't have happened, while others were the result of some unique positioning behaviors on the part of Internet Explorer.

x positioning not based on left of canvas

The biggest Internet Explorer difference in a page where directionality is set to rtl is that the x/y positioning of the page is altered so that position (0,0) is not the top left corner of the browser canvas. Instead, (0,0) is the top left corner of the browser window, when the browser window is fully scrolled to the right (or there is no horizontal scrollbar for the page). In other words, a left pixel position of 0 is located at a distance of clientWidth less than the right edge of the browser document.

This is not an easy point to visualize, so let's see if a simple graphic will help:

rtl documents in Internet Explorer

In the above graphic, we've opened an HTML document that renders wider than the width of our current browser window. In this scenario, with dir="rtl" in effect, Internet Explorer's default behavior is to move the vertical scroll bar to the left of the page, and then immediately "scroll" the page all the way to the right when initially displaying it. The net effect, then, is that the initial browser window is displayed with pixel position 0 in the top left corner of the screen, and in order to see the remaining portion of the document (to the left of the browser window), you must use the horizontal scrollbar.

Note that when the page is scrolled to the left, the left pixel positions become negative. Or, in other words, objects can be positioned in the area to the left of the initial browser window by setting negative left positions. However, if the browser window is resized, then position 0,0 is altered as described above--so that it's always positioned at:

(the right edge of the document)  - 
   (the width of the browser window)

This latter point is important. If you need to know what the offset between the left edge of the document and the actual pixel position 0 is (we'll revisit this in a moment), you'll need to refresh your calculation each time the window is resized (or simply retrieve it dynamically every time). Finally, note that this pixel positioning logic only applies when the document itself is wider than than the browser window. When the browser window is equal to or wider than the document, (i.e., when there is no need for horizontal scrolling) then pixel positioning on the document behaves as you would expect it to.

All this is well and good; but doesn't effect HierMenus directly, since all of our absolute pixel positions for permanently displayed menus are specified as simple x/y positions. And since the page content itself is right-aligned when dir="rtl", having the pixel positions be based on the right edge of the document allows the objects to appear within the user's default browser window--where they would expect them to appear. But understanding this scheme will help you understand the following points:

scrollLeft doesn't match pixel layout of page

In conjunction with the above, you might expect that the canvas's scrollLeft property (the property used by Internet Explorer to note the offset of the horizontal scrollbar) would initially be 0, to match the 0,0 pixel position of the left side of the window; and as you scroll the page to the left, scrollLeft would take on negative numbers. And, in fact, this is the behavior in IE 5.0.

In IE 5.5+, scrollLeft is never a negative number, and is initially set to whatever the distance is between the left edge of the canvas and the left edge of the browser window. As you scroll the page to the left, scrollLeft is gradually decremented until it reaches 0, the left edge of the document. We suspect Microsoft made this change between 5.0 and 5.5 to honor their documented scrollLeft behavior, which explicitly states that scrollLeft cannot be a negative number. In fact, specifically setting scrollLeft to a negative number results in it being automatically set to 0, a behavior that occurs in IE 5.0 as well (in IE 5.0, scrollLeft can have a negative number as the result of horizontal scrolling, but you cannot assign it a negative number). Microsoft's documentation for the scrollLeft parameter can be found here.

Perhaps the most common use of scrollLeft--and the use that is problematic for us in HierMenus--is to add it to the position of the mouse to arrive at a true x position for the mouse on the document, regardless of where the page is scrolled (in IE, the event.clientX property represents the position of the mouse in the window, not necessarily the x position of the mouse in relationship to the document). To determine what the mouse position is in Internet Explorer as it relates to the document, we might use this calculation:

var mouse_x_position = 
   document.documentElement.scrollLeft + event.clientX;

When dir="rtl" is used in IE5.5+ this calculation won't work; since scrollLeft is not necessarily in sync with the left x position of the document. Therefore, when these two conditions (IE5.5+ and dir="rtl") are true, we must subtract the horizontal offset--the distance between the left edge of the document and the left edge of the browser window--from the scrollLeft property to arrive at the position of the mouse as it relates to the actual document itself. Translated into HM code, our (abbreviated) adjustment looks like this:

var mouse_x_position = 
   HM_Canvas.scrollLeft + event.clientX;
if (HM_IE&&!HM_IE50W&&HM_f_RTLCheck()) 
   mouse_x_position-=
      (HM_Canvas.scrollWidth-HM_Canvas.clientWidth);

where HM_IE50W is a new sniffing variable we set up to tell us if the browser in question is IE5.0 Windows and HM_f_RTLCheck is a new function that tells us if the browser document is currently rendering in rtl mode:

// 5.3
function HM_f_RTLCheck() {
   if(HM_IE5M) return false;
   var TempElement=HM_MenusTarget.document.body;
   while(!TempElement.dir&&TempElement.parentNode) 
      TempElement=TempElement.parentNode;
   return ((typeof(TempElement.dir)=="string")&&
           (/^rtl$/i.test(TempElement.dir))) 
           ? true : false;
}

Note that simply referring to the offsetLeft property of the canvas will not be valid, since it is always zero (it is the outermost container and therefore its left pixel offset should be zero). And using the document.body.offsetLeft property directly would only be valid in pages where IE is running in standards mode.

Initial positioning of menus

When initially creating menus, we've always positioned them offscreen (way offscreen) so as to avoid a quirk in Internet Explorer where the initial horizontal/vertical scrollbars are expanded unnecessarily to make room for the menus (which are initially hidden and can't be seen anyways). Browsers do not expand their documents upwards or to the left of the initial browser window to accommodate these offscreen menus, making it an effective workaround.

When dir="rtl" in Internet Explorer, the positions to the left of the initial browser window (as described above), are actually negative pixel positions and therefore the browser will expand the canvas to accommodate them. This is not what we want, since the width of the document is then initially set to be much wider than it should. Therefore, when rtl mode is in effect, we'll create the menus at pixel position 0, instead of a left pixel position.

HM scrollParent and scrollbar inconsistencies

The automatic right-alignment of elements when in rtl mode in Internet Explorer caused some confusion with our internal elements, especially the scrollParent element and the individual scrollbars of scrolling menus. Specifically, in the past we've created these elements without an explicit left pixel position, assuming it would be 0 in all cases. Not true in Internet Explorer, where we found that both the scrollParent and scrollbars tended to drift slightly to the right or left of 0, causing some strange menu displays. To correct the problem we simply removed our original assumption and explicitly set the initial left pixel position of the newly created elements to 0px.

Similarly, with horizontal menus we never bothered to specifically adjust the width of scrollParent elements when we changed the width of the horizontal menus themselves. This resulted in horizontal menus where the menu border appeared in the proper dimensions, but the menu content--i.e., the individual menu items--were positioned as if the first menu item was in the rightmost slot of the menu. A picture's worth a thousand words:

previous HM horizontal rtl behavior

In HM 5.3, we correct this bug by ensuring that the scrollParent width is always set when its corresponding menu's width is set. This HM bug affected all rtl capable browsers, not just Internet Explorer.

On page 6 we continue discussing rtl mode issues.

To page 1To page 2To page 3To page 4current pageTo page 6To page 7
[previous] [next]

Created: October 23, 2003
Revised: October 23, 2003

URL: http://www.webreference.com/dhtml/hiermenus/inprogress/9/5.html

Justtechjobs.comFind a programming school near you






Online Campus Both