views:

174

answers:

2

A blog I read has some annoying commenters. I thought I would try my hand at Greasemonkey to turn them off.

The basic structure of the HTML is simple - a comment looks something like this:

<li>
  <cite>user name ...</cite>
  comment text
</li>

So with that in mind, I bashed my head against the keyboard for a while until this dropped out:

var killlist = /user1|user2/;

var comments = document.getElementsByTagName('li');

if (comments.length) {
  for ( var i = 0; i < comments.length; i ++ ) {
    var comment = comments[i];
    var cites = comment.getElementsByTagName('cite');
    if (cites.length) {
      var cite = cites[0];
      var title = cite.textContent;
      if (killlist.test(title)) {
        comment.parentNode.removeChild(comment);
      }
    }
  }
}

window.alert('Done!')

(the window.alert is just so I know if the script runs to completion)

This mostly works. e.g. on one test page, it removed 13 of 16 posts by one of the users. I tried replacing the removeChild line with this:

comment.style.visibility = 'hidden';

That appears to get everything, but at the expense of leaving great empty spaces where the comments would have been.

I'm a complete javascript newbie, so can anyone see anything obvious I'm doing wrong?

+1  A: 

You should be able to fix it by reversing the order of your for loop and deleting elements from the end of the comments array first:

for ( var i = comments.length - 1; i >= 0; i-- )
Pat
I wondered if that might be a problem, so I tried making an array to comments to delete, and then deleting frrom it, but to no avail. But this is looking promising so far! I will test for a little longer and then come back.
John Fouhy
+2  A: 

The behavior you're seeing is due to comments being a live NodeList. As you remove elements referenced by comments from the DOM, comments is mutated (and its length updated) and your loop goes out the window.

You can loop in reverse order as @Pat suggested, or "unhook" the NodeList from the DOM with a copy operation first:

var comments = Array.slice(document.getElementsByTagName('li'));

Then proceed as before.

Crescent Fresh