Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Javascript > Iterating though nodes

Reply
Thread Tools

Iterating though nodes

 
 
matth
Guest
Posts: n/a
 
      11-01-2007
I'm trying to iterate through nodes in a Selection Range, but I'm
having a bit of trouble determining why all nodes in the range aren't
being hit. It seems like deeply nested nodes aren't being hit for some
reason.

Here's the code I'm using.

var n = startNode;
while (n) {
this.visited.push('[' + n.nodeName + ']');

if (n == endNode) {
break;
}

if (n != startNode && n.hasChildNodes()) {
n = n.firstChild;
} else {
while (!n.nextSibling) {
n = n.parentNode;
}
n = n.nextSibling;
}
}

 
Reply With Quote
 
 
 
 
Evertjan.
Guest
Posts: n/a
 
      11-01-2007
matth wrote on 01 nov 2007 in comp.lang.javascript:

> I'm trying to iterate through nodes in a Selection Range, but I'm
> having a bit of trouble determining why all nodes in the range aren't
> being hit. It seems like deeply nested nodes aren't being hit for some
> reason.
>
> Here's the code I'm using.
>
> var n = startNode;
> while (n) {
> this.visited.push('[' + n.nodeName + ']');
>
> if (n == endNode) {
> break;
> }
>
> if (n != startNode && n.hasChildNodes()) {
> n = n.firstChild;
> } else {
> while (!n.nextSibling) {
> n = n.parentNode;
> }
> n = n.nextSibling;
> }
>}


Ty this reentrant function:

========== test.html ========

<body id=b>
<div id=d1>qq</div>
<div id=d2><div id=d21><span id=211>x</span></div>
<div id=d22>qq</div><div id=d23>qq</div></div>
<div id=d3>qq</div>
</body>

<script type='text/javascript'>

var a = [];
travel(document.body);
alert(a.join('\n'))

function travel(n){
if (n.tagName)
a.push(' tagName: '+n.tagName+ ' id: '+ n.id)
if (n.firstChild)
travel(n.firstChild)
if (n.nextSibling)
travel(n.nextSibling)
}

</script>

=============================


--
Evertjan.
The Netherlands.
(Please change the x'es to dots in my emailaddress)
 
Reply With Quote
 
 
 
 
pr
Guest
Posts: n/a
 
      11-01-2007
matth wrote:
> I'm trying to iterate through nodes in a Selection Range, but I'm
> having a bit of trouble determining why all nodes in the range aren't
> being hit. It seems like deeply nested nodes aren't being hit for some
> reason.
>
> Here's the code I'm using.
>
> var n = startNode;
> while (n) {
> this.visited.push('[' + n.nodeName + ']');
>
> if (n == endNode) {
> break;
> }
>
> if (n != startNode && n.hasChildNodes()) {
> n = n.firstChild;
> } else {
> while (!n.nextSibling) {
> n = n.parentNode;
> }
> n = n.nextSibling;
> }
> }
>


Hello again. That code won't retrieve nodes that are children of the
startNode, because you only visit firstChild for subsequent nodes. Is
that the difficulty? Could you supply URLs of pages that fail?
 
Reply With Quote
 
pr
Guest
Posts: n/a
 
      11-01-2007
Evertjan. wrote:
> matth wrote on 01 nov 2007 in comp.lang.javascript:
>
>> I'm trying to iterate through nodes in a Selection Range, but I'm
>> having a bit of trouble determining why all nodes in the range aren't
>> being hit. It seems like deeply nested nodes aren't being hit for some
>> reason.
>>

> [...]
> <script type='text/javascript'>
>
> var a = [];
> travel(document.body);
> alert(a.join('\n'))
>
> function travel(n){
> if (n.tagName)
> a.push(' tagName: '+n.tagName+ ' id: '+ n.id)
> if (n.firstChild)
> travel(n.firstChild)
> if (n.nextSibling)
> travel(n.nextSibling)
> }
>
> </script>
>


Nice idea, but a DOM Range can contain some distinctly un-well-formed
HTML. We've already had some fun with this in a recent thread if you
want to take a look.
 
Reply With Quote
 
Evertjan.
Guest
Posts: n/a
 
      11-01-2007
pr wrote on 01 nov 2007 in comp.lang.javascript:

> Evertjan. wrote:
>> matth wrote on 01 nov 2007 in comp.lang.javascript:
>>
>>> I'm trying to iterate through nodes in a Selection Range, but I'm
>>> having a bit of trouble determining why all nodes in the range
>>> aren't being hit. It seems like deeply nested nodes aren't being hit
>>> for some reason.
>>>

>> [...]
>> <script type='text/javascript'>
>>
>> var a = [];
>> travel(document.body);
>> alert(a.join('\n'))
>>
>> function travel(n){
>> if (n.tagName)
>> a.push(' tagName: '+n.tagName+ ' id: '+ n.id)
>> if (n.firstChild)
>> travel(n.firstChild)
>> if (n.nextSibling)
>> travel(n.nextSibling)
>> }
>>
>> </script>
>>

>
> Nice idea, but a DOM Range can contain some distinctly un-well-formed
> HTML.


This 'but' is nonsense IMHO, without explanation or example.

My code travels through the DOM-tree and documents all tagNamed nodes.

The given base node of the travel simply is the parameter of travel().

It does not matter if the HTML is un-well-formed, DOM nodes either have
children and/or siblings, or they have not, and they always either have a
parent or or they are at the top or they are not part of the DOM-tree.

> We've already had some fun with this in a recent thread if you
> want to take a look.


I better don't wnat to look,
it will spoil your passed fun,
taking your sentence litterally.

=====================

Documenting the depth goes like this:

<script type='text/javascript'>

var a = [];
var depth = 1;
travel(document.body);
alert(a.join('\n'));

function travel(n){
if (n.tagName)
a.push('['+depth+'] tagName: '+n.tagName+' id: '+n.id);
if (n.firstChild){
depth++;
travel(n.firstChild);
depth--;
};
if (n.nextSibling)
travel(n.nextSibling);
};

</script>

--
Evertjan.
The Netherlands.
(Please change the x'es to dots in my emailaddress)
 
Reply With Quote
 
matth
Guest
Posts: n/a
 
      11-03-2007
On Nov 1, 4:08 pm, "Evertjan." <(E-Mail Removed)> wrote:
> pr wrote on 01 nov 2007 in comp.lang.javascript:
>
>
>
> > Evertjan. wrote:
> >> matth wrote on 01 nov 2007 in comp.lang.javascript:

>
> >>> I'm trying to iterate through nodes in a Selection Range, but I'm
> >>> having a bit of trouble determining why all nodes in the range
> >>> aren't being hit. It seems like deeply nested nodes aren't being hit
> >>> for some reason.

>
> >> [...]
> >> <script type='text/javascript'>

>
> >> var a = [];
> >> travel(document.body);
> >> alert(a.join('\n'))

>
> >> function travel(n){
> >> if (n.tagName)
> >> a.push(' tagName: '+n.tagName+ ' id: '+ n.id)
> >> if (n.firstChild)
> >> travel(n.firstChild)
> >> if (n.nextSibling)
> >> travel(n.nextSibling)
> >> }

>
> >> </script>

>
> > Nice idea, but a DOM Range can contain some distinctly un-well-formed
> > HTML.

>
> This 'but' is nonsense IMHO, without explanation or example.
>
> My code travels through the DOM-tree and documents all tagNamed nodes.
>
> The given base node of the travel simply is the parameter of travel().
>
> It does not matter if the HTML is un-well-formed, DOM nodes either have
> children and/or siblings, or they have not, and they always either have a
> parent or or they are at the top or they are not part of the DOM-tree.
>
> > We've already had some fun with this in a recent thread if you
> > want to take a look.

>
> I better don't wnat to look,
> it will spoil your passed fun,
> taking your sentence litterally.
>
> =====================
>
> Documenting the depth goes like this:
>
> <script type='text/javascript'>
>
> var a = [];
> var depth = 1;
> travel(document.body);
> alert(a.join('\n'));
>
> function travel(n){
> if (n.tagName)
> a.push('['+depth+'] tagName: '+n.tagName+' id: '+n.id);
> if (n.firstChild){
> depth++;
> travel(n.firstChild);
> depth--;
> };
> if (n.nextSibling)
> travel(n.nextSibling);
>
> };
>
> </script>
>
> --
> Evertjan.
> The Netherlands.
> (Please change the x'es to dots in my emailaddress)


Thank you both for your help.
I'm going to include the full bookmarklet code I'm using.
A specific instance that fails is when I select the links and image
typically present at the top of drudgereport.com (the stuff right
above Drudge's header graphic).

I'll try implementing your code Evertjan, and report back.

javascript{
visited: [],
iterate: function(r, startNode, endNode) {
var n = startNode;
var sel = window.getSelection().toString();
var text = null;
while (n) {
if ((n == r.startContainer || n == r.endContainer) && n.nodeType ==
3) {
if (r.startContainer == r.endContainer) {
text = n.nodeValue.substring(r.startOffset, r.endOffset);
} else if (n == r.startContainer) {
text = n.nodeValue.substring(r.startOffset);
} else if (n == r.endContainer) {
text = n.nodeValue.substring(0, r.endOffset);
}
} else if (n.nodeType == 3) {
text = n.nodeValue;
}

this.visited.push('[' + n.nodeName + ']: ' + (n.nodeType == 3 &&
text != null ? text : ''));
text = null;

if (n == endNode) {
break;
}

if (n.hasChildNodes()) {
n = n.firstChild;
} else if (n.nextSibling){
n = n.nextSibling;
} else {
n = n.parentNode.nextSibling;
}
}
},
go: function(r) {
this.iterate(r, r.startContainer, r.endContainer);
var w = window.open(), d = w.document;
var sel = window.getSelection().toString();
d.write(this.visited.join('<br>'));
d.write("<br><br>Selection:<br>" + sel);
d.close();
}
}).go(window.getSelection().getRangeAt(0));

 
Reply With Quote
 
pr
Guest
Posts: n/a
 
      11-05-2007
matth wrote:
> Thank you both for your help.
> I'm going to include the full bookmarklet code I'm using.
> A specific instance that fails is when I select the links and image
> typically present at the top of drudgereport.com (the stuff right
> above Drudge's header graphic).
>
> I'll try implementing your code Evertjan, and report back.
>

[...]

Here's my latest take on the question (another bookmarklet), which you
may find useful. As far as I'm aware, it lists all the nodes beneath a
range's commonAncestorContainer, but the bug is that (so far) it doesn't
indicate whether it's arriving at a node or leaving it. Still, it does
show a couple of things missing in your code:

- child offsets of the startContainer and endContainer when the parent
is an element object or another node having children.

- a slightly different approach to ascending node ancestors in
search of nextSibling (your version quits if there is no
parentNode.nextSibling).

- escaped debug output! This may explain the funny things at Drudge
Report (a couple of <noscript>'s in there).

See what you think...


javascript:

function RangeIterator() {
this.onNode = function (str, node) {}; /* default function: supply
your own */
this.iterate = function (r) {
var me = this, node = r.startContainer, offset = r.startOffset,
finalNode = r.endContainer, finalOffset = r.endOffset;

function visitNode(node, offset) {
var isFinal = (node == finalNode), lastChildIndex, i, c,
text = '';

switch (node.nodeType) {
case 3: /* text, CDATA, processing instruction, comment */
case 4:
case 7:
case 8:
text = node.nodeValue;

if (isFinal) {
text = text.substring(0, finalOffset);
}
if (offset) {
text = text.substring(offset);
}
me.onNode(text, node);
break;
default:
me.onNode(text, node);
lastChildIndex = isFinal ? finalOffset :
node.childNodes.length;

for (i = offset, c = node.childNodes.item(i);
i < lastChildIndex;
c = c.nextSibling, i++) {
if (!visitNode(c, 0)) {
return false;
}
}
}
return !isFinal;
}
/* end function */

while (visitNode(node, offset)) {
if (!node.nextSibling) {
node = node.parentNode;
/* doesn't indicate when it's leaving an incompletely
selected node */
offset = node.childNodes.length;
} else {
node = node.nextSibling;
offset = 0;
}
}
return true;
};
}
/* for testing: */
({
iterator: new RangeIterator(),
visited: [],
toHTML: function (a) {
return ['&lt;', '&gt;', '&amp;']['<>&'.indexOf(a)];},
go: function () {
var timer, w = window, s = w.getSelection(), i, wd, me = this;

this.iterator.onNode = function (str, node) {
me.visited.push(node.nodeName + ': ' + str);};
timer = +new Date();
if (s.rangeCount && this.iterator.iterate(s.getRangeAt(0))) {
w.alert(this.visited.length + ' node(s) visited in ' +
(+new Date() - timer) + ' ms.');

for (i = this.visited.length; i--; ) {
this.visited[i] = this.visited[i].replace(/[<>&]/g,
this.toHTML);
}

w = window.open();
wd = w.document;
wd.write(this.visited.join('<br>'));
wd.close();
} else {
w.alert("No selection");
}
}
}).go();
 
Reply With Quote
 
matth
Guest
Posts: n/a
 
      11-08-2007
On Nov 5, 2:20 pm, pr <(E-Mail Removed)> wrote:
> matth wrote:
> > Thank you both for your help.
> > I'm going to include the full bookmarklet code I'm using.
> > A specific instance that fails is when I select the links and image
> > typically present at the top of drudgereport.com (the stuff right
> > above Drudge's header graphic).

>
> > I'll try implementing your code Evertjan, and report back.

>
> [...]
>
> Here's my latest take on the question (another bookmarklet), which you
> may find useful. As far as I'm aware, it lists all the nodes beneath a
> range's commonAncestorContainer, but the bug is that (so far) it doesn't
> indicate whether it's arriving at a node or leaving it. Still, it does
> show a couple of things missing in your code:
>
> - child offsets of the startContainer and endContainer when the parent
> is an element object or another node having children.
>
> - a slightly different approach to ascending node ancestors in
> search of nextSibling (your version quits if there is no
> parentNode.nextSibling).
>
> - escaped debug output! This may explain the funny things at Drudge
> Report (a couple of <noscript>'s in there).
>
> See what you think...
>
> javascript:
>
> function RangeIterator() {
> this.onNode = function (str, node) {}; /* default function: supply
> your own */
> this.iterate = function (r) {
> var me = this, node = r.startContainer, offset = r.startOffset,
> finalNode = r.endContainer, finalOffset = r.endOffset;
>
> function visitNode(node, offset) {
> var isFinal = (node == finalNode), lastChildIndex, i, c,
> text = '';
>
> switch (node.nodeType) {
> case 3: /* text, CDATA, processing instruction, comment */
> case 4:
> case 7:
> case 8:
> text = node.nodeValue;
>
> if (isFinal) {
> text = text.substring(0, finalOffset);
> }
> if (offset) {
> text = text.substring(offset);
> }
> me.onNode(text, node);
> break;
> default:
> me.onNode(text, node);
> lastChildIndex = isFinal ? finalOffset :
> node.childNodes.length;
>
> for (i = offset, c = node.childNodes.item(i);
> i < lastChildIndex;
> c = c.nextSibling, i++) {
> if (!visitNode(c, 0)) {
> return false;
> }
> }
> }
> return !isFinal;
> }
> /* end function */
>
> while (visitNode(node, offset)) {
> if (!node.nextSibling) {
> node = node.parentNode;
> /* doesn't indicate when it's leaving an incompletely
> selected node */
> offset = node.childNodes.length;
> } else {
> node = node.nextSibling;
> offset = 0;
> }
> }
> return true;
> };
> }
> /* for testing: */
> ({
> iterator: new RangeIterator(),
> visited: [],
> toHTML: function (a) {
> return ['&lt;', '&gt;', '&amp;']['<>&'.indexOf(a)];},
> go: function () {
> var timer, w = window, s = w.getSelection(), i, wd, me = this;
>
> this.iterator.onNode = function (str, node) {
> me.visited.push(node.nodeName + ': ' + str);};
> timer = +new Date();
> if (s.rangeCount && this.iterator.iterate(s.getRangeAt(0))) {
> w.alert(this.visited.length + ' node(s) visited in ' +
> (+new Date() - timer) + ' ms.');
>
> for (i = this.visited.length; i--; ) {
> this.visited[i] = this.visited[i].replace(/[<>&]/g,
> this.toHTML);
> }
>
> w = window.open();
> wd = w.document;
> wd.write(this.visited.join('<br>'));
> wd.close();
> } else {
> w.alert("No selection");
> }
> }
> }).go();


Don't think I'm ignoring you! I'm doing my best. You threw up a Hail
Mary there, I'm going to need a minute to catch up.

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Iterating a std::vector vs iterating a std::map? carl C++ 5 11-25-2009 09:55 AM
Text nodes and element nodes query asd Java 3 05-23-2005 10:01 AM
Looking A Nodes From Within Nodes Johnny Ooi XML 10 11-14-2004 06:55 PM
selecting nodes between other nodes Timo Nentwig XML 1 06-17-2004 04:54 AM
Reality check: Is it sensible to link XML nodes to other XML nodes in the same file? gavnosis XML 0 08-02-2003 08:22 AM



Advertisments