Skip to main content
3 of 7
Rollback to Revision 1

StackExchange – Expand Hidden Comments

In principle that what Expand all comments script does, but with two major differences:

  • Scrolls page back to the initial point of the target of the link you selected (i.e. to question, question comment, answer or answer comment) after comment expansion (since also "clicking" on a link programmatically – show n more comments in this case – scrolls the page to that link).
  • [internal] Uses regex for @include and @exclude. (Agreed, this prevents the really nice Sites favicons in Tampermonkey's Installed userscripts tab.)
// ==UserScript==
// @name        StackExchange – Expand Hidden Comments
// @description Expands hidden comments of SE questions and answers on sites with the new naming convention <something>.stackexchange.com and on Ask Ubuntu, Code Review, Server Fault, Super User and MathOverflow (the script is easily adaptable for more).
// @version     19.12.1
// @author      Gerold 'Geri' Broser <https://stackoverflow.com/users/1744774>
// @license     GNU GPLv3 <http://www.gnu.org/licenses/gpl-3.0.html>
// @supportURL  <>
// ------------
// @include /^https:\/\/(\w*\.+){0,2}(stack|ask|code|server|super|math)\w*\.(com|net)\/questions\/?.*$/
// Matches:             |<none>     ||      ⬑– Domains that don't follow |  | TLDs  || Paths        |
//                      |meta.|chat.||      the <something>.stackexchange|           | + possible   |
//                      |chat.meta. ||      scheme...                    |           |   fragment   |
//                      |⬑–––––––––––⬑–––– ...and those that do.         |

// @exclude /^https:\/\/(\w*\.+){0,2}(stack|ask|code|server|super|math)\w*\.(com|net)\/questions\/ask\/?.*$/
// Matches:             |<none>     ||      ⬑– Domains that don't follow |  | TLDs  || Path              |
//                      |meta.|chat.||      the <something>.stackexchange|           |+ possible fragment|
//                      |chat.meta. ||      scheme...                    |
//                      |⬑–––––––––––⬑–––– ...and those that do.         |
//              ---- extend bracket expression(s) above for new site(s) ----
// @namespace   igb
// @grant       none
// ==/UserScript==

(function() {
  'use strict'

  try {
    console.log("BEGIN StackExchange – Expand Hidden Comments...");

    // Get top first element in viewport to scroll to it after expansion, such restoring the viewport view.
    // The top first element can be one of the following:
    //   - a question (i.e. top of the page)
    //   - a question comment --+
    //   - an answer            +--> opened via a corresponding link
    //   - an answer cpmment  --+

    let topFirst = void(0)

    // Is question top first?
    const search = document.getElementById('search')
    topFirst = search.getBoundingClientRect().top > 0 ? search.parentNode : void(0)
    //console.debug("Is question top first?...", topFirst === void(0) ? "No" : "Yes")

    if ( topFirst === void(0) ) {
      // Is question comment top first?
      let questionComment = void(0)
      for ( questionComment of document.querySelectorAll('div#question div.comment-text') ) {
        //console.debug(questionComment, questionComment.getBoundingClientRect().top)
        if ( questionComment.getBoundingClientRect().top > 0 ) {
          topFirst = questionComment
          break
        } // if
      } // for
      //console.debug("Is question comment top first?...", topFirst === void(0) ? "No" : "Yes")
    } // if

    let answer = void(0)
    if ( topFirst === void(0) ) {
      // Is answer top first?
      for ( answer of document.getElementsByClassName('answercell') ) {
        //console.debug("answer:", answer, answer.getBoundingClientRect().top)
        if ( answer.getBoundingClientRect().top > 0 ) {
          topFirst = answer
          break
        }
        else {
          // Is answer comment top first?
          let answerComment = void(0)
          for ( answerComment of document.querySelectorAll('div#answers div.comment-text') ) {
            //console.debug("answerComment:", answerComment, answerComment.getBoundingClientRect().top)
            if ( answerComment.getBoundingClientRect().top > 0 ) {
              topFirst = answerComment
              break
            } // if
          } // for ( answer comments )
          //console.debug("Is answer comment top first?...", topFirst === void(0) ? "No" : "Yes")
          if ( topFirst !== void(0) )
            break
        } // if
      } // for ( answers )
      //console.debug("Is answer top first?...", topFirst === answer ? "Yes" : "No")
    } //  if

    [...document.getElementsByClassName('js-show-link')].forEach( link => {
      link.click() // scrolls page till last clicked link, therefore view is saved above and restored below
    })

    setTimeout( () => {
      console.log('BEGIN StackExchange – Expand Hidden Comments...delayed...')
      // Restore viewport view
      topFirst.scrollIntoView(true)
      //console.debug(topFirst, topFirst.getBoundingClientRect().top)
      console.log("END StackExchange – Expand Hidden Comments...delayed.")
    }, 1000 ) // increase if time isn't enough to scroll view to initial position
    console.log("END StackExchange – Expand Hidden Comments.")
  }
  catch (e) {
    console.error(e)
  }
})();

(Possible) TODO

  • Use jQuery to become browser agnostic if according issues arise.

Hints for improvement are welcome!