|
home / bulletins / 8 / page 2
The Cure For Small Menus
In previous HM releases, our KeepInWindow logic always forced the
lower edge of the menu to be (at least) just above the lower border of the browser window. When
we introduced the KeepInWindow overrides in HM 5.2, however, we had to change this
assumption; since it was possible that the user wanted the menu to remain exactly
where it was, even if part of it was below the lower browser window border. Therefore, we needed
to check for potential menu scrolling by looking at the locations of both the top and bottom
of the menus:
if(((this.yPos < WindowTopEdge)&&
(this.hasParent||
this.tree.TopKeepInWindowY))||
(MenuBottomEdge > WindowBottomEdge)){
This was all well and good; but what we forgot about is that the
MenuBottomEdge is not readjusted when the menu is repositioned upwards as
part of the normal KeepInWindow routine. So the actual
bottom edge of the menu in the window may no longer be where MenuBottomEdge
says it is. The fix for this, of course, is to ensure that MenuBottomEdge is
corrected whenever the menu is moved vertically:
if ((MenuBottomEdge > WindowBottomEdge) &&
(this.hasParent||this.tree.TopKeepInWindowY)) {
var dif = MenuBottomEdge - WindowBottomEdge;
this.yPos -= dif;
// 5.2.1
MenuBottomEdge = WindowBottomEdge;
}
This fix alone corrects both of the problems displayed on the previous page;
since in both of those cases the standard KeepInWindow logic should have
been applied. However, what if the user wanted a small, top level menu
to appear at a specific spot (utilizing the KeepInWindow overrides), and
that particular spot was near or at the lower border of the browser window?
In that case, we may still have a problem; since we added no checks
to the logic to ensure that the menu itself was large enough to accommodate
scrollbars. Our normal calculation for setting the scrolling height of a menu is
to take the larger of the available space for the menu (which is either the
height of the window itself or the difference between the current top of the
menu and the bottom of the viewable area of the browser window) or the minimum scroll
height (introduced with HierMenus 5.0)
plus two times the scrollbar height. In pseudo-code:
ScrollHeight = Math.max(available space,
minimum scroll height +
2x scroll bar height);
Nowhere in this calculation is the initial total height
of the menu accounted for; and thus HM 5.2 will, in the right combination
of circumstances, attempt to set the scrolling height of the menu to be
taller than the menu's total height. This results in a confusing, unhelpful
menu display; so beginning with HM 5.2.1 we will not apply scrollbars to a
menu if its total height is less then the height we need to display scrollbars
in the first place.
Spoofin' Safari
Safari, like most--if not all--other modern browsers, allows
an end user to "spoof" a different browser; that is, it allows the user to
surf to a site using Safari, while identifying itself as something other
than "Safari." Like the other browsers, Safari accomplishes this spoofing by
changing various identifiers within the browser itself. The most notable of
these changes is the HTTP User Agent string, which can be accessed in
JavaScript through navigator.userAgent.
In HM we try to avoid identifying specific browsers;
preferring, where possible, to identify specific features of a browser or
its general capabilities in order to make logical decisions. However,
there are some cases where we need to identify a particular browser or
browser version in order to work around an implementation difference
within that browser that cannot easily be identified otherwise. For
example, when Netscape changed the way offsetLeft and
offsetTop were utilized between verion 6 and 6.1, it became
necessary to identify these browsers and differentiate between
them in order to properly support menu positioning in both. In the case
of Safari, two HM behaviors are handled differently from its Gecko
counterpart. The innerHeight property of the window
object accounts for the space used or not used by the horizontal scroll
bars (Gecko doesn't), and Safari does not support the onload
handler of a frame element (later version Gecko browsers do).
In HM, when the need arises to identify a specfic
browser, we turn to the various properties of the navigator
object for the necessary information. This is the purpose of the
navigator object, to provide general information about the
client and its capabilities, and we prefer using it as opposed to sniffing
for the existence (or absence) of unique--but unrelated--JavaScript
objects or methods within that browser.
In past HM 5 versions, we've sniffed for Safari by looking
for the "Safari" keyword in the userAgent string as mentioned
above. When, spoofing, however, Safari's userAgent does not
contain the term "Safari." (Note that this is unlike Opera,
which does contain the "Opera" keyword even when spoofing.) Obviously,
a different approach will be necessary to identify the Safari browser.
As a result, we've created a slight tweak within
HM_ScriptDOM.js. The new code specifically related to Safari
spoofing is as follows:
HM_IsSafari = ((parseInt(navigator.productSub)>=20020000)&&
(navigator.vendor.indexOf("Apple Computer")!=-1));
HM_NS6 = ((navigator.product == "Gecko")||(HM_IsSafari));
While not the prettiest of code, it accomplishes our
goal; which is to identify the browser utilizing
only information within the navigator object. Safari does not
appear to alter the productSub or vendor strings in
any of its spoof settings, and to the best of our knowledge it is the
only browser which supplies both as above (and do contact us if you
know otherwise). Note that having identified Safari, we also include
it in the HM_NS6 class of browsers, so that in general it will
follow logic branches in the same manner that Gecko browsers do; true to
Safari's "like Gecko" capabilities. The HM_NS6 variable itself
is a misnomer (what we really mean is IsGecko) but for historical
and compatibility reasons we're leaving it as is.
Conclusion
As we mentioned at the outset, you may or may not
consider v 5.2.1 as being a required upgrade; but if you are an existing
HM 5 user and you are seeing or concerned with either of the problems
discussed here then you are encouraged to grab the new code. And new
users, of course, are always encouraged to start out with the latest
release.
Files Changed in HM 5.2.1
- HM_ScriptDOM.js
- HM_ScriptOPR.js
- HM_ScriptIE4.js
- HM_ScriptNS4.js
- optimized/HM_ScriptDOM.js
- optimized/HM_ScriptOPR.js
- optimized/HM_ScriptIE4.js
- optimized/HM_ScriptNS4.js
 
[previous]
|