Why does an invisible FORM tag have offSetLeft == 8??

S

Saqib Ali

Please excuse me, this is a fairly involved question that will likely
require you to save the file below to a file and open it in a browser.
I use Mozilla 1.5, so the problem I describe below should be
reproducible with that version at least.

BACKGROUND:
===========

When you open this page in your browser, you will see a 4 cell table.
The cells contain the following items respectively:
1) Gray background
2) Pink background showing the current mouse X position
3) White background showing the X-coord of the left edge of Cell #1
4) Yellow background showing a traversal of nodes from Cell #1 up the
tree to the root node


I need to dynamically calculate the X-coord value of the left edge of
the gray box. By placing the mouse on the left edge of the gray box,
and observing the value in the Pink cell, you can find out what the
"correct" value should be.

The way I calculate the X-coord of the left edge of the Gray cell is
to walk up the tree till I hit the root, accummulating the offSetLeft
values along the way. In theory this should give me the x-coord value
of my cell. This is the value you see in the White cell. In the yellow
cell, you see each node along the way and its offset value.

PROBLEM:
========

Now here is the issue: The "correct" value and the computed value
differ (approx 10 VS 18). I am trying to figure out why. I have found
that FORM tag adds 8 pixels to the computed value.... even though it
is completely invisible and doesn't affect the actual onscreen
placement of its child nodes. You can try it yourself by removing the
form tag.


So does anyone know how to get around this issue? Why does an
invisible form tag add 8 pixels? Is there some alternate/easier way to
get the X coord of the left edge of an Element??



------------------------------------------------------------------------

<HTML>
<HEAD>



<SCRIPT language="JavaScript1.2">
<!--
var IE = document.all?true:false;


// If NS -- that is, !IE -- then set up for mouse capture
if (!IE) document.captureEvents(Event.MOUSEMOVE)

// Set-up to use getMouseXY function onMouseMove
document.releaseEvents(Event.MOUSEMOVE);
document.onmousemove = getMousePos;

// Temporary variables to hold mouse x-y pos.s
var mouseX = 0



// Main function to retrieve mouse x-y pos.s
function getMousePos(e) {
if (IE) // grab the x pos.s if browser is IE
mouseX = event.clientX + document.body.scrollLeft;
else // grab the x pos.s if browser is NS
mouseX = e.pageX;

// catch possible negative values in NS4
if (mouseX < 0){mouseX = 0}
document.getElementById('MOUSE_XPOS').childNodes[0].data = mouseX;
return true;
}

function getLeftXCoord(element)
{
currElement = element;
xOffSet = 0;

document.getElementById('TRAVERSAL_TEXT').childNodes[0].data =
'\tTag=' + currElement.tagName + ',\tOffset=' + currElement.offsetLeft
+ ',\tCummulative Offset=' + xOffSet + '\n';
while (currElement.parentNode != null)
{
xOffSet += currElement.offsetLeft;
currElement = currElement.parentNode;
document.getElementById('TRAVERSAL_TEXT').childNodes[0].data
+= '\tTag=' + currElement.tagName + ',\tOffset=' +
currElement.offsetLeft + ',\tCummulative Offset=' + xOffSet + '\n';
}
// alert(xOffSet + '; ' + element.scrollTop)
// alert(xOffSet + ' | ' + window.status);
return xOffSet;
}




//-->
</SCRIPT>


</HEAD>
<FORM name="myForm">
<BODY>


<table border=1 >
<TR>
<TD
bgcolor="gray"
name="TABLE_CELL"
id="TABLE_CELL"Gray Box
</TD>
</TR>
<TR>
<TD bgcolor="pink">Mouse X Position: <PRE
name="MOUSE_XPOS" id="MOUSE_XPOS">0</PRE>
</TD>
</TR>
<TR>
<TD>Left Edge of Gray Box: &nbsp;
<input
type="text"
value="xxx"
name="TABLE_TEXT"
id="TABLE_TEXT"

onMouseOver="javascript:getElementById('TABLE_TEXT').value =
getLeftXCoord(document.getElementById('TABLE_CELL'));"</TD>
</TR>
<TR>
<TD bgcolor="yellow">Tree Traversal from Gray Box to
Root: <BR>
<PRE name="TRAVERSAL_TEXT"
id="TRAVERSAL_TEXT">XXX</PRE>
</TD>
</TR>
</TABLE>
</BODY>
</FORM>
</HTML>
 
M

Michael Winter

Please excuse me, this is a fairly involved question that will likely
require you to save the file below to a file and open it in a browser.
I use Mozilla 1.5, so the problem I describe below should be
reproducible with that version at least.

[snip]

Your form isn't invisible - it's invalid.

You can't expect JavaScript or CSS to behave properly when they operate on
invalid HTML. Validate your pages first, then re-test.

You can use the W3C validator at:

http://validator.w3.org/

Mike
 
M

Michael Winter

[This followup was posted to comp.lang.javascript and a copy was sent to
the cited author.]

Your post below isn't much help.

I tried using the validator that you specified but it
didn't tell me what specific change I need to make to
my file to make it pass.

Incidentally, I gave the validator the following HTML
and it said it was invalid as well.

<HTML>
<HEAD>
</HEAD>
<BODY>
Hello World
</BODY>
</HTML>

That's because it *is* invalid HTML. Valid HTML documents need a DOCTYPE
declaration, a default character set (sometimes sent automatically by the
server), and a TITLE element in the HEAD block.

Here is my default template[1].

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">

<html>
<head>
<meta http-equiv="Content-Type"
content="text/html; charset=iso-8859-1">
<meta http-equiv="Content-Script-Type" content="text/javascript">
<meta http-equiv="Content-Style-Type" content="text/javascript">

<title>Untitled</title>
</head>

<body>
</body>
</html>

However, based on your post to the newsgroup, you will have to use the
Transitional DOCTYPE which allows elements and attributes such as FONT and
bgcolor. The Transitional DOCTYPE is:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">

Mike

[1] As it stands, it won't validate either, but that's only because the
BODY section has no content.
 
R

Randy Webb

Michael said:
[This followup was posted to comp.lang.javascript and a copy was sent to
the cited author.]

Your post below isn't much help.

I tried using the validator that you specified but it
didn't tell me what specific change I need to make to
my file to make it pass.

Incidentally, I gave the validator the following HTML
and it said it was invalid as well.

<HTML>
<HEAD>
</HEAD>
<BODY>
Hello World
</BODY>
</HTML>


That's because it *is* invalid HTML. Valid HTML documents need a DOCTYPE
declaration, a default character set (sometimes sent automatically by
the server), and a TITLE element in the HEAD block.

I could be dead wrong here, but I seem to recall a debate, I believe in
ciwah, and the only tag that was found to be required in HTML was the
title tag, the rest are optional. The Validator requires the DTD for
validation purposes. Or at least thats my understanding of it all.
Here is my default template[1].

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">

<html>
<head>
<meta http-equiv="Content-Type"
content="text/html; charset=iso-8859-1">
<meta http-equiv="Content-Script-Type" content="text/javascript">
<meta http-equiv="Content-Style-Type" content="text/javascript">

Is that a typo? Content-Style-Type of text/javascript?
 
M

Michael Winter

Michael Winter wrote:
[snip]
That's because it *is* invalid HTML. Valid HTML documents need a
DOCTYPE declaration, a default character set (sometimes sent
automatically by the server), and a TITLE element in the HEAD block.

I could be dead wrong here, but I seem to recall a debate, I believe in
ciwah, and the only tag that was found to be required in HTML was the
title tag, the rest are optional. The Validator requires the DTD for
validation purposes. Or at least thats my understanding of it all.

After reading various bits of the specification...

Technically speaking, the DTD is required as it defines the elements and
their attributes used in the document. Realistically, we know this doesn't
happen, but the fact that browsers render documents differently depending
on the DTD provided shows that it is needed for (semi-) consistent display.

From Section 5.1 of the HTML Standard:

"To promote interoperability, SGML requires that each application
(including HTML) specify its document character set."

That would indicate to me that either a server or META declaration is
required on all documents.

As for only needing TITLE, according to the Strict DTD, both HEAD and BODY
must occur, in that order, which implies the inclusion of the HTML element:

<!ENTITY % html.content "HEAD, BODY">

<!ELEMENT HTML O O (%html.content;)>
<!ATTLIST HTML
%i18n; -- lang, dir --

%head.content; - TITLE and an optional BASE - must occur in HEAD:

<!ENTITY % head.content "TITLE & BASE?">

<!ELEMENT HEAD O O (%head.content;) +(%head.misc;)>


It also specifies that at least one block or SCRIPT element must occur in
BODY:

<!ELEMENT BODY O O (%block;|SCRIPT)+ +(INS|DEL)>

Minus the Content-Script-Type and Content-Style-Type META elements, and
the inclusion of some content in the BODY section, the template I posted
is the *minimum* HTML that can be viewed as valid.
Here is my default template[1].

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">

<html>
<head>
<meta http-equiv="Content-Type"
content="text/html; charset=iso-8859-1">
<meta http-equiv="Content-Script-Type" content="text/javascript">
<meta http-equiv="Content-Style-Type" content="text/javascript">

Is that a typo? Content-Style-Type of text/javascript?

What? Smeg.

Unfortunately, that's not a typo. It's a direct copy of my template. Thank
goodness that:

1) Most browsers seem to ignore the default script type anyway,
2) I rarely use inline styles, and
3) It has only existed since I built this machine (a few weeks - the
template was correct before).

How embarassing... Thank you for pointing that out. It has been corrected.

Mike
 
R

Richard Cornford

Michael Winter said:
As for only needing TITLE, according to the Strict DTD,
both HEAD and BODY must occur, in that order, which implies
the inclusion of the HTML element:

<!ENTITY % html.content "HEAD, BODY">

The head and body elements may be required but:-

<!ELEMENT HTML O O (%html.content;)>
^ ^
Optional opening tag |
Optional closing tag

- and the same with:-

<!ELEMENT HEAD O O (%head.content;) +(%head.misc;)>
<!ELEMENT BODY O O (%block;|SCRIPT)+ +(INS|DEL)>
<snip> ^ ^
But:-

<!ELEMENT TITLE - - (#PCDATA) -(%head.misc;) >
^ ^
Requires opening and closing tags for the title (but there is an SGML
shorthand, which I don't remember so won't be using here).

The transitional HTML 4 DTD allows BODY to be empty so a short valid
transitional HTML page could be the doctype declaration followed by:-

<title></title>

As the tags for all of the other required (implied?) elements are
optional (Disregarding any MATA tag stuff).

There is no way I would recommend omitting any of the optional tags.
Better for people to learn to create formally complete valid HTML first
and then when they are getting that right they can start considering
which tags are optional and can be left out. But personally I prefer to
include the optional tags anyway, it is just easier not to attempt to
remember which can be omitted.

Richard.
 
M

Michael Winter

The head and body elements may be required but:-


^ ^
Optional opening tag |
Optional closing tag

- and the same with:-



<snip> ^ ^
But:-

<!ELEMENT TITLE - - (#PCDATA) -(%head.misc;) >
^ ^
Requires opening and closing tags for the title (but there is an SGML
shorthand, which I don't remember so won't be using here).

The transitional HTML 4 DTD allows BODY to be empty so a short valid
transitional HTML page could be the doctype declaration followed by:-

<title></title>

As the tags for all of the other required (implied?) elements are
optional (Disregarding any MATA tag stuff).

There is no way I would recommend omitting any of the optional tags.
Better for people to learn to create formally complete valid HTML first
and then when they are getting that right they can start considering
which tags are optional and can be left out. But personally I prefer to
include the optional tags anyway, it is just easier not to attempt to
remember which can be omitted.

Richard.
 
M

Michael Winter

[snip]
<!ENTITY % html.content "HEAD, BODY">

The head and body elements may be required but:-
<!ELEMENT HTML O O (%html.content;)>
^ ^
Optional opening tag |
Optional closing tag

- and the same with:-

<!ELEMENT HEAD O O (%head.content;) +(%head.misc;)>
<!ELEMENT BODY O O (%block;|SCRIPT)+ +(INS|DEL)>
<snip> ^ ^
But:-

<!ELEMENT TITLE - - (#PCDATA) -(%head.misc;) >
^ ^
Requires opening and closing tags for the title (but there is an SGML
shorthand, which I don't remember so won't be using here).

That hadn't escaped my notice, but I don't think it means what you propose
here. After all, SCRIPT elements have required opening and closing tags,
just like TITLE. That doesn't mean you must have one in every document.

What does indicate that it is required is:

1) The word "must" is written in bold when describing the presence of
TITLE in the Specification. "Must" in that sense uses the definition in
RFC2119.
2) %head.content; (TITLE and optional BASE) is required, *and* the start
and end tags are required for TITLE.

I must admit that marking the tags for the HTML, HEAD and BODY elements as
optional is a rather strange thing to do, and certainly not a practice
that should be encouraged.

What is more strange is that I rebuilt my template, starting with the
DOCTYPE, character set, and TITLE, and added the other elements until it
validated. It didn't do so until the entire template was written. When I
reversed the process before writing this reply, it did validate with just
those three elements and a DIV (for content).

I must have done something wrong last night, like not including content
until I added all the optional elements... I was tired, OK :p

Well, once again, my ideas about a technology have just been turned on its
head.

Mike
 
S

Saqib Ali

Michael Winter said:
Michael Winter wrote:
[snip]
That's because it *is* invalid HTML. Valid HTML documents need a
DOCTYPE declaration, a default character set (sometimes sent

<SNIP>

Can you tell me what I need to do to make it valid?
I copied your head and your doctype stuff into my code and
the validator complained that all the attributes that I am using were
invalid.It said that this is most commonly caused by using
vendor-specific attributes without setting the document type
appropriately. So what is the appropriate document type??

Here is my default template[1].

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">

<html>
<head>
<meta http-equiv="Content-Type"
content="text/html; charset=iso-8859-1">
<meta http-equiv="Content-Script-Type" content="text/javascript">
<meta http-equiv="Content-Style-Type" content="text/javascript">

Is that a typo? Content-Style-Type of text/javascript?

What? Smeg.

Unfortunately, that's not a typo....

Could you please post the correction??
 
M

Michael Winter

Michael Winter said:
Michael Winter wrote:
[snip]

That's because it *is* invalid HTML. Valid HTML documents need a
DOCTYPE declaration, a default character set (sometimes sent

<SNIP>

Can you tell me what I need to do to make it valid?
I copied your head and your doctype stuff into my code and
the validator complained that all the attributes that I am using were
invalid.It said that this is most commonly caused by using
vendor-specific attributes without setting the document type
appropriately. So what is the appropriate document type??

Here is my default template[1].

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">

<html>
<head>
<meta http-equiv="Content-Type"
content="text/html; charset=iso-8859-1">
<meta http-equiv="Content-Script-Type" content="text/javascript">
<meta http-equiv="Content-Style-Type" content="text/javascript">

Is that a typo? Content-Style-Type of text/javascript?

What? Smeg.

Unfortunately, that's not a typo....

Could you please post the correction??
 
M

Michael Winter

Michael Winter wrote:
[snip]

That's because it *is* invalid HTML. Valid HTML documents need a
DOCTYPE declaration, a default character set (sometimes sent

<SNIP>

Can you tell me what I need to do to make it valid?
I copied your head and your doctype stuff into my code and
the validator complained that all the attributes that I am using were
invalid. It said that this is most commonly caused by using
vendor-specific attributes without setting the document type
appropriately. So what is the appropriate document type??

As I stated in my first post, you will be unable to use the Strict DTD as
you use the deprecated attributes, bgcolor and language. You either need
to use the Transitional DTD, or style sheets. The latter, in my opinion,
should be used by all new web sites: there is no need for presentational
HTML (unless special circumstances apply).

[snip]
Could you please post the correction??

The correct content type for CSS is text/css. The META element should read:

<meta http-equiv="Content-Style-Type" content="text/css">


I read through your document and compiled the following HTML errors and
script problems. I then made an equivalent page that will validate as HTML
Strict. You can view it at this address:

http://www.mlwinter.pwp.blueyonder.co.uk/clj/ali/offset.html

It's not great. It would need work before it could be classed as
"production quality" (comments from other members are more than welcome),
but it is better.

If the example page you gave was for personal use, some of the comments
below might not apply, as long as you acknowledge their validity in
general use.
<SCRIPT language="JavaScript1.2">
<!--

The language attribute is deprecated. You should use the type attribute:

<script type="text/javascript">

The practice of hiding scripts with SGML comment delimiters is obsolete.
Don't bother in future.
var IE = document.all?true:false;

This will *not* detect IE, it just infers that if the document.all
collection is supported, the browser is IE. As Opera also supports
document.all, it is clear what problems can be encountered with this
approach. Use feature detection, instead.
if (!IE) document.captureEvents(Event.MOUSEMOVE)
document.releaseEvents(Event.MOUSEMOVE);
document.onmousemove = getMousePos;

IE doesn't support document.releaseEvents, but you call it anyway.
Besides, I'm not sure how necessary it is for you to use captureEvents()
and releaseEvents() in Gecko browsers. Newer versions of Mozilla and
Netscape will call getMousePos() when the mousemove event is fired if that
last line is used by itself.
var mouseX = 0

Why is this variable global? It is only used in the getMousePos()
function. It should be local.
if (IE) // grab the x pos.s if browser is IE
mouseX = event.clientX + document.body.scrollLeft;
else // grab the x pos.s if browser is NS
mouseX = e.pageX;

Another example of potentially bad guess work.
document.getElementById('MOUSE_XPOS').childNodes[0].data = mouseX;

You haven't checked for support of any of these methods or properties. As
earlier versions of IE have poor support for DOM components, that is a bad
idea.
function getLeftXCoord(element) {
currElement = element;
xOffSet = 0;

Both of these variables are needlessly global. currElement isn't
necessary, anyway.
document.getElementById('TRAVERSAL_TEXT').childNodes[0].data =
'\tTag=' + currElement.tagName + ',\tOffset=' +
currElement.offsetLeft + ',\tCummulative Offset=' + xOffSet + '\n';
while (currElement.parentNode != null)

More assumed support. That assignment is also duplicated (bad algorithm).

Using \n alone to add a new line in a PRE element doesn't work in IE: it
requires \r. Using \r alone doesn't work in Netscape and Mozilla. Using
both (\r\n) adds a space in the latter two. As it happens, Opera supports
all three combinations properly.

In my page, I used Node.nodeName in place of Element.tagName so that the
#document node was shown.
</HEAD>
<FORM name="myForm">
<BODY>

If the BODY element is included, which is recommended, content mark-up
*must* appear within the start tag. You should also use the id attribute
in preference to name.
<table border=1 >

The use of table in this document is "element abuse": there is nothing
tabular about the data contained in it. DIVs would be more appropriate. I
kept the table in my version of the page as it shows the DOM node
traversal nicely.
<TD bgcolor="gray" name="TABLE_CELL" id="TABLE_CELL">

The bgcolor attribute is deprecated. Use the background-color style
property instead.

Table cells do not, and never have had as far as I know, a name attribute.
Only id is valid.
<TD bgcolor="pink">Mouse X Position: <PRE name="MOUSE_XPOS"
id="MOUSE_XPOS">0</PRE>

Like table cells, PRE has never had a name attribute.
<input type="text" value="xxx" name="TABLE_TEXT" id="TABLE_TEXT"
onMouseOver="javascript:getElementById('TABLE_TEXT').value=
getLeftXCoord(document.getElementById('TABLE_CELL'));"

There are no HTML problems here, but the script code is faulty:

1) Using "javascript:" in an intrinsic event does not specify the language
in any browser other than IE. The defined way of specifying the default
language is shown in my template (the second META element).
2) getElementById() is not a global. You must fully specify it with
"document.". You must also test for support before using it.
3) You made life more difficult for yourself than it needed to be. That
intrinsic event could have been written:

function getRefById( id ) {
if( document.getElementById ) {
return document.getElementById( id );
} else if( document.all ) {
return document.all[ id ];
}
return null;
}
...
onmouseover="this.value=getLeftXCoord(getRefById('TABLE_CELL'));"
</BODY>
</FORM>

These should be interchanged.

Some of the problems above are repeated in places.

To address the original question, the offset calculations seem to behave
correctly in IE 6, Opera 7.23 and Mozilla 1.6. For some reason, Netscape
7.0 decides that the table body, cell and row are at an offset of -1 each,
so the result is off by 3 pixels.

Mike
 
R

Richard Cornford

Michael said:
... . Besides, I'm not sure how necessary it is for you to use
captureEvents() and releaseEvents() in Gecko browsers. Newer
versions of Mozilla and Netscape will call getMousePos() when
the mousemove event is fired if that last line is used by itself.
<snip>

I haven't looked at what this code is trying to do but mostly it would
not be wise to be calling captureEvents on non-Netscape 4 (and close
imitators) because more recent browsers will trigger the event handler
"at target" and if you call captureEvents they will also trigger the
handler in the capturing phase. Meaning the same function will handle
the same event twice.

With mouse move events that can be particularly bad as you get an event
pretty much whenever the mouse crosses a pixel boundary, so a gesture
with the mouse can easily trigger a couple of hundred events. Call
captureEvents and you double the number of calls to the handler.
(Obviously mouse move handlers also badly need to be really efficiently
coded, with as much feature detection and configuration done up front as
possible).

Richard.
 

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,564
Members
45,039
Latest member
CasimiraVa

Latest Threads

Top