USTC icourse reviews enhanced

USTC icourse fold reviews and expand control

当前为 2024-04-29 提交的版本,查看 最新版本

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         USTC icourse reviews enhanced
// @namespace    http://tampermonkey.net/
// @version      2024-04-32
// @description  USTC icourse fold reviews and expand control
// @author       liuly
// @match        https://icourse.club/course/*
// @icon         data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
// @license      MIT
// ==/UserScript==

function addStyle(aCss){
    'use strict';
    let head = document.getElementsByTagName('head')[0];
    if (head) {
      let style = document.createElement('style');
      style.setAttribute('type', 'text/css');
      style.textContent = aCss;
      head.appendChild(style);
      return style;
    }
    return null;
}

addStyle(`
.folded {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 20;
    overflow: hidden;
}
.display-folded .review-content {
    -webkit-line-clamp: unset !important;
}
.read-more {
    display: block;
    margin-top: 10px;
}
.display-folded .read-more {
    display: none !important;
}
.fold-button {
    display: none;
}
.display-folded .fold-button {
    display: inline !important;
}
.fixed-bottom-bar {
    position: fixed;
    width: 100%;
    bottom: 0;
    padding-top: 15px;
    background-color: #fff;
}
`);

(function() {
    'use strict';

    let requestId;

    // 为所有过长评论默认折叠,并在内容末尾增加“打开”文字按钮;在底栏增加“折叠”文字按钮
    function initFoldedElements() {
        const reviewContents = document.querySelectorAll('.review-content');

        for (const reviewContent of reviewContents) {
            const reviewContentHeight = reviewContent.scrollHeight;
            if (reviewContentHeight < 30 * parseFloat(window.getComputedStyle(reviewContent).lineHeight)) {
                continue;
            }
            const wrapperDiv = document.createElement('div');
            wrapperDiv.className = 'review-wrapper';

            // 移动到 wrapper 内,限制行数
            reviewContent.parentNode.insertBefore(wrapperDiv, reviewContent);
            wrapperDiv.appendChild(reviewContent);
            reviewContent.classList.add('folded');

            // 查看更多
            const readMoreButton = document.createElement('button');
            readMoreButton.classList.add('read-more');
            readMoreButton.textContent = '查看更多';
            readMoreButton.addEventListener('click', () => {
                wrapperDiv.parentNode.classList.add('display-folded');
            });
            wrapperDiv.appendChild(readMoreButton);

            // 折叠
            const foldButton = document.createElement('button');
            foldButton.classList.add('fold-button');
            foldButton.textContent = '折叠';
            foldButton.addEventListener('click', () => {
                wrapperDiv.parentNode.classList.remove('display-folded');
                window.scrollTo({top: wrapperDiv.offsetTop, left: 0});
            });
            wrapperDiv.nextElementSibling.appendChild(foldButton);
        }
    }

    // 在每一帧中执行的函数
    function checkContentPosition() {
        // 获取所有可能折叠的评课内容元素
        const reviewContents = document.querySelectorAll('.review-wrapper');

        // 获取页面底部位置信息
        const pageBottom = window.innerHeight;

        // 遍历评课内容元素
        reviewContents.forEach(reviewContent => {
            // 获取评课内容元素的位置信息
            const reviewContentRect = reviewContent.getBoundingClientRect();
            const reviewContentTop = reviewContentRect.top;
            const reviewContentBottom = reviewContentRect.bottom;

            const bottomBar = reviewContent.nextElementSibling;
            // 如果评课内容元素出现,且处在打开状态
            const isOpen = reviewContent.parentNode.classList.contains('display-folded');
            if (reviewContentTop < pageBottom && reviewContentBottom > pageBottom && isOpen) {
                // 设置底栏元素的 fixed bottom 样式
                bottomBar.classList.add('fixed-bottom-bar');
            } else {
                bottomBar.classList.remove('fixed-bottom-bar');
            }
        });

        // 继续在下一帧中执行
        requestId = window.requestAnimationFrame(checkContentPosition);
    }

    // 在页面加载完成后执行
    window.addEventListener('load', () => {
        initFoldedElements();
        // 在每一帧中检查评课内容元素的位置并设置底栏样式
        requestId = window.requestAnimationFrame(checkContentPosition);
    });
})();