您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Force YouTube to show compact grid (max 6 videos per row) rather than "slim" grid (max 3 videos per row)
当前为
// ==UserScript== // @name YouTube - Force Compact Grid (increases max # videos per row) // @namespace https://gist.github.com/lbmaian/8c6961584c0aebf41ee7496609f60bc3 // @version 0.1 // @description Force YouTube to show compact grid (max 6 videos per row) rather than "slim" grid (max 3 videos per row) // @author lbmaian // @match https://www.youtube.com/* // @exclude https://www.youtube.com/embed/* // @icon https://www.youtube.com/favicon.ico // @run-at document-start // @grant none // ==/UserScript== (function() { 'use strict'; const DEBUG = false; const logContext = '[YouTube - Force Compact Grid]'; var debug; if (DEBUG) { debug = function(...args) { console.debug(logContext, ...args); }; } else { debug = function() {}; } function log(...args) { console.log(logContext, ...args); } function info(...args) { console.info(logContext, ...args); } function warn(...args) { console.warn(logContext, ...args); } function error(...args) { console.error(logContext, ...args); } function updateResponseData(response, label) { const tabs = response?.contents?.twoColumnBrowseResultsRenderer?.tabs; debug(label, 'contents.twoColumnBrowseResultsRenderer.tabs', tabs); if (tabs) { for (const tab of tabs) { const tabRenderer = tab.tabRenderer; if (tabRenderer) { const richGridRenderer = tabRenderer.content?.richGridRenderer; if (richGridRenderer && richGridRenderer.style == 'RICH_GRID_STYLE_SLIM') { log(label, 'tab', tabRenderer.title, 'tabRenderer.content.richGridRenderer.style:', richGridRenderer.style, '=> RICH_GRID_STYLE_COMPACT'); richGridRenderer.style = 'RICH_GRID_STYLE_COMPACT'; } } } } } // Note: Both of the following event listeners are too late: // ytd-app's own yt-page-data-fetched event listener (onYtPageDataFetched) already fires // by the time our own yt-page-data-fetched event listener fires, // and yt-page-data-fetched fires before yt-navigate-finish fires // document.addEventListener('yt-page-data-fetched', evt => { // debug('Navigated to', evt.detail.pageData.url); // debug(evt); // updateResponseData(evt.detail.pageData.response, 'yt-page-data-fetched pageData.response'); // }); // document.addEventListener('yt-navigate-finish', evt => { // debug('Navigated to', evt.detail.response.url); // debug(evt); // updateResponseData(evt.detail.response.response, 'yt-navigate-finish response.response'); // }); document.addEventListener('DOMContentLoaded', evt => { // Handle the initial page debug('ytInitialData', window.ytInitialData); updateResponseData(window.ytInitialData, 'ytInitialData'); // Handle changing tabs (e.g. 'videos' or 'live' tab) // Need to hook into ytd-app's ytd-app's own yt-page-data-fetched event listener (onYtPageDataFetched), // so that we can modify the data before that event listener fires const ytdApp = document.getElementsByTagName('ytd-app')[0]; debug('ytd-app', ytdApp); if (!ytdApp) { error('unexpectedly could not find ytd-app after page load'); return; } const origOnYtPageDataFetched = ytdApp.onYtPageDataFetched; ytdApp.onYtPageDataFetched = function(evt, detail) { debug('Navigated to', detail.pageData.url); debug(evt); updateResponseData(evt.detail.pageData.response, 'yt-page-data-fetched pageData.response'); return origOnYtPageDataFetched.call(this, evt, detail); }; }); })();