// ==UserScript== // @name JRM: JoyReactor Mod // @description Модификация JoyReactor // @version 2.4.2 // @author DmitriyMX // @namespace https://gitlab.com/DmitriyMX/joyreactor-mod // @downloadURL https://gitlab.com/DmitriyMX/joyreactor-mod/raw/master/jrm.user.js // @updateURL https://gitlab.com/DmitriyMX/joyreactor-mod/raw/master/jrm.user.js // @match http://joy.reactor.cc/* // @grant none // @run-at document-end // ==/UserScript== class Post { /** * @param {HTMLElement} elmPost */ constructor(elmPost) { const pc_len = 'postContainer'.length; /** @public {Number} */ this.id = parseInt(elmPost.id.substring(pc_len)); /** @public {String} */ this.author = elmPost.getElementsByClassName('uhead_nick')[0].getElementsByTagName('a')[0].text; /** @public {String[]} */ this.tags = []; for (const elmChild of elmPost.getElementsByClassName('taglist')[0].children) { this.tags.push(elmChild.textContent.trim()); } } } class Comment { /** * @param {HTMLElement} elmComment */ constructor(elmComment) { const cm_len = 'comment'.length; /** @public {HTMLElement} */ this.element = elmComment; /** @public {Number} */ this.id = parseInt(elmComment.id.substring(cm_len)); const elmsTxt = elmComment.getElementsByClassName('txt'); /** @public {String} */ this.author = null; /** @public {String} */ this.text = null; if (elmsTxt.length > 0) { let elms = elmsTxt[0].getElementsByClassName('comment_username'); if (elms.length > 0) { this.author = elmsTxt[0].getElementsByClassName('comment_username')[0].textContent; this.text = elmsTxt[0].children[0].textContent; } else if (elmComment.getElementsByClassName('comment_show').length > 0) { this.author = elmComment.getElementsByClassName('comments_bottom')[0].children[1].children[0].textContent; this.text = '[HIDDEN COMMENT]'; } } if (this.author === null) { throw new Error('author is NULL'); } /** @public {String} */ this.image = null; if (elmComment.getElementsByClassName('image').length > 0) { this.image = elmComment.getElementsByClassName('image')[0].children[0].href; } /** @public {Comment[]} */ this.children = []; for (const childComment of document.getElementById('comment_list_comment_' + this.id).children) { if (childComment.id.startsWith('comment_list_comment_')) { continue; } try { this.children.push(new Comment(childComment)); } catch (e) { console.error("--- ERROR ---"); console.error(childComment); console.error(e); console.error("--- END ---"); } } } } class JRApi { constructor() { /** @private {RegExp} */ this._urlPostRegexp = new RegExp("https?:\/\/.+/post/([0-9]+)"); /** @private {Comment[]} */ this._comments = null; } /** * @return {Boolean} */ isPostPage() { return (document.URL.match(this._urlPostRegexp) !== null); } /** * @return {Post} */ post() { const postId = document.URL.match(this._urlPostRegexp)[1]; const elmPostContainer = document.getElementById('postContainer' + postId); return new Post(elmPostContainer); } /** * @return {Post[]} */ posts() { const elmPostList = document.getElementById('post_list'); const postList = []; for (const elmPostContainer of elmPostList.children) { postList.push(new Post(elmPostContainer)); } return postList; } /** * @return {Comment[]} */ comments() { if (this._comments == null) { const postId = document.URL.match(this._urlPostRegexp)[1]; this._comments = []; for (const elmComment of document.getElementById('comment_list_post_' + postId).children) { if (elmComment.id.startsWith('comment_list_comment_')) { continue; } this._comments.push(new Comment(elmComment)); } } return this._comments; } } class JRMod { /** * @param {JRApi} jrApi */ constructor(jrApi) { this.jrApi = jrApi; } /** * Добавляем кнопку сворачивания ветки комментариев */ addCollapseTreeCommentsButton() { /** * @param {Comment} comment * @return {HTMLElement} */ const createButton = function (comment) { const aTag = document.createElement('a'); aTag.href = "#"; aTag.innerHTML = '➖'; aTag.style.fontWeight = 'bold'; aTag.style.color = '#656464'; aTag.style.lineHeight = '31px'; aTag.style.textDecoration = 'none'; aTag.style.margin = '0 10px'; aTag.style.padding = '0 10px' aTag.style.borderRadius = '15px'; aTag.style.background = '#dfdfdf'; const elmSubCommentList = document.getElementById('comment_list_comment_' + comment.id); aTag.onclick = function () { if (elmSubCommentList.style.display === 'none') { elmSubCommentList.style.display = ''; aTag.innerHTML = '➖'; // ➖, - } else { elmSubCommentList.style.display = 'none'; aTag.innerHTML = '➕'; // ➕, + } return false; } return aTag; } /** @param {Comment} comment */ const func = function (comment) { if (comment.children.length === 0) return; comment.element.getElementsByClassName('reply-link')[0].appendChild(createButton(comment)); comment.children.forEach(comment => func(comment)); } this.jrApi.comments().forEach(comment => func(comment)); } /** * Удалить пункты меню "Люди" и "О проекте" */ removeTopMenuItems() { //@formatter:off Array.from(document.querySelectorAll('#navlist li')) .filter(elm => { return elm.querySelector('a').text === "Люди" || elm.querySelector('a').text === "О проекте" }) .forEach(elm => { elm.remove() }); //@formatter:on } /** * Удалить правую колонку */ removeRightColumn() { document.getElementById('sidebar').remove(); const width = '930px'; document.getElementById('header').style.width = width; document.getElementById('page').style.width = width; document.getElementById('topbar').children[0].style.width = width; document.getElementById('container').style.minWidth = '0'; } /** * Удалить переключатель языков */ removeLangSwitch() { Array.from(document.getElementsByClassName('lang_select')).forEach(elm => { elm.remove() }); } /** * Удалить из поста блоки "Тренды" и "Фэндомы" */ removeTrandsAndFandomsBlock() { const elements = document.getElementsByClassName('additional_info'); if (elements.length > 0) { elements[0].remove(); } } /** * Удалить из поста блок "Похожие посты" */ removeSimilarPostsBlock() { const elements = Array.from(document.getElementsByClassName('mainheader')) .filter(elm => { return elm.innerText === "Похожие посты" }); if (elements.length === 1) { elements[0].nextElementSibling.remove(); elements[0].remove(); } } } (function() { 'use strict'; const api = new JRApi(); const mod = new JRMod(api); mod.removeLangSwitch(); mod.removeTopMenuItems(); mod.removeRightColumn(); if (api.isPostPage()) { mod.addCollapseTreeCommentsButton(); mod.removeTrandsAndFandomsBlock() mod.removeSimilarPostsBlock() } else { console.log(api.posts()); } })();