11

I have a document with a debugging comment in it that looks like this:

<!--SERVER_TRACE {...}-->

Is there a way to query the DOM to access this node? I am looking for a vanilla JavaScript solution, without the aid of any libraries.

My first thought was to depth first search the DOM and compare nodes found against the node type value for comments, Node.COMMENT_NODE. Is there an easier way?

Rick Viscomi
  • 8,180
  • 4
  • 35
  • 50
  • 1
    possible duplicate of [Selecting HTML Comments with jQuery](http://stackoverflow.com/questions/1623734/selecting-html-comments-with-jquery) – Sébastien Renauld Apr 22 '13 at 16:21
  • Wow, I was **sure** I knew that comment nodes were stripped. But not as far as I can tell: http://jsbin.com/ivufav/1/edit Tried it on Firefox, Chrome, and even IE7. They all had a node with `nodeType == 8` in the target, thus, didn't strip comments. – T.J. Crowder Apr 22 '13 at 16:22
  • 7
    @SébastienRenauld: Not a duplicate, as that question specifies the `jquery` tag, this one doesn't. It explicitly asks for a DOM API, not a library. (And the OP further clarified in the comment on an answer that he doesn't want to use jQuery.) – T.J. Crowder Apr 22 '13 at 16:23
  • @T.J.Crowder: Point made, I've put a pure JS implementation on. Also, he explicitely asks for a *way to query the DOM* - not an API. `childNode` recursion has never *not* been a way to access the DOM. Anyway - the OP has the only way of doing so. Case closed? – Sébastien Renauld Apr 22 '13 at 16:39
  • 1
    Perhapes this helps: https://developer.mozilla.org/en-US/docs/DOM/Node.nodeType But I haven't tested it. – Zim84 Apr 22 '13 at 16:18
  • This should be a comment – Ruan Mendes Apr 22 '13 at 16:44

2 Answers2

12

There's the TreeWalker APIs:

var tw = document.createTreeWalker(document, NodeFilter.SHOW_COMMENT, null, null),
    comment;
while (comment = tw.nextNode()) {
    // ...
}

This isn't supported by IE8 and lower.

T.J. in the comments provided a link to the specs. I kind of always use just TreeWalkers, but in your case a NodeIterator is fine too.

MaxArt
  • 22,200
  • 10
  • 82
  • 81
  • 1
    +1 Wow, and they're not even new: http://www.w3.org/TR/DOM-Level-2-Traversal-Range/traversal.html What's support like (other than – T.J. Crowder Apr 22 '13 at 16:56
  • @T.J.Crowder Uh, never done extensive testings, but Chrome, Firefox and Opera all support it. I guess you can find it in mobile browsers too. Anyway, I've even coded a polyfill for those browsers that don't support it. – MaxArt Apr 22 '13 at 17:05
  • 4
    Here is my previous JSFiddle updated to use the `document.createTreeWalker()` : http://jsfiddle.net/JCDnh/3/ much smaller and easier to read, technically the same steps, but possibly faster if the JavaScript engine is leveraging native code – Jason Sperske Apr 22 '13 at 17:56
  • 2
    @T.J.Crowder: It's existed for ever in Mozilla and a very long time in WebKit and Opera: I've been using it for many years. Apart from IE <= 8, support is universal, AFAIK (I haven't tested all the mobile browsers). – Tim Down Apr 23 '13 at 10:46
  • @TimDown: Cool, thanks! Too bad about IE8, I think we're going to be stuck with it for a while... But very, very useful thing to have in the back pocket. – T.J. Crowder Apr 23 '13 at 16:19
9

The nodeType core property allows you to differentiate between types of nodes. In this particular case, 8 represents comments. As they have no selector, you'll need to loop through their parent to get them (which sucks, I know). The following code filters them out for you:

$("*").contents().filter(function(){
    return this.nodeType == Node.COMMENT_NODE;
})

And my own jQuery-less version, because some people don't have it:

function getAllComments() {
    var t = [],
        recurse = function (elem) {
            if (elem.nodeType == Node.COMMENT_NODE) {
                t.push(elem);
            };
            if (elem.childNodes && elem.childNodes.length) {
                for (var i = 0; i < elem.childNodes.length; i++) {
                    recurse(elem.childNodes[i]);
                };
            };
        };
    recurse(document.getElementsByTagName("html")[0]);
    return t;
};

If you'd like to search on a specific node, re-bind the document.getElementsByTagName call to a variable of your choosing.

Edit: fiddle to demonstrate the use, done by Jason Sperske!

Community
  • 1
  • 1
Sébastien Renauld
  • 19,203
  • 2
  • 46
  • 66
  • And where does the OP say he's using jQuery? – T.J. Crowder Apr 22 '13 at 16:21
  • 2
    Previous comment is correct, I don't want a jQuery solution. Edit: this means that this question is _not_ a duplicate of "Selecting HTML Comments with jQuery". – Rick Viscomi Apr 22 '13 at 16:22
  • @T.J.Crowder: where does the OP *not* say? Nevertheless, I've added a pure JS implementation. – Sébastien Renauld Apr 22 '13 at 16:33
  • 4
    @SébastienRenauld: The absense of the `jquery` tag is, itself, sufficient, and the specificity of saying "a DOM API" makes it perfectly clear. Don't answer non-jQuery questions with jQuery-specific answers. (And of course, as of your update, now you haven't -- you've given an actual answer.) – T.J. Crowder Apr 22 '13 at 16:34
  • 3
    A JSFiddle demo of the (very impressive) non jQuery approach: http://jsfiddle.net/JCDnh/ – Jason Sperske Apr 22 '13 at 16:41
  • 1
    I don't see why this is downvoted. It wasn't downvoted before the non-jQuery option was added (which might have been reasonable), and is certainly "useful" now the non-jQuery version has been added. There are a couple of issues with the code (extraneous semicolons and using `childNodes[i]` instead of using `firstChild` / `nextSibling`), but nothing remotely downvote-worthy. – T.J. Crowder Apr 23 '13 at 06:40
  • The OP asks for an easier way than traversing the DOM and comparing the `nodeType`. This answer pretty much just regurgitated that. Nicely done, but not what was asked. – Rick Viscomi Apr 23 '13 at 18:07
  • Because that question totally wasn't edited 6 hours after the fact to add the nodeType idea. Oh wait. – Sébastien Renauld Apr 23 '13 at 18:12