Greasy Fork

Greasy Fork is available in English.

去掉飞书虚拟滚动

去掉飞书虚拟滚动,连接整个网页

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         去掉飞书虚拟滚动
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  去掉飞书虚拟滚动,连接整个网页
// @author       You
// @match        https://*.feishu.cn/docx/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=feishu.cn
// @grant        none
// @license      MIT
// ==/UserScript==

(function () {
  "use strict";
  async function accumulate() {
    const scrollContainer = document.querySelector(".bear-web-x-container");
    const contentContainer = document.querySelector(".render-unit-wrapper");
    await setScrollTop();
    const frag = await scroll(scrollContainer, contentContainer);
    return frag;
  }

  function appendFragment(frag) {
    document.body.innerHTML = "";
    document.body.appendChild(frag);
    document.body.style.cssText = `
        width: 80%;
        padding: 0 100px;
        margin: auto;
        height: auto;
        overflow: auto;
    `;
  }

  function scroll(el, container, options) {
    let resolve;
    const promise = new Promise((r) => (resolve = r));
    const fragment = observe(container);
    const { scrollGap, scrollInterval } = Object.assign(
      {
        scrollGap: 300,
        scrollInterval: 200,
      },
      options
    );

    let lastScrollHeight = -1;

    const end = (window.stop = () => {
      clearInterval(interval);
      resolve(fragment);
    });
    const interval = setInterval(() => {
      if (el.scrollTop === lastScrollHeight) {
        end();
        return;
      }
      lastScrollHeight = el.scrollTop;
      el.scrollBy(0, scrollGap);
    }, scrollInterval);

    return promise;
  }

  function observe(target, callback) {
    const fragment = (window.f = document.createDocumentFragment());

    appendNodes(target.childNodes);

    function appendNodes(nodes) {
      for (let node of [...nodes]) {
        if (
          node.hasAttribute("data-block-id") &&
          !node.classList.contains("isEmpty")
        ) {
          fragment.appendChild(node.cloneNode(true));
        }
      }
    }

    const observer = new MutationObserver((mutationsList) => {
      for (let mutation of mutationsList) {
        if (mutation.type === "childList") {
          setTimeout(() => {
            appendNodes(mutation.addedNodes);
          }, 2000);
        }
      }

      if (callback) {
        callback(fragment);
      }
    });

    observer.observe(target, {
      childList: true,
    });

    return fragment;
  }

  async function setScrollTop() {
    const els = document.querySelectorAll(".catalogue__item-title");
    let anchor;
    for (let i = 0; i < els.length; i++) {
      let el = els[i];
      if (el.innerText.includes("上课")) {
        anchor = el;
      }
    }
    anchor.click();
    await wait(2000);
  }

  async function wait(ms) {
    return new Promise((resolve) => {
      setTimeout(() => {
        resolve();
      }, ms);
    });
  }

  async function waitPageLoad() {
    return new Promise((resolve) => {
      if (document.readyState === "complete") resolve();
      window.addEventListener("load", async (event) => {
        await wait(1000);
        resolve();
      });
    });
  }

  async function main() {
    await waitPageLoad();
    const frag = await accumulate();
    appendFragment(frag);
  }

  main();
})();