Freedom of Position
Cross-Browser positioning of DHTML divs/layers relative to old-style table flow
(IE4, IE5, NS4, NS6)
Thought you had to position everything relative to the top left corner of the page? Think again! Anywhere you can put an inline image, you can place a DHTML element on or under that image. The convention I used here is to name the positioner image by starting with the name of the layer/div and adding "Pos" (don't forget to use both id and name in the positioner's img tag; id is for IE4/IE5/NS6 and name is for netscape 4).
Try turning the mookie element's visibility on and off by clicking the arrow. Try resizing the browser window while the element is visible. Use your browser's view-source to see how simple it is to use.
Hello World |
Hello I'll get covered up |
view tjmlib.js source |
view html source |
skip to next example |
Netscape 4 will be unable to find the image if it is nested in a layer or two, because each netscape layer has its own images array. Really, I should add a method which will poke around all the layers of the document until it finds the positioner image.
Cross-Browser Techniques
Interesting fact: apparently you don't have to use the layer tag in
Netscape 4 at all! All div tags are available in the document.layers
array. This removes the need for any branching within the HTML, which
is nice.
The javascript is another story, though. Referencing elements in javascript across browsers can be a pain, but the tables that follow provide a quick reference that can make things easier. In IE and NS6, note that the style properties .left and .top are strings (eg, '45px') so you must be careful to call parseInt(...) to convert them back to numbers before you do any mathematical manipulation of positions.
div's style (.left, .top, .visible, etc.) | flowed image | |
NS4 | document.layers['div_id'] | document.images['img_name'] |
IE4/IE5 | document.all['div_id'].style | document.all['image_id'] |
IE5/NS6 | document.getElementById('div_id').style | document.getElementById('image_id') |
The crux of the example above is establishing the pixel offset of a 'flowed' image (meaning, not absolutely positioned or even styled in any way). Oddly enough, the only browser that exposes this directly is Netscape 4. In NS4, once you have a handle to the flowed image (see table above, last column), you simply use its .x and .y properties.
In IE and NS6, the image handle has properties .offsetLeft and .offsetTop, but these are relative to the parent container, and most images are nested several containers deep (especially if inside a table cell as in this example). IE and NS6 differ on what constitutes a container, but for obtaining an absolute offset, a simple recursive algorithm which walks up the parents and adds up all the offsets will work in both:
// get the true offset of anything on NS4, IE4/5 & NS6, even if it's in a table! function getAbsX(elt) { return (elt.x) ? elt.x : getAbsPos(elt,"Left"); } function getAbsY(elt) { return (elt.y) ? elt.y : getAbsPos(elt,"Top"); } function getAbsPos(elt,which) { iPos = 0; while (elt != null) { iPos += elt["offset" + which]; elt = elt.offsetParent; } return iPos; } |
Testing for different browsers
Finally, rather than mess around with the hairy navigator object, I
borrow a technique in common practice. I cut some corners by testing
for objects whose existence uniquely identifies the specific
javascript capabilities which I want to use.
global boolean | test | |
NS4 | isNS4 | document.layers ? true : false |
IE4/IE5 | isIE | document.all ? true : false |
IE5/NS6 | isDOM (is more DOM-compliant) | document.getElementById ? true : false |
In tweaking my example to work on NS6, I was pleased to find that we seem to be getting closer to a convergence in adherence to the CSS and DOM specs. If I had wanted to abandon back-compatiblity, I was able to tweak my javascript to get a version that worked for both IE5 and NS6 with no ugly browser-specific code.
Happy coding! -tom (tjmATcoolquotesDOTcom)
x My name is mookie. Try the date picker example. |