Video description, long comments and list of subscriptions are expanded automatically; all the replies are shown after pressing "Show more replies" button
// ==UserScript== // @name Youtube: expand description and long comments; show all the replies // @description Video description, long comments and list of subscriptions are expanded automatically; all the replies are shown after pressing "Show more replies" button // @author MK // @namespace max44 // @homepage https://greasyfork.org/en/users/309172-max44 // @match *://*.youtube.com/* // @match *://*.youtu.be/* // @icon https://cdn.icon-icons.com/icons2/1488/PNG/512/5295-youtube-i_102568.png // @version 1.2.15 // @license MIT // @require https://openuserjs.org/src/libs/sizzle/GM_config.js // @grant GM_getValue // @grant GM_setValue // @grant GM_registerMenuCommand // @run-at document-end // ==/UserScript== (function () { 'use strict'; //WORKAROUND: This document requires 'TrustedHTML' assignment if (window.trustedTypes && trustedTypes.createPolicy) { if (!trustedTypes.defaultPolicy) { const passThroughFn = (x) => x; trustedTypes.createPolicy('default', { createHTML: passThroughFn, createScriptURL: passThroughFn, createScript: passThroughFn, }); } } var gm_css = ` #yt_expand_desc_comments_replies * { font-family: Roboto, Arial, sans-serif !important; } #yt_expand_desc_comments_replies .config_header { font-size: 20px !important; font-weight: bold !important; } #yt_expand_desc_comments_replies .field_label { font-size: 13px !important; font-weight: 400 !important; } #yt_expand_desc_comments_replies input[type="text"] { width: 50px !important; font-size: 12px !important; font-weight: bold !important; border-radius: 3px !important; } #yt_expand_desc_comments_replies button { font-size: 12px !important; }`; var gm_frameStyle = `border: 2px solid rgb(0, 0, 0); border-radius: 6px; height: 50%; width: 30%; margin: 0px; max-height: 350px; max-width: 95%; min-height: 350px; min-width: 500px; opacity: 1; overflow: auto; padding: 0px; position: fixed; z-index: 9999; display: block;`; GM_config.init({ id: 'yt_expand_desc_comments_replies', title: 'Settings for "' + GM_info.script.name + '" script', css: gm_css, frameStyle: gm_frameStyle, fields: { 'fldExpandDesc': { 'label': 'Expand video description', 'labelPos': 'above', 'type': 'checkbox', 'default': true }, 'fldExpandLongComments': { 'label': 'Expand long comments', 'labelPos': 'above', 'type': 'checkbox', 'default': true }, 'fldExpandLongReplies': { 'label': 'Expand long replies to comments', 'labelPos': 'above', 'type': 'checkbox', 'default': true }, 'fldShowAllReplies': { 'label': 'Show all the replies to a comment', 'labelPos': 'above', 'type': 'checkbox', 'default': true }, 'fldExpandSubs': { 'label': 'Expand list of subscriptions', 'labelPos': 'above', 'type': 'checkbox', 'default': true } } }); GM_registerMenuCommand('Settings', () => { GM_config.open(); }); var videoIdAtLastCheck = ""; var btnClick = null; var waitVideo; var i; var observerBody = null; var observerSubs = null; var flgSubsDone = false; var observerDesc = null; var observerComments = null; //var observerCommentsTabview = null; var observerCommentsNotif = null; var observerComPost = null; const delay = ms => new Promise(res => setTimeout(res, ms)); const waitAndScroll = async () => { await delay(500); window.scrollTo(0, 0); }; //--- //--- Listen to global page changes //--- const callbackBody = function (mutationsList, observer) { var pathArray = window.location.pathname.split('/'); var firstPath = pathArray[1]; var lastPath = pathArray[pathArray.length - 1]; //Check whether video is new to expand description if (firstPath === "watch" || firstPath === "live") { //var player = $( "div#content ytd-watch-flexy" ); var player = document.querySelectorAll("div#content ytd-watch-flexy"); if (player != null && player.length > 0) { clearInterval(waitVideo); //Stop waiting for video var videoId = player[0].getAttribute("video-id"); player = null; if (videoIdAtLastCheck != videoId) { videoIdAtLastCheck = videoId; expandDesc(); waitAndScroll(); } } } /* //--- //--- Listen to description and expand it //--- if (observerDesc == null) { const callbackDesc = function (mutationsList, observer) { //Check whether video is new to expand description if (firstPath === "watch") { var player = $( "div#content ytd-watch-flexy" ); if (player != null && player.length > 0) { clearInterval(waitVideo); //Stop waiting for video var videoId = player[0].getAttribute("video-id"); player = null; if (videoIdAtLastCheck != videoId) { videoIdAtLastCheck = videoId; console.log("new video"); expandDesc(); } } } } let nodeDesc = document.querySelector("#player");//document.querySelector(".watch-active-metadata"); if (nodeDesc != null) { observerDesc = new MutationObserver(callbackDesc); observerDesc.observe(nodeDesc, {childList: true, subtree: true, attributes: true, characterData: false}); console.log("desc observer added"); } }*/ //Remove subscriptions observer after subscriptions have been expanded if (flgSubsDone && observerSubs != null) { observerSubs.disconnect(); //Expand subscriptions only once observerSubs = null; } //--- //--- Listen to community posts and expand them //--- if (observerComPost == null && lastPath === "community") { const callbackComPost = function (mutationsList, observer) { expandComPosts(); expandComments(); } let nodeComPost = document.querySelector("#primary #contents #contents"); if (nodeComPost != null) { observerComPost = new MutationObserver(callbackComPost); observerComPost.observe(nodeComPost, {childList: true, subtree: true, attributes: true, characterData: false}); } } //Remove community post observer on non-community pages if (observerComPost != null && lastPath != "community") { observerComPost.disconnect(); observerComPost = null; } //--- //--- Listen to comments and expand them //--- if (observerComments == null && (firstPath === "watch" || firstPath === "live" || firstPath === "post" || firstPath === "shorts" || lastPath === "community")) { const callbackComments = function (mutationsList, observer) { expandComments(); } let nodeComments = null; let nodeCommentsTabview = null; if (firstPath === "shorts") { nodeComments = document.querySelector("ytd-shorts ytd-comments:not([hidden='']"); if (nodeComments != null) { observerComments = new MutationObserver(callbackComments); observerComments.observe(nodeComments, {childList: true, subtree: true, attributes: true, characterData: false}); } } else { nodeComments = document.querySelector("#primary ytd-comments:not([hidden='']"); if (nodeComments != null) { observerComments = new MutationObserver(callbackComments); observerComments.observe(nodeComments, {childList: true, subtree: true, attributes: true, characterData: false}); } nodeCommentsTabview = document.querySelector("#right-tabs ytd-comments:not([hidden='']"); if (nodeCommentsTabview != null) { observerComments = new MutationObserver(callbackComments); observerComments.observe(nodeCommentsTabview, {childList: true, subtree: true, attributes: true, characterData: false}); } } } //Remove comments observer if (observerComments != null && firstPath != "watch" && firstPath != "live" && firstPath != "shorts" && firstPath != "post" && lastPath != "community") { observerComments.disconnect(); observerComments = null; } //--- //--- Listen to comments in notification submenu and expand them //--- if (observerCommentsNotif == null) { const callbackCommentsNotif = function (mutationsList, observer) { expandCommentsNotif(); } let nodeCommentsNotif = null; nodeCommentsNotif = document.querySelector("ytd-popup-container #contentWrapper"); if (nodeCommentsNotif != null) { observerCommentsNotif = new MutationObserver(callbackCommentsNotif); observerCommentsNotif.observe(nodeCommentsNotif, {childList: true, subtree: true, attributes: true, characterData: false}); } } } let nodeBody = document.querySelector("body"); if (nodeBody != null) { const observerBody = new MutationObserver(callbackBody); observerBody.observe(nodeBody, {childList: true, subtree: true, attributes: true, characterData: false}); } //--- //--- Listen to subscriptions and expand them //--- const callbackSubs = function (mutationsList, observer) { expandSubs(); } let nod###bs = document.querySelector("div#guide-wrapper"); if (nod###bs != null) { observerSubs = new MutationObserver(callbackSubs); observerSubs.observe(nod###bs, {childList: true, subtree: true, attributes: true, characterData: false}); } //--------------------------------------- // Expand description //--------------------------------------- function expandDesc() { if (GM_config.fields['fldExpandDesc'].value) { //Expand description /*btnClick = $( "div#description ytd-text-inline-expander tp-yt-paper-button#expand[role='button']:not([hidden=''])" ); if (btnClick != null && btnClick.length > 0) {// && isVisible(btnClick)) { btnClick[0].click(); }*/ //Expand description - suggested by gcobc12632 //btnClick = $( "yt-interaction#description-interaction" ); btnClick = document.querySelector("yt-interaction#description-interaction"); if (btnClick != null) {// && isVisible(btnClick)) { btnClick.click(); return; } //Expand description after 7ktTube | 2016 REDUX script //btnClick = $( "div#meta-contents ytd-video-secondary-info-renderer div ytd-expander tp-yt-paper-button#more:not([hidden=''])" ); btnClick = document.querySelectorAll("div#meta-contents ytd-video-secondary-info-renderer div ytd-expander tp-yt-paper-button#more:not([hidden=''])"); if (btnClick != null && btnClick.length > 0) {// && isVisible(btnClick)) { btnClick[0].click(); } } } //--------------------------------------- // Expand post and comments in community section //--------------------------------------- function expandComPosts() { if (GM_config.fields['fldExpandLongComments'].value) { //Expand long post in community section btnClick = document.querySelectorAll("#post tp-yt-paper-button#more:not([hidden='']) > span.more-button"); if (btnClick != null && btnClick.length > 0) { for (i = 0; i < btnClick.length; i++) { btnClick[i].click(); btnClick[i].parentNode.previousElementSibling.setAttribute("style", "display:none;"); //Hide "Show less" button } } } } //--------------------------------------- // Expand comments //--------------------------------------- function expandComments() { if (GM_config.fields['fldExpandLongComments'].value) { //Expand long comments and hide "show less" button in comments section btnClick = document.querySelectorAll("ytd-comments ytd-comment-thread-renderer > ytd-comment-view-model#comment tp-yt-paper-button#more:not([hidden='']) > span.more-button"); if (btnClick != null) { for (i = 0; i < btnClick.length; i++) { btnClick[i].click(); btnClick[i].setAttribute("clicked-by-script", "true"); //Do not click it again btnClick[i].parentNode.previousElementSibling.setAttribute("style", "display:none;"); //Hide "Show less" button } } } if (GM_config.fields['fldExpandLongReplies'].value) { //Expand long replies and hide "show less" button in comments section btnClick = document.querySelectorAll("ytd-comments #replies tp-yt-paper-button#more:not([hidden='']) > span.more-button"); if (btnClick != null) { for (i = 0; i < btnClick.length; i++) { btnClick[i].click(); btnClick[i].setAttribute("clicked-by-script", "true"); //Do not click it again btnClick[i].parentNode.previousElementSibling.setAttribute("style", "display:none;"); //Hide "Show less" button } } } if (GM_config.fields['fldShowAllReplies'].value) { //Show all replies upon pressing "Show more replies" button (not in notification submenu) btnClick = document.querySelectorAll("#primary div#replies div#expander div#expander-contents div#button.ytd-continuation-item-renderer:not([hidden]) ytd-button-renderer.ytd-continuation-item-renderer button.yt-spec-button-shape-next:not([clicked-by-script='true'])"); if (btnClick != null) { for (i = 0; i < btnClick.length; i++) { btnClick[i].click(); btnClick[i].setAttribute("clicked-by-script", "true"); //Do not click it again } } //Rearm "Show more replies" button btnClick = document.querySelectorAll("#primary div#replies div#expander div#expander-contents div#button.ytd-continuation-item-renderer[hidden=''] ytd-button-renderer.ytd-continuation-item-renderer button.yt-spec-button-shape-next[clicked-by-script='true']"); if (btnClick != null) { for (i = 0; i < btnClick.length; i++) { btnClick[i].removeAttribute("clicked-by-script", "true"); //Click it again when it becomes not hidden } } //Show all replies upon pressing "View more comments" button (7ktTube | 2016 REDUX script) btnClick = document.querySelectorAll("#primary div#replies div#expander div#expander-contents div#button.ytd-continuation-item-renderer:not([hidden]) ytd-button-renderer tp-yt-paper-button#button[role='button']:not([clicked-by-script='true'])"); if (btnClick != null) { for (i = 0; i < btnClick.length; i++) { btnClick[i].click(); btnClick[i].setAttribute("clicked-by-script", "true"); //Do not click it again } } //Rearm "View more comments" button (7ktTube | 2016 REDUX script) btnClick = document.querySelectorAll("#primary div#replies div#expander div#expander-contents div#button.ytd-continuation-item-renderer[hidden=''] ytd-button-renderer tp-yt-paper-button#button[role='button'][clicked-by-script='true']"); if (btnClick != null) { for (i = 0; i < btnClick.length; i++) { btnClick[i].click(); btnClick[i].removeAttribute("clicked-by-script", "true"); //Click it again when it becomes not hidden } } } } //--------------------------------------- // Expand comments in notification submenu //--------------------------------------- function expandCommentsNotif() { if (GM_config.fields['fldExpandLongComments'].value) { //Expand long comments and hide "show less" button in notification submenu btnClick = document.querySelectorAll("#submenu ytd-comment-thread-renderer > #comment tp-yt-paper-button#more:not([hidden='']) > span.more-button[slot='more-button']:not([clicked-by-script='true'])"); if (btnClick != null) { for (i = 0; i < btnClick.length; i++) { btnClick[i].click(); btnClick[i].setAttribute("clicked-by-script", "true"); //Do not click it again btnClick[i].parentNode.previousElementSibling.setAttribute("style", "display:none;"); //Hide "Show less" button } } } if (GM_config.fields['fldExpandLongReplies'].value) { //Expand long replies and hide "show less" button in notification submenu btnClick = document.querySelectorAll("#submenu ytd-comment-thread-renderer > #replies tp-yt-paper-button#more:not([hidden='']) > span.more-button[slot='more-button']:not([clicked-by-script='true'])"); if (btnClick != null) { for (i = 0; i < btnClick.length; i++) { btnClick[i].click(); btnClick[i].setAttribute("clicked-by-script", "true"); //Do not click it again btnClick[i].parentNode.previousElementSibling.setAttribute("style", "display:none;"); //Hide "Show less" button } } } } //--------------------------------------- // Show all subscriptions //--------------------------------------- function expandSubs() { if (GM_config.fields['fldExpandSubs'].value) { //btnClick = $( "#guide div#sections div#items ytd-guide-collapsible-entry-renderer.ytd-guide-section-renderer[can-show-more=''] #expander-item" ); btnClick = document.querySelectorAll("#guide div#sections div#items ytd-guide-collapsible-entry-renderer.ytd-guide-section-renderer:not([expanded='']) #expander-item"); if (btnClick != null) { for (i = 0; i < btnClick.length; i++) { if (isVisible(btnClick[i])) { btnClick[i].click(); flgSubsDone = true; } } } } } //--------------------------------------- // Check all the parents of element to find whether it is visible or not //--------------------------------------- function isVisible(pObj) { if (pObj != null) { var checkNext = true; var vObj = pObj; while (checkNext) { checkNext = false; //console.log("checking element " + vObj.tagName + "#" + vObj.id + ": '" + document.defaultView.getComputedStyle(vObj,null)['display'] + "'"); if (document.defaultView.getComputedStyle(vObj,null)['display'] != "none") { if (vObj.parentElement != null) { vObj = vObj.parentElement; checkNext = true; } } else { return false; } } return true; } return false; } })(); /*//Detect spinner at main comments var spinnerMain = $( "#primary div#replies div#expander tp-yt-paper-spinner#spinner[active]" ); if (spinnerMain != null && spinnerMain.length > 0) { console.log("main active spinner detected"); spinnerActive = true; //Listen to spinner changes const spinnerCallback = function (mutationsList, observer) { expandComments(); //spinnerMain = $( "#primary div#replies div#expander tp-yt-paper-spinner#spinner[active]" ); if (spinnerMain[0].getAttribute("active") == null || spinnerMain[0].getAttribute("active") == "") { console.log("main spinner deactivated"); spinnerObserver.disconnet(); } } var spinnerNode = document.querySelector("#primary div#replies div#expander tp-yt-paper-spinner#spinner[active]"); if (spinnerNode != null) { const spinnerObserver = new MutationObserver(spinnerCallback); spinnerObserver.observe(spinnerNode, {childList: true, subtree: true, attributes: true, characterData: true}); } } else if (spinnerActive) { console.log("spinner stopped"); spinnerActive = false; expandComments(); }*/