Greasy Fork is available in English.

Expand comments at webinar.ru

Добавляет кнопки, раскрывающие ветки с обсуждениями на сайте webinar.ru

// ==UserScript==
// @name        Expand comments at webinar.ru
// @namespace   Webinar Scripts
// @match       https://events.webinar.ru/course-info/*
// @grant       none
// @version     1.3
// @author      in_vite
// @description Добавляет кнопки, раскрывающие ветки с обсуждениями на сайте webinar.ru
// ==/UserScript==

const waitForElement = async selector => {
  while (document.getElementsByClassName(selector).length == 0) {
    await new Promise(resolve => requestAnimationFrame(resolve))
  }

  return document.getElementsByClassName(selector)
}

const waitAndClickElement = async (where, selector, selector2, minimumExpectedLength=1) => {
  while ((where.getElementsByClassName(selector).length == 0) &&
         (where.getElementsByClassName(selector2).length < minimumExpectedLength)) {
    await new Promise(resolve => requestAnimationFrame(resolve))
  }

  if (where.getElementsByClassName(selector).length > 0) {
    where.getElementsByClassName(selector)[0].click()
  }

  return where.getElementsByClassName(selector2).length
}

function main() {
  'use strict'

  const nameCommentsCount = 'PostNewsComments__commentsCount____zB8X'
  const nameFetchMoreComments = 'PostNewsComments__fetchMoreCommentsBtn___tyN_f'
  const nameNewsItem = 'NewsFeed__newsItem___VAlN_'
  const nameCommentRoot = 'Comment__root___sd3C5'
  const nameButton = 'ExpandingButton'
  
  // wait till the page is loaded and add two kinds of buttons with different behavior
  waitForElement(nameCommentsCount).then((selector) => {
    // check there are no buttons yet
    if (document.getElementsByClassName(nameButton).length == 0) {
      addButtons('Развернуть комментарии', '10px', openComments, false)
      addButtons('Развернуть и прокрутить', '20px', openComments, true)
    }
  })

  function addButtons(text, leftPosition, onClick, withScroll) {
    // find all elements with information about total number of comments
    let elementCommentsCounts = document.getElementsByClassName(nameCommentsCount)

    // default button style and position
    let cssObj = {
      position: 'relative',
      left: leftPosition,
      //'-webkit-appearance': 'none',
      //'-moz-appearance': 'none',
      //'appearance': 'none',   
      background: 'white',
      color: 'black',
      'border-radius': '3px',
      'border-color': 'lightgray'
    }

    // for every such element create a button with specified style, position and behavior
    for (let i = elementCommentsCounts.length; i--;) {
      let button = document.createElement('button'), btnStyle = button.style
      elementCommentsCounts[i].appendChild(button)
      button.className = nameButton
      button.innerHTML = text
      button.onclick = onClick.bind(button, withScroll)
      Object.keys(cssObj).forEach(key => btnStyle[key] = cssObj[key])
    }
  }

  async function openComments(withScroll) {
    // find an element with the whole discussion
    let post = this.parentElement.parentElement
    // retrieve total number of comments
    let totalCommentsNumber = parseInt(post.getElementsByClassName(nameCommentsCount)[0].innerText, 10)
    let done = false
    let currentCommentsNumber = 0
    const whileGenerator = function* () {
      while (!done) {
        yield currentCommentsNumber
      }
    }

    for (let i of whileGenerator()) {
      // find the link for expansion while it exists and click it
      currentCommentsNumber = await waitAndClickElement(post, nameFetchMoreComments, nameCommentRoot, totalCommentsNumber)

      // stop when we got all possible comments
      if (currentCommentsNumber >= totalCommentsNumber) {
        done = true;
      }
    }

    // change button style when it expanded everything
    this.style.background = '#f6f6f6'
    this.style.color = 'black'

    if (withScroll && (totalCommentsNumber > 0)) {
      // get element with the last comment
      let lastComment = post.getElementsByClassName(nameCommentRoot)[totalCommentsNumber - 1]
      let yOffset = -90
      // get element position and correct it
      let y = lastComment.getBoundingClientRect().top + window.pageYOffset + yOffset

      // scroll to the corrected position
      window.scrollTo({top: y, behavior: 'smooth'});
    }
  }
}

let oldHref = ''

// check url is changed to add buttons again
window.onload = function() {
    let bodyList = document.querySelector('body')
    let observer = new MutationObserver(function(mutations) {
      mutations.forEach(function(mutation) {
        if (oldHref != document.location.href) {
          oldHref = document.location.href
          main()
        }
      })
    })

    let config = {
      childList: true,
      subtree: true
    }

    observer.observe(bodyList, config)
}