Discussions » Creation Requests

Auto-expanding comments under LiveJournal blog posts

§
Posted: 2016-06-30
Edited: 2016-06-30

Auto-expanding comments under LiveJournal blog posts

I wish to expand all the comments under a LiveJournal blog post after complete loading of the web page. According to LiveJournal's FAQ (http://www.livejournal.com/support/faq/62.html) when a post gets more than 50 comments they are automatically collapsed and LiveJournal doesn't provide an easy way to expand them: there is no "Expand All" button and the user must stupidly click on the every "Expand" button on the web page in order to get finally all the comments expanded. I wish to automatize this process using Greasemonkey.

I have the following basic Javascript code which should be able to expand all the comments. In needs some improvement: the process of clicking the buttons should start only after complete loading of the web page.

Here is the code:

var links = document.links; for(i=0; i<links.length; i++) { if( links[i].text=='Expand' ) { links[i].click(); } };

And here is an example post with collapsed comments for testing purposes:

http://suggestions.livejournal.com/825341.html

I'm completely new to Greasemonkey and have only very little experience with Javascript. Could anyone help me do develop working script?

§
Posted: 2016-06-30

You can use the class names of the parent of the EXPAND link to select a smaller set to operate on:

var elinks = document.querySelectorAll('.b-tree-twig-1 .b-leaf-actions-expandchilds > a');
for (var i=0; i<elinks.length; i++){
  elinks[i].click();
}

The idea behind that is to hit only the ones at the top level of the outline (not indented from the left margin) indicated by the b-tree-twig-1 class, and then only the EXPAND links that apply to multiple children below indicated by the b-leaf-actions-expandchilds class.

§
Posted: 2016-06-30
Edited: 2016-06-30

Thank you for suggestion! But being a newbie to Greasemonkey I still can't create a script which works. Could you please provide at least a minimal script which just works at least partially for my purposes? The following is what I have created but it doesn't work:

// ==UserScript==
// @name Auto-expand LiveJournal comments
// @description Auto-expanding comments under LiveJournal blog posts
// @include http://*.livejournal.com/*
// @grant none
// ==/UserScript==

var links = document.links;
for(i=0; i

§
Posted: 2016-07-01

It could be a timing problem with the page not being completely loaded. How about a 3 second delay:

// ==UserScript==
// @name        Expand Comments on LiveJournal
// @namespace   YourNameHere
// @include     http*://*.livejournal.com/*
// @version     1
// @grant       none
// ==/UserScript==

function clickEm(){
  console.log("Running clickEm");
  var elinks = document.querySelectorAll('.b-tree-twig-1 .b-leaf-actions-expandchilds > a');
  for (var i=0; i<elinks.length; i++){
    elinks[i].click();
  }
}
// Run the function after a 3 second delay
window.setTimeout(clickEm, 3000);
§
Posted: 2016-07-01

Thank you very much! The script works but has one significant shortcoming: it does not expand comments when another page of comments under the same blog post is loaded. For example, there are 13 pages of comments under the following post:

http://news.livejournal.com/141929.html#comments

When the above web page is loaded, only the first page of comments is shown (all the comments are expanded by the script). But after opening any other page of comments the script doesn't expand the comments. Is it possible to overcome this problem?

§
Posted: 2016-07-01
Edited: 2016-07-01

I have found a quick-and-dirty solution: simply run the function every 2 seconds infinitely. Addition of the following at the end of the script does the trick:

// Run the function every 2 seconds infinitely
window.setInterval (clickEm, 2000);

Of course it isn't the best way to achieve my goal.

§
Posted: 2016-07-01
Edited: 2016-07-01

Currently I have come to the following script which isn't ideal but works sufficiently well:

// ==UserScript==
// @name        Expand Comments on LiveJournal
// @namespace   YourNameHere
// @include     http*://*.livejournal.com/*
// @version     1
// @grant       none
// ==/UserScript==

function clickEm(){
  console.log("Running clickEm");
  var elinks = document.querySelectorAll('.b-tree-twig-1 .b-leaf-actions-expandchilds > a');
  for (var i=0; i<elinks.length; i++){
    elinks[i].click();
  }
}

window.addEventListener("load", function(e) { clickEm(); }, false);

var checkLocationInterval = setInterval(checkLocation, 500);
var lastLocation = window.location.href.toString();

function checkLocation() {

    if (
        lastLocation != window.location.href.toString()
    ) {
        window.setTimeout(clickEm, 3000); lastLocation = window.location.href.toString();
    } 
};

Probably it can be done much better using Progress Listeners (but it isn't clear for me how to use them): https://developer.mozilla.org/en-US/Add-ons/Codesnippets/ProgressListeners

§
Posted: 2016-07-02

Here is also a bookmarklet which expands all the comments:

javascript:(function(){var elinks = document.querySelectorAll('.b-tree-twig-1 .b-leaf-actions-expandchilds > a'); for (var i=0; i<elinks.length; i++){elinks[i].click();}})();

One should create a new bookmark in the browser and put the above code into the URL field. Then clicking the bookmark will expand all the comments under the opened LiveJournal blog post.

§
Posted: 2016-07-06

How about this. It's a little slow. I think 2 seconds might not be optimal.

// ==UserScript==
// @name        Expand Comments on LiveJournal
// @namespace   YourNameHere
// @include     http*://*.livejournal.com/*
// @version     1
// @grant       none
// ==/UserScript==

// Create a MutationObserver to watch for new comments or other updates
var MutOb, chgMon, i, opts, t_expandEm;
var MutOb = (window.MutationObserver) ? window.MutationObserver : window.WebKitMutationObserver;
if (MutOb){
  chgMon = new MutOb(function(mutationSet){
    mutationSet.forEach(function(mutation){
      for (i=0; i<mutation.addedNodes.length; i++){
        if (mutation.addedNodes[i].nodeType == 1){
          // Reschedule clickEm for two seconds from now
          if (t_expandEm) window.clearTimeout(t_expandEm);
          t_expandEm = window.setTimeout(eclj_clickEm, 2000);
        }
      }
    });
  });
  // attach chgMon to document.body
  opts = {childList: true, subtree: true};
  chgMon.observe(document.body, opts);
}
function eclj_clickEm(){
  var elinks = document.querySelectorAll('.b-tree-twig-1 .b-leaf-actions-expandchilds > a, .b-leaf-seemore-expand > a');
  for (var j=0; j<elinks.length; j++){
    elinks[j].click();
  }
}
§
Posted: 2016-07-06
Edited: 2016-07-06

Thank you very much for the update, now it indeed works reliably!

The only thing that worries me is that for some large blog posts (containing many images and embedded video) the page loading time become 2-3 times longer than was with the original version (I mean the time spent until the page can be scrolled smoothly). A bright example is this blog post.

I have performed some tests with this post. Both with 2000 and 200 milliseconds delay clickEm runs 4 times. With 4 seconds delay the number of runs reduces to 3 and as a result the page loading time decreases significantly. With 8 seconds delay there are only 2 runs (the last run is very fast) and the page loading time is minimal. Of course such a large delay is inappropriate for small blog posts. In all cases comments were completely expanded by the script.

§
Posted: 2016-07-06

Hmm, I don't know how best to fix it.

The goal of the rescheduling code is to try to run clickEm only once, but once it starts, that could be resetting the clock to have it run again before the first run actually is finished. I guess this isn't working for the initial page load, which takes much longer than adding another set of comments.

Perhaps the main part of the script shouldn't even run until, say, 5-10 seconds after the initial page load? It probably will be a while before you get down to the comments...

§
Posted: 2016-07-07
Edited: 2016-07-07

I have one idea. At the bottom of the page there is a footer which code starts from:

<footer class="s-footer cf">
            <div class="s-footer-in">
               <div class="s-options">
                    <dl class="s-option">

This footer is only one and probably when this footer is loaded the comment section must be already loaded. So we can add a condition do not run clickEm until the footer is loaded. Probably we can use document.getElementsByTagName("footer").length for this.

UPDATE: It seems I was wrong: the footer is loaded before the comment section.

Post reply

Sign in to post a reply.