Hacker News Toggle Comments

·

3 min read

Hacker News Toggle Comments

I like to read Hacker News especially due to the quality of the user comments, the more active comments are those that offer and have more useful information, most of the time we can learn more in the comments section than the story itself.

But, the UI/UX Hacker News comment section doesn't offer much options, we can pretty much only collapse the comments individually. There is no option to collapse all of them at once, and no option either to sort by the most active comments.

To have my minimal needs filled, I just need a way to collapse all the comments at once, after that, it's easier to browse the comment section picking at first the comments with more activity.

THE SOLUTION

First step, let's do an inspection in the comment collapse button

image.png

The solution seems to be right there: we just need to pick all the comments id's and call the toggle function, something like this:

var entries = document.getElementsByClassName('athing comtr');
Object.entries(entries).forEach(e => { 
    try{ toggle( {}, e[1].getAttribute("id") ); } catch {}
});

Right?

Wrong!

image.png

It looks like for each comment there is a call to the server to try to save the comment state. If we manually collapse only one comment we can see a HTTP GET being done to the server, It seems the request is being blocked if they are all made at the same time, a server defense against DOS attacks perhaps. One solution would be to add a timeout, but we will have to wait to have all the comments collapsed. Anyway, we don't need to save the state, we only need to have all the goddammit comments collapsed, so let's inspect where it's being done.

function toggle (ev, id) {
  var tr = $(id), on = !hasClass(tr, 'coll');
  collstate(tr, on);
  kidvis(tr, on);
  if ($('logout')) {
    new Image().src = 'collapse?id=' + id + (on ? '' : '&un=true');
  }
  ev.stopPropagation();
  return false;
}

new Image() ???? Where is the need to download an image here? Well!!! guess what! Do you want the straight way to make an Ajax call to the server? There you have it, just make an image instance where the src attribute points to the endpoint you want to make a GET call, in this particular case, the endpoint to save the comment state.

We can get rid of that call and the try that avoids the exception in the ev.stopPropagation();, after that we end up with this solution:

function toggleWithoutRequest (id) {
  var tr = $(id), on = !hasClass(tr, 'coll'); 
  collstate(tr, on);
  kidvis(tr, on);
} 

var mytoggle = async () => {
  var entries = document.getElementsByClassName('athing comtr'); 
  Object.entries(entries).forEach(e => {
    toggleWithoutRequest(e[1].getAttribute("id")); 
  }); 
};

Finally, we can wrap this solution in a Javascript self-execution function function(){}(), add the JS URL identifier so the browser knows he is dealing with JS: javascript: and save it as a Bookmarklet favorite:

javascript:(function(){function toggleWithoutRequest (id) {var tr = $(id), on = !hasClass(tr, 'coll'); (on ? addClass : remClass)(tr, 'coll'); collstate(tr,on); kidvis(tr, on); } var mytoggle = async () => {var entries = document.getElementsByClassName('athing comtr'); Object.entries(entries).forEach(e => {toggleWithoutRequest(e[1].getAttribute("id")); }); }; mytoggle(); })();

Now when at a Hacker News page with comments we can collapse them all with a simple click in the Favourite.