Find out the page dimensions

D

Daniel Norden

Hello.

I'm trying create a DIV element that covers the whole page. To do this, I
need to find out the exact size of the current page. I've seen the very
comprehensive topic about the viewport size in the group FAQ. Is there
anything comparable for reading the size of the page, not just the
viewport?

I've tried the following function (which was adapted from the Lightbox2
script). It's supposed to return the size of my DIV..... if the page is
small, the DIV should at least cover the whole viewport. It works nicely in
IE6, IE7, Safari, Opera, but not quite in Firefox (2 and 3):

function getPageSize(){
var body = document.body;
var docEle = document.documentElement;
var doc_w, doc_h;
var vp_w, vp_h;
if (window.innerHeight && window.scrollMaxY) {
doc_w = window.innerWidth + window.scrollMaxX;
doc_h = window.innerHeight + window.scrollMaxY;
} else if (body.scrollHeight > body.offsetHeight) {
doc_w = body.scrollWidth;
doc_h = body.scrollHeight;
} else {
doc_w = body.offsetWidth;
doc_h = body.offsetHeight;
}
if (window.innerHeight) {
if (docEle && docEle.clientWidth) {
vp_w = docEle.clientWidth;
} else {
vp_w = window.innerWidth;
}
vp_h = window.innerHeight;
} else if (docEle && docEle.clientHeight) {
vp_w = docEle.clientWidth;
vp_h = docEle.clientHeight;
} else {
vp_w = body.clientWidth;
vp_h = body.clientHeight;
}
return {
height: Math.max(doc_h, vp_h),
width: Math.max(doc_w, vp_w)
};
}

In Firefox the width and height are a little too large, which makes the
scrollbars jump (if there are scrollbars). How can I avoid this? Is there a
better way to write this function?

Thanks in advance!
Dano
 
S

SAM

Le 12/1/08 4:30 PM, Daniel Norden a écrit :
Hello.

I'm trying create a DIV element that covers the whole page. To do this, I
need to find out the exact size of the current page. I've seen the very
comprehensive topic about the viewport size in the group FAQ. Is there
anything comparable for reading the size of the page, not just the
viewport?


<https://developer.mozilla.org/En/DOM/Element.offsetHeight>
<http://msdn.microsoft.com/en-us/library/ms534199(VS.85).aspx>

head's script :

onload = function() {
var d = document.createElement('DIV');
d.style.height = document.body.offsetHeight + 'px';
d.style.width = document.body.offsetWidth + 'px';
d.style.position = 'absolute;
d.style.top = d.style..left = 0;
d.style.background = 'black';
d.title = 'click to close me';
d.onclick= function() { this.style.display='none'; };
document.body.appendChild(d);
}

Not tested !
 
D

David Mark

Le 12/1/08 4:30 PM, Daniel Norden a écrit :



Why?

<http://msdn.microsoft.com/en-us/library/ms534199(VS.85).aspx>

head's script :

onload = function() {
?

var d = document.createElement('DIV');
d.style.height = document.body.offsetHeight + 'px';
d.style.width  = document.body.offsetWidth  + 'px';

This is supposed to be a joke, right? See the FAQ.
d.style.position = 'absolute;

Syntax error.
d.style.top = d.style..left = 0;
Again.

d.style.background = 'black';

Use backgroundColor and don't use named colors.
d.title = 'click to close me';
d.onclick= function() { this.style.display='none'; };

Memory leak. You know what to do.
document.body.appendChild(d);

}

Not tested !

Always a bad idea.
 
D

David Mark

David's right, this is neither syntactically correct, nor would it do

Except the FAQ doesn't have the exact example as he wants to cover the
document, not the viewport. Of course, the code above won't do that
either.
what the OP requires. Daniel, here's something to get you started; with
a few caveats:
 - I didn't have any older browsers around for testing; the function
should probably be improved to return something useful for them.

 - It uses browser sniffing. Yeah, I know. I'm going to get flamed for
this -- if anybody here knows a way to adjust the results for IE in
quirks mode with feature testing, that would be great.

See the FAQ viewport example.
 - It may not work if the body has a negative margin. If you need to
handle this case, you'll have to edit the function to account for it.

 - I didn't handle the height bug in Opera 9 in this example, there's a
test and workaround for that in the group FAQ.

There is? I remember talking about adding one, but I didn't know it
was changed.
That said, as far as I can see, it apperars to do the job in FF2, FF3,
IE6, IE7, Safari 3, Konqueror 3.5, and Opera 9 (if the body is higher
than the viewport).

var isMSIE;
/*@cc_on
    isMSIE = true;
@*/

See what the document.documentElement.clientWidth/Height properties
are in IE quirks mode (or IE < 6.) IIRC, they are 0. In that case,
use the scrollWidth/Height properties of the body, and otherwise use
the documentElement. There are other issues related to margins (on
the body in quirks mode, documentElement in standards mode.) Best to
avoid those at the design stage.

Also, make sure the expected properties are numbers.

[snip]
 
D

David Mark

[snip]
 - I didn't handle the height bug in Opera 9 in this example, there's a
test and workaround for that in the group FAQ.

That entry needs some rewriting.

"What the number returned from either of these properties represents
depends on the environment. The environment includes the browser, its
version, and the rendering mode of the document. In quirks mode, we'll
mostly want to use body.clientHeight (except for in Safari 2)."

What it boils down to is the outermost scrolling element. Normally
this is the documentElement. In IE quirks mode (and IE < 6), it is
the body.

" document.body.clientHeight

Some environments will return the viewport height. Others will return
0. Yet others will return the clientHeight of the BODY element."

"I don't know about 0, except not to use it, most will indeed return
the client height of the body, which may or may not be a good starting
point for determining the viewport height (depends if it is the
outermost scrolling element.)

document.documentElement.clientHeight

This is the more "standard" property for getting the height of the
viewport. It usually "works" in modern browsers in standards mode."

No, this is the standard way to measure the client height of the
documentElement. In IE quirks mode (and IE < 6), it is 0, which is a
great indicator that it is useless (the HTML element is not rendered.)

"Notable exceptions include Safari 2 and Opera <= 9.25, both of which
return the clientHeight of the html element. (Oddly, Opera <= 9.25 in
standards mode returns the width of the viewport for
documentElement.clientWidth)."

Not sure about Safari 2, but the Opera problem is that it returns the
scrollHeight instead of the clientHeight (and this bug is not present
in clientWidth.)

"Conversely, document.body.clientHeight will return the height of the
viewport in most cases where document.documentElement.clientHeight
does not. An exception to that is Safari 2, where
documentElement.clientHeight and body.clientHeight both return the
height of their corresponding element (not what we want). "

The client height of the outermost scrolling element is exactly what
we want. We then have to deal with margins on that element to get a
complete cross-browser viewport measurement. None of these client*
properties have anything to do with the viewport (they are just a
starting point), with the exception of the (previously unknown to me)
document.clientWidth/Height properties, which though perfectly logical
for this purpose (without the margin issues), are apparently rarely
seen.

I don't care for the creation of the huge DIV either. There is a
solution for this in my library, which figures out enough about the
scrollbar dimensions to use innerHeight as a replacement for the
broken clientHeight. I'll have to remember to test it in Safari 2 one
of these days though.

At the very least, the explanation needs to be updated.
 
S

SAM

Le 12/1/08 11:14 PM, Conrad Lender a écrit :
David's right, this is neither syntactically correct, nor would it do
what the OP requires.

The corrected code bellow tested in :
FF.3, Safary.3, Opera.9, iCab.4, all on Mac and IE.6,
,if not perfect, works not so badly except in quirksmode in Opera.

The black div cover the 'body' as asked.
(with a little error of positioning if the body has a border)

onload = function() {
var d = document.createElement('DIV');
d.style.height = document.body.offsetHeight + 'px';
d.style.width = document.body.offsetWidth + 'px';
d.style.position = 'absolute';
d.style.top = d.style.left = 0;
d.style.background = 'black';
d.title = 'click to close me';
d.onclick= clos;
document.body.appendChild(d);
}
function clos(e) { this.style.display='none'; }

I've not older browsers than those cited for testing.
 
D

David Mark

Le 12/1/08 11:14 PM, Conrad Lender a écrit :



The corrected code bellow tested in :
FF.3, Safary.3, Opera.9, iCab.4, all on Mac and IE.6,
,if not perfect, works not so badly except in quirksmode in Opera.

The black div cover the 'body' as asked.

No, he wanted to cover the "whole page."
(with a little error of positioning if the body has a border)

Will also add scrollbars in IE quirks mode.
onload = function() {

Will you please stop doing that?
var d = document.createElement('DIV');
d.style.height = document.body.offsetHeight + 'px';
d.style.width  = document.body.offsetWidth  + 'px';
d.style.position = 'absolute';
d.style.top = d.style.left = 0;
d.style.background = 'black';
d.title = 'click to close me';
d.onclick= clos;

Well, at least this one doesn't leak.

[snip]
 
D

David Mark

I see from your other post that you've found it (and didn't like it ;-).
I'm not sure if that workaround is actually necessary in Daniel's case;
the updated function (see below) works fine with Opera 9.6x, with only a
minor adjustment. I couldn't test 9.2x, because I couldn't figure out
how to do a parallel install of two Opera versions :-/



Thanks, I've added this and removed the browser check.


Oh yeah, I forgot about that, thanks. A single undefined or NaN, and
Math.max will return NaN.

Here's is the updated version; browser sniffing and Opera height bug are
addressed, negative margins and old browsers still untested.

function getPageSize () {
    var d = document,
        db = d.body,
        de = d.documentElement,
        mode = d.compatMode;

You don't really need this.
        w = Math.max(db && +db.scrollWidth || 0,
                     de && +de.scrollWidth || 0),
        h = Math.max(db && +db.scrollHeight || 0,
                     de && Math.max(+de.scrollHeight || 0,
                                    +de.clientHeight || 0) || 0);
    if (mode == "BackCompat" && db && de && de.clientWidth === 0) {

This will fail in IE < 6. Just lose the "BackCompat" check.

if (db && (!de || !de.clientWidth)) {
        w = +db.scrollWidth;
        h = +db.clientHeight;

scrollHeight.

And you were supposed to test the properties, not attempt to convert
any old thing you find there.

[snip]
 
T

Thomas 'PointedEars' Lahn

That does _not_ test for Internet Explorer; it tests for JScript instead.
Oh yeah, I forgot about that, thanks. A single undefined or NaN, and
Math.max will return NaN.

Here's is the updated version; browser sniffing and Opera height bug are
addressed, negative margins and old browsers still untested.


function getPageSize () {
var d = document,
db = d.body,
de = d.documentElement,
mode = d.compatMode;
w = Math.max(db && +db.scrollWidth || 0,
de && +de.scrollWidth || 0),
h = Math.max(db && +db.scrollHeight || 0,
de && Math.max(+de.scrollHeight || 0,
+de.clientHeight || 0) || 0);
if (mode == "BackCompat" && db && de && de.clientWidth === 0) {
w = +db.scrollWidth;
h = +db.clientHeight;
}

You really don't have to make the explicit type conversion to Number every
time.

Where the d* property is available, its value type-converts to `true' (we
assume an object reference as its value) and the second operand is
evaluated. Where it is not available, its value type-converts to `false'
and the result of the expression is 0 because of the `||' operation.

Where the scroll* property is available, one can assume its value is of type
Number. If that is zero, the result is zero (because the first zero
type-converts to `false'); if it is not zero, the result is it.

Where it is not available (i.e. `undefined' or `NaN'), it type-converts to
`false' in a boolean expression already, and then the result is still 0
because of the `||' operation.

What you might want to take care of, though, is that either property value
could be a negative number, in which case it would type-convert to `true'
and result of the expression would be a negative number. An easy
possibility for doing that is to test if Math.max() accepts more than two
arguments as specified, and overwrite or replace it with a method that does
if required; then pass 0 as the third argument:

if (Math.max(1, 2, 3) == 2)
{
Math.max = function(...)
{
...
};
}

... = Math.max(..., ..., 0);


HTH

PointedEars
 
D

David Mark

Done. I don't know what else would fail in IE5... to be honest, I'm not
losing any sleep over IE5 compatibility. That browser is almost 10 years
old now, and I don't support it any longer.



No, clientHeight. I had scrollHeight originally, but that would always
be higher than intended, while clientHeight gave the correct height (in
this branch).

Definitely scrollHeight. The clientHeight property doesn't enter into
covering the page. You botched something else.
How does that make a difference? If the property's value converts to a
number > 0, I'll use it; if it doesn't, it should have a falsy +value,
and the '||0' at the end will still convert it to a number. I've never
heard of client* or scroll* to cause errors when they're accessed in
this way.

To wit:

w = +db.scrollWidth;
h = +db.clientHeight;

What would you expect to happen if these properties are undefined?

[snip]
 
T

Thomas 'PointedEars' Lahn

Conrad said:
On 2008-12-02 01:21, David Mark wrote: [...]
And you were supposed to test the properties, not attempt to convert
any old thing you find there.

How does that make a difference?

Well, it's hopelessly inefficient to begin with.
If the property's value converts to a number > 0, I'll use it; if it
doesn't, it should have a falsy +value,

If it has a "falsy" `+value', it has a "falsy" `value'.
and the '||0' at the end will still convert it to a number.

No, it is not type conversion that takes place then. Anyhow, when
conversion does not matter for the outcome, why force conversion
to number? Where is the benefit of that?
I've never heard of client* or scroll* to cause errors when they're
accessed in this way.

That's not the point here, however previous experience would not mean much
in that regard. We are talking about host objects here.


PointedEars
 
D

David Mark

On 2008-12-02 01:21, David Mark wrote: [..]
w = +db.scrollWidth; h = +db.clientHeight;
scrollHeight.
No, clientHeight. I had scrollHeight originally, but that would always
be higher than intended, while clientHeight gave the correct height (in
this branch).
Definitely scrollHeight.  The clientHeight property doesn't enter into
covering the page.  You botched something else.

I just tested it again - scrollHeight includes the height of the
horizontal scroll bar, clientHeight doesn't.

You are dreaming. The example in the FAQ and the requested example
are different animals. The FAQ covers the viewport, but the OP wanted
to "cover the page." What you have created is some sort of bastard
child of the two.
 
S

SAM

Le 12/2/08 12:53 AM, David Mark a écrit :
No, he wanted to cover the "whole page."

Yes you're right.
He has to have to suppress the marges, hop!
Will also add scrollbars in IE quirks mode.

How do you know all that ?

It's not my fault if IE is a BS.
Anyway that doesn't disturb me and it is possible to do not turn it in
this mode.
Will you please stop doing that?

Certainly not.

Why ?

What's wrong ?

(...)
Well, at least this one doesn't leak.

Ouf !
 
D

David Mark

Le 12/2/08 12:53 AM, David Mark a écrit :



Yes you're right.
He has to have to suppress the marges, hop!
?



How do you know all that ?

Because offsetWidth/Height includes the scroll bars and in IE quirks
mode (or IE < 6), the body is the outermost rendered element. Unless
the body has overflow:hidden style, the measurement will be incorrect
and unless both scroll bars are present, a new scroll bar will be
created.
It's not my fault if IE is a BS.

IE isn't at fault. Realize that offsetWidth/Height were the wrong
choices, regardless of the browser or rendering mode.
Anyway that doesn't disturb me and it is possible to do not turn it in
this mode.

Yes, you can (and should) avoid quirks mode. But if code is designed
for the context of a specific mode, then it should be documented as
such.
Certainly not.

That seems capricious and arbitrary!

You already dismissed the notion, so what does it matter?
What's wrong ?

Don't use implied globals. It is bad form.

[snip]
 
S

SAM

Le 12/2/08 9:35 AM, David Mark a écrit :

body { marge: 0; } :)

Because offsetWidth/Height includes the scroll bars and in IE quirks
mode (or IE < 6), the body is the outermost rendered element. Unless
the body has overflow:hidden style, the measurement will be incorrect
and unless both scroll bars are present, a new scroll bar will be
created.

Yes it's what I've seen (without knowing the why)
IE isn't at fault. Realize that offsetWidth/Height were the wrong
choices, regardless of the browser or rendering mode.

If you want.
(was a kind of joke)
Yes, you can (and should) avoid quirks mode. But if code is designed
for the context of a specific mode, then it should be documented as
such.

Did I say your are tiring ? :)
(hope you excuse my humor)
That seems capricious and arbitrary!

No as I don't understand why.
You already dismissed the notion,

Probably ?
Is there yet leaks memory ?
so what does it matter?

Is it again that history of <body onload="... ?
Don't use implied globals. It is bad form.

I could say :
- that works, it's OK.
- I allways did like that without error

But really I do not understand why, doesn't they exist to use them?
(and it is not flying over the posts about win = window.this || this;
and/or window or not window and such very long opposite considerations
that I can really see where is the problem, if you could light me in
few words ? (but not too much few) it would be fine)
 
T

Thomas 'PointedEars' Lahn

Conrad said:
Good enough for me. If somebody wrote a browser that implements JScript
and CC, they'd better implement IE's quirks as well.

You must be kidding.
Anyway, thanks to David's input, this test is now gone.

Good to hear that.
That's interesting. I thought Math.max took an arbitrary number of
arguments anyway? At least it's specified that way.

Maybe you want to read my posting again? Yes, it is *specified* so *since
ECMAScript Ed. 3*, but not always *implemented* so. For example, according
to my tests, more than two arguments are not supported by JavaScript 1.3 and
earlier, JScript 5.1 and earlier (information buried in my 2005 math
library, now added to the local version of the ES Matrix.)


PointedEars
 
D

David Mark

Then maybe we were both dreaming. Neither scrollHeight nor clientHeight
will give the correct height on their own; both are required:

No, as I have an implementation of this in my library. It was tested
in everything, in every mode, etc. And what on earth would
clientHeight have to do with the scrollHeight? Do you have any
concept of what these properties are for?
  Math.max(db.scrollHeight, db.clientHeight)

Makes no sense at all.
Here's a simple demonstration; resize the window and note the numbers.

[snip]

Not interested.
 
T

Thomas 'PointedEars' Lahn

Conrad said:
Conrad said:
On 2008-12-02 01:21, David Mark wrote: [...]
And you were supposed to test the properties, not attempt to convert
any old thing you find there.
How does that make a difference?
Well, it's hopelessly inefficient to begin with.

Come on, conversion to Number doesn't even register, compared to
resizing an element.

One type conversion does not register.
Nope.

var a = "hello";
if (+a) print("won't print");
if (a) print("will print");

Right, I should have emphasized object references and numeric strings.
I guess I was being overly paranoid, attempting to correct cases where
an implementation chose to return "3" (string) or "3px". But I guess
that I could let Math.max handle the conversion there.

The unary plus operation (or the Number() function) does not handle the
"3px" case, though; you need parseInt() or parseFloat() for that. And yes,
you were being overly paranoid; the property value has nothing to do with
CSS to begin with.
That's true. But remember that I was posting this as a "starting point",
not as a 100% bullet-proof implementation. Out of curiosity, how would
you write this function, if you were to use it in one of your projects?

I would not write this function or use it in one of my projects in the first
place. What would it be good for? If I were to place a dark layer over the
viewport in order to give the appearance of disabled background (like
Lightbox does), the height of the rendered document would not concern me at
all. I would disable the scrollbars of the body, enable them for my layer
and be done with it.

The whole thread looks to me like looking for a solution to a non-existent
problem.


HTH

PointedEars
 
D

David Mark

Conrad said:
Conrad Lender wrote:
On 2008-12-02 01:21, David Mark wrote: [...]
And you were supposed to test the properties, not attempt to convert
any old thing you find there.
How does that make a difference?
Well, it's hopelessly inefficient to begin with.
Come on, conversion to Number doesn't even register, compared to
resizing an element.

One type conversion does not register.
var a = "hello";
if (+a) print("won't print");
if (a) print("will print");

Right, I should have emphasized object references and numeric strings.
I guess I was being overly paranoid, attempting to correct cases where
an implementation chose to return "3" (string) or "3px". But I guess
that I could let Math.max handle the conversion there.

The unary plus operation (or the Number() function) does not handle the
"3px" case, though; you need parseInt() or parseFloat() for that.  And yes,
you were being overly paranoid; the property value has nothing to do with
CSS to begin with.
That's true. But remember that I was posting this as a "starting point",
not as a 100% bullet-proof implementation. Out of curiosity, how would
you write this function, if you were to use it in one of your projects?

I would not write this function or use it in one of my projects in the first
place.  What would it be good for?  If I were to place a dark layer over the
viewport in order to give the appearance of disabled background (like

It isn't clear whether he wants to cover the viewport or the document
or why he wants to do it.
Lightbox does), the height of the rendered document would not concern me at
all.  I would disable the scrollbars of the body, enable them for my layer
and be done with it.

Right. But, as noted, all a waste of time as the keyboard still
works. It's just a silly effect.
The whole thread looks to me like looking for a solution to a non-existent
problem.

Pretty much a waste at this point.

[snip]
 

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,764
Messages
2,569,566
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top