Komica 檔案區自定義篩選與排序工具

這個腳本可以讓使用者自定義最小回覆數,按回覆數排序並且高亮顯示回覆數大於一定數值的貼文。

// ==UserScript==
// @name Komica 檔案區自定義篩選與排序工具
// @namespace https://chat.openai.com/
// @description 這個腳本可以讓使用者自定義最小回覆數,按回覆數排序並且高亮顯示回覆數大於一定數值的貼文。
// @version      3.0.1
// @author ChatGPT
// @match https://*.komica1.org/*/pixmicat.php?mode=module&load=mod_threadlist*
// @match https://*.komica2.cc/*/pixmicat.php?mode=module&load=mod_threadlist*
// @icon https://www.google.com/s2/favicons?sz=64&domain=komica.org
// @grant none
// @license MIT
// ==/UserScript==

(function() {
'use strict';

// 從 localStorage 中獲取最小回覆數和排序方式,如果沒有存儲則使用默認值
let minRepliesToShow = parseInt(localStorage.getItem('minRepliesToShow')) || 30;
let sortByReplies = localStorage.getItem('sortByReplies') === 'true';
const table = document.querySelector('table[align="center"][width="97%"], #contents > table > tbody');
const rows = Array.from(table.querySelectorAll('tr:not(:first-child)'));
const responseIndex = Array.from(table.querySelectorAll('th')).findIndex(th => th.textContent.trim() === '回應');
let rowsArray = [];

rows.forEach(row => {
const replies = parseInt(row.cells[responseIndex]?.textContent.trim()) || 0;
row.style.display = replies >= minRepliesToShow ? '' : 'none';
});

const options = document.createElement('div');
options.innerHTML = `
<label for="min-replies-to-show">最小回應數</label>
<select id="min-replies-to-show" name="min-replies-to-show">
<option value="0" ${minRepliesToShow === 0 ? 'selected' : ''}>0</option>
<option value="10" ${minRepliesToShow === 10 ? 'selected' : ''}>10</option>
<option value="30" ${minRepliesToShow === 30 ? 'selected' : ''}>30</option>
<option value="50" ${minRepliesToShow === 50 ? 'selected' : ''}>50</option>
<option value="100" ${minRepliesToShow === 100 ? 'selected' : ''}>100</option>
</select>
<label for="sort-by-replies">按回應數排序</label>
<input type="checkbox" id="sort-by-replies" name="sort-by-replies" checked>
`;
options.style.position = 'fixed';
options.style.left = '20px';
options.style.bottom = '20px';
options.style.color = 'red';
options.style.backgroundColor = 'white';
options.style.padding = '20px';
options.style.borderRadius = '20px';
document.body.appendChild(options);

const minRepliesToShowInput = document.getElementById('min-replies-to-show');
const sortByRepliesInput = document.getElementById('sort-by-replies');
minRepliesToShowInput.addEventListener('change', (event) => {
minRepliesToShow = parseInt(event.target.value);
localStorage.setItem('minRepliesToShow', minRepliesToShow);

rows.forEach(row => {
const replies = parseInt(row.cells[responseIndex]?.textContent.trim()) || 0;
row.style.display = replies >= minRepliesToShow ? '' : 'none';
});
});

sortByRepliesInput.addEventListener('change', (event) => {
sortByReplies = event.target.checked;
localStorage.setItem('sortByReplies', sortByReplies);
if (sortByReplies) {
sortRows();
} else {
restoreRowOrder();
}
});

function restoreRowOrder() {
rows.forEach(row => {
table.appendChild(row);
});
}
function sortRows() {
rowsArray = Array.from(rows);
rowsArray.sort(function(row1, row2) {
var response1 = parseInt(row1.cells[responseIndex].textContent.trim(), 10);
var response2 = parseInt(row2.cells[responseIndex].textContent.trim(), 10);
return response2 - response1;
});

for (var j = 0; j < rowsArray.length; j++) {
table.appendChild(rowsArray[j]);
}
}

document.getElementById('sort-by-replies').addEventListener('change', (event) => {
sortByReplies = event.target.checked;
if (sortByReplies) {
sortRows();
} else {
restoreRowOrder();
}
});

sortRows();

minRepliesToShowInput.dispatchEvent(new Event('change'));

var style = document.createElement('style');
style.innerHTML = '.highlight-yellow { background-color: yellow; } .highlight-green { background-color: #D8FAD8;; }';
document.head.appendChild(style);

rowsArray.forEach(row => {
let replies = parseInt(row.cells[responseIndex].textContent.trim()) || 0;
if (replies >= 100) {
row.classList.remove('ListRow1_bg', 'ListRow2_bg');
row.classList.add('highlight-yellow');
row.style.fontWeight = 'bold';
} else if (replies >= 50) {
row.classList.remove('ListRow1_bg', 'ListRow2_bg');
row.classList.add('highlight-green');
row.style.fontWeight = 'bold';
}
});

window.addEventListener('load', () => {
if (localStorage.getItem('sortByReplies') === 'false') {
sortByRepliesInput.checked = false;
restoreRowOrder();
}

const replyLinks = document.querySelectorAll('a[href^="pixmicat.php?res="]');
replyLinks.forEach(link => {
link.target = "_blank";
});
});
})();