对keylol琪露诺折扣贴表格按价格或折扣排序
- // ==UserScript==
- // @name Keylol Table Sort
- // @namespace http://tampermonkey.net/
- // @version 0.33
- // @description 对keylol琪露诺折扣贴表格按价格或折扣排序
- // @author 冰雪聪明琪露诺
- // @match https://keylol.com/*
- // @grant none
- // ==/UserScript==
- (function() {
- 'use strict';
- let optionsContainer;
- // 用于存储原始的表格行顺序
- let originalRows = [];
- const setupSort = () => {
- optionsContainer && optionsContainer.remove();
- const table = document.querySelector('.t_fsz table.t_table');
- if (!table) return;
- const priceHeader = [...table.rows[0].cells].find(cell => cell.textContent.includes('商店价格'));
- const reviewHeader = [...table.rows[0].cells].find(cell => cell.textContent.includes('游戏评价'));
- const nameHeader = [...table.rows[0].cells].find(cell => cell.textContent.includes('游戏名称'));
- if (!priceHeader || !reviewHeader || !nameHeader) return;
- // 存储原始行顺序
- originalRows = [...table.rows].slice(1);
- optionsContainer = document.createElement('div');
- Object.assign(optionsContainer.style, {
- position: 'absolute', display: 'none', background: 'white',
- border: '1px solid #ccc', padding: '5px', zIndex: 100
- });
- optionsContainer.className = 'keylol-sort-options';
- const priceIndex = [...table.rows[0].cells].findIndex(cell => cell.textContent.includes('商店价格'));
- const reviewIndex = [...table.rows[0].cells].findIndex(cell => cell.textContent.includes('游戏评价'));
- const nameIndex = [...table.rows[0].cells].findIndex(cell => cell.textContent.includes('游戏名称'));
- const createSortOptions = (header, options, index) => {
- let visible = false;
- header.addEventListener('click', e => {
- e.stopPropagation();
- if (visible) {
- optionsContainer.style.display = 'none';
- visible = false;
- } else {
- optionsContainer.innerHTML = '';
- options.forEach(option => {
- const opt = document.createElement('div');
- opt.textContent = option.text;
- opt.style.cssText = 'cursor: pointer; padding: 5px';
- opt.addEventListener('click', () => {
- sortTable(table, option.fn, index);
- optionsContainer.style.display = 'none';
- visible = false;
- });
- optionsContainer.appendChild(opt);
- });
- const { left, bottom } = header.getBoundingClientRect();
- const { pageXOffset, pageYOffset } = window;
- Object.assign(optionsContainer.style, { left: left + pageXOffset + 'px', top: bottom + pageYOffset + 'px', display: 'block' });
- visible = true;
- }
- });
- };
- const priceSortOptions = [
- { text: '按价格排序(升序)', fn: (a, b, idx) => parseFloat(a.cells[idx].textContent.match(/¥(\d+\.\d+)/)[1]) - parseFloat(b.cells[idx].textContent.match(/¥(\d+\.\d+)/)[1]) },
- { text: '按价格排序(降序)', fn: (a, b, idx) => parseFloat(b.cells[idx].textContent.match(/¥(\d+\.\d+)/)[1]) - parseFloat(a.cells[idx].textContent.match(/¥(\d+\.\d+)/)[1]) },
- { text: '按折扣排序(升序)', fn: (a, b, idx) => parseFloat(a.cells[idx].textContent.match(/-(\d+)%/)[1]) - parseFloat(b.cells[idx].textContent.match(/-(\d+)%/)[1]) },
- { text: '按折扣排序(降序)', fn: (a, b, idx) => parseFloat(b.cells[idx].textContent.match(/-(\d+)%/)[1]) - parseFloat(a.cells[idx].textContent.match(/-(\d+)%/)[1]) }
- ];
- const reviewSortOptions = [
- { text: '按好评率排序(升序)', fn: (a, b, idx) => {
- const ratingA = parseFloat(a.cells[idx].textContent.match(/(\d+)%/)[1]);
- const ratingB = parseFloat(b.cells[idx].textContent.match(/(\d+)%/)[1]);
- return ratingA === ratingB ?
- parseInt(a.cells[idx].textContent.match(/(\d+)篇/)[1]) - parseInt(b.cells[idx].textContent.match(/(\d+)篇/)[1]) :
- ratingA - ratingB;
- } },
- { text: '按好评率排序(降序)', fn: (a, b, idx) => {
- const ratingA = parseFloat(a.cells[idx].textContent.match(/(\d+)%/)[1]);
- const ratingB = parseFloat(b.cells[idx].textContent.match(/(\d+)%/)[1]);
- return ratingA === ratingB ?
- parseInt(b.cells[idx].textContent.match(/(\d+)篇/)[1]) - parseInt(a.cells[idx].textContent.match(/(\d+)篇/)[1]) :
- ratingB - ratingA;
- } },
- { text: '按评测数排序(升序)', fn: (a, b, idx) => parseInt(a.cells[idx].textContent.match(/(\d+)篇/)[1]) - parseInt(b.cells[idx].textContent.match(/(\d+)篇/)[1]) },
- { text: '按评测数排序(降序)', fn: (a, b, idx) => parseInt(b.cells[idx].textContent.match(/(\d+)篇/)[1]) - parseInt(a.cells[idx].textContent.match(/(\d+)篇/)[1]) }
- ];
- const nameSortOptions = [
- {
- text: '恢复默认排序',
- fn: (table) => {
- while (table.rows.length > 1) table.deleteRow(1);
- originalRows.forEach(row => table.appendChild(row));
- }
- },
- { text: '按名称排序(升序)', fn: (a, b, idx) => a.cells[idx].textContent.localeCompare(b.cells[idx].textContent) },
- { text: '按名称排序(降序)', fn: (a, b, idx) => b.cells[idx].textContent.localeCompare(a.cells[idx].textContent) }
- ];
- createSortOptions(priceHeader, priceSortOptions, priceIndex);
- createSortOptions(reviewHeader, reviewSortOptions, reviewIndex);
- createSortOptions(nameHeader, nameSortOptions, nameIndex);
- document.body.appendChild(optionsContainer);
- document.addEventListener('click', e => {
- optionsContainer && !optionsContainer.contains(e.target) && (optionsContainer.style.display = 'none');
- });
- };
- const sortTable = (table, sortFunction, index) => {
- if (sortFunction.length === 1) {
- // 如果是恢复默认排序
- sortFunction(table);
- } else {
- const rows = [...table.rows].slice(1);
- rows.sort((a, b) => sortFunction(a, b, index));
- while (table.rows.length > 1) table.deleteRow(1);
- rows.forEach(row => table.appendChild(row));
- }
- };
- document.body.addEventListener('click', e => {
- if (e.target.closest('.tindex li, div[style*="text-align: center;margin-top: 10px;"] a')) {
- setTimeout(setupSort, 1000);
- }
- });
- setTimeout(setupSort, 1000);
- })();