473,396 Members | 1,995 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,396 software developers and data experts.

Blank textNodes in the DOM

Daz
Hi everyone.

This might be a straight forward question, but when I open the DOM
inspector inside of Firefox, I see that almost every DOM element seems
to have a textNode above it. When I try to see the contents, it shows
as being 'undefined'. Can anyone plase explain to me the purpose that
they server. Perhaps then I will be able to understand them better, as
quite often, when I use firstChild, instead of getting the element I
want, I end up with what appears to be a blank text node.

Many thanks.

Daz.

Dec 27 '06 #1
10 1537
VK

Daz wrote:
This might be a straight forward question, but when I open the DOM
inspector inside of Firefox, I see that almost every DOM element seems
to have a textNode above it. When I try to see the contents, it shows
as being 'undefined'. Can anyone plase explain to me the purpose that
they server. Perhaps then I will be able to understand them better, as
quite often, when I use firstChild, instead of getting the element I
want, I end up with what appears to be a blank text node.
1)
<http://en.wikipedia.org/wiki/Phantom_nodes>
<http://en.wikipedia.org/wiki/Talk:Phantom_nodes>

2)
<https://bugzilla.mozilla.org/show_bug.cgi?id=26179>

3)
<http://developer.mozilla.org/en/docs/DOM:element.firstChild#Notes>

That's a RWAR (<http://mindprod.com/jgloss/rwar.html>) topic, so just
make your own decision and choose from existing workarounds.

Dec 27 '06 #2
Daz

VK wrote:
Daz wrote:
This might be a straight forward question, but when I open the DOM
inspector inside of Firefox, I see that almost every DOM element seems
to have a textNode above it. When I try to see the contents, it shows
as being 'undefined'. Can anyone plase explain to me the purpose that
they server. Perhaps then I will be able to understand them better, as
quite often, when I use firstChild, instead of getting the element I
want, I end up with what appears to be a blank text node.

1)
<http://en.wikipedia.org/wiki/Phantom_nodes>
<http://en.wikipedia.org/wiki/Talk:Phantom_nodes>

2)
<https://bugzilla.mozilla.org/show_bug.cgi?id=26179>

3)
<http://developer.mozilla.org/en/docs/DOM:element.firstChild#Notes>

That's a RWAR (<http://mindprod.com/jgloss/rwar.html>) topic, so just
make your own decision and choose from existing workarounds.
Aha. Phantom nodes. Thanks VK! :) Looks like I've walked into an rwar
zone...

Dec 27 '06 #3
VK

Daz wrote:
Aha. Phantom nodes. Thanks VK! :) Looks like I've walked into an rwar
zone...
Yeah, with the first step and right in the middle :-)

For Firefox DOM Inspector itself you can change the view option by
going in DOM Inspector window to View Show Whitespace Nodes. This
affects the DOM Inspector display *only*, no DOM Tree changes.

To deal with the ... observed phenomenon ... programwise see for
instance:

<http://www.codingforums.com/showthread.php?t=7028>
<http://developer.mozilla.org/en/docs/Whitespace_in_the_DOM>
<http://developer.mozilla.org/en/docs/Talk:Whitespace_in_the_DOM>

Dec 27 '06 #4
Daz schreef:
Hi everyone.

This might be a straight forward question, but when I open the DOM
inspector inside of Firefox, I see that almost every DOM element seems
to have a textNode above it. When I try to see the contents, it shows
as being 'undefined'. Can anyone plase explain to me the purpose that
they server. Perhaps then I will be able to understand them better, as
quite often, when I use firstChild, instead of getting the element I
want, I end up with what appears to be a blank text node.

Many thanks.

Daz.
The purpose that they serve:
<span>Hi,</span>
<span>how are you?</span>

Should return:
Hi, how are you?

If the white-space were discarded, this would return:
Hi,how are you?
Dec 27 '06 #5
Daz

VK wrote:
Daz wrote:
Aha. Phantom nodes. Thanks VK! :) Looks like I've walked into an rwar
zone...

Yeah, with the first step and right in the middle :-)

For Firefox DOM Inspector itself you can change the view option by
going in DOM Inspector window to View Show Whitespace Nodes. This
affects the DOM Inspector display *only*, no DOM Tree changes.

To deal with the ... observed phenomenon ... programwise see for
instance:

<http://www.codingforums.com/showthread.php?t=7028>
<http://developer.mozilla.org/en/docs/Whitespace_in_the_DOM>
<http://developer.mozilla.org/en/docs/Talk:Whitespace_in_the_DOM>
That's some very interesting stuff! However, I think I will just leave
the 'phantom nodes' be for now, and learn to work with them.

After reading the articles you suggested, the thought of attempting to
remove the phantom nodes terrified me somewhat. Perhaps it WILL work
effectively, but to me it looks like there is always something that
just 'might' go wrong, so you may not get the results you'd expect,
(for example, you could accidentally concatenate two words without the
whitespace). Also, removing them takes time, and resources, and
apparently IE renders the phantom nodes differently to other browsers
(no surprises there), so it would just make sense to make a small
abstraction layer which can be placed over methods such as
firstChild(), nextSibling(), childNodes() etc... just check to see if
the child is a whitespace, and if it is, perhaps return the next child
(even if that happens to be a whitespace, too).

For childNodes(), we could have a method that will return an array of
elements and textNodes, without the phantom spaces. How will we know if
it's a phantom node? This I am not entirely sure of. From observation,
it looks like phantom nodes tend to follow elements of nodeType '1'.
Although there is a chance the whitespace we are assuming is a phantom
node, actually is not, it doesn't matter. It's very unlikely that we
will need to do anything with the whitespace, even if it's not a
phantom node, so we can work with the text/element that follows. As we
aren't removing anything from the page, the formatting will remain the
same.

We can also use the normalize() method, which when used on an example
like this:

<span>
This is
some
text
</span>
will join text nodes so we will end up with the code rendered like
this:

<span>
This is some text
</span>

I think this is a useful method to utilise, but I seem to remember
reading that IE doesn't support it, so I guess it's just a case of
going back to basics, and doing everything with XP scripting, and not
relying on methods that aren't supported by all browsers.

I am not saying my method is correct, however, I noticed that it wasn't
posted on any of the forums you suggested, and as you rightly said,
there may never be an agreement as to who's method is the best. Granted
that sometimes a certain method can be better than others, and other
times a different approach is more effective, but in my humble opinion,
I believe that removing the phantom nodes is a recipe for disaster! I
think we should all just work with them. :D

I think it's the programmers responsibility to ensure that their HTML
comes with phantom nodes in all of the right places, or none at all. If
they are sending both the HTML and the JavaScript to the user, there is
no reason for the script not to be compatible with the code, and vice
versa. Having to phantom nodes at all would be the preference as it
would save page loading times (marginally, yes, but exponantially in
the long run on a busy server). I think my method (which probably isn't
unique) should cover both scenarios, and of course be helpful to people
who are coding JavaScript that works independantly of the page (i.e a
Firefox extension).

Thanks again VK.

Dec 29 '06 #6
Daz

VK wrote:
Daz wrote:
Aha. Phantom nodes. Thanks VK! :) Looks like I've walked into an rwar
zone...

Yeah, with the first step and right in the middle :-)

For Firefox DOM Inspector itself you can change the view option by
going in DOM Inspector window to View Show Whitespace Nodes. This
affects the DOM Inspector display *only*, no DOM Tree changes.

To deal with the ... observed phenomenon ... programwise see for
instance:

<http://www.codingforums.com/showthread.php?t=7028>
<http://developer.mozilla.org/en/docs/Whitespace_in_the_DOM>
<http://developer.mozilla.org/en/docs/Talk:Whitespace_in_the_DOM>
Here are some ideas for method names. I would appreciate any input you
might have to offer, as I am contemplating making my first JavaScript
library, but it's pointless if I am going to be the only one to use it.
It might be overkill, and it's only a few rough ideas that could do
with some tweaking:

// All functions return null if there is nothing to return.

firstChildElement:
Returns the first child node of the specified parent node, that is an
element, if one exists.

firstChildTextNode:
Returns the first child node of the specified parent node that is a
textNode, but not a whitespace, if one exists.
lastChildElement:
Returns the last child node of the specified parent node that is an
element, if one exists.

lastChildTextNode:
Returns the last child node of the specified parent node that is an
textNode, but not a whitespace, if one exists.

nextSiblingElement:
Returns the next sibling node of the specified node that is an element,
if one exists.

nextSiblingTextNode:
Returns the next sibling node of the specified node that is a textNode,
but not a whitespace, if one exists.

previousSiblingElement:
Returns the previous sibling node of the specified node that is an
element, if one exists.

previousSiblingTextNode:
Returns the previous sibling node of the specified node that is a
textNode, but not a whitespace, if one exists.

childElements[]:
Returns an array of all of the child nodes of the specified parent
node, that are elements, if any exist.

childTextNodes[]:
Returns an array of all of the child nodes of the specified parent
node, that are textNodes, but not whitespaces, if any exist.
Please let me know if such a library already exists, it might save me
reinventing the wheel. I think the functions I have named above would
be seriously easy to implement, and also they should cover all of the
methods that might be effected by phantom nodes (i.e. the methods that
return a node of an unspecified type, unlike getElementsByTagName(), or
getElementById(), which shouldn't be effected by phantom nodes).

All the best.

Daz.

Dec 29 '06 #7
Daz wrote:

[snip]
Here are some ideas for method names. I would appreciate any input you
might have to offer, as I am contemplating making my first JavaScript
library, but it's pointless if I am going to be the only one to use it.
Not really. There's no harm in writing functions that can be reused in
the future, though writing a library might not be a good idea. It
depends on what you attribute to the idea of a library.

[snip]
firstChildElement:
Returns the first child node of the specified parent node, that is an
element, if one exists.

firstChildTextNode:
Returns the first child node of the specified parent node that is a
textNode, but not a whitespace, if one exists.
[snipped similar definitions]
Please let me know if such a library already exists, it might save me
reinventing the wheel.
I took a different approach to this sort of thing that's closer, in
principle, to the W3C DOM Traversal methods. That is, a few methods are
used to traverse the document tree given a filter with which to test the
nodes that are encountered. So, rather than a function that is dedicated
to returning the first child element, there's a function that is passed
a callback to test for elements, returning the first one for which the
callback returns true.

function createElementCallback(tagName) {
return function (node) {
return isElement(node, tagName);
};
}
function getFirstChild(parent, test) {
var node = parent.firstChild;

if (node) {
return test(node) ? node : this.getNextSibling(node, test);
}
return null;
}
function getLastChild(parent, test) {
var node = parent.lastChild;

if (node) {
return test(node)
? node : this.getPreviousSibling(node, test);
}
return null;
}
function getNextSibling(node, test) {
while ((node = node.nextSibling)) {
if (test(node)) {
return node;
}
}
return null;
}
function getPreviousSibling(node, test) {
while ((node = node.previousSibling)) {
if (test(node)) {
return node;
}
}
return null;
}
function isElement(node, tagName) {
return (node.nodeType == 1)
&& (tagName ? (node.nodeName == tagName)
: (node.nodeName != '!'));
}
function isTextNode(node) {
return node.nodeType == 3;
}

So,

firstChildElement(parent)

would be implemented as:

getFirstChild(parent, isElement)

To find a specific element type, use:

var isAnchor = createElementCallback('A');

getFirstChild(parent, isAnchor)
Your specific definition of

firstChildTextNode(parent)

could be implemented as:

getFirstChild(parent, function (node) {
return isTextNode(node) && /\W/.test(node.data);
})

I prefer the flexibility that this approach offers.

[snip]

Mike
Dec 29 '06 #8
Daz

Michael Winter wrote:
Daz wrote:

[snip]
Here are some ideas for method names. I would appreciate any input you
might have to offer, as I am contemplating making my first JavaScript
library, but it's pointless if I am going to be the only one to use it.

Not really. There's no harm in writing functions that can be reused in
the future, though writing a library might not be a good idea. It
depends on what you attribute to the idea of a library.

[snip]
firstChildElement:
Returns the first child node of the specified parent node, that is an
element, if one exists.

firstChildTextNode:
Returns the first child node of the specified parent node that is a
textNode, but not a whitespace, if one exists.

[snipped similar definitions]
Please let me know if such a library already exists, it might save me
reinventing the wheel.

I took a different approach to this sort of thing that's closer, in
principle, to the W3C DOM Traversal methods. That is, a few methods are
used to traverse the document tree given a filter with which to test the
nodes that are encountered. So, rather than a function that is dedicated
to returning the first child element, there's a function that is passed
a callback to test for elements, returning the first one for which the
callback returns true.

function createElementCallback(tagName) {
return function (node) {
return isElement(node, tagName);
};
}
function getFirstChild(parent, test) {
var node = parent.firstChild;

if (node) {
return test(node) ? node : this.getNextSibling(node, test);
}
return null;
}
function getLastChild(parent, test) {
var node = parent.lastChild;

if (node) {
return test(node)
? node : this.getPreviousSibling(node, test);
}
return null;
}
function getNextSibling(node, test) {
while ((node = node.nextSibling)) {
if (test(node)) {
return node;
}
}
return null;
}
function getPreviousSibling(node, test) {
while ((node = node.previousSibling)) {
if (test(node)) {
return node;
}
}
return null;
}
function isElement(node, tagName) {
return (node.nodeType == 1)
&& (tagName ? (node.nodeName == tagName)
: (node.nodeName != '!'));
}
function isTextNode(node) {
return node.nodeType == 3;
}

So,

firstChildElement(parent)

would be implemented as:

getFirstChild(parent, isElement)

To find a specific element type, use:

var isAnchor = createElementCallback('A');

getFirstChild(parent, isAnchor)
Your specific definition of

firstChildTextNode(parent)

could be implemented as:

getFirstChild(parent, function (node) {
return isTextNode(node) && /\W/.test(node.data);
})

I prefer the flexibility that this approach offers.

[snip]

Mike
Hi Mike.

Thanks for your input, I really appreciate it. When my methods are
compared to yours, mine soon become 2D, as opposed to 3D as I thought
they were. Your methods are certainly more versatile, and beyond any
doubt give a LOT more flexibility.

Just one thing I don't understand about your code:
function isElement(node, tagName) {
return (node.nodeType == 1)
&& (tagName ? (node.nodeName == tagName)
: (node.nodeName != '!'));
}
Please could you explain what:
(node.nodeName != '!')
does? I don't understand why a nodeName might be '!'.

All the best.

Daz.

Dec 29 '06 #9
Daz wrote:
Michael Winter wrote:
[snip]
> function isElement(node, tagName) {
return (node.nodeType == 1)
&& (tagName ? (node.nodeName == tagName)
: (node.nodeName != '!'));
}

Please could you explain what:
> (node.nodeName != '!')

does? I don't understand why a nodeName might be '!'.
An irritating error in IE 5.x is that the nodeType property of comment
nodes evaluates to a value of 1 (ELEMENT_NODE) not 8 (COMMENT_NODE).
However, one can distinguish between the two by testing whether the
nodeName or tagName properties evaluate to '!'.

Comments aren't a frequent occurrence in hand-written markup, but
content generation tools do include them, and IE 5.x users do still
exist. If you know that neither will ever be an issue, the isElement
function can be rewritten:

function isElement(node, tagName) {
return (node.nodeType == 1)
&& (!tagName || (node.nodeName == tagName));
}

Mike
Dec 29 '06 #10
Daz

Michael Winter wrote:
Daz wrote:
Michael Winter wrote:

[snip]
function isElement(node, tagName) {
return (node.nodeType == 1)
&& (tagName ? (node.nodeName == tagName)
: (node.nodeName != '!'));
}
Please could you explain what:
(node.nodeName != '!')
does? I don't understand why a nodeName might be '!'.

An irritating error in IE 5.x is that the nodeType property of comment
nodes evaluates to a value of 1 (ELEMENT_NODE) not 8 (COMMENT_NODE).
However, one can distinguish between the two by testing whether the
nodeName or tagName properties evaluate to '!'.

Comments aren't a frequent occurrence in hand-written markup, but
content generation tools do include them, and IE 5.x users do still
exist. If you know that neither will ever be an issue, the isElement
function can be rewritten:

function isElement(node, tagName) {
return (node.nodeType == 1)
&& (!tagName || (node.nodeName == tagName));
}

Mike
Good stuff!

Thanks again. :)

Daz.

Dec 29 '06 #11

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

12
by: dan glenn | last post by:
Hi. I'm finding that if I have text entered into a <textarea ...> </textarea> in a form, and that text has leading blank lines (with no spaces or anything else), that when I retrieve the entered...
2
by: Johm | last post by:
How can i go to the next blank record in the table , such a blank record exists ? In my form Customers, i have a command button with the following command : DoCmd.GoToRecord , "", acNewRec...
5
by: ChadDiesel | last post by:
My basic question is why does my print report button on my subform print a blank report when my cursor is on a blank entry line? Here is a more detailed explanation of my problem. I have a...
2
by: Ken Loomis | last post by:
Hello: I'm using the validating event on a text boxes to test for valid dates, doubles, etc. The problem is that if the field is not required and a blank value is OK and the user deletes a...
6
by: Johann Blake | last post by:
I fill a table in a dataset with values that will be used by a combobox for the combobox's items. The combobox is a drop down list that only allows the user to select from the list but not enter...
4
by: sparks | last post by:
I am trying to fix a database that someone did about 4 yrs ago in access97. The main table just contains demographics and is on the main form of the database. It has a subform on a tab that...
0
by: mollyf | last post by:
I've got a combo box that I want to bind a collection to. I got the error "Complex Data Binding accepts as a data source either an IList or an IListSource" so I tried using the BindingSource,...
19
by: billa856 | last post by:
Hi, I have to use the table(PRODUCTION) already generated in MS Access in which all fields are of TEXT type.fields like (orderdate,palletno,customercode,itemno,pono,carto n,pcs,totalquantity)Now i...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.