By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
459,317 Members | 1,329 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 459,317 IT Pros & Developers. It's quick & easy.

Document nodes returning null

P: 7
Im writing some Javascript code that requires me to loop all child nodes and sub child nodes of a certain parent node and execute a function with the child node in question.

I decided to write a recursive function with said functionality, with a node and a function as parameters, but it simply wont work.

My problem is that whenever i pass a node to this function parameter it is always, regardless of what i change, equal to null. I even modified my custom passed function to ignore null nodes, and now it throw a null variable error every time my function recurses.
(exact error: node.childNodes has no properties)

To me it looks like a problem with these infamous 'closures' i keep hearing about. I understand the concept, but I dont know exactly how they work in this context due to a great lack of experience :(.

I know there are many sample codes out there that can do the job, but I want to know why THIS function, which looks perfectly logical to me, doesnt behave as i would expect it too.

I read a few posts here and there relating to this, and I modified my code accordingly, but i cant seem to figure out just what is causing my problem.

Expand|Select|Wrap|Line Numbers
  1. var ProcNodes=function(node,fn)
  2. {
  3.     var n=0,
  4.         i=0,
  5.         nodes=node.childNodes,
  6.         length=nodes.length;
  7.     for(i=0;i<length;i++)
  8.     {
  9.         var node=nodes[i];
  10.         fn.call(node);
  11.         if(node.childNodes.length>0)
  12.             n+=ProcNodes(fn,node);
  13.         n++;
  14.     }
  15.     return n;
  16. }
thx in advance,
Yoann Arseneau
Nov 20 '07 #1
Share this Question
Share on Google+
14 Replies


gits
Expert Mod 5K+
P: 5,390
hi ...

welcome to TSDN ...

i fixed your code ... have a close look at the example ... i tested it with google.com in firebug and it worked:

Expand|Select|Wrap|Line Numbers
  1. var ProcNodes = function(node, fn) {
  2.     var nodes  = node.childNodes;
  3.     var length = nodes.length;
  4.  
  5.     for (var i = 0 ; i < length; i++) {
  6.         var node = nodes[i];
  7.  
  8.         fn.call(node);
  9.  
  10.         if (node.childNodes.length > 0) {
  11.             ProcNodes(node, fn);
  12.         }
  13.      }   
  14. }
  15.  
  16. ProcNodes(document.getElementsByTagName('body')[0], function() {
  17.     alert(this.nodeType);
  18. });
  19.  
we don't need the n and i fixed the order of params in the recursion call

kind regards
Nov 20 '07 #2

P: 7
heh... well im kinda embarrassed :\

thx for your help XD
Nov 20 '07 #3

100+
P: 428
Excuse this- I missed gits post.

Expand|Select|Wrap|Line Numbers
  1. nodecall= function(node,fun){
  2.     var n= [],tem;    
  3.     tem= node.firstChild;
  4.     while(tem){        
  5.         n.push(fun.call(tem));
  6.         if(tem.hasChildNodes()) n.push(arguments.callee(tem,fun));
  7.         tem= tem.nextSibling;        
  8.     }
  9.     return n;
  10. }
Expand|Select|Wrap|Line Numbers
  1. function ahoy(){
  2.     return this.nodeName;
  3. }
var A=nodecall(document.body,ahoy);
alert(A.join('\n\n'));
Nov 20 '07 #4

gits
Expert Mod 5K+
P: 5,390
heh... well im kinda embarrassed :\

thx for your help XD
hi ...

no problem ... post back to the forum anytime you have more questions ...

kind regards
Nov 20 '07 #5

P: 7
Im still getting some null nodes, but i think i just figured it out.

From what i can tell, firefox (browser im currently testing on) returns whitespace textnodes as null objects.

Can someone confirm this so i can finally stop worrying about this insignificant part of my app :\
Nov 20 '07 #6

gits
Expert Mod 5K+
P: 5,390
it returns them as textnodes ... nodeType == 3 or nodeName == '#text' ... so with that you may handle them ... could tell where you get a null-value?
Nov 20 '07 #7

P: 7
Expand|Select|Wrap|Line Numbers
  1. if(node==null)
  2. {
  3.     alert("ParseNode: null node");
  4.     return;
  5. }
this message alerts several times during my loop, it is the first statement inside my calling function (fn parameter)

<EDIT>
the node variable is the one directly passed from the recursive function
Nov 20 '07 #8

gits
Expert Mod 5K+
P: 5,390
hmmm ... that is strange ... could you post your html ... i think in case of a text node it should alert a '[object Text]' ...
Nov 20 '07 #9

P: 7
Well this is prety wierd... When i changed the statement on line 7 my script suddenly started acting exactly like expected.

Expand|Select|Wrap|Line Numbers
  1. var ProcNodes=function(node,fn)
  2. {
  3.     var nodes=node.childNodes,length=nodes.length,n=0;
  4.     for(var i=0;i<length;i++)
  5.     {
  6.         var node=nodes[i];
  7.         if(!fn(node))// was previously fn.call(node)
  8.             return-n;
  9.         if(node.childNodes.length>0)
  10.             n+=ProcNodes(node,fn);
  11.         n++;
  12.     }
  13.     return n;
  14. }
(the n variable is there because i need it for debugging purposes)

Honestly, I only used the call method because I saw another script use it and I thought it looked cool. :P
I assumed it worked identical to normal calling syntax which appears not to be the case, atleast not on my firefox. Can anyone confirm if there is a difference between these two lines of code?

Expand|Select|Wrap|Line Numbers
  1. someFunction("parameter")
  2. someFunction.call("parameter")
<Edit>And yes, it does alert text node objects for whitespace nodes with the new code
Nov 21 '07 #10

gits
Expert Mod 5K+
P: 5,390
hi ...

the following is a regular function call:

Expand|Select|Wrap|Line Numbers
  1. func(param);
  2.  
the call() method may receive more than one parameter ... where the first parameter is used as the scope that the function should be called in ... so when we use:

Expand|Select|Wrap|Line Numbers
  1. func.call(param, param1);
  2.  
then param is used for the scope and param1 as function-parameter ... but as far as i can see the code i fixed for you works as intended ... the fn alerts the correct nodeType for textnodes ... because the this is the node-context itself in the case of passing the node to the function.call(node) ... so to check that could you please post your html that produces the error? and/or the fn-code?

kind regards
Nov 21 '07 #11

P: 7
While you did answer my question as to how the call function works, and i tested it to assure i understood, this definition explains why it did not work.

when you say this:
where the first parameter is used as the scope that the function should be called in
That means that when i was calling the function previously, i was sending the node as the context, and not as a parameter for the function body. For my code to work this way, i need to refer to the this object rather than the node parameter i was trying to access.
Nov 21 '07 #12

gits
Expert Mod 5K+
P: 5,390
While you did answer my question as to how the call function works, and i tested it to assure i understood, this definition explains why it did not work.

when you say this:


That means that when i was calling the function previously, i was sending the node as the context, and not as a parameter for the function body. For my code to work this way, i need to refer to the this object rather than the node parameter i was trying to access.
exactly ;)

kind regards
Nov 21 '07 #13

P: 7
this will teach me to use random functions without knowing what they do :P

this has been very instructive, thx very much :)
Nov 21 '07 #14

gits
Expert Mod 5K+
P: 5,390
glad to hear that :) ... post back to the forum anytime you would have more questions ...

kind regards
Nov 22 '07 #15

Post your reply

Sign in to post your reply or Sign up for a free account.