Forum Moderators: open
If it still occurs to anyone to do this, what's used, then, are simply fixed position elements. That's fine for Firefox and Opera. But 20-30% of the browsers is use are still IE 6. And IE 6 needs 'floaters'. It has no fixed positioning.
This was encouraged by a thread in the CSS forum, using CSS inline javascript expressions to float an element. Problems were suggested with using CSS expressions. And if scripting is switched off, it's also off for such expressions. It occurred to me that the old floaters could still be used, for IE 6, for produce a similar, if 'jittery' effect. They were, after all, used as substitutes for, fixed, back in 'the day'.
There were two ways to approach it. Use attachEvent, or a single handler. First I tried attachEvent, quickly discovering the Dean Edwards/Zijdel workarounds to account for context and garbage collection. But I couldn't get these to work for 'onscroll'. They worked otherwise, but not for that. So instead, I used a single handler, attaching various elements to it, rather than taking separate elements and attaching event handlers as Edward/Zijdel and the orig attachEvent.
IE seems to like to handle onscroll as a global, so in 'going with the grain', I also detach all elements to be scrolled, and move them up to the main container. It also assumes, I think, that the elements don't use much if anything in the way of margin or padding styles.
[pre][fixed]
var Tuli = { };
Tuli.C.container = "mcontainer";/*Trailing edge. This whole thing needed by only IE 5/6 in order to simulate fixed css positioning.
*It's run by calling the Init function, first, then add each Item, in turn, to be moved along with the scrollbar.
*
*These are the old style 'floaters', ala NN4, but without the accel/decel gimic some of these once used.
*(even Zijdel IE addevent overrides were not used because scroll didn't seem to work with these,
* so instead FixPos is the single IE scroll func, handling all scrolled elements, for IE 5/6.)
*
*The vertical attach to the bottom of some element seems to hold position best as IE is zoomed in and out.
*The two positions otherwise for scrolling might suggest a home position that is not flush with the margin.
*/
Tuli.FixPos = function Fixpos100 (){var pub = { };
var idElmt, objElmt;
var googAdj =0;
var loopctr = 0;
var timoFix;
var arItems = [[ ]];/*
each arItems, (standard/default is "no" or 0, except for keepin, which is "yes"; and use the number 0 for, don't care)
[0] ID of object,
[1] vertical attach - to bottom of element, identified here by, id (this overrides offsets 6 or 8 !),
[2] if attached, offset -- for offset values: number ¦ percent(use quotes) ¦ em(use quotes), negative values allowed,
[3] horiz centered, "yes" ¦ "no",
[4] vert centered, "yes" ¦ "no",
[5] 0 scroll, home position, x offs, offset value,
[6] 0 scroll, home position, y offs, "",
[7] scrolled x offs, "",
[8] scrolled y offs, "",
[9] keep in "yes", minimum margin, "", (basically the same as setting all offs to the same value)
[10] keep in window, "yes" ¦ "no",
*/var c = {
objId: "0",
vattach: "1",
attoffs: "2",
xcent: "3",
ycent: "4",
xhome: "5",
yhome: "6",
xoffs: "7",
yoffs: "8",
keepmgn: "9",
keepin: "10"
};pub.Fix = function Fixpos110 (){
for (var i=0; i<arItems.length; i +=1){
pub.FixItem(arItems[i]);
}/* Certain resize cases won't trigger an event, so just keep it covered. */
clearTimeout(timoFix);
timoFix = setTimeout("Tuli.FixPos.Fix();", 1500);
};/* Find element/pixel equivalent of percent or em. Percent is percent of client window, not full page. */
function convToEls(strOffs, mainDim, isWd){
strOffs = strOffs.toString();
numOffs = parseFloat(strOffs);if (strOffs.indexOf("%") !== -1){ numOffs = numOffs/100 *mainDim; }
if (strOffs.indexOf("em") !== -1){
var tenEms = $(Tuli.C.emMeas);
numOffs = numOffs * ( isWd ? tenEms.offsetWidth/10 : tenEms.offsetHeight/10 );
}
return numOffs;
}pub.FixItem = function Fixpos120 (){
var tuple = arguments[0];
idElmt = tuple[c.objId];
objElmt = $(idElmt);
if (!objElmt){ return; }var pgXY = Tuli.Pos.pageDim();
var pgX = pgXY[0], pgY = pgXY[1];
var yhome = convToEls(tuple[c.yhome], pgY);
var xhome = convToEls(tuple[c.xhome], pgX, 1);
var yoffs = convToEls(tuple[c.yoffs], pgY);
var xoffs = convToEls(tuple[c.xoffs], pgX, 1);
var kmgnX = convToEls(tuple[c.keepmgn], pgX, 1);
var kmgnY = convToEls(tuple[c.keepmgn], pgY);
var objElmtHt = objElmt.offsetHeight;
var objElmtWd = objElmt.offsetWidth;var vscroll = Tuli.Pos.Scroll()[1];
var btmWndwPos = vscroll +pgY;
var topWndwPos = vscroll;
if (tuple[c.vattach].length >0){
var objAnchor = $(tuple[c.vattach]);
vscroll += objAnchor.offsetTop +objAnchor.offsetHeight +convToEls(tuple[c.attoffs], pgY);
} else {
vscroll += (vscroll ===0) ? yhome : yoffs;
if (tuple[c.ycent] ==="yes"){ vscroll += pgY/2 - objElmtHt/2; }
}
if (tuple[c.keepin] ==="yes"){
if ( vscroll +objElmtHt >btmWndwPos){ vscroll = btmWndwPos -kmgnY -objElmtHt; }
if ( vscroll -kmgnY <topWndwPos){ vscroll = topWndwPos +kmgnY; }
}
vscroll = vscroll - googAdj;
objElmt.style.top = vscroll +"px";var hscroll = Tuli.Pos.Scroll()[0];
var rgtWndwPos = hscroll +pgX;
var lftWndwPos = hscroll;
hscroll += (hscroll ===0) ? xhome : xoffs;
if (tuple[c.xcent] ==="yes"){ hscroll += pgX/2 - objElmtWd/2; }
if (tuple[c.keepin] ==="yes"){
if ( hscroll +objElmtWd >rgtWndwPos){ hscroll = rgtWndwPos -kmgnX -objElmtWd; }
if ( hscroll -kmgnX <lftWndwPos){ hscroll = lftWndwPos +kmgnY; }
}
objElmt.style.left = hscroll +"px";
};pub.Init = function Fixpos130 (){
window.onscroll = pub.Fix;
timoFix = setTimeout("Tuli.FixPos.Fix();", 100);/* Simple, but crude, way of determining pixel equivalent of current EM. Create blank div of know EM dimension. */
Tuli.DOM.Add(Tuli.C.emMeas,Tuli.C.container,"div");
$(Tuli.C.emMeas).style.width = "10em";
$(Tuli.C.emMeas).style.height = "10em";/* Adjust for google cache insertion of a table before even the HTML and HEAD tags. */
if ( document.getElementsByTagName("div")[0] ) {
if ( (document.getElementsByTagName("div")[0].offsetTop >100) && (vscroll !=0) ) {
googAdj = document.getElementsByTagName("div")[0].offsetTop;
}
}
};/*Add another element to the IE 'scroll handler'; add to the list. */
pub.Item = function Fixpos140 (){
var tuple = arguments;
idElmt = tuple[0];var arFound = "no";
var rcrds = 0;
for (var i=0; i <arItems.length; i +=1){
if ( arItems[i].length >0 ){
if ( arItems[i][c.objId] === idElmt ){
arFound = i;
}
rcrds +=1;
}
}
if ( arFound !=="no"){ return; }arItems[rcrds] = [ ];
arItems[rcrds][c.objId] = idElmt;
arItems[rcrds][c.xcent] = tuple[c.xcent] ¦¦ "no";
arItems[rcrds][c.ycent] = tuple[c.ycent] ¦¦ "no";
arItems[rcrds][c.keepin] = tuple[c.keepin] ¦¦ "yes";
arItems[rcrds][c.keepmgn] = tuple[c.keepmgn] ¦¦ "0";
arItems[rcrds][c.xhome] = tuple[c.xhome] ¦¦ 0;
arItems[rcrds][c.yhome] = tuple[c.yhome] ¦¦ 0;
arItems[rcrds][c.xoffs] = tuple[c.xoffs] ¦¦ 0;
arItems[rcrds][c.yoffs] = tuple[c.yoffs] ¦¦ 0;
arItems[rcrds][c.vattach] = tuple[c.vattach] ¦¦ "";
arItems[rcrds][c.attoffs] = tuple[c.attoffs] ¦¦ 0;$(idElmt).style.position = "absolute";
/* For IE, best to remove any element nesting - move the node up to the container div.
* (removeNode is an IE shortcut instead of first cloning and then removing the orig after appending)
*/
$(Tuli.C.container).appendChild( $(idElmt).removeNode(true) );
};return pub;
}();
[/fixed][/pre]
Tuli.C.emMeas can be named whatever you like. "Tuli", could be something else, or whatever. The .scroll function just gives the current x and y scroll positions. Most people have a function that does that. And I'd add a check to see if the elmt exists before trying to fix it. But other than that, I think that's it.