length unit convert and position: fixed in IE

A

Aquila Deus

Hi all!

I got the two things work last night, the code is here:

//////////////////////////////////////////////////////////
var ojsIsIe = (navigator.appName == "Microsoft Internet Explorer");

var ojsUnitPointWidth; // Pixels per point (float)
var ojsUnitCentimeterWidth; // Pixels per cm (float)
var ojsUnitMillimeterWidth; // Pixels per mm (float)
var ojsUnitInchWidth; // Pixels per inch (float)
var ojsUnitPicasWidth; // Pixels per picas (float)

var ojsUnitPointHeight;
var ojsUnitCentimeterHeight;
var ojsUnitMillimeterHeight;
var ojsUnitInchHeight;
var ojsUnitPicasHeight;

function ojsInitMeasureUnits() {
var x = document.createElement("div");
x.style.position = "absolute";
x.style.width = "1000pt";
x.style.height = "1px";
document.body.appendChild(x);
ojsUnitPointWidth = x.offsetWidth / 1000;
document.body.removeChild(x);
delete x;

ojsUnitInchWidth = ojsUnitPointWidth * 72;
ojsUnitPicasWidth = ojsUnitPointWidth * 12;
ojsUnitCentimeterWidth = ojsUnitInchWidth / 2.54;
ojsUnitMillimeterWidth = ojsUnitCentimeterWidth * 10;

var y = document.createElement("div");
y.style.position = "absolute";
y.style.width = "1px";
y.style.height = "1000pt";
document.body.appendChild(y);
ojsUnitPointHeight = y.offsetHeight / 1000;
document.body.removeChild(y);
delete y;

ojsUnitInchHeight = ojsUnitPointHeight * 72;
ojsUnitPicasHeight = ojsUnitPointHeight * 12;
ojsUnitCentimeterHeight = ojsUnitInchHeight / 2.54;
ojsUnitMillimeterHeight = ojsUnitCentimeterHeight * 10;
}

// baseWidth is used only when the width is a percentage
function ojsParseWidth(widthText, baseWidth) {
if (widthText == "auto" || widthText == "") {
return null;
} else if (widthText.substr(widthText.length - 1) == "%" ) {
return parseInt(widthText) * baseWidth / 100;
} else {
var unit = widthText.substr(widthText.length - 2);
var value = parseInt(widthText);

if (unit == "px") {
return value;
} else if (unit == "pt") {
return value * ojsUnitPointWidth;
} else if (unit == "in") {
return value * ojsUnitInchWidth;
} else if (unit == "cm") {
return value * ojsUnitCentimeterWidth;
} else if (unit == "mm") {
return value * ojsUnitMillimeterWidth;
}
}
return parseInt(widthText);
}

// baseWidth is used only when the height is a percentage
function ojsParseHeight(heightText, baseHeight) {
if (heightText == "auto" || heightText == "") {
return null;
} else if (heightText.substr(heightText.length - 1) == "%" ) {
return parseInt(heightText) * baseHeight / 100;
} else {
var unit = heightText.substr(heightText.length - 2);
var value = parseInt(heightText);

switch (unit) {
case "px":
return value;
case "pt":
return value * ojsUnitPointHeight;
case "pc":
return value * ojsUnitPicasHeight;
case "in":
return value * ojsUnitInchHeight;
case "cm":
return value * ojsUnitCentimeterHeight;
case "mm":
return value * ojsUnitMillimeterHeight;
}
}
return parseInt(heightText);
}

function ojsRelocateFixedElement(element, event) {
// The function works on IE only. And there is no need to call this in
// web browsers that support position: fixed.
if (! ojsIsIe) {
return;
}

var p = document.body;

var left = ojsParseWidth(element.style.left, p.offsetWidth);
if (left) {
element.runtimeStyle.left = p.scrollLeft + left;
}

var right = ojsParseWidth(element.style.right, p.offsetWidth);
if (right) {
element.runtimeStyle.right = p.scrollLeft + p.offsetWidth - right;
}

var top = ojsParseHeight(element.style.top, p.offsetHeight);
if (top) {
element.runtimeStyle.top = p.scrollTop + top;
}

var bottom = ojsParseHeight(element.style.bottom, p.offsetHeight);
if (bottom) {
element.runtimeStyle.bottom = p.scrollTop + p.offsetHeight -
bottom;
}
}

function ojsUpdateFixedElement(element, propertyName) {
if (propertyName == "style.left"
|| propertyName == "style.right"
|| propertyName == "style.top"
|| propertyName == "style.bottom") {
ojsRelocateFixedElement(element);
}
}

// The function set "position: fixed" for given DOM element. On IE it
// captures onpropertychange event so that later you can just change
// style.left, style.right, style.top, style.bottom to control the
// element's position on browser.
function ojsSetElementFixed(ele) {
if (ojsIsIe) {
ele.ojsFixed = true;
ele.style.position = "absolute";
window.attachEvent("onscroll", function t(event){
ojsRelocateFixedElement(ele, event);
});
window.attachEvent("onresize", function t(event){
ojsRelocateFixedElement(ele, event);
});
ele.attachEvent("onpropertychange", function t(event){
var pn = window.event.propertyName;
ojsUpdateFixedElement(ele, pn);
});
} else {
ele.style.position = "fixed";
}

return ele;
}

//////////////////////////////////////////////////////////////////

Notes:

1.UnitXXXPerPixel reflects the DPI set in web browser, not the real monitor
DPI.

2.The position of element set by ojsSetElementFixed() is uneffected by
predefined styles. ex: you set the "top" of div#FIXED in css file, then
call this function with a div whose id is FIXED, but the "top" set in css
file doesn't affect it at all. I don't know why, maybe it's about the
order. The "top" may appear in element.currentStyle, but never in
element.style.

3.Currently ojsSetElementFixed works only for top-level elements. And if
you set both of left and right, and specify a width which doesn't equal to
right - left (or top, bottom, with specified height), things may work
weird...

4.Code is tested on IE6 and Moz 1.7.1 only... Can somebody tell me how to
install more than one version of IE on the same computer? (no multi-OS)


Cheers!
 
A

Aquila Deus

Kris said:
Don't do that. Post a URL to the stuff instead.

Well, but currently there is no good way to do this. I don't trust my
web-site (damned windows!)
 
A

Aquila Deus

(e-mail address removed) (Aquila Deus) wrote in message <snip>

fixed code:


function ojsRelocateFixedElement(element, event) {
if (! ojsIsIe) {
window.alert("ojsRelocateFixedElement should never be called in non-IE"
+ " browser");
}

var p = document.body;

if (! element.ojsFixedRelocateCalled) {
element.ojsFixedUpdating = true;
var left = ojsParseWidth(element.currentStyle.left, p.offsetWidth);
var right = ojsParseWidth(element.currentStyle.right, p.offsetWidth);
var top = ojsParseHeight(element.currentStyle.top, p.offsetHeight);
var bottom = ojsParseHeight(element.currentStyle.bottom, p.offsetHeight);

if (left != null) {
element.style.left = left;
}
if (right != null) {
element.style.right = right;
}
if (top != null) {
element.style.top = top;
}
if (bottom != null) {
element.style.bottom = bottom;
}

element.ojsFixedRelocateCalled = true;
element.ojsFixedUpdating = false;
}

var left = ojsParseWidth(element.style.left, p.offsetWidth);
var right = ojsParseWidth(element.style.right, p.offsetWidth);
var top = ojsParseHeight(element.style.top, p.offsetHeight);
var bottom = ojsParseHeight(element.style.bottom, p.offsetHeight);

if (left != null) {
element.runtimeStyle.left = p.scrollLeft + left;
}
if (right != null) {
element.runtimeStyle.left = p.scrollLeft + p.clientWidth - right
- element.offsetWidth;
}
if (top != null) {
element.runtimeStyle.top = p.scrollTop + top;
}
if (bottom != null) {
element.runtimeStyle.top = p.scrollTop + p.clientHeight - bottom
- element.offsetHeight;
}
}

function ojsUpdateFixedElement(element, propertyName) {
if ((! element.ojsFixedUpdating)
&& (propertyName == "style.left"
|| propertyName == "style.right"
|| propertyName == "style.top"
|| propertyName == "style.bottom"
|| propertyName == "style.width"
|| propertyName == "style.height")) {
element.ojsFixedUpdating = true;
ojsRelocateFixedElement(element);
element.ojsFixedUpdating = false;
}
}



style.right and style.bottom and pre-defined stylesheet can work now, done!
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,767
Messages
2,569,571
Members
45,045
Latest member
DRCM

Latest Threads

Top