Re: proposal for a new acceptNode() return value for TreeWalker.

Hi Leo,

On 08/10/2012 09:40 AM, Leo Deng wrote:
> Hello,
>
> According to DOM4, when an author creates a TreeWalker object, the
> return value of the acceptNode() method would be one of the following
> three:
>
>    FILTER_ACCEPT   the current node passes the filter (and the
>                    descendant would still be traversed).
>    FILTER_REJECT   the current node doesn't pass the filter, and the
>                    descendant would not be traversed.
>    FILTER_SKIP     the current node doesn't pass the filter, but
>                    continue traversing the decendants.
>
> All three values can't describe the "the current node passes the filter,
> but the descendants would not be traversed" state. In other words,
> there's a missing value:
>
>                FILTER_ACCEPT   FILTER_REJECT   FILTER_SKIP   FILTER_?
>
> passes the         YES             NO             NO           YES
>    filter
>
> descendants        YES             NO             YES          NO
>    traversed
>
>
> Consider a use case when an author wants to select any <div> element in
> an element with id "myid" such that it's not a descendant of an element
> matching ".any". With TreeWalker, the following JavaScript code can
> achieve this.
>
>    var selected = [];
>    var domWalker = document.createTreeWalker(
>      document.getElementById('myid'),
>      NodeFilter.SHOW_ELEMENT,
>      { acceptNode: function(node) {
>          if((node.parentNode.classList.contains('any')) {
>            return NodeFilter.FILTER_REJECT;
>          } else if(node.tagName == 'DIV') {
>            return NodeFilter.FILTER_ACCEPT;
>          } else {
>            return NodeFilter.FILTER_SKIP;
>          }
>      } },
>      false
>    );
>
>    while(domWalker.nextNode()) {
>      selected.push(domWalker.currentNode);
>    }
>
> For a node matching "div.any", when UA traverses it, among all three
> possible return value of acceptNode(), only FILTER_ACCEPT indicates that
> this node passes the filter. However, FILTER_ACCEPT couldn't stop  UA
> from traversing its children, so when its children is being traversed,
> the code has to determine if the parent node is matching ".any" to
> determine if acceptNode() can return a FILTER_REJECT here.
>
> If acceptNode() can return a value representing "the current node
> passeds the filter, but the descendants would not be traversed", say,
> FILTER_FINISH, then when UA traverses a node that passes the filter, it
> may still decide not to traverse the children of the node. Therefore,
> there's no longer a need to use *the characteristics of the parent node*
> to decide what the return value of acceptNode() for the current node is
> (which is also prone to error. For example, the above code throws when
> the element with id "myid" doesn't have a parent):
>
>    var selected = [];
>    var domWalker = document.createTreeWalker(
>      document.getElementById('myid'),
>      NodeFilter.SHOW_ELEMENT,
>      { acceptNode: function(node) {
>          if((node.parentNode.classList.contains('any')) {
>            return node.tagName == 'DIV' ? NodeFilter.FILTER_FINISH :
>                                           NodeFilter.FILTER_REJECT;
>          } else {
>            return node.tagName == 'DIV' ? NodeFilter.FILTER_ACCEPT :
>                                           NodeFilter.FILTER_SKIP;
>          }
>      } },
>      false
>    );
>
>    while(domWalker.nextNode()) {
>      selected.push(domWalker.currentNode);
>    }
>
> FILTER_FINISH would be equivalent to FILTER_ACCEPT when used
> for a filter of a NodeIterator.

To track this proposal, I filed bug 18540 [1].

I would be interested to hear if there is implementer interest in this 
feature.

Thanks
Ms2ger

[1] https://www.w3.org/Bugs/Public/show_bug.cgi?id=18540

Received on Sunday, 12 August 2012 20:17:22 UTC