您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
排序+變成待辦清單
// ==UserScript== // @name P&D戰友網 - 首頁活動管理 // @description 排序+變成待辦清單 // @icon https://pad.skyozora.com/images/egg.ico // @author jaychsu // @version 1.0.0 // @license WTFPL // @include *://pad.skyozora.com/ // @namespace https://greasyfork.org/users/420771 // ==/UserScript== (function () { 'use strict' /** * Config */ const enableSort = true const sortFactor = true ? 1 : -1 // 1 for ascend const enableTodos = true /** * Main */ window.addEventListener('DOMContentLoaded', function () { const $eventContainer = document.querySelector('.hasCountdown').parentNode.parentNode.parentNode if (enableTodos) { removeExpiredKeys() addTodoStyle() initTodos($eventContainer) } if (enableSort) sortEvents($eventContainer) }) /** * Helpers */ function initTodos($eventContainer) { const expires = JSON.parse(localStorage.getItem('td:expires')) || {} const now = Date.now() const currentYear = new Date().getFullYear() let $checkbox, $checkboxContainer, time, deadline Array.prototype.forEach.call($eventContainer.children, $row => { $checkboxContainer = document.createElement('TD') if (!Array.prototype.slice.call($row.children, -1)[0].children[0].classList.contains('hasCountdown')) { $row.prepend($checkboxContainer) return } let $children = Array.from($row.children) let key = `td:${$children[2].innerText.trim()}` $checkbox = document.createElement('INPUT') $checkbox.type = 'checkbox' $checkbox.addEventListener('click', ({target: $el}) => { if (!expires.hasOwnProperty(key)) { time = $children[0].innerText.match(/~(.*)?/)[1].slice(0, -1) deadline = +new Date(`${currentYear} ${time}:00`) expires[key] = ((deadline < now) ? +new Date(`${currentYear + 1} ${time}:00`) : deadline) + 86400 * 1000 localStorage.setItem('td:expires', JSON.stringify(expires)) } if ($el.checked) { $row.classList.add('padtodo') localStorage.setItem(key, 1) } else { $row.classList.remove('padtodo') localStorage.setItem(key, 0) } }, false) if (+localStorage.getItem(key)) { $checkbox.checked = true $row.classList.add('padtodo') } $checkboxContainer.append($checkbox) $row.prepend($checkboxContainer) }) } function removeExpiredKeys() { const expires = JSON.parse(localStorage.getItem('td:expires')) || {} const now = Date.now() Object.keys(expires) .filter(key => expires[key] < now) .forEach(key => { delete expires[key] localStorage.removeItem(key) }) localStorage.setItem('td:expires', JSON.stringify(expires)) } function addTodoStyle() { const $head = document.head || document.getElementsByTagName('head')[0] const $style = document.createElement('STYLE') const css = ` tr.padtodo { opacity: 20%; } ` $style.type = 'text/css' if ($style.styleSheet) { // This is required for IE8 and below. $style.styleSheet.cssText = css } else { $style.appendChild(document.createTextNode(css)) } $head.appendChild($style) } function sortEvents($eventContainer) { let ha, hb, ma, mb, isstarta, isstartb, isdonea, isdoneb Array.from(document.querySelectorAll('.hasCountdown')).sort(($a, $b) => { isdonea = $a.parentNode.parentNode.children[0].children[0].checked isdoneb = $b.parentNode.parentNode.children[0].children[0].checked isstarta = $a.parentNode.innerText.slice(-2) === '開始' isstartb = $b.parentNode.innerText.slice(-2) === '開始' ha = parseInt($a.children[0].children[0].innerText) hb = parseInt($b.children[0].children[0].innerText) ma = parseInt($a.children[1].children[0].innerText) mb = parseInt($b.children[1].children[0].innerText) if (isdonea !== isdoneb) return (isdonea) ? 1 : -1 if (isstarta !== isstartb) return (isstarta) ? 1 : -1 if (ha < hb) return -1 * sortFactor if (ha > hb) return 1 * sortFactor if (ma < mb) return -1 * sortFactor if (ma > mb) return 1 * sortFactor return 0 }).forEach($el => { $eventContainer.appendChild($el.parentNode.parentNode) }) } })()