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 click me!
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)

All Articles:
  • Java meets Flash (server/client)
  • Freedom of Position (dhtml)
  • Freedom of Position II: Date Picker (dhtml)
  • Video Poker Obsession (optimization)
  • Tag, You're It! Chunk, the All-Purpose Template Engine (java)
  • Look, Ma! Real Scroll Bars! (flash 5)
  • Perl, curl, and HTTPS Post for XML