It's quite simple to walk to the DOM tree going forward however I can't
figure out a nice clean way to walk the DOM tree in reverse. Checking
previousSibling is not sufficient as the previousSibling could be a
node which has childNodes and therefore the 'true' previousSibling
would be the *deepest* lastChild of the previousSibling ...
For example, given this graph:
1 myAnchor nodeType 1
2 myAnchorText1 nodeType 3
3 myAnchorText2 nodeType 3
4 myBold nodeType 1
5 myText1 nodeType 3
6 myText2 nodeType 3
I want to be able to walk the tree in reverse starting from position 6
so that I get:
myText2
myText1
myBold
myAnchorText2
myAnchorText1
myAnchor
Any ideas?
Thanks,
Cliff. 22 5402 de*******@gmail .com wrote: It's quite simple to walk to the DOM tree going forward however I can't figure out a nice clean way to walk the DOM tree in reverse. Checking previousSibling is not sufficient as the previousSibling could be a node which has childNodes and therefore the 'true' previousSibling would be the *deepest* lastChild of the previousSibling ...
For example, given this graph:
1 myAnchor nodeType 1 2 myAnchorText1 nodeType 3 3 myAnchorText2 nodeType 3 4 myBold nodeType 1 5 myText1 nodeType 3 6 myText2 nodeType 3
I want to be able to walk the tree in reverse starting from position 6 so that I get:
myText2 myText1 myBold myAnchorText2 myAnchorText1 myAnchor
Any ideas?
I might be missing your problem:- an actual HTML code would be helpful.
The tree is...uhm... a tree. It means that can be a lot of children
(leaves) but only one parent (branch) for each child. Or - using
database terms - these are one-to-many relations, not many-to-many. de*******@gmail .com wrote: It's quite simple to walk to the DOM tree going forward however I can't figure out a nice clean way to walk the DOM tree in reverse. Checking previousSibling is not sufficient as the previousSibling could be a node which has childNodes and therefore the 'true' previousSibling would be the *deepest* lastChild of the previousSibling ...
You have to recurse into the subtree of the previousSibling until
there are no more child nodes, i.e. until there is no lastChild.
For example, given this graph:
1 myAnchor nodeType 1 2 myAnchorText1 nodeType 3 3 myAnchorText2 nodeType 3 4 myBold nodeType 1 5 myText1 nodeType 3 6 myText2 nodeType 3
I want to be able to walk the tree in reverse starting from position 6 so that I get:
myText2 myText1 myBold myAnchorText2 myAnchorText1 myAnchor
Any ideas?
myText2.previou sSibling....par entNode.previou sSibling.lastCh ild...
..previousSibli ng....parentNod e...
See?
PointedEars de*******@gmail .com writes: It's quite simple to walk to the DOM tree going forward however I can't figure out a nice clean way to walk the DOM tree in reverse.
You want a depth-first right-to-left traversal of the nodes.
That sounds like a job for recursion:
---
function traverseDFRTL(e lement, action) {
for(var child = element.lastChi ld; child; child = child.previousS ibling) {
traverseDFRTL(c hild, action);
}
action(element) ;
}
---
Calling
---
traverseDFRTL(s omeElement, function(node) {
alert([node.tagName, node.nodeType]);
});
---
will alert the nodes in the desired order.
If you don't want recursion, you can do it iteratively as well, but it
will never be as simple.
/L
--
Lasse Reichstein Nielsen - lr*@hotpop.com
DHTML Death Colors: <URL:http://www.infimum.dk/HTML/rasterTriangleD OM.html>
'Faith without judgement merely degrades the spirit divine.'
Lasse Reichstein Nielsen wrote: --- function traverseDFRTL(e lement, action) { for(var child = element.lastChi ld; child; child = child.previousS ibling) { traverseDFRTL(c hild, action); } action(element) ; } ---
Calling --- traverseDFRTL(s omeElement, function(node) { alert([node.tagName, node.nodeType]); }); --- will alert the nodes in the desired order.
Very nice. There is one catch, though: after the very first node of the
document tree has been processed, action() is called with `null', and if
the reference to the above function is passed as callback, there will be
a script error in the end ("null has no properties"). So either the
callback is modified so that `node.tagName' and `node.nodeType' are only
evaluated if `node' refers to an object, or the second call of `action'
should not take place if `element' does not refer to an object.
Furthermore, text nodes have no `tagName' property.
It would also be nice if one could use the return value of traverseDFTRL() ,
and to allow for another identifier without modifying the function body.
Hence the following suggestion:
function isMethod(a)
{
var t;
return (a && ((t = typeof a) == "function" || t == "object"));
}
function traverseDFRTL(e lement, action)
{
for (var child = (element || document.docume ntElement).last Child;
child;
child = child.previousS ibling)
{
arguments.calle e(child, action);
}
if (isMethod(actio n))
{
return action(element) ;
}
}
var nodes = [];
alert(traverseD FRTL(
null,
function(node)
{
if (node)
{
nodes.push(node .nodeName
+ (typeof node.nodeValue == "string"
? (' "' + node.nodeValue + '"')
: ""));
}
return nodes;
}).join("\n"));
PointedEars
Thomas 'PointedEars' Lahn <Po*********@we b.de> writes: Lasse Reichstein Nielsen wrote:
--- function traverseDFRTL(e lement, action) { for(var child = element.lastChi ld; child; child = child.previousS ibling) { traverseDFRTL(c hild, action); } action(element) ; } ---
Calling --- traverseDFRTL(s omeElement, function(node) { alert([node.tagName, node.nodeType]); }); --- will alert the nodes in the desired order. Very nice. There is one catch, though: after the very first node of the document tree has been processed, action() is called with `null',
I can't see how. The "action" callback function is only ever called
with the value of the "element" parameter. It can only be called with
a null value if "element" is null. The recursive calls are only made
if "child" is not null, so they can't cause it, so "action" should
only be called with null arguemnt if someone calls traverseDFRTL with
a first parameter that is null.
and if the reference to the above function is passed as callback, there will be a script error in the end ("null has no properties").
Could you post an example, including which browser causes it?
Furthermore, text nodes have no `tagName' property.
True. It was just a quick example.
It would also be nice if one could use the return value of traverseDFTRL() ,
What would the return value be? But yes, it could easily be turned into
a catemorphism (fold-like function):
function foldDOM(element , action) {
var childRets = [];
for(var child = element.lastChi ld; child; child = child.previousS ibling) {
childRets.push( foldDOM(child, action));
}
return action(element, childRets);
}
Then you could collect the innerText of a DOM element as:
foldDOM(element , function(node,c hildTexts) {
if (node.nodeType == 3) { // Text node
return node.nodeValue;
} else { // Element node
return childTexts.join ("");
}
});
and to allow for another identifier without modifying the function body.
If you want another name for it, treat the above as a function expression,
not a function declaration. Then you can call it whatever you like:
var myOwnName = function foldDOM(...){.. .foldDOM(...).. .};
I don't find the use of arguments.calle e particularly readable.
If a function can't know its own declared name inside its body,
what can it know?
Hence the following suggestion:
function isMethod(a) { var t; return (a && ((t = typeof a) == "function" || t == "object")); }
function traverseDFRTL(e lement, action) { for (var child = (element || document.docume ntElement).last Child; child; child = child.previousS ibling) { arguments.calle e(child, action); }
if (isMethod(actio n)) { return action(element) ;
If you insist on having a default argument, it should also apply here,
so,
return action(element || document.docume ntElement);
For default parameters, I prefer setting them at the top of the function,
i.e., as first line:
element = element || document.docume ntElement;
}
if you make this test (and I wouldn't - someone callig the function
should know that he is expected to pass a function as second argument),
I would at least fail if it's not:
else {
throw Error("Not a function as second argument!");
}
function(node) { if (node)
So here you depend on having the documentElement being traversed, but
null still being passed to the action function. That seems awfully
fragile and not very generic. I prefer to have a more generic, and
preferably simpler, function like my original traversal or the foldDOM
above, and then create a specialized function to call it with special
arguments that makes sense to the page it is used on.
/L
--
Lasse Reichstein Nielsen - lr*@hotpop.com
DHTML Death Colors: <URL:http://www.infimum.dk/HTML/rasterTriangleD OM.html>
'Faith without judgement merely degrades the spirit divine.'
Lasse Reichstein Nielsen wrote: de*******@gmail .com writes: It's quite simple to walk to the DOM tree going forward however I can't figure out a nice clean way to walk the DOM tree in reverse.
You want a depth-first right-to-left traversal of the nodes. That sounds like a job for recursion:
--- function traverseDFRTL(e lement, action) { for(var child = element.lastChi ld; child; child = child.previousS ibling) { traverseDFRTL(c hild, action); } action(element) ; } ---
Calling --- traverseDFRTL(s omeElement, function(node) { alert([node.tagName, node.nodeType]); }); --- will alert the nodes in the desired order.
If you don't want recursion, you can do it iteratively as well, but it will never be as simple.
<body onload="test()" ><table><tr><td >Help</td></tr></table>
<script type='text/javascript'>
function lessSimpleTrave rseDFRTL(elemen t, action) {
var next, prev=element.la stChild || element, lcOK=true;
for (; prev!=element; lcOK=prev.paren tNode!=(prev=ne xt)) {
if (lcOK && (next=prev.last Child)) continue; else action (prev);
next = prev.previousSi bling || prev.parentNode ; }
action(element) ; }
function test() {
lessSimpleTrave rseDFRTL(docume nt.body, function(node) {
alert(node.node Name+ "\n" + outerHTML(node) ); }); }
function outerHTML(elem) {
if (elem.outerHTML ) return elem.outerHTML;
var dup=elem.cloneN ode(true); //event handlers, some attribs omitted
var dummyDiv=elem.o wnerDocument.cr eateElement('DI V');
dummyDiv.append Child(dup);
var outer=dummyDiv. innerHTML;
delete dummyDiv;
return outer;
}
</script>
<div><span>Hi mom</span><p>Hi dad</p></div>
</body>
Tested with IE 6, FF 1.5.0.1,
Csaba Gabor from Vienna
Csaba Gabor wrote: Lasse Reichstein Nielsen wrote: de*******@gmail .com writes: It's quite simple to walk to the DOM tree going forward however I can't figure out a nice clean way to walk the DOM tree in reverse.
You want a depth-first right-to-left traversal of the nodes. That sounds like a job for recursion:
--- function traverseDFRTL(e lement, action) { for(var child = element.lastChi ld; child; child = child.previousS ibling) { traverseDFRTL(c hild, action); } action(element) ; } ---
Calling --- traverseDFRTL(s omeElement, function(node) { alert([node.tagName, node.nodeType]); }); --- will alert the nodes in the desired order.
If you don't want recursion, you can do it iteratively as well, but it will never be as simple.
<body onload="test()" ><table><tr><td >Help</td></tr></table> <script type='text/javascript'>
function lessSimpleTrave rseDFRTL(elemen t, action) { var next, prev=element.la stChild || element, lcOK=true; for (; prev!=element; lcOK=prev.paren tNode!=(prev=ne xt)) { if (lcOK && (next=prev.last Child)) continue; else action (prev); next = prev.previousSi bling || prev.parentNode ; } action(element) ; }
Kidding aside, the iterative version does offer something that the
recursive version doesn't because the recursive version only does
subtrees. The iterative version is happy to walk all the way back to
the root, from a given element. I found it quite instructive.
<body onload="test()" ><table><tr>< td id=td>Help</td></tr></table>
<script type='text/javascript'>
function backwalk(elem, action) {
// iterative reverse depth first traversal to root from elem
for (var next, lcOK=false; elem; lcOK=elem.paren tNode!=(elem=ne xt)) {
if (lcOK && (next=elem.last Child)) continue; else action (elem);
next = elem.previousSi bling || elem.parentNode ; } }
function test() {
backwalk(docume nt.getElementBy Id('td'), function(node) {
alert(node.node Name+ " (" + node.nodeType +
")\n" + outerHTML(node) ); }); }
function outerHTML(elem) {
if (elem.outerHTML ||elem.nodeType >8) return elem.outerHTML;
var dup=elem.cloneN ode(true);
var dummyDiv=elem.o wnerDocument.cr eateElement('DI V');
dummyDiv.append Child(dup);
var outer=dummyDiv. innerHTML;
delete dummyDiv;
return outer; }
</script>
<div><span>Hi mom</span><p id=p>Hi dad</p></div>
</body>
Plus the code is simpler. ;)
Csaba Gabor from Vienna
Lasse Reichstein Nielsen wrote: Thomas 'PointedEars' Lahn <Po*********@we b.de> writes: Lasse Reichstein Nielsen wrote: --- function traverseDFRTL(e lement, action) { for(var child = element.lastChi ld; child; child = child.previousS ibling) { traverseDFRTL(c hild, action); } action(element) ; } ---
Calling --- traverseDFRTL(s omeElement, function(node) { alert([node.tagName, node.nodeType]); }); --- will alert the nodes in the desired order. Very nice. There is one catch, though: after the very first node of the document tree has been processed, action() is called with `null',
I can't see how. The "action" callback function is only ever called with the value of the "element" parameter. It can only be called with a null value if "element" is null. The recursive calls are only made if "child" is not null, so they can't cause it, so "action" should only be called with null arguemnt if someone calls traverseDFRTL with a first parameter that is null.
You are correct, the original code runs without error. It was in fact my
optimization which caused the problem. I passed `null' for triggering the
default value `document.docum entElement' and forgot that this would not
affect the value of `element' as passed to the second action() call. It would also be nice [...] to allow for another identifier without modifying the function body.
If you want another name for it, treat the above as a function expression, not a function declaration. Then you can call it whatever you like:
var myOwnName = function foldDOM(...){.. .foldDOM(...).. .};
I don't find the use of arguments.calle e particularly readable. If a function can't know its own declared name inside its body, what can it know?
Think about it. That there are function expressions, i.e. functions
are first-level objects, is precisely why arguments.calle e is useful. Hence the following suggestion:
function isMethod(a) { var t; return (a && ((t = typeof a) == "function" || t == "object")); }
function traverseDFRTL(e lement, action) { for (var child = (element || document.docume ntElement).last Child; child; child = child.previousS ibling) { arguments.calle e(child, action); }
if (isMethod(actio n)) { return action(element) ;
If you insist on having a default argument, it should also apply here, so, return action(element || document.docume ntElement);
In fact, it MUST then, unless one sets a requirement for checking
the argument of the callback in the callback. See above.
For default parameters, I prefer setting them at the top of the function, i.e., as first line: element = element || document.docume ntElement;
I prefer
if (!element) element = document.docume ntElement;
as it strikes me as being more efficient. }
if you make this test (and I wouldn't - someone callig the function should know that he is expected to pass a function as second argument), I would at least fail if it's not: else { throw Error("Not a function as second argument!"); }
Agreed, although I would consider an alternative to a plain `throw'.
PointedEars
"Csaba Gabor" <da*****@gmail. com> writes: function backwalk(elem, action) { // iterative reverse depth first traversal to root from elem for (var next, lcOK=false; elem; lcOK=elem.paren tNode!=(elem=ne xt)) { if (lcOK && (next=elem.last Child)) continue; else action (elem); next = elem.previousSi bling || elem.parentNode ; } }
I'm not entirely sure I read this correctly, but doesn't it follow
just a path through prevous siblings and parents from a note to the
root? It doesn't traverse children of the siblings, nor later
siblings at the same level.
An iterative function that works like the original traversal could be:
---
function leftMostInnerMo stDescendent(no de) {
while (node.hasChildN odes()) {
node = node.lastChild;
}
return node;
}
function traverse(elemen t, action) {
var next = leftMostInnerMo stDescendent(el ement);
do {
action(next);
if (next.previousS ibling) {
next = leftMostInnerMo stDescendent(ne xt.previousSibl ing);
} else {
next = next.parentNode ;
}
} while (next != element);
action(element) ;
}
---
A much more engenious (but probably dangerous) method is to use
rotation of the tree, putting the parent as the last child of its
first child and continuing that until the original shape is
restored (as it will be eventually). It's probably not doable in
general in a tree structure like HTML where not every node can
be a child of every other node. :)
/L
--
Lasse Reichstein Nielsen - lr*@hotpop.com
DHTML Death Colors: <URL:http://www.infimum.dk/HTML/rasterTriangleD OM.html>
'Faith without judgement merely degrades the spirit divine.' This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics |
by: Marcello Pietrobon |
last post by:
Hello,
I am using Pyton 2.3
I desire to walk a directory without recursion
this only partly works:
def walk_files() :
for root, dirs, files in os.walk(top, topdown=True):
for filename in files:
print( "file:" + os.path.join(root, filename) )
for dirname in dirs:
|
by: pembed2003 |
last post by:
Hi,
I have a question about how to walk a binary tree. Suppose that I have
this binary tree:
8
/ \
5 16
/ \ / \
3 7 9 22
/ \ / \ / \
|
by: Zri Man |
last post by:
I'm relatively new to DB2 and was reasonably amused to see the REVERSE
SCAN availability for Indexes.
My assumptions are as follows:
DB2/UDB uses B-Tree for indexing by default and is likely the main
offering for Indexing within the DB.
Reverse Scans could possibly only happen on the the leaf node of
the index
|
by: KraftDiner |
last post by:
The os.walk function walks the operating systems directory tree.
This seems to work, but I don't quite understand the tupple that is
returned...
Can someone explain please?
for root, dirs, files in os.walk('/directory/'):
print root
# print dirs
# print files
|
by: Bruce |
last post by:
Hi all,
I have a question about traversing file systems, and could use some
help. Because of directories with many files in them, os.walk appears
to be rather slow. I`m thinking there is a potential for speed-up since
I don`t need os.walk to report filenames of all the files in every
directory it visits. Is there some clever way to use os.walk or another
tool that would provide functionality like os.walk except for the
listing of the...
| |
by: Andre Meyer |
last post by:
Hi all
os.walk() is a nice generator for performing actions on all files in a
directory and subdirectories. However, how can one use os.walk() for walking
through two hierarchies at once? I want to synchronise two directories (just
backup for now), but cannot see how I can traverse a second one. I do this
now with os.listdir() recursively, which works fine, but I am afraid that
recursion can become inefficient for large hierarchies.
...
|
by: silverburgh.meryl |
last post by:
i am trying to use python to walk thru each subdirectory from a top
directory. Here is my script:
savedPagesDirectory = "/home/meryl/saved_pages/data"
dir=open(savedPagesDirectory, 'r')
for file in dir:
if (isdir(file)):
# get the full path of the file
|
by: Joe Ardent |
last post by:
Good day, everybody! From what I can tell from the archives, this is
everyone's favorite method from the standard lib, and everyone loves
answering questions about it. Right? :)
Anyway, my question regards the way that the visit callback modifies
the names list. Basically, my simple example is:
##############################
def listUndottedDirs( d ):
dots = re.compile( '\.' )
|
by: Martin Marcher |
last post by:
Hello,
I'm playing around with os.walk and I made up del_tree(path) which I
think is correct (in terms of the algorithm, but not as python wants
it :)).
As soon as some directory is deleted the iterator of os.walk chokes.
OK that is somehow clear to me as it can't be valid anymore since it
can't go to the just deleted directory but it is in the iterator.
|
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 tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth.
The Art of Business Website Design
Your website is...
|
by: Hystou |
last post by:
Overview:
Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
| |
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, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own....
Now, this would greatly impact the work of software developers. The idea...
|
by: isladogs |
last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM).
In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules.
He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms.
Adolph will...
|
by: TSSRALBI |
last post by:
Hello
I'm a network technician in training and I need your help.
I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs.
The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols.
I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
|
by: adsilva |
last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
|
by: 6302768590 |
last post by:
Hai team
i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
|
by: muto222 |
last post by:
How can i add a mobile payment intergratation into php mysql website.
| |
by: bsmnconsultancy |
last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...
| |