...

View Full Version : identyfing heirarchy groups within getElementsByTagName



brothercake
03-23-2003, 01:28 AM
I've got a complex <ul> structure and I want to return a collection of only those <li> nodes which are direct children of the root node.

How can I do that? getElementsByTagName returns all of them, without any way of identifying the location of each of its members in the heirarchy.

liorean
03-23-2003, 02:22 AM
var lisWithSameParent=[];
for(var i in liCollection)
liCollection[i].parentNode==[object parentNode]&&lisWithSameParent.push(liCollection[i]);


Or you could use NodeIterator or TreeWalker from DOM2 TR or have a look at DOM3 XPath

brothercake
03-23-2003, 03:04 AM
Cool :) thanks

jkd
03-23-2003, 04:22 AM
Originally posted by liorean


var lisWithSameParent=[];
for(var i in liCollection)
liCollection[i].parentNode==[object parentNode]&&lisWithSameParent.push(liCollection[i]);


Or you could use NodeIterator or TreeWalker from DOM2 TR or have a look at DOM3 XPath

I think DOM2 Traversal is overkill, and DOM3 XPath certainly is.

But your code... why purposely obfusticate just to save a few lines of Javascript? I consider it important to write clear, concise code, especially when dealing with the DOM:



var lis = [];
for (var i = 0; i < myUl.childNodes.length; i++) {
if (myUl.childNodes.item(i).nodeName == "LI") {
lis.push(myUl.childNodes.item(i));
}
}


Certainly a little more obvious than doing a getElementsByTagName("LI"), then iterating through that NodeList and relying on short-circuit validation to push a proper <li> into the vector,

Arguably, depending on how getElementsByTagName is implemented, more efficient too. Seems to me that iterating through one level of nodes may take less time than what getElementsByTagName may have to do behind the scenes (recurse through all childnodes?).

Anyhoo, that's a debate on coding style. For kicks and giggles, here is a TreeWalker that'll do the same thing:



var lis = [];
var walker = document.createTreeWalker(myUl, NodeFilter.SHOW_ELEMENT,
{ acceptNode: function (node) { return (node.nodeName == "LI" && node.parentNode == myUl) ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT } },
false);
while (walker.nextNode()) lis.push(walker.currentNode);

brothercake
03-23-2003, 04:25 AM
My God!! Is that Luke TreeWalker or Anekin? Looks liks it's verging on the dark side either way :D

I like your first solution - childNodes is more efficient, and I could use the improvement (but you wouldn't really query a length property in a loop, now would you ;))

jkd
03-23-2003, 04:36 AM
Originally posted by brothercake
My God!! Is that Luke TreeWalker or Anekin? Looks liks it's verging on the dark side either way :D

I like your first solution - childNodes is more efficient, and I could use the improvement (but you wouldn't really query a length property in a loop, now would you ;))

Heh, TreeWalker's can be scary... but they are soooo awesome too! They allow you effectively strip out anything you don't want to look at via the NodeFilter argument. NodeIterators too, but nothing supports those yet ;).

Anyway, as for querying the length property, I'm sure you seen me tell beetle I'm a theory guy? :D
In theory, the length property is a property with no cost, but of course it is a rather elaborate getter function I don't want to even think about. :p
But I don't care about that - since this isn't code I'm actually going to use. You know well enough to store the length somewhere because you can assert that it will be static throughout this operation, so you can have all the "fun" and deal with implementation. :)

brothercake
03-23-2003, 04:42 AM
Originally posted by jkd
so you can have all the "fun" and deal with implementation. :)
Dang students ... :D

jkd
03-23-2003, 04:47 AM
Just because liorean mentioned it, DOM3 XPath coming at you!



var lis = [], temp;
var result = document.evaluate("li", myUl, null, XPathResult.UNORDERED_NODE_ITERATOR_TYPE, null);
while (temp = result.iterateNext()) lis.push(temp);


Or you could iterate through the snapshotItem() list.

beetle
03-24-2003, 07:56 PM
Or skip the length property altogether :D


var lis = [];
for ( var itm, i = 0; ( itm = myUl.childNodes.item(i) ); i++ )
{
if ( itm.nodeName == "LI" )
{
lis.push( itm );
}
}

liorean
03-24-2003, 08:29 PM
Doesn't that produce a warning using mozilla's strict warnings? I hate when scripts clog up my jsconsole by doing that.

beetle
03-24-2003, 10:28 PM
Not that I know of. And, according to some tests (http://www.peterbailey.net/test/loops.htm) I just did, if a reference to itm is needed, then my above example is the fastest of the for-loop methods in IE and Opera. In Mozilla, all tests were virtually the same.

In IE and Opera the while loop was consistently the fastest (I ran the test 10 times each) with the for loop I show above consistently being 2nd fastest.

I've read about IE being loop-optimized. The results I see here show that, with IE consistently being 2-3 times faster than Opera or Mozilla (Please, I'm not trying to start some sort of IE vs the world thing here, just fact-finding)

liorean
03-24-2003, 10:55 PM
Beetle: Yep, ie is VERY loop optimised. Moz on the other hand is object optimised. Opera is getting better at both, but is far from either except in special cases.

I just found out the reason this doesn't produce a warning, by the way: [index] with a too large index returns undefined, .item(index) with a too large index returns null. Undefined as rhe produces a warning.

brothercake
03-24-2003, 11:12 PM
Originally posted by liorean
Beetle: Yep, ie is VERY loop optimised. Moz on the other hand is object optimised. Opera is getting better at both, but is far from either except in special cases.
Hey now that explains a lot ... I had no idea browsers could be optimised for a particular kind of process; obvious now you think about it.

Now that could give rise to a particularly interesting (or twisted, depending on how you look at it) kind of browsers sniffing; like

if(you_like_it_like_this)
{
do it like this
}

kind of thing ..? I like the optimisation potential there, if the implementation might be a bit confusing ...

.. dang; and I was only just getting round the concept of DOM-model sniffing :eek:

But thanks guys anyway for all the input on this; eventually what I'm doing is building like an XML parser for navigational data stored as a <ul> tree; so it can be parsed into dropdown menus, or expanding folder thingies; all manner of what have you; and its core data is completely accessible to any user-agent that understands HTML :D

liorean
03-24-2003, 11:45 PM
Heh, there's more!

Try timing these:


/* First testcase */
var
i=50,
j=0,
a=0,
t=1e3;
while(i-->0)// Oh, the beauty!
for(j=0;j<t;j++)
a++;

/* Second testcase */
var
i=50,
j=0,
a=0,
t=1e3;
while(i-->0){
j=0;
while(j++<t)
a++;
}

/* Third testcase, using something known as "Duff's Device" */
var
i=50,
a=0,
n,
m,
t=1e3;
while(i-->0){
n=t/11;
m=t%11;
while(n-->0){
switch(m){
case 0: a++;
case 10: a++;
case 9: a++;
case 8: a++;
case 7: a++;
case 6: a++;
case 5: a++;
case 4: a++;
case 3: a++;
case 2: a++;
case 1: a++;
}
m=0;
}
}

/* Fourth example, a version of Duff's Device optimised for JavaScript*/
var
i=50,
a=0,
n,
t=1e3;
while(i-->0){
n=t%11;
while(n--)
a++;
n=parseInt(t/11);
while(n--){
a++;
a++;
a++;
a++;
a++;
a++;
a++;
a++;
a++;
a++;
a++;
}
}


My results here say that if you do looping in unorthodox ways, you can get moz to be as fast as or faster than ie.

beetle
03-25-2003, 12:26 AM
Ah ya, I've already seen Duff's Device. I may test it later ;)

brothercake
03-25-2003, 12:33 AM
Duff's device??

btw - the push() method isn't supported in mac/ie5, I just discovered; it throws an error.

jkd
03-25-2003, 01:09 AM
*laughs at silly optimizations which shouldn't matter :p*

beetle
03-25-2003, 02:07 AM
C'mon jkd! Aren't optimizations like this more theory than application? (in respect to javascript)

No???

jkd
03-25-2003, 02:20 AM
Look at things from an algorithmic standpoint. A loop is a loop is a loop. Shouldn't matter if a loop in an algorithm is done this way or that. Hence the language-neutral tendency of an algorithm.

for...in, for(;;), while(), pick your poison. :)

liorean
03-25-2003, 07:06 AM
Originally posted by jkd
*laughs at silly optimizations which shouldn't matter :p*

You can laugh all you want, but the fact is, I can take down the time if takes to increment a 50 000 times from 359 to 70 ms by doing that in mozilla, from 243 to 110 in ie6, and from 1023 to 460 in op7.

Duff's device is something that was developed for speeding up Pascal and C loop implementations - it can be used in javascript as well.


For...in, for, do...while and while loops aren't exactly the same, because they compile to different algorithms, taking different time to execute because the processor have to do a slightly different set of operations. Also note that a comparison to zero is faster than a comparison to non-zero.


Oh well, that really doesn't belong in a DOM scripting thread, does it?

liorean
03-25-2003, 11:15 AM
Originally posted by brothercake
Duff's device??

btw - the push() method isn't supported in mac/ie5, I just discovered; it throws an error.

Ah, yes. I know that.



if(!'push' in [])Array.prototype.push=function(){
var i=0,b=this.length,a=arguments;
for(i;i<a.length;i++)this[b+i]=a[i];
return this.length
};


Remember that this will show up in a for...in loop if you try to handle an index array as an associative array (iow object).

jkd
03-25-2003, 11:43 AM
Originally posted by liorean
You can laugh all you want, but the fact is, I can take down the time if takes to increment a 50 000 times from 359 to 70 ms by doing that in mozilla, from 243 to 110 in ie6, and from 1023 to 460 in op7.


I was just joking with beetle about the theory versus application we find funny. Computers are fast, a few milliseconds don't really matter in programs I'm expected to write for school, or in scripts I wrote for myself or for others that will increase complexity and decrease readability that immensely.

brothercake
03-25-2003, 10:13 PM
I generally take the view that process is cheap - that coding in a way which makes the page faster at the expense of human-readability and ease of maintenance is counter-productive, because servers and clients can get faster. But I also accept how idealised that is; sometimes you really need the edge ...

liorean
03-25-2003, 10:34 PM
When doing something for functionality, especially if DOM is involved, I try to optimise for processing. If I'm writing for giving an example or something people might find interesting to dissect, I try to go for readability.

I usually keep one readable and commented version, and one compact and small/efficient version.

brothercake
03-27-2003, 06:53 PM
Well I've been told that the simple expedient of removing tabs, line breaks and unecessary spaces makes a script run faster.

Obviously it would make the code fewer K, but make it run faster? Is that really true?

beetle
03-27-2003, 07:35 PM
Who told you that bcake? I suppose it's true from a standpoint that all the code has to be read, and that more spaces and such mean more reading, but the time for a computer these days to read even a quadruple-tab (normally 16 spaces) is so negligible it's not worth mentioning.

liorean
03-27-2003, 08:02 PM
JavaScript is a special case when it comes to this: semicolon insertion takes some (but very little) processing. That makes a script with semicolons instead of linebreaks a triffle faster.
Both the loading time you add by including whitespace and the processing time you add by having to do extensive semicolon insertion are small and happen only once per page load. In general, it's better to optimise operation instead of processing and loading, since operation generally is the big time-consumer. Reducing loading times might be of interest for larger scripts with much extra commenting and whitespace, though.

brothercake
03-27-2003, 08:24 PM
I do have a script which is 40K verbose, but only 28K stripped of extraneous stuff, so I maintain the proper version, but the distributed zipfile has the compressed version. 12K is worth saving ... and of course that means semi-colons and braces. I always use both, all the time.

Can't remember who told me it would process faster like that .. I'll make a note to unlearn that ;)



EZ Archive Ads Plugin for vBulletin Copyright 2006 Computer Help Forum