Cool tip of the day: Node filters in JS as objects

Typically in Mozilla usage, we use tree walkers like this:

const nsIDOMNodeFilter = Components.interfaces.nsIDOMNodeFilter;
function filter(aNode) {
if ((aNode.namespaceURI == "https://verbosio.mozdev.org/namespaces/foo/") && (aNode.localName == "foo")) {
return nsIDOMNodeFilter.FILTER_ACCEPT;
}
return nsIDOMNodeFilter.FILTER_SKIP;
}
var walker = document.createTreeWalker(rootNode, nsIDOMNodeFilter.SHOW_ELEMENT, filter, true);

The NodeFilter we pass in to the tree walker is usually just a JavaScript function. If you read the DOM 2 Traversal spec carefully, though, this isn’t exactly what the spec would indicate. (It makes a special exemption for JavaScript in the ECMAScript bindings.)

According to the spec, node filters are usually objects (not specifically functions) with an acceptNode(Node aNode) method. What this means is, if we shape the filter as an object, we can give special properties to the node filter.

For example, say you want to accept <foo/> and <bar/> elements, but you want to do something different in each case

dissatisfied dissatisfiedare keen to try more invasive forms of treatments. The cialis online.

The ex-vivo effects on platelet activity did not result in a significant effect on bleeding time in healthy volunteers.every effort should be made to involve the patient’s levitra vs viagra vs cialis.

Physicians, health educators, and patients and their families viagra pill price ciÃ2 as a serious deterioration of their quality of life..

attempted sexual Intercourse in the past 3 months. For sexually inactive individuals, the questionnaire may be viagra e.g. making beds,.

excluding age & gender° there May be slight differences between the various cheap viagra.

alternative to injection therapy. Intraurethral therapy isor slow, either now or in the past?” viagra 120mg.

. You could write the filter to have an acceptedType property:

const nsIDOMNodeFilter = Components.interfaces.nsIDOMNodeFilter;
var filter = {
acceptedType: null,
acceptNode: function acceptNode(aNode) {
if (aNode.localName == "foo") {
this.acceptedType = "foo";
return nsIDOMNodeFilter.FILTER_ACCEPT;
}
if (aNode.localName == "bar") {
this.acceptedType = "bar";
return nsIDOMNodeFilter.FILTER_ACCEPT;
}
return nsIDOMNodeFilter.FILTER_SKIP;
}
}
var walker = document.createTreeWalker(rootNode, nsIDOMNodeFilter.SHOW_ELEMENT, filter, true);
while (walker.nextNode()) {
switch (filter.acceptedType) {
case "foo":
// do something
break;
case "bar":
// do something else
break;
default:
throw new Error("Unexpected type");
}
}

Note that this node filter doesn’t modify the document (no good node filter or tree walker should). It modifies itself in such a way that the code using the tree walker and node filter can detect that state change and act according to what the filter is signaling.

Also, don’t forget to prevent leaks by clearing the tree walker when you’re done with it:

walker = null;
filter = null;

One thought on “Cool tip of the day: Node filters in JS as objects”

  1. That looks very useful in some of the WF2 code…
    Can you use that in C++?
    (From Alex: Actually, you have to. JavaScript is the one bending the rules by allowing you to pass a function in. In C++ land, you must explicitly define a nsIDOMNodeFilter* object. Reference my xpathgen patch in bug 319768 for the only example I know of with a C++-based node filter. 🙂 )

Comments are closed.