您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
2021. 1. 6. 오전 11:17:30
- // ==UserScript==
- // @name Infinite scroller
- // @namespace Violentmonkey Scripts
- // @match https://*.arca.live/*
- // @grant none
- // @version 1.0.3
- // @author awk
- // @description 2021. 1. 6. 오전 11:17:30
- // ==/UserScript==
- // bounce-back element size
- const bounceBackBuffer = 96;
- // last-checked page
- let scrolledPage = 1;
- let isLoading = false;
- // from Arca Refresher@LeKAKiD v2.6.8
- function getTimeStr(datetime) {
- const date = new Date(datetime);
- let hh = date.getHours();
- let mm = date.getMinutes();
- if (hh.toString().length == 1) {
- hh = `0${hh}`;
- }
- if (mm.toString().length == 1) {
- mm = `0${mm}`;
- }
- return `${hh}:${mm}`;
- }
- function in24(datetime) {
- const target = new Date(datetime);
- const criteria = new Date();
- criteria.setHours(criteria.getHours() - 24);
- if (target > criteria) return true;
- return false;
- }
- const bounceBack = () => {
- if ((window.innerHeight + window.scrollY) >= document.body.offsetHeight) {
- scrollBy({
- 'top': -bounceBackBuffer,
- 'left': 0,
- 'behavior': 'smooth'
- });
- }
- };
- const getArticleId = elem => ~~elem.href.match(/\/b\/[^/]+\/(\d+)/)[1];
- const loadMore = async () => {
- if(isLoading) return;
- isLoading = true;
- // true if scrolledPage value is reached to unread page
- let reached = false;
- const currentArticles = [...document.querySelectorAll('.vrow')];
- const currentLastArticleId = getArticleId(currentArticles[currentArticles.length - 1]);
- // determine if current page doesn't include any article
- if(!currentLastArticleId) {
- isLoading = false;
- return;
- }
- while(!reached) {
- ++scrolledPage;
- // get next-page url
- const nextPage = (() => {
- // determine if current url includes page information
- if(location.href.match(/[&?]p=(\d+)/)) {
- return location.href.replace(/[&?]p=\d+/, pageString => {
- return pageString.replace(/\d+/, scrolledPage);
- });
- }
- // determine if current url includes query string
- else if(location.href.match(/\?.+?=.+?/)){
- return `${location.href}&p=${scrolledPage}`;
- }
- // it might be first-page of the board
- else {
- return `${location.href}?p=${scrolledPage}`;
- }
- })();
- console.log(nextPage);
- // fetch and parse next-page DOM
- const nextPageDOM = await fetch(nextPage)
- .then(res => res.text())
- .then(pageText => new DOMParser().parseFromString(pageText, 'text/html'));
- const nextPageArticles = [...nextPageDOM.querySelectorAll('.vrow:last-child')];
- const nextPageLastArticle = nextPageArticles[nextPageArticles.length - 1];
- // determine if reached to end
- if(!nextPageLastArticle || nextPageLastArticle.classList.length != 1) {
- // reached to end
- bounceBack();
- break;
- }
- // determine if reached to unread page
- const nextPageLastArticleId = getArticleId(nextPageLastArticle);
- if(currentLastArticleId > nextPageLastArticleId) {
- // filter unread articles
- const unreadArticles = [...nextPageDOM.querySelectorAll('.vrow')].filter(article => {
- // filter out notices
- if(article.classList.length != 1) return false;
- return getArticleId(article) < currentLastArticleId;
- });
- // attach unread articles with applying <time> js
- const articleList = document.querySelector('.list-table');
- unreadArticles.forEach(article => {
- const time = article.querySelector('time');
- if (time && in24(time.dateTime)) {
- time.innerText = getTimeStr(time.dateTime);
- }
- articleList.appendChild(article)
- });
- break;
- }
- }
- document.dispatchEvent(new Event('ar_article'));
- isLoading = false;
- return;
- }
- window.addEventListener('load', e => {
- // load current page
- const pageMatch = location.href.match(/[&?]p=(\d+)/);
- console.log(location.href);
- scrolledPage = pageMatch ? ~~pageMatch[1] : 1;
- // attach bounce-back element
- const bounceBackElement = document.createElement('div');
- bounceBackElement.style.width = 'inherit';
- bounceBackElement.style.height = `${bounceBackBuffer}px`;
- // center-align text
- bounceBackElement.style.textAlign = 'center';
- bounceBackElement.style.lineHeight = `${bounceBackBuffer}px`;
- // element color
- bounceBackElement.style.backgroundColor = 'grey';
- bounceBackElement.style.color = 'white';
- // element text
- bounceBackElement.innerText = 'Loading next page...';
- bounceBackElement.fontWeight = 'bold';
- document.body.appendChild(bounceBackElement);
- // apply smooth-scroll for bounce-back
- document.body.style.scrollBehavior = 'smooth';
- });
- window.addEventListener('scroll', e => {
- if ((window.innerHeight + window.scrollY) >= document.body.offsetHeight) {
- loadMore();
- }
- });