您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Sorts visible videos by length (↑/↓) on VK Video channel pages
// ==UserScript== // @name VK/VKVideo: sort by time by ChatGPT 5 (v2.0 – fixed selectors) // @namespace https://vkvideo.ru/ // @version 2.0 // @description Sorts visible videos by length (↑/↓) on VK Video channel pages // @match *://vkvideo.ru/* // @match *://vk.com/* // @icon https://upload.wikimedia.org/wikipedia/commons/thumb/2/21/VK.com-logo.svg/1200px-VK.com-logo.svg.png // @grant none // @license MIT // ==/UserScript== (function () { 'use strict'; // Selectors from your page: const SEL = { LIST: '[data-testid="catalog_list_videos"]', ITEM: ':scope > [data-testid="grid-item"]', DURATION: '[data-testid="video_card_duration"]', }; const MAX_Z = 2147483647; let ascending = true; const log = (...a) => console.log('[VK sort 2.0]', ...a); function timeToSeconds(t) { if (!t) return 0; const p = t.trim().split(':').map(Number); if (p.some(Number.isNaN)) return 0; if (p.length === 2) return p[0] * 60 + p[1]; if (p.length === 3) return p[0] * 3600 + p[1] * 60 + p[2]; return 0; } function toast(msg) { const t = document.createElement('div'); t.textContent = msg; Object.assign(t.style, { position: 'fixed', bottom: '140px', right: '20px', zIndex: MAX_Z, padding: '10px 14px', background: '#2b2b2b', color: '#fff', borderRadius: '8px', boxShadow: '0 2px 8px rgba(0,0,0,.35)', fontFamily: 'system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif', }); document.body.appendChild(t); setTimeout(() => t.remove(), 1600); } function findListAndItems() { const list = document.querySelector(SEL.LIST); if (!list) return { list: null, items: [] }; const items = Array.from(list.querySelectorAll(SEL.ITEM)); return { list, items }; } function collect() { const { list, items } = findListAndItems(); if (!list || !items.length) return { list: null, rows: [] }; const rows = items.map(li => { const dur = li.querySelector(SEL.DURATION); return { li, seconds: timeToSeconds(dur?.textContent || ''), txt: dur?.textContent?.trim() || '' }; }); return { list, rows }; } function sortNow() { const { list, rows } = collect(); if (!list || !rows.length) { toast('Could not find the list/tiles. Scroll to load more and try again.'); log('collect()', { list, rowsLen: rows.length }); return; } rows.sort((a, b) => ascending ? a.seconds - b.seconds : b.seconds - a.seconds); const frag = document.createDocumentFragment(); rows.forEach(r => frag.appendChild(r.li)); list.appendChild(frag); toast(ascending ? 'Sorted ↑ (shorter → longer)' : 'Sorted ↓ (longer → shorter)'); const btn = document.getElementById('vkvideo-sort-btn'); if (btn) btn.textContent = ascending ? 'Sort by time ↓' : 'Sort by time ↑'; ascending = !ascending; } function addButton() { if (document.getElementById('vkvideo-sort-btn')) return; const btn = document.createElement('button'); btn.id = 'vkvideo-sort-btn'; btn.textContent = 'Sort by time ↑'; Object.assign(btn.style, { position: 'fixed', bottom: '200px', right: '20px', zIndex: MAX_Z, padding: '12px 18px', fontSize: '16px', lineHeight: '1', background: '#4a76a8', color: '#fff', border: 'none', borderRadius: '10px', cursor: 'pointer', boxShadow: '0 4px 12px rgba(0,0,0,.35)', pointerEvents: 'auto', userSelect: 'none', }); btn.addEventListener('click', e => { e.preventDefault(); e.stopPropagation(); sortNow(); }, true); document.body.appendChild(btn); // shortcut: Alt+S window.addEventListener('keydown', e => { if (e.altKey && e.key.toLowerCase() === 's') { e.preventDefault(); sortNow(); } }, true); } function init() { addButton(); // SPA: ensure the button remains when the DOM changes const obs = new MutationObserver(() => addButton()); obs.observe(document.documentElement, { childList: true, subtree: true }); } if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', init); else init(); })();